msg_send.c 3.9 KB

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