linux - Synchronizing processes with semaphores and signals in C -


i have write program in c on linux. has have 3 processes - first reads stdin, sends message through fifo second process, counts lenght of recevied message , sends result third process (also through fifo), displays on stdout. have synchronize using semaphores. have add signal handling (which doing using shared memory) - 1 signal end program, second stop it, third resume. signal can send of processes. have code already, it's not working should.

first problem synchronization - can see running it, first message received second process, stuck. first , second processes showing messages, not third one. there similar, it's confusing. have send message, p3 showing length of previous one.

second problem signals - after sending one, have press enter (for sigusr) or send message (for sigint) served.

any ideas what's wrong? there improvements posted before, it's still not working , don't have time finish (till monday). know it's lot of code, if analyze communication of second , third process, grateful.

#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ipc.h> #include <unistd.h> #include <sys/sem.h> #include <signal.h> #include <sys/shm.h> #include <sys/wait.h> #include <string.h> #include <errno.h>  #define write 1 #define read 0 #define mem_id 1 #define mem_size 1  #define ok  "[ \033[1;32mok\033[0m ]\n" #define err "[\033[1;31mfail\033[0m] " #define signal "\033[1;33m\033[5m>> signal <<\033[0m\n"  #define s1 sigint #define s2 sigusr1 #define s3 sigusr2 #define s4 sigcont  /* union semun - posix specification semctl() */ /* nb: on mac os x, , apparently in defiance of posix, <sys/sem.h> declares union semun */ /* union semun {     int val;     struct semid_ds *buf;     unsigned short  *array; } arg; */  /* union semun {     int val;     ushort *array; }; */  int process1(void); int process2(void); int process3(void); void signal_callback(int signo); //void signal_handling(int snd, int rcv);   // jl void signal_handling(void);     // jl void sem_down(int semid, int semnum); void sem_up(int semid, int semnum);  char work = 1, quit = 0; char inter_snd = 0, inter_rcv = 0; struct sembuf semstruct; int sem23, sem12, mem; char *message; int res[3];  static const char *fifoname[] = { "1fifo2", "2fifo3" };  static void main_quit(int n) {     printf("%s(): signal %d\n", __func__, n);  // jl     kill(res[0], s1); }  int main(void) {     //union semun arg;  // jl     printf("[g] launching\n");      signal(sigint, main_quit);     signal(sigterm, main_quit);     // creating fifo     printf("[g] creating fifo... ");     res[0] = mkfifo(fifoname[0], 0644);     res[1] = mkfifo(fifoname[1], 0644);     if ((res[0] == -1) || (res[1] == -1))     {         perror(err);         unlink(fifoname[0]);         unlink(fifoname[1]);         return 1;     }     else         printf(ok);      // create 2 semaphores , set values     printf("[g] creating semaphores... ");     sem12 = semget(read, 1, ipc_creat | 0644);     sem23 = semget(write, 1, ipc_creat | 0644);      if ((sem23 == -1) || (sem12 == -1))     {         perror(err);         return 1;     }     else         printf(ok);      printf("[g] initializing semaphores values... ");     semctl(sem12, 0, setval, 0);     semctl(sem12, 1, setval, 1);     semctl(sem23, 0, setval, 0);     semctl(sem23, 1, setval, 1);     printf(ok);      // creating shared memory     printf("[g] reserving shared memory... ");     mem = shmget(mem_id, mem_size, ipc_creat | 0644);     message = (char *)shmat(mem, 0, 0);      if (mem == -1)     {         perror(err);         return 1;     }     else         printf(ok);      if ((res[0] = fork()) == 0)     {         process1();         exit(0);     }      if ((res[1] = fork()) == 0)     {         process2();         exit(0);     }      if ((res[2] = fork()) == 0)     {         process3();         exit(0);     }      printf("[g] building process tree... ");     if ((res[0] == -1) || (res[1] == -1) || (res[2] == -1))     {         perror(err);         return 1;     }     else     {         printf(ok);         printf("[g] p1[pid]: %d, p2[pid]: %d, p3[pid]: %d\n", res[0], res[1], res[2]);     }      wait(null);     wait(null);     wait(null);      printf("[g] deleting fifo... ");     res[0] = unlink(fifoname[0]);     res[1] = unlink(fifoname[1]);     if ((res[0] == -1) || (res[1] == -1))         perror(err);     else         printf(ok);      printf("[g] freeing shared memory... ");     res[0] = shmdt((char *)message);     res[1] = shmctl(mem, ipc_rmid, 0);     if ((res[0] == -1) || (res[1] == -1))         perror(err);     else         printf(ok);      printf("[g] deleting semaphores... ");     res[0] = semctl(sem23, 0, ipc_rmid, 0);     res[1] = semctl(sem12, 0, ipc_rmid, 0);     if ((res[0] == -1) || (res[1] == -1))         perror(err);     else         printf(ok);      printf("[g] ending...\n");     return 0; }  int process1(void) {     char tab[100];     file *fifoh;      signal(s1, signal_callback);     signal(s2, signal_callback);     signal(s3, signal_callback);     signal(s4, signal_callback);      fifoh = fopen(fifoname[0], "w");     setbuf(fifoh, null);      printf("[p1] ready.\n");     //while (fgets(tab, sizeof(tab), stdin) > 0)    // jl     while (fgets(tab, sizeof(tab), stdin) != 0)     // jl     {         if (work)         {             sem_down(sem12, write);             printf("[p1] sending: %s", tab);             fprintf(fifoh, "%s\n", tab);             sem_up(sem12, read);         }         //signal_handling(inter_snd, inter_rcv);    // jl         signal_handling();  // jl     }     fclose(fifoh);     printf("[p1] ending...\n");     return 0; }  int process2(void) {     char tab[100];     file *fifo_in, *fifo_out;      printf("[p2] ready.\n");      fifo_in = fopen(fifoname[0], "r");     fifo_out = fopen(fifoname[1], "w");      setbuf(fifo_out, null);     setbuf(fifo_in, null);      signal(s1, signal_callback);     signal(s2, signal_callback);     signal(s3, signal_callback);     signal(s4, signal_callback);          {         if (work)         {             sem_down(sem12, read);             fscanf(fifo_in, "%s", (char *)tab);             sem_up(sem12, write);             printf("[p2] received \"%s\" length %zu.\n", tab, strlen(tab));             sem_down(sem23, write);             fprintf(fifo_out, "%d\n", (int)strlen(tab));             sem_up(sem23, read);         }         //signal_handling(inter_snd, inter_rcv);    // jl         signal_handling();  // jl     } while (!quit);      fclose(fifo_in);     fclose(fifo_out);     printf("[p2] ending...\n");     return 0; }  int process3(void) {     file *fifo_in;     int count;      printf("[p3] ready.\n");      signal(s1, signal_callback);     signal(s2, signal_callback);     signal(s3, signal_callback);     signal(s4, signal_callback);      fifo_in = fopen(fifoname[1], "r");     setbuf(fifo_in, null);          {         if (work)         {             sem_down(sem23, read);             fscanf(fifo_in, "%d\n", (int *)&count);             sem_up(sem23, write);             printf("[p3] received: %d characters.\n", count);         }         //signal_handling(inter_snd, inter_rcv);    // jl         signal_handling();  // jl     } while (!quit);     fclose(fifo_in);     printf("[p3] ending...\n");     return 0; }  //void signal_handling(int snd, int rvc) void signal_handling(void) {     if (inter_snd > 0)     {         printf("signal received...\n");          semstruct.sem_op = -3;         semop(sem23, &semstruct, 1);          *message = inter_snd;         inter_snd = 0;          semstruct.sem_op = 3;         semop(sem12, &semstruct, 1);          printf("sending other processes\n");         kill(0, s4);     }     if (inter_rcv)     {         inter_rcv = 0;          semstruct.sem_op = -1;         semop(sem12, &semstruct, 1);          switch (*message)         {         case 1:             printf("quitting...\n");             quit = 1;             break;         case 2:             printf("stopping...\n");             work = 0;             break;         case 3:             printf("starting...\n");             work = 1;             break;         default:             printf("there's garbage in memory :/..\n");         }         semstruct.sem_op = 1;         semop(sem23, &semstruct, 1);     } }  void signal_callback(int signo) {     printf(signal);     switch (signo)     {     case s1:         inter_snd = 1;         break;     case s2:         inter_snd = 2;         break;     case s3:         inter_snd = 3;         break;     case s4:         inter_rcv = 1;         break;     } }  void sem_down(int semid, int semnum) {     semstruct.sem_flg = 0;     semstruct.sem_num = semnum;     semstruct.sem_op = -1;         {         errno = 0;         semop(semid, &semstruct, 1);     } while (errno == eintr); }  void sem_up(int semid, int semnum) {     semstruct.sem_flg = 0;      semstruct.sem_num = semnum;     semstruct.sem_op = 1;     semop(semid, &semstruct, 1); } 

expected behaviour:

[p3] ready. [p2] ready. [p1] ready. asd [p1] sending: asd [p2] received "asd" length 3. [p3] received: 3 characters. [p1] sending: [p2] received "as" length 2. [p3] received: 2 characters. 

signals:

signal should recieved , sent every other processes. happens next specified in singnal_handling. every process should show message (quitting/stopping/etc).

actual behaviour:

[p3] ready. [p2] ready. [p1] ready. asd  [p1] sending: asd [p2] received "asd" length 3. dd [p1] sending: dd [p2] received "dd" length 2. [p3] received: 3 characters. //first message [p1] sending: [p2] received "as" length 2. [p3] received: 2 characters. //second asd [p1] sending: asd [p2] received "asd" length 3. [p3] received: 2 characters. // third 

and signals, well... figured out after sigint send message, hit enter twice , got expected behaviour (quitting program). pressing enter works when i'm sending signals:

$ kill -s sigusr1 2900 $ kill -s sigusr2 2900 

gives:

asd [p1] sending: asd [p2] received "asd" length 3. [p3] received: 3 characters. signal received... sending other processes >> signal << stopping... >> signal << >> signal << >> signal << signal received... sending other processes >> signal << >> signal << >> signal << starting...  [p1] sending:  starting... asd [p1] sending: asd [p2] received "asd" length 3. starting... [p3] received: 3 characters. 

so again - after sending signal have send message handled. so, it's kinda working. very, bad.

taking code verbatim onto mac running mac os x 10.10.3, using gcc 5.1.0, using standard compilation options use compiling code stack overflow, compilation warnings shown (i called code semshm.c):

$ gcc -o3 -g -std=c11 -wall -wextra -wmissing-prototypes -wstrict-prototypes \ >     -wold-style-definition -werror semshm.c -o semshm semshm.c:29:7: error: redefinition of ‘union semun’  union semun {        ^ in file included semshm.c:8:0: /usr/include/sys/sem.h:176:7: note: defined here  union semun {        ^ semshm.c:48:6: error: no previous prototype ‘main_quit’ [-werror=missing-prototypes]  void main_quit(int n) {       ^ semshm.c: in function ‘main_quit’: semshm.c:48:20: error: unused parameter ‘n’ [-werror=unused-parameter]  void main_quit(int n) {                     ^ semshm.c: in function ‘main’: semshm.c:54:17: error: unused variable ‘arg’ [-werror=unused-variable]      union semun arg;                  ^ semshm.c: in function ‘process1’: semshm.c:161:43: error: ordered comparison of pointer integer 0 [-werror=extra]      while (fgets(tab, sizeof(tab), stdin) > 0) {                                            ^ semshm.c: in function ‘process2’: semshm.c:197:20: error: format ‘%d’ expects argument of type ‘int’, argument 3 has type ‘size_t {aka long unsigned int}’ [-werror=format=]              printf("[p2] recieved \"%s\" length %d.\n", tab, strlen(tab));                     ^ semshm.c:197:20: error: format ‘%d’ expects argument of type ‘int’, argument 3 has type ‘size_t {aka long unsigned int}’ [-werror=format=] semshm.c: in function ‘signal_handling’: semshm.c:239:26: error: unused parameter ‘snd’ [-werror=unused-parameter]  void signal_handling(int snd, int rvc) {                           ^ semshm.c:239:35: error: unused parameter ‘rvc’ [-werror=unused-parameter]  void signal_handling(int snd, int rvc) {                                    ^ cc1: warnings being treated errors 

the first problem peculiar mac os x; seems define union semun in <sys/sem.h> despite posix specification semctl() saying explicitly:

the semctl() function provides variety of semaphore control operations specified cmd. fourth argument optional , depends upon operation requested. if required, of type union semun, application shall explicitly declare:

union semun {     int val;     struct semid_ds *buf;     unsigned short  *array; } arg; 

the excuse posix requirement bad historical precedent, mac os x has over-ridden. so, double declaration of struct semun not held against you. curious posix requires member, though, compared specify. anyway, commented out declaration past that.

there other warnings, though many of them not serious. unused variables not good, not hugely harmful. format mismatch between %d , size_t matters if, on machine, %d looks 32-bit value , size_t 64-bit quantity. test fgets() should != 0; returns null (or 0 — use 0 too) on failure.

the curious problem unused arguments signal_handling(). calls pass global variables inter_snd , inter_rcv function, function ignores values , manipulates global variables. there @ least serious disconnect between calling , called code here.

for purposes of getting on life, converted signal_handling() parameterless function void signal_handling(void); , left body unchanged (but fixed calls it). added:

printf("%s(): signal %d\n", __func__, n); 

to main_quit() in defiance of advice on how avoid using printf() in signal handler. fixed 'i' before 'e' except after 'c' spelling mistakes. 'quitting' has 2 t's , 'stopping' has 2 p's — english such weird language.

finally, extracted 2 fifo names (1fifo2 , 2fifo3) array:

static const char *fifoname[] = { "1fifo2", "2fifo3" }; 

and used either fifoname[0] or fifoname[1] in place of literals. repeated file name literals bad idea. used new names clean (unlink(fifoname[0]); unlink(fifoname[1]);) fifos if either existed after failing create them.

  • despite collection of warnings, code not bad; few programs pass set of options unscathed without editing make pass cleanly.

with code compiled, ran few times. 1 of last runs was:

$ ./semshm [g] launching [g] creating fifo... [ ok ] [g] creating semaphores... [ ok ] [g] initializing semaphores values... [ ok ] [g] reserving shared memory... [ ok ] [g] building process tree... [ ok ] [g] p1[pid]: 36030, p2[pid]: 36031, p3[pid]: 36032 [p2] ready. [p1] ready. [p3] ready. ^c>> signal << main_quit(): signal 2 >> signal << >> signal << >> signal << absolute baloney [p1] sending: absolute baloney signal received... [p2] received "absolute" length 8. signal received... commestible goods ^c>> signal << >> signal << main_quit(): signal 2 >> signal << sending other processes >> signal << sending other processes >> signal << >> signal << >> signal << quitting... >> signal << quitting... [p2] ending... [p3] received: 8 characters. signal received... sending other processes >> signal << >> signal << quitting... >> signal << [p3] ending... ^\quit: 3 $ 

i typed interrupt, handled. typed 'absolute baloney', of 'absolute' part apparently received in 1 place, 'baloney' part never made it. that's puzzling. typed 'commestible goods everyone' , appearances, ignored. tried interrupt, apparently interrupted things. tried control-d (eof), apparently did nothing. used control-backslash (control-\) generate quit signal, did indeed stop program. i'd done before; reruns showed wisdom of cleaning after spotting fifos created got failure message, reran code , worked ok. output shows green ok messages, , flashing yellow-ish >>> signal <<< messages.

so, didn't tell how use program, or output expect it.

your 'no compiler warnings' assertion little optimistic, not far off truth.

now need upgrade question specify/illustrate inputs give , expected behaviour input , show unexpected behaviour it.

one semi-working version of semshm.c

this 'as compiled', partially annotated code compiled , ran. compile on linux or other more accurately posix-compliant platform (more accurate mac os x, is), you'll need uncomment 1 of union semun blocks. i'd remove <sys/types.h> (modern posix never requires include it; older versions last millennium did require — see posix 1997 did, compare posix 2004 did not).

#include <stdio.h> 

…code co-opted question…see revision 3 @ https://stackoverflow.com/posts/30813144/revisions

…i ran on 30,000 character limit code on board…

} 

another working version of semshm.c

taking information how code supposed working, , putting in lot of diagnostic printing, , observing process 2 , 3 stuck waiting on semaphore not signalled, came variant of code:

#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ipc.h> #include <unistd.h> #include <sys/sem.h> #include <signal.h> #include <sys/shm.h> #include <sys/wait.h> #include <string.h> #include <errno.h>  #define write 1 #define read 0 #define mem_id 1 #define mem_size 1  #define ok  "[ \033[1;32mok\033[0m ]\n" #define err "[\033[1;31mfail\033[0m] " #define signal "\033[1;33m\033[5m>> signal <<\033[0m\n"  #define s1 sigint #define s2 sigusr1 #define s3 sigusr2 #define s4 sigcont  int process1(void); int process2(void); int process3(void); void signal_callback(int signo); void signal_handling(void); void sem_down(int semid, int semnum); void sem_up(int semid, int semnum);  char work = 1, quit = 0; char inter_snd = 0, inter_rcv = 0; struct sembuf semstruct; int sem23, sem12, mem; char *message; int res[3];  static const char *fifoname[] = { "1fifo2", "2fifo3" };  static void main_quit(int n) {     printf("%s(): signal %d\n", __func__, n);     kill(res[0], s1); }  int main(void) {     printf("[g] launching\n");      signal(sigint, main_quit);     signal(sigterm, main_quit);     // creating fifo     printf("[g] creating fifo... ");     res[0] = mkfifo(fifoname[0], 0644);     res[1] = mkfifo(fifoname[1], 0644);     if ((res[0] == -1) || (res[1] == -1))     {         perror(err);         unlink(fifoname[0]);         unlink(fifoname[1]);         return 1;     }     else         printf(ok);      // create 2 semaphores , set values     printf("[g] creating semaphores... ");     sem12 = semget(read, 1, ipc_creat | 0644);     sem23 = semget(write, 1, ipc_creat | 0644);      if ((sem23 == -1) || (sem12 == -1))     {         perror(err);         return 1;     }     else         printf(ok);      printf("[g] initializing semaphores values... ");     semctl(sem12, 0, setval, 0);     semctl(sem12, 1, setval, 1);     semctl(sem23, 0, setval, 0);     semctl(sem23, 1, setval, 1);     printf(ok);      // creating shared memory     printf("[g] reserving shared memory... ");     mem = shmget(mem_id, mem_size, ipc_creat | 0644);     message = (char *)shmat(mem, 0, 0);      if (mem == -1 || message == 0)     {         perror(err);         return 1;     }     else         printf(ok);      if ((res[0] = fork()) == 0)     {         process1();         printf("returned process1() - exiting\n");         exit(0);     }      if ((res[1] = fork()) == 0)     {         process2();         printf("returned process2() - exiting\n");         exit(0);     }      if ((res[2] = fork()) == 0)     {         process3();         printf("returned process3() - exiting\n");         exit(0);     }      printf("[g] building process tree... ");     if ((res[0] == -1) || (res[1] == -1) || (res[2] == -1))     {         perror(err);         return 1;     }     else     {         printf(ok);         printf("[g] p1[pid]: %d, p2[pid]: %d, p3[pid]: %d\n", res[0], res[1], res[2]);     }      int corpse;     int status;     while ((corpse = wait(&status)) > 0)         printf("[g] pid %d exited status 0x%.4x\n", corpse, status);      printf("[g] deleting fifo... ");     res[0] = unlink(fifoname[0]);     res[1] = unlink(fifoname[1]);     if ((res[0] == -1) || (res[1] == -1))         perror(err);     else         printf(ok);      printf("[g] freeing shared memory... ");     res[0] = shmdt((char *)message);     res[1] = shmctl(mem, ipc_rmid, 0);     if ((res[0] == -1) || (res[1] == -1))         perror(err);     else         printf(ok);      printf("[g] deleting semaphores... ");     res[0] = semctl(sem23, 0, ipc_rmid, 0);     res[1] = semctl(sem12, 0, ipc_rmid, 0);     if ((res[0] == -1) || (res[1] == -1))         perror(err);     else         printf(ok);      printf("[g] ending...\n");     return 0; }  int process1(void) {     char tab[100];     file *fifoh;      signal(s1, signal_callback);     signal(s2, signal_callback);     signal(s3, signal_callback);     signal(s4, signal_callback);      fifoh = fopen(fifoname[0], "w");     setbuf(fifoh, null);      printf("[p1] ready.\n");     while (fgets(tab, sizeof(tab), stdin) != 0)     {         if (work)         {             sem_down(sem12, write);             printf("[p1] sending: %s", tab);             fprintf(fifoh, "%s", tab);             sem_up(sem12, read);         }         else             printf("[p1] ignoring line because work zero: %s", tab);         signal_handling();     }     fclose(fifoh);     printf("[p1] ending...\n");     sem_up(sem12, read);    // crucial     return 0; }  int process2(void) {     char tab[100];     file *fifo_in, *fifo_out;      printf("[p2] ready.\n");      fifo_in = fopen(fifoname[0], "r");     fifo_out = fopen(fifoname[1], "w");      setbuf(fifo_out, null);     setbuf(fifo_in, null);      signal(s1, signal_callback);     signal(s2, signal_callback);     signal(s3, signal_callback);     signal(s4, signal_callback);          {         if (work)         {             printf("[p2]: waiting on semaphore sem12/r\n");             sem_down(sem12, read);             printf("[p2]: proceed on semaphore sem12/r\n");             if (fscanf(fifo_in, "%s", (char *)tab) != 1)             {                 printf("[p2]: eof\n");                 break;             }             printf("[p2]: signalling semaphore sem12/w\n");             sem_up(sem12, write);             printf("[p2]: proceeding semaphore sem12/w\n");             printf("[p2] received \"%s\" length %zu.\n", tab, strlen(tab));             printf("[p2]: waiting on semaphore sem23/r\n");             sem_down(sem23, write);             printf("[p2]: proceed on semaphore sem23/r\n");             fprintf(fifo_out, "%zu\n", strlen(tab));             printf("[p2]: signalling semaphore sem23/w\n");             sem_up(sem23, read);             printf("[p2]: proceeding semaphore sem23/w\n");         }         else             printf("[p2] looping: work zero\n");         printf("[p2]: signal handling\n");         signal_handling();         printf("[p2]: signal handling done\n");     } while (!quit);      fclose(fifo_in);     fclose(fifo_out);     printf("[p2] ending...\n");     sem_up(sem23, read);    // crucial     return 0; }  int process3(void) {     file *fifo_in;     int count;      printf("[p3] ready.\n");      signal(s1, signal_callback);     signal(s2, signal_callback);     signal(s3, signal_callback);     signal(s4, signal_callback);      fifo_in = fopen(fifoname[1], "r");     setbuf(fifo_in, null);          {         if (work)         {             printf("[p3]: waiting on semaphore sem23\n");             sem_down(sem23, read);             if (fscanf(fifo_in, "%d", &count) == 1)                 printf("[p3] received: %d length.\n", count);             else             {                 printf("[p3] failed read integer\n");                 break;             }             sem_up(sem23, write);         }         else             printf("[p3] looping: work zero\n");         printf("[p3]: signal handling\n");         signal_handling();         printf("[p3]: signal handling done\n");     } while (!quit);     fclose(fifo_in);     printf("[p3] ending...\n");     return 0; }  void signal_handling(void) {     if (inter_snd > 0)     {         printf("pid %d: signal received...\n", (int)getpid());          semstruct.sem_op = -3;         semop(sem23, &semstruct, 1);          *message = inter_snd;         inter_snd = 0;          semstruct.sem_op = 3;         semop(sem12, &semstruct, 1);          printf("sending other processes\n");         kill(0, s4);     }     else         printf("pid %d: inter_snd = %d\n", (int)getpid(), inter_snd);      if (inter_rcv)     {         inter_rcv = 0;          semstruct.sem_op = -1;         semop(sem12, &semstruct, 1);          switch (*message)         {         case 1:             printf("quitting...\n");             quit = 1;             break;         case 2:             printf("stopping...\n");             work = 0;             break;         case 3:             printf("starting...\n");             work = 1;             break;         default:             printf("there's garbage in memory :/..\n");         }         semstruct.sem_op = 1;         semop(sem23, &semstruct, 1);     }     else         printf("pid %d: inter_rcv = %d\n", (int)getpid(), inter_rcv); }  void signal_callback(int signo) {     printf("%ssignal %d in pid %d\n", signal, signo, (int)getpid());     switch (signo)     {     case s1:         inter_snd = 1;         break;     case s2:         inter_snd = 2;         break;     case s3:         inter_snd = 3;         break;     case s4:         inter_rcv = 1;         break;     } }  void sem_down(int semid, int semnum) {     semstruct.sem_flg = 0;     semstruct.sem_num = semnum;     semstruct.sem_op = -1;         {         errno = 0;         semop(semid, &semstruct, 1);     } while (errno == eintr); }  void sem_up(int semid, int semnum) {     semstruct.sem_flg = 0;      semstruct.sem_num = semnum;     semstruct.sem_op = 1;     semop(semid, &semstruct, 1); } 

note 2 sum_up() calls marked 'crucial'; indeed crucial. note input operations error checked; crucial. if don't check worked, miss eof indications. always, always check i/o operations worked correctly.

with code, sample run was:

$ ./semshm [g] launching [g] creating fifo... [ ok ] [g] creating semaphores... [ ok ] [g] initializing semaphores values... [ ok ] [g] reserving shared memory... [ ok ] [g] building process tree... [ ok ] [g] p1[pid]: 36545, p2[pid]: 36546, p3[pid]: 36547 [p2] ready. [p3] ready. [p1] ready. [p3]: waiting on semaphore sem23 [p2]: waiting on semaphore sem12/r absolutely-ineffable-twaddle-for-onward-transmission [p1] sending: absolutely-ineffable-twaddle-for-onward-transmission pid 36545: inter_snd = 0 pid 36545: inter_rcv = 0 [p2]: proceed on semaphore sem12/r [p2]: signalling semaphore sem12/w [p2]: proceeding semaphore sem12/w [p2] received "absolutely-ineffable-twaddle-for-onward-transmission" length 52. [p2]: waiting on semaphore sem23/r [p2]: proceed on semaphore sem23/r [p2]: signalling semaphore sem23/w [p2]: proceeding semaphore sem23/w [p2]: signal handling pid 36546: inter_snd = 0 pid 36546: inter_rcv = 0 [p2]: signal handling done [p2]: waiting on semaphore sem12/r [p3] received: 52 length. [p3]: signal handling pid 36547: inter_snd = 0 pid 36547: inter_rcv = 0 [p3]: signal handling done [p3]: waiting on semaphore sem23 [p1] ending... returned process1() - exiting [p2]: proceed on semaphore sem12/r [p2]: eof [p2] ending... returned process2() - exiting [p3] failed read integer [p3] ending... returned process3() - exiting [g] pid 36545 exited status 0x0000 [g] pid 36546 exited status 0x0000 [g] pid 36547 exited status 0x0000 [g] deleting fifo... [ ok ] [g] freeing shared memory... [ ok ] [g] deleting semaphores... [ ok ] [g] ending... $ 

i've not worked out how of code eliminated — suspicion 'quite lot' accurate statement. semaphore operations not necessary; processes block correctly on file streams anyway. i'm not convinced shared memory helps @ all, either. , i'm not convinced work helping much, might conceivably useful under signal handling. note not shared between processes (it private each process), changes made work 1 process affect process, not other processes.


Comments

Popular posts from this blog

facebook - android ACTION_SEND to share with specific application only -

python - Creating a new virtualenv gives a permissions error -

javascript - cocos2d-js draw circle not instantly -