Download | Plain Text | No Line Numbers


  1. /* define SUSv2 standard */
  2. #define _XOPEN_SOURCE 500
  3.  
  4. #include <unistd.h>
  5. #include <sys/types.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <sys/wait.h>
  9. #include <signal.h>
  10. #include <string.h>
  11.  
  12. #include <sys/ipc.h>
  13. #include <sys/sem.h>
  14. #include <sys/shm.h>
  15.  
  16. #include <math.h>
  17. #include <time.h>
  18. #include <sys/time.h>
  19.  
  20. #define NUM_CHILDS 10
  21. #define SIZE_RINGBUF 50
  22.  
  23. void P(int semaphoresId,int semaphoreNr);
  24. void V(int semaphoresId,int semaphoreNr);
  25. void child_write();
  26. void child_read();
  27.  
  28. typedef struct
  29. {
  30. unsigned buf[SIZE_RINGBUF];
  31. unsigned insert;
  32. unsigned remove;
  33. } ringbuffer;
  34.  
  35. ringbuffer *ringbuf;
  36.  
  37. int main(int argv, char** argc)
  38. {
  39. int shmid, semid, i, pid;
  40. int childs[NUM_CHILDS];
  41. struct sembuf sbuf;
  42.  
  43. /* create shared memory */
  44. shmid = shmget(IPC_PRIVATE, sizeof(ringbuffer), IPC_CREAT | 0600);
  45.  
  46. /* create + initialize semaphor */
  47. semid = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600);
  48. sbuf.sem_num = 0;
  49. sbuf.sem_op = 1;
  50. sbuf.sem_flg = 0;
  51. semop(semid, &sbuf, 1);
  52.  
  53. /* attach and initialize shared memory */
  54. ringbuf = shmat(shmid, NULL, 0);
  55. ringbuf->insert = ringbuf->remove = 0;
  56.  
  57. /* create and start childs */
  58. for(i = 0; i < NUM_CHILDS; i++)
  59. {
  60. if((pid = fork()) == 0)
  61. {
  62. /* child */
  63. while(1)
  64. {
  65. P(semid, 0);
  66. if (i % 2 == 0)
  67. child_write();
  68. else
  69. child_read();
  70. V(semid, 0);
  71. /*usleep(10000);*/
  72. }
  73.  
  74. /* although this will never be reached this would be the correct shutdown behaviour */
  75. shmdt(ringbuf);
  76. exit(1);
  77. }
  78. else
  79. {
  80. /* parent */
  81. childs[i] = pid;
  82. }
  83. }
  84.  
  85. /* wait for any key press */
  86. getchar();
  87.  
  88. /* send sigterm to all childs */
  89. for(i = 0; i < NUM_CHILDS; i++)
  90. {
  91. kill(childs[i], SIGTERM);
  92. int status;
  93. waitpid(childs[i], &status, 0);
  94. }
  95.  
  96. /* remove semaphor */
  97. semctl(semid, 0, IPC_RMID);
  98.  
  99. /* detach and remove shared memory */
  100. shmdt(ringbuf);
  101. shmctl(shmid, 0, IPC_RMID);
  102.  
  103. return 1;
  104. }
  105.  
  106. void child_write()
  107. {
  108. unsigned num;
  109. struct timeval tp;
  110.  
  111. if (ringbuf->buf[ringbuf->insert] != 0)
  112. return;
  113.  
  114. /* srand + some entropy */
  115. gettimeofday(&tp, NULL);
  116. srand(tp.tv_sec + tp.tv_usec + getpid());
  117. num = 1 + (unsigned) (RAND_MAX * (rand() / (RAND_MAX + 1.0)));
  118.  
  119. ringbuf->buf[ringbuf->insert] = num;
  120. printf("[%d] W [%u] = %u\n", getpid(), ringbuf->insert, num);
  121.  
  122. ringbuf->insert++;
  123. if (ringbuf->insert >= SIZE_RINGBUF)
  124. ringbuf->insert = 0;
  125. }
  126.  
  127. void child_read()
  128. {
  129. unsigned num;
  130.  
  131. num = ringbuf->buf[ringbuf->remove];
  132. if (num == 0)
  133. return;
  134.  
  135. ringbuf->buf[ringbuf->remove] = 0;
  136. printf("[%d] R [%u] = %d\n", getpid(), ringbuf->remove, num);
  137.  
  138. ringbuf->remove++;
  139. if (ringbuf->remove >= SIZE_RINGBUF)
  140. ringbuf->remove = 0;
  141. }
  142.  
  143. void P(int semaphoresId,int semaphoreNr)
  144. {
  145. struct sembuf semaphoreOperation;
  146. semaphoreOperation.sem_num = semaphoreNr;
  147. semaphoreOperation.sem_op = -1;
  148. semaphoreOperation.sem_flg = 0;
  149. semop(semaphoresId, &semaphoreOperation, 1);
  150. }
  151.  
  152. void V(int semaphoresId,int semaphoreNr)
  153. {
  154. struct sembuf semaphoreOperation;
  155. semaphoreOperation.sem_num = semaphoreNr;
  156. semaphoreOperation.sem_op = 1;
  157. semaphoreOperation.sem_flg = 0;
  158. semop(semaphoresId, &semaphoreOperation, 1);
  159. }
  160.