• 进程间通信之匿名管道和命名管道


    目录

    管道是什么

    匿名管道

    命名管道

    命名管道创建方式

    管道的特点:


    管道是什么

    概念管道是计算机通信领域设计者,设计出的一种单向通信的方式,linux原生提供管道通信

    管道都是单向传输内容的
    管道中传输的都是"资源"
    管道通信不会将内容刷新到磁盘,是内存级的通信(效率高)

    管道是半双工的:

    全双工:既可以收又可以发,同时进行

    半双工:要么在收要么发

    匿名管道

    1. //头文件
    2. #include
    3. //函数
    4. int pipe(int pipefd[2]);
    5. //返回值
    6. //成功返回0,失败返回-1,会设置错误码到errno中
    7. //参数
    8. //int pipefd[2]
    9. //输出型参数,我们提供一个数组传入,这个数组会被填充两个文件描述符,pipefd[0]是读,pipefd[1]是写

    1、分别以读写方式打开同一个文件

    2、fork()创建子进程

    3、双方进程各自关闭自己不需要的文件描述符

    4、进行通信

    5、通信结束

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. using namespace std;
    8. int main()
    9. {
    10. int pipefd[2]; //创建一个数组,接受文件描述符
    11. if(pipe(pipefd) < 0) //判断管道是否创建成功
    12. {
    13. perror("pipe"); //失败打印pipe,然后退出
    14. return -1;
    15. }
    16. pid_t id = fork(); //创建一个进程
    17. if(id < 0) //判读进程是否创建成功
    18. {
    19. perror("fork"); //失败打印fork,然后退出
    20. return -1;
    21. }
    22. if(id == 0) //我们让子进程进行读取
    23. {
    24. close(pipefd[1]); //关闭写进程
    25. char buff[64];
    26. while(1) //进行通信
    27. {
    28. ssize_t s = read(pipefd[0], buff, sizeof(buff));
    29. if(s > 0)
    30. {
    31. if(strcmp(buff, "q") == 0)
    32. {
    33. cout << "quit" << endl;
    34. break;
    35. }
    36. cout << "parent say: " << buff << endl;
    37. }
    38. else if(s == 0)
    39. {
    40. cout << "eof" << endl;
    41. break;
    42. }
    43. else
    44. {
    45. cout << "read error" << endl;
    46. break;
    47. }
    48. }
    49. close(pipefd[0]); //关闭读进程
    50. }
    51. //父进程进程通信
    52. close(pipefd[0]); //关闭读
    53. if(id > 0)
    54. {
    55. char buff[64];
    56. while(1)
    57. {
    58. cin >> buff;
    59. write(pipefd[1], buff, sizeof(buff));
    60. if(strcmp(buff, "q") == 0)
    61. {
    62. break;
    63. }
    64. }
    65. }
    66. //通信结束
    67. wait(NULL);
    68. close(pipefd[1]); //关闭写
    69. return 0;
    70. }

     

    匿名管道的特点:

    管道是用来进行具有血缘关系的进程进行进程间同通信 -- 常用于父子通信

    a、写快,读慢,写满就不能写了

    b、写慢,读快,管道没有数据的时候,读必须等待

    c、写关,读0,表示读到了文件结尾

    d、读关,写继续写,os终止写进程

    命名管道

    为了解决匿名管道只能父子间通信,产生了命名管道

    命名管道创建方式

    方式一:

    mkfifo指令:

    mkfifo 管道名        --创建一个命名管道

    方式二:

    mkfifo函数

    1. //头文件
    2. #include
    3. #include
    4. //函数
    5. int mkfifo(const char *pathname, mode_t mode);
    6. //返回值 创建成功返回0,失败返回-1
    7. //参数
    8. //const char *pathname,创建的路径
    9. //mode_t mode,创建权限

    命名管道fifo是p标识管道文件

    1、分别写一个客户端,一个服务端

    2、服务端创建命名管道

    3、服务端发送信息,客服端接受信息

    4、通信结束,客服端和服务端退出

     服务端,server.cpp

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. using namespace std;
    9. int main()
    10. {
    11. umask(0000); //将权限掩码设置为0000
    12. if(mkfifo("./fifo", 0666)) //创建命名管道fifo
    13. {
    14. perror("mkfifo");
    15. return -1;
    16. }
    17. int fd = open("./fifo", O_WRONLY); //以写方式打开命名管道
    18. if(fd < 0)
    19. {
    20. perror("open");
    21. return -1;
    22. }
    23. char buff[64];
    24. while(1)
    25. {
    26. cin >> buff;
    27. write(fd, buff, sizeof(buff));
    28. if(strcmp(buff, "q") == 0)
    29. {
    30. cout << "quit" << endl;
    31. break;
    32. }
    33. }
    34. unlink("./fifo"); //删除命名管道
    35. return 0;
    36. }

     客服端,client.cpp

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. using namespace std;
    9. int main()
    10. {
    11. umask(0000); //将权限掩码设置为0000
    12. if(mkfifo("./fifo", 0666)) //创建命名管道fifo
    13. {
    14. perror("mkfifo");
    15. return -1;
    16. }
    17. int fd = open("./fifo", O_WRONLY); //以写方式打开命名管道
    18. if(fd < 0)
    19. {
    20. perror("open");
    21. return -1;
    22. }
    23. char buff[64];
    24. while(1)
    25. {
    26. cin >> buff;
    27. write(fd, buff, sizeof(buff));
    28. if(strcmp(buff, "q") == 0)
    29. {
    30. cout << "quit" << endl;
    31. break;
    32. }
    33. }
    34. unlink("./fifo"); //删除命名管道
    35. return 0;
    36. }

     

    管道的特点:

    1、匿名管道是用来进行具有血缘关系的进程进行进程间同通信 -- 常用于父子通信

    2、管道具有通过让进程间协同,提供了访问控制 假如写满,需要等待被读取才能继续写入

    3、管道提供的是面向流式的服务 -- 面向字节流 -- 协议

    4、管道是基于文件的,文件的生命周期是随进程的,管道的生命周期是随子进程的

    5、管道是单向通信的(半双工通信的一种特殊情况)

    全双工:既可以收又可以发,同时进行

    半双工:要么在收要么发

  • 相关阅读:
    数字密码锁verilog设计+仿真+上板验证
    应对互联网用户激增与IP地址短缺的挑战
    uniapp使用技巧及例子
    DHorse(K8S的CICD平台)的实现原理
    【云原生Docker系列第十篇】搭建本地私有仓库(我问青山何时老,青山问我几时闲)
    腾讯云服务器如何使用WooCommerce 应用镜像搭建电商独立网站
    批量录入表格中回车事件处理
    CSP 202005-1 重复局面
    MySQL - 主键索引和非主键索引
    Ubuntu18.04 realsenseD435i深度摄像头外参标定的问题
  • 原文地址:https://blog.csdn.net/qq_45358642/article/details/128053106