当前位置:   article > 正文

Linux 管道通信_linux管道通信

linux管道通信

一 管道的概念:

管道是一种最基本的IPC机制,作用于有血缘关系的进程之间,完成数据传递。调用pipe系统函数即可创建一个管道。有如下特质:

1. 其本质是一个伪文件(实为内核缓冲区)

2. 由两个文件描述符引用,一个表示读端,一个表示写端。

3. 规定数据从管道的写端流入管道,从读端流出。

管道的原理: 管道实为内核使用环形队列机制,借助内核缓冲区(4k)实现。

管道  分为 标准流管道,无名管道(PIPE),命名管道(FIFO)

管道的局限性:

① 数据自己读不能自己写。

② 数据一旦被读走,便不在管道中存在,不可反复读取。

③ 由于管道采用半双工通信方式。因此,数据只能在一个方向上流动。

其中 无名管道 ’标准管道 只能在有公共祖先的进程间使用管道。

二 无名管道建立流程

 

 demo 两个子进程 写父进程读

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <sys/wait.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. int main(void)
  7. {
  8. pid_t pid;
  9. int fd[2], i, n;
  10. char buf[1024];
  11. int ret = pipe(fd);
  12. if (ret == -1)
  13. {
  14. perror("pipe error");
  15. exit(1);
  16. }
  17. for (i = 0; i < 2; i++)
  18. {
  19. if ((pid = fork()) == 0)
  20. {
  21. if (i == 0)
  22. {
  23. close(fd[0]);
  24. write(fd[1], "1.hello\n", strlen("1.hello\n"));
  25. }
  26. else if (i == 1)
  27. {
  28. close(fd[0]);
  29. write(fd[1], "2.world\n", strlen("2.world\n"));
  30. }
  31. break;
  32. }
  33. else if (pid == -1)
  34. {
  35. perror("pipe error");
  36. exit(1);
  37. }
  38. }
  39. if (pid > 0)
  40. {
  41. close(fd[1]); //父进程关闭写端,留读端读取数据
  42. // sleep(1);
  43. n = read(fd[0], buf, 1024); //从管道中读数据
  44. write(STDOUT_FILENO, buf, n);
  45. for (i = 0; i < 2; i++) //两个儿子wait两次
  46. wait(NULL);
  47. }
  48. return 0;
  49. }

结果 

三 标准管道

 demo

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <stdlib.h>
  4. #include <fcntl.h>
  5. #define BUFSIZE 1024
  6. int main()
  7. {
  8. FILE *fp;
  9. char *cmd = "printenv";
  10. char buf[BUFSIZE];
  11. buf[BUFSIZE-1] = '\0';
  12. if((fp=popen(cmd,"r"))==NULL)
  13. perror("popen");
  14. while((fgets(buf,BUFSIZE,fp))!=NULL)
  15. printf("%s",buf);
  16. pclose(fp);
  17. exit(0);
  18. }

 

四 FIFO


上述管道虽然实现了进程间通信,但是它具有一定的局限性:首先,这个管道只能是具有血缘关系的进程之间通信;第二,它只能实现一个进程写另一个进程读,而如果需要两者同时进行时,就得重新打开一个管道。 
为了使任意两个进程之间能够通信,就提出了命名管道(named pipe 或 FIFO)

不支持seek 先进先出

原型

fifo_read.c

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<errno.h>
  4. #include<fcntl.h>
  5. #include<sys/stat.h>
  6. int main()
  7. {
  8. int fd;
  9. int len;
  10. char buf[1024];
  11. if(mkfifo("fifo1", 0666) < 0 && errno!=EEXIST) // 创建FIFO管道
  12. perror("Create FIFO Failed");
  13. if((fd = open("fifo1", O_RDONLY)) < 0) // 以读打开FIFO
  14. {
  15. perror("Open FIFO Failed");
  16. exit(1);
  17. }
  18. while((len = read(fd, buf, 1024)) > 0) // 读取FIFO管道
  19. printf("Read message: %s", buf);
  20. close(fd); // 关闭FIFO文件
  21. return 0;
  22. }

 

 fifo_read.c

  1. #include<stdio.h>
  2. #include<stdlib.h> // exit
  3. #include<fcntl.h> // O_WRONLY
  4. #include<sys/stat.h>
  5. #include<time.h> // time
  6. int main()
  7. {
  8. int fd;
  9. int n, i;
  10. char buf[1024];
  11. time_t tp;
  12. printf("I am %d process.\n", getpid()); // 说明进程ID
  13. if((fd = open("fifo1", O_WRONLY)) < 0) // 以写打开一个FIFO
  14. {
  15. perror("Open FIFO Failed");
  16. exit(1);
  17. }
  18. for(i=0; i<10; ++i)
  19. {
  20. time(&tp); // 取系统当前时间
  21. n=sprintf(buf,"Process %d's time is %s",getpid(),ctime(&tp));
  22. printf("Send message: %s", buf); // 打印
  23. if(write(fd, buf, n+1) < 0) // 写入到FIFO中
  24. {
  25. perror("Write FIFO Failed");
  26. close(fd);
  27. exit(1);
  28. }
  29. sleep(1); // 休眠1秒
  30. }
  31. close(fd); // 关闭FIFO文件
  32. return 0;
  33. }

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/212063
推荐阅读
相关标签
  

闽ICP备14008679号