当前位置:   article > 正文

LInux管道实现进程间通信及实例说明_linux管道通信示例

linux管道通信示例

目录

一、管道

二、管道的类型

1、无名管道

2、有名管道

三、管道的创建

1、无名管道的创建

2、有名管道的创建

四、实例说明

1、无名管道实例

2、有名管道实例

(1)、创建管道文件

(2)、写文件

(3)、读文件


一、管道

        管道是Linux中进程间通信的一种方式,它把一个程序的输出直接连接到另一个程序的输入,Linux的管道主要包括两种:无名管道和有名管道。

二、管道的类型

1、无名管道

1、只能用于具有亲缘关系的进程之间的通信

2、是一个单工的通行模式,具有固定的读端和写端

3、创建之后存在于内核中,在文件系统中不可见

读写特性:

        读特性:
                写端存在:
                        管道有数据:返回读到的字节数
                        管道无数据:程序阻塞
    
                写段不存在:
                        管道有数据:返回读到的字节数
                        管道无数据:返回0
            

        写特性:
                读端存在:
                        管道有空间:返回写入的字节数
                        管道无空间:程序阻塞,直到有空间为止
            
                读端不存在:
                        无论管道是否有空间,管道破裂,管道破裂进程终止

2、有名管道

1、可用于任意类型的进程之间

2、双工通信,没有固定的读端或者写端

3、创建之后可在文件系统中查看到

读写特性:

        适用所有情况

三、管道的创建

1、无名管道的创建

头文件:

        #include <unistd.h>

        int pipe(int pipefd[2]);

参数:

        pipefd:存放无名管道读端和写端的数组首地址

        pipefd[0]——读端
        pipefd[1]——写端

返回值:

        成功返回0,失败返回-1

2、有名管道的创建

头文件:

        #include <sys/types.h>
        #include <sys/stat.h>

函数原型:

        int mkfifo(const char *pathname, mode_t mode);

参数:

        pathname:创建管道文件的文件名

        mode:创建管道文件的权限


返回值:

        成功返回0,失败返回1

四、实例说明

1、无名管道实例

利用管道实现子进程输入,父进程输出

  1. /*===============================================================
  2. * Copyright (C) 2022 All rights reserved.
  3. *
  4. * 文件名称:comunication.c
  5. * 创 建 者:QiuCC
  6. * 创建日期:2022年08月10日
  7. * 描 述:利用无名管道实现子进程输入,父进程输出
  8. *
  9. * 更新日志:
  10. *
  11. ================================================================*/
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include <strings.h>
  16. #include <sys/types.h>
  17. #include <sys/wait.h>
  18. #include <unistd.h>
  19. #define N 100
  20. int main(int argc, char *argv[])
  21. {
  22. int pipefd[2] = {0};//pipefd[0]存放管道的读端,pipefd[1]存放管道的写端
  23. int ret;
  24. ret = pipe(pipefd);
  25. pid_t pid = fork();//创建子进程
  26. if(-1 == pid){
  27. perror("fork");
  28. exit(-1);
  29. }
  30. if(ret == -1){
  31. perror("pipe");
  32. exit(-1);
  33. }
  34. if(pid == 0){//子进程
  35. while(1){
  36. char str[N];
  37. fgets(str, N, stdin);//从终端获取数据
  38. str[strlen(str) - 1] = '\0';
  39. write(pipefd[1], str, N);//将数据写入管道
  40. }
  41. }else{
  42. while(1){
  43. char str[N];
  44. read(pipefd[0], str, N);//将管道内容读入
  45. puts(str);//向终端输出数据
  46. }
  47. wait(NULL);//等待子进程结束
  48. }
  49. return 0;
  50. }

运行结果如图:子进程输入一个,父进程打印一个

2、有名管道实例

通过有名管道,实现一个程序输入,另一个程序输出

(1)、创建管道文件

  1. /*===============================================================
  2. * Copyright (C) 2022 All rights reserved.
  3. *
  4. * 文件名称:mkfifo.c
  5. * 创 建 者:QiuCC
  6. * 创建日期:2022年08月10日
  7. * 描 述:利用mkfifo()函数创建管道文件
  8. *
  9. * 更新日志:
  10. *
  11. ================================================================*/
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include <strings.h>
  16. #include <sys/types.h>
  17. #include <sys/stat.h>
  18. #define N 100
  19. int main(int argc, char *argv[])
  20. {
  21. int ret = mkfifo("fifo", 0664);//创建管道文件
  22. if(ret == -1){
  23. perror("mkfifo");
  24. }
  25. return 0;
  26. }

(2)、写文件

  1. /*===============================================================
  2. * Copyright (C) 2022 All rights reserved.
  3. *
  4. * 文件名称:in.c
  5. * 创 建 者:QiuCC
  6. * 创建日期:2022年08月10日
  7. * 描 述:创建文件实现向管道写入的功能
  8. *
  9. * 更新日志:
  10. *
  11. ================================================================*/
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include <strings.h>
  16. #include <sys/types.h>
  17. #include <sys/stat.h>
  18. #include <fcntl.h>
  19. #include <unistd.h>
  20. #define N 100
  21. int main(int argc, char *argv[])
  22. {
  23. int fd = open("fifo", O_WRONLY);//以只写方式打开管道文件
  24. if(fd == -1){
  25. perror("open fifo");
  26. exit(-1);
  27. }
  28. printf("I am in.c\n");
  29. while(1){
  30. char str[N] = {0};
  31. fgets(str, N, stdin);
  32. str[strlen(str)-1] = '\0';
  33. write(fd, str, strlen(str));//向管道文件写入数据
  34. }
  35. return 0;
  36. }

(3)、读文件

  1. /*===============================================================
  2. * Copyright (C) 2022 All rights reserved.
  3. *
  4. * 文件名称:out.c
  5. * 创 建 者:QiuCC
  6. * 创建日期:2022年08月10日
  7. * 描 述:从管道文件读取数据并输出到终端
  8. *
  9. * 更新日志:
  10. *
  11. ================================================================*/
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #include <fcntl.h>
  17. #include <unistd.h>
  18. #include <stdlib.h>
  19. #include <strings.h>
  20. #define N 100
  21. int main(int argc, char *argv[])
  22. {
  23. int fd = open("fifo", O_RDONLY);//以只读方式打开管道文件
  24. if(fd == -1){
  25. perror("open fifo");
  26. exit(-1);
  27. }
  28. while(1){
  29. char str[N] = {0};
  30. int ret = read(fd, str, N);//从管道文件读取数据
  31. if(ret == -1){
  32. perror("read");
  33. exit(-1);
  34. }
  35. puts(str);//输出到终端
  36. }
  37. return 0;
  38. }

        通过上述三个程序,我们先编译运行创建管道的文件,会发现此时有一个名为fifo的管道文件生成,显示具体信息,文件类型为管道文件。

        

        我们接着编译in.c和out.c

        我们此时打开一个另一个终端,我们先单独运行./in 。

        此时我们发现,我们的终端处于等待状态,但是,我们在输入前准备输出的话“I am in.c”并没有输出。

        我们接着在另一个终端运行./out,此时我们的“I am in.c”打印并输出,可见,我们的有名管道必须两端同时打开才有效。

         我们接着输入数据,我们in输入一个,out就打印一个,可见我们的管道实现了两个文件之间的通信,也就是两个独立进程之间的通信。

好的,以上就是本期内容,欢迎大家参考,指正!!!

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

闽ICP备14008679号