#multithreading #pthreads #futex
Вопрос:
Я пытаюсь использовать futex
системный вызов для синхронизации двух независимых программ на языке си. progA
создает несколько потоков и из каждого потока вызывает futex_test
. Я пытаюсь убедиться, что progA
futex_test
за раз запускается только один поток.
Мой подход, поскольку я не могу придумать способ инициализации любой глобальной переменной, которая является общей для этих двух программ, progA
создает и записывает 1(available)
в общую память. И после вызова futex_test
считайте из той же памяти, записывайте 0(unavailable)
и вызывайте FUTEX_WAIT
системный вызов. Когда закончите, он записывает 1
данные в общую память и вызывает FUTEX_WAKE
.
Но это не работает. Я понимаю, что это ошибочная логика. Есть идеи, как это сделать?
Н.Б: Я не хочу вносить какие-либо изменения в «progA». Я могу вносить изменения только в futex_test
прогА.с
typedef struct file{ int pid; } file_entry; pthread_t tid[5]; int counter=0; void write_1_mem(){ int shmid; int n; file_entry *entries; if ((shmid = shmget(20541, sizeof(file_entry) 256, IPC_CREAT | 0666)) == -1) { printf("problem3"); exit(2); } entries = (file_entry *) shmat(shmid, 0, 0); if (entries == NULL ) { printf("problem4"); exit(2); } int pidD = 1; entries-gt;pid = pidD; shmdt(amp;shmid); } void* trythis(void* arg){ printf("Thread %d createdn",counter); system("./futex_test"); printf("Thread %d finishedn",counter); return NULL; } int main(){ int i = 0; int error; int k=0; write_1_mem(); while (i lt; 5) { counter=i; error = pthread_create(amp;(tid[i]),NULL,amp;trythis, NULL); if (error != 0) printf("nThread can't be created :[%s]",strerror(error)); i ; } for (k=0;klt;5;k ){ pthread_join(tid[k], NULL); } return 0; }
futex_test.c
typedef struct file{ int pid; } file_entry; // Global variable int shmid; file_entry *entries; static int *ftex; //system call static int futex(int *uaddr, int futex_op, int val, const struct timespce *timeout, int *uaddr2, int val3 ){ return syscall(SYS_futex,uaddr,futex_op,val,timeout,uaddr,val3); } void read_shared_mem(){ int n; if ((shmid = shmget(20541, sizeof(file_entry) 256, IPC_CREAT | 0666)) == -1) { printf("shmget"); exit(2); } entries = (file_entry *) shmat(shmid, 0, 0); if (entries == NULL) { printf("problem2"); exit(2); } } void write_0_shared_mem(){ if ((shmid = shmget(20541, sizeof(file_entry) 256, IPC_CREAT | 0666)) == -1) { printf("problem3"); exit(2); } entries = (file_entry *) shmat(shmid, 0, 0); if (entries == NULL ) { printf("problem4"); exit(2); } int pidD = 0; entries-gt;pid = pidD; shmdt(amp;shmid); } void write_1_shared_mem(){ if ((shmid = shmget(20541, sizeof(file_entry) 256, IPC_CREAT | 0666)) == -1) { printf("problem3"); exit(2); } entries = (file_entry *) shmat(shmid, 0, 0); if (entries == NULL ) { printf("problem4"); exit(2); } int pidD = 1; entries-gt;pid = pidD; shmdt(amp;shmid); } static void fwait(file_entry *futexp){ int s; while (1) { if(futexp-gt;pid==1) { write_0_shared_mem(); break; } s = futex(amp;futexp-gt;pid, FUTEX_WAIT, 0, NULL, NULL, 0); if (s == -1 amp;amp; errno != EAGAIN) exit("futex-FUTEX_WAIT"); } } static void fpost(file_entry *futexp){ int s; if(futexp-gt;pid==0){ write_1_shared_mem(); s = futex(amp;futexp-gt;pid, FUTEX_WAKE, 1, NULL, NULL, 0); if (s == -1) exit("futex-FUTEX_WAKE"); } } int main(){ int volatile I; read_shared_mem(); fwait(entries); for(i=0;ilt;5;i ){ printf("i=%dn",I); } fpost(entries); return 0; }
Выход
$./progA Thread 3 created Thread 3 created Thread 4 created Thread 4 created Thread 2 created i=0 i=1 i=2 i=3 i=4 Thread 4 finished i=0 i=1 i=2 i=3 i=4 i=0 i=1 i=2 i=3 i=4 Thread 4 finished Thread 4 finished i=0 i=1 i=2 i=3 i=4 i=0 i=1 i=2 i=3 i=4 Thread 4 finished Thread 4 finished
Комментарии:
1. Неопределенное поведение для несинхронизированного, не только для чтения, неатомного доступа к объекту из нескольких потоков.