[关闭]
@MicroCai 2015-03-22T09:26:27.000000Z 字数 5988 阅读 2593

进程间通信的方式

计算机基础


「计算机基础」系列用以复习基础之用,文章整理自网络


本文代码是大学时期整理的,放在 我的 CSDN 下载频道,在 Linux 平台下全部编译通过。

管道

  1. #include <unistd.h>
  2. #include <sys/types.h>
  3. #include <errno.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. int main(void)
  8. {
  9. int pipe_fd[2];
  10. pid_t pid;
  11. char r_buf[100];
  12. char w_buf[4];
  13. char* p_wbuf;
  14. int r_num;
  15. int cmd;
  16. memset(r_buf, 0, sizeof(r_buf));
  17. memset(w_buf, 0, sizeof(r_buf));
  18. p_wbuf = w_buf;
  19. if(pipe(pipe_fd) < 0)
  20. {
  21. printf("pipe create error\n");
  22. return -1;
  23. }
  24. if((pid=fork()) == 0)
  25. {
  26. printf("child\n");
  27. printf("\n");
  28. close(pipe_fd[1]);
  29. sleep(3);//确保父进程关闭写端
  30. r_num = read(pipe_fd[0], r_buf,100);
  31. printf("read num is %d the data read from the pipe is %d\n", r_num, atoi(r_buf));
  32. close(pipe_fd[0]);
  33. printf("child exit\n");
  34. }
  35. else if(pid > 0)
  36. {
  37. printf("parent\n");
  38. close(pipe_fd[0]);//read
  39. strcpy(w_buf, "111");
  40. if(write(pipe_fd[1], w_buf,4) != -1)
  41. printf("parent write over\n");
  42. close(pipe_fd[1]);//write
  43. printf("parent close fd[1] over\n");
  44. printf("parent exit\n");
  45. }
  46. exit(0);
  47. }

信号量

  1. /*
  2. 功能: 创建信号量
  3. 参数:
  4. char *pszSemFile 文件名
  5. char cId ID
  6. int iSems 多少个信号量
  7. int *piInitvVal 对应信号量的初始值数组指针
  8. 返回:
  9. -1 错误
  10. 成功信号量id
  11. */
  12. int CreateSem(char *pszSemFile, char cId, int iSems, int *piInitvVal)
  13. {
  14. key_t key;
  15. int iSemId;
  16. int i;
  17. if ((key = GetIpcKey(pszSemFile, cId)) < 0)
  18. {
  19. WriteLogTxt(FILELINE, LOG_FILE, "GetIpcKey( %s, %d ) return %d", pszSemFile, cId, key);
  20. return ( -1 );
  21. }
  22. if ((iSemId = semget(key, iSems, 0666|IPC_CREAT|IPC_EXCL)) < 0)
  23. {
  24. if (errno == EEXIST)
  25. {
  26. return(GetSem(pszSemFile, cId, iSems));
  27. }
  28. WriteLogTxt(FILELINE, LOG_FILE, "CreateSem(): Semget fail. errno[%d]", errno);
  29. return(-1);
  30. }
  31. for (i = 0; i < iSems; i++)
  32. {
  33. if (semctl(iSemId, i, SETVAL, piInitvVal[i]) < 0)
  34. {
  35. WriteLogTxt(FILELINE, LOG_FILE, "CreateSem(): Semctl fail. errno[%d]", errno);
  36. return(-1);
  37. }
  38. }
  39. return ( iSemId );
  40. }
  41. /*
  42. 功能: 获取信号量
  43. 参数:
  44. char *pszSemFile 文件名
  45. char cId ID
  46. int iSems 多少个信号量
  47. 返回:
  48. -1 错误
  49. 成功信号量id
  50. */
  51. int GetSem(char *pszSemFile, char cId, int iSems)
  52. {
  53. key_t key;
  54. int iSemId;
  55. if ((key = GetIpcKey(pszSemFile, cId)) < 0)
  56. {
  57. WriteLogTxt(FILELINE, LOG_FILE, "GetIpcKey( %s, %d ) return %d", pszSemFile, cId, key);
  58. return ( -1 );
  59. }
  60. if ((iSemId = semget(key, iSems, 0)) < 0)
  61. {
  62. WriteLogTxt(FILELINE, LOG_FILE, "GetSem(): semget fail! errno[%d]", errno);
  63. return(-1);
  64. }
  65. return (iSemId);
  66. }
  67. /*
  68. 功能: 信号量PV操作
  69. 参数:
  70. char *pszSemFile 文件名
  71. char cId ID
  72. int iSems 多少个信号量
  73. struct sembuf *pstSemBuf
  74. 返回:
  75. 0 成功
  76. 其它错误
  77. */
  78. int PVSem(char *pszSemFile, char cId, int iSems, struct sembuf *pstSemBuf)
  79. {
  80. int iSemId;
  81. if ((iSemId = GetSem(pszSemFile, cId, iSems)) < 0)
  82. {
  83. return ( -1 );
  84. }
  85. if (semop(iSemId, pstSemBuf, 1) < 0)
  86. {
  87. WriteLogTxt(FILELINE, LOG_FILE, "PV():Semaphore operater fail! errno[%d]", errno);
  88. return ( -1 );
  89. }
  90. return ( 0 );
  91. }
  92. /*
  93. 功能: 删除信号量
  94. 参数:
  95. char *pszSemFile 文件名
  96. char cId ID
  97. int iSems 多少个信号量
  98. 返回:
  99. 0 成功
  100. 其它错误
  101. */
  102. int RmSem(char *pszSemFile, char cId, int iSems)
  103. {
  104. int iSemId;
  105. if ((iSemId = GetSem(pszSemFile, cId, iSems)) < 0)
  106. {
  107. return ( -1 );
  108. }
  109. if (semctl(iSemId, 0, IPC_RMID, 0) < 0)
  110. {
  111. WriteLogTxt(FILELINE, LOG_FILE, "RmSem(): semctl fail! errno[%d]", errno);
  112. return ( -1 );
  113. }
  114. return ( 0 );
  115. }

消息队列

  1. #include <sys/types.h>
  2. #include <sys/msg.h>
  3. #include <unistd.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. void msg_stat(int, struct msqid_ds);
  8. int main(void)
  9. {
  10. int gflags,sflags,rflags;
  11. key_t key;
  12. int msgid;
  13. int reval;
  14. struct msgsbuf{
  15. int mtype;
  16. char mtext[1024];
  17. }msg_sbuf, msg_rbuf;
  18. struct msqid_ds msg_ginfo,msg_sinfo;
  19. char *msgpath="/root/msgid";
  20. key=ftok(msgpath,'b');
  21. gflags=IPC_CREAT;
  22. msgid=msgget(key,gflags|00666);
  23. if(msgid==-1)
  24. {
  25. printf("msg create error\n");
  26. return;
  27. }
  28. //创建一个消息队列后,输出消息队列缺省属性
  29. msg_stat(msgid,msg_ginfo);
  30. sflags=IPC_NOWAIT;
  31. msg_sbuf.mtype=10;
  32. bzero(msg_sbuf.mtext, 1024);
  33. strcpy(msg_sbuf.mtext, "hello\n");
  34. reval=msgsnd(msgid,&msg_sbuf,sizeof(msg_sbuf.mtext),sflags);
  35. if(reval==-1)
  36. {
  37. printf("message send error\n");
  38. }
  39. //发送一个消息后,输出消息队列属性
  40. msg_stat(msgid,msg_ginfo);
  41. rflags=IPC_NOWAIT|MSG_NOERROR;
  42. reval=msgrcv(msgid,&msg_rbuf,1024,10,rflags);
  43. if(reval==-1)
  44. printf("read msg error\n");
  45. else
  46. {
  47. printf("read from msg queue %d bytes\n",reval);
  48. printf("read from msg queue data: %s\n",msg_rbuf.mtext);
  49. }
  50. //从消息队列中读出消息后,输出消息队列属性
  51. msg_stat(msgid,msg_ginfo);
  52. msg_sinfo.msg_perm.uid=8;//just a try
  53. msg_sinfo.msg_perm.gid=8;//
  54. msg_sinfo.msg_qbytes=16388;
  55. //此处验证超级用户可以更改消息队列的缺省msg_qbytes
  56. //注意这里设置的值大于缺省值
  57. reval=msgctl(msgid,IPC_SET,&msg_sinfo);
  58. if(reval==-1)
  59. {
  60. printf("msg set info error\n");
  61. return;
  62. }
  63. msg_stat(msgid,msg_ginfo);
  64. //验证设置消息队列属性
  65. reval=msgctl(msgid,IPC_RMID,NULL);//删除消息队列
  66. if(reval==-1)
  67. {
  68. printf("unlink msg queue error\n");
  69. return;
  70. }
  71. }
  72. void msg_stat(int msgid,struct msqid_ds msg_info)
  73. {
  74. int reval;
  75. sleep(1);//只是为了后面输出时间的方便
  76. reval=msgctl(msgid,IPC_STAT,&msg_info);
  77. if(reval==-1)
  78. {
  79. printf("get msg info error\n");
  80. return;
  81. }
  82. printf("\n");
  83. printf("current number of bytes on queue is %d\n",msg_info.msg_cbytes);
  84. printf("number of messages in queue is %d\n",msg_info.msg_qnum);
  85. printf("max number of bytes on queue is %d\n",msg_info.msg_qbytes);
  86. //每个消息队列的容量(字节数)都有限制MSGMNB,值的大小因系统而异。在创建新的消息队列时
  87. //msg_qbytes的缺省值就是MSGMNB
  88. printf("pid of last msgsnd is %d\n",msg_info.msg_lspid);
  89. printf("pid of last msgrcv is %d\n",msg_info.msg_lrpid);
  90. printf("last msgsnd time is %s", ctime(&(msg_info.msg_stime)));
  91. printf("last msgrcv time is %s", ctime(&(msg_info.msg_rtime)));
  92. printf("last change time is %s", ctime(&(msg_info.msg_ctime)));
  93. printf("msg uid is %d\n",msg_info.msg_perm.uid);
  94. printf("msg gid is %d\n",msg_info.msg_perm.gid);
  95. }

共享内存

  1. //fifo_read.c
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <errno.h>
  5. #include <fcntl.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #define FIFO_SERVER "/root/fifoserver"
  10. int main(int argc,char** argv)
  11. {
  12. char r_buf[4096*2];
  13. int fd;
  14. int ret_size;
  15. memset(r_buf,0,sizeof(r_buf));
  16. if((mkfifo(FIFO_SERVER, S_IRUSR | S_IWUSR)<0)&&(errno!=EEXIST))
  17. printf("cannot create fifoserver\n");
  18. fd=open(FIFO_SERVER,O_RDONLY,0);
  19. if(fd==-1)
  20. {
  21. printf("open %s for read error\n");
  22. exit(1);
  23. }
  24. while(1)
  25. {
  26. memset(r_buf,0,sizeof(r_buf));
  27. ret_size=read(fd, r_buf, 4096);
  28. if(ret_size==-1)
  29. {
  30. printf("no data avlaible\n");
  31. break;
  32. }
  33. printf("real read bytes %d\n", ret_size);
  34. printf("real read : %s\n", r_buf);
  35. }
  36. unlink(FIFO_SERVER);
  37. exit(1);
  38. }
  1. //fifo_write.c
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <errno.h>
  5. #include <fcntl.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #define FIFO_SERVER "/root/fifoserver"
  10. //参数为即将写入的字节数
  11. int main(int argc,char** argv)
  12. {
  13. int fd;
  14. char w_buf[4096*2];
  15. int real_wnum;
  16. memset(w_buf,0,4096*2);
  17. fd=open(FIFO_SERVER, O_WRONLY|O_NONBLOCK); //设置非阻塞标志
  18. if(fd==-1){
  19. printf("open error\n");
  20. exit(1);
  21. }
  22. while (1)
  23. {
  24. strcpy(w_buf, "hello\n");
  25. real_wnum=write(fd,w_buf, strlen(w_buf));
  26. if(real_wnum==-1)
  27. {
  28. printf("write to fifo error\n");
  29. break;
  30. }
  31. else
  32. printf("real write num is %d\n",real_wnum);
  33. sleep(1);
  34. }
  35. exit(0);
  36. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注