sem.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. #define _GNU_SOURCE
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <sys/ipc.h>
  6. #include <sys/sem.h>
  7. #include <sys/time.h>
  8. #include <sys/types.h>
  9. #include <sys/wait.h>
  10. #include <unistd.h>
  11. #define TEST_TIMES 1000
  12. #define DO_BENCH 1
  13. enum { PARALLEL, SERIAL, IN_PROCESS } mode = PARALLEL;
  14. int pipefds[2], key;
  15. /* server always sends messages */
  16. void server(void) {
  17. struct timeval tv1, tv2;
  18. int semid;
  19. struct sembuf buf;
  20. if ((semid = semget(key, 2, mode == SERIAL ? 0600 | IPC_CREAT : 0)) < 0) {
  21. perror("semget");
  22. exit(1);
  23. }
  24. gettimeofday(&tv1, NULL);
  25. for (int i = 0; i < TEST_TIMES; i++) {
  26. buf.sem_num = 0;
  27. buf.sem_op = 1;
  28. buf.sem_flg = 0;
  29. if (semop(semid, &buf, 1) < 0) {
  30. perror("semop");
  31. exit(1);
  32. }
  33. #ifndef DO_BENCH
  34. printf("Semaphore %d signaled\n", i);
  35. #endif
  36. }
  37. gettimeofday(&tv2, NULL);
  38. printf("time spent on %d semop (signal): %llu microsecond\n", TEST_TIMES,
  39. (tv2.tv_sec * 1000000ull + tv2.tv_usec) - (tv1.tv_sec * 1000000ull + tv1.tv_usec));
  40. if (mode == PARALLEL) {
  41. close(pipefds[0]);
  42. char byte = 0;
  43. if (write(pipefds[1], &byte, 1) != 1) {
  44. perror("write error");
  45. exit(1);
  46. }
  47. buf.sem_num = 1;
  48. buf.sem_op = -1;
  49. buf.sem_flg = 0;
  50. if (semop(semid, &buf, 1) < 0) {
  51. perror("semop");
  52. exit(1);
  53. }
  54. semctl(semid, 0, IPC_RMID);
  55. }
  56. if (mode != IN_PROCESS)
  57. exit(0);
  58. }
  59. /* client always sends messages */
  60. void client(void) {
  61. struct timeval tv1, tv2;
  62. int semid;
  63. struct sembuf buf;
  64. if (mode == PARALLEL) {
  65. close(pipefds[1]);
  66. char byte = 0;
  67. if (read(pipefds[0], &byte, 1) != 1) {
  68. perror("read error");
  69. exit(1);
  70. }
  71. }
  72. if ((semid = semget(key, 0, 0)) < 0) {
  73. perror("semget");
  74. exit(1);
  75. }
  76. gettimeofday(&tv1, NULL);
  77. for (int i = 0; i < TEST_TIMES; i++) {
  78. buf.sem_num = 0;
  79. buf.sem_op = -1;
  80. buf.sem_flg = 0;
  81. if (semop(semid, &buf, 1) < 0) {
  82. perror("semop");
  83. exit(1);
  84. }
  85. #ifndef DO_BENCH
  86. printf("Semaphore %d wakened\n", i);
  87. #endif
  88. }
  89. gettimeofday(&tv2, NULL);
  90. if (mode == PARALLEL) {
  91. buf.sem_num = 1;
  92. buf.sem_op = 1;
  93. buf.sem_flg = 0;
  94. if (semop(semid, &buf, 1) < 0) {
  95. perror("semop");
  96. exit(1);
  97. }
  98. } else {
  99. semctl(semid, 0, IPC_RMID);
  100. }
  101. printf("time spent on %d semop (wait): %llu microsecond\n", TEST_TIMES,
  102. (tv2.tv_sec * 1000000ull + tv2.tv_usec) - (tv1.tv_sec * 1000000ull + tv1.tv_usec));
  103. if (mode != IN_PROCESS)
  104. exit(0);
  105. }
  106. int main(int argc, char** argv) {
  107. int semid;
  108. key = rand();
  109. #ifndef DO_BENCH
  110. printf("Semaphore key: 0x%8x\n", key);
  111. #endif
  112. /* server run first and client run later */
  113. if (argc == 2 && strcmp(argv[1], "serial") == 0) {
  114. mode = SERIAL;
  115. if (fork() == 0)
  116. server();
  117. wait(NULL);
  118. if (fork() == 0)
  119. client();
  120. wait(NULL);
  121. }
  122. if ((semid = semget(key, 2, 0600 | IPC_CREAT)) < 0) {
  123. perror("semget");
  124. exit(1);
  125. }
  126. /* server run first and client run later (in the same process) */
  127. if (argc == 2 && strcmp(argv[1], "in-process") == 0) {
  128. mode = IN_PROCESS;
  129. server();
  130. client();
  131. semctl(semid, 0, IPC_RMID);
  132. return 0;
  133. }
  134. if (pipe(pipefds) < 0) {
  135. perror("pipe error");
  136. return 1;
  137. }
  138. /* server to be the parent and client to be the child */
  139. if (argc == 1) {
  140. if (fork() == 0)
  141. client();
  142. else
  143. server();
  144. }
  145. /* client to be the parent and server to be the child */
  146. if (argc == 2 && strcmp(argv[1], "reverse") == 0) {
  147. if (fork() == 0)
  148. server();
  149. else
  150. client();
  151. }
  152. /* both client and server are children */
  153. if (argc == 2 && strcmp(argv[1], "children") == 0) {
  154. if (fork() == 0)
  155. server();
  156. if (fork() == 0)
  157. client();
  158. wait(NULL);
  159. wait(NULL);
  160. }
  161. semctl(semid, 0, IPC_RMID);
  162. return 0;
  163. }