开启辅助访问 切换到窄版

打印 上一主题 下一主题

Linux系统编程—管道

[复制链接]
作者:痴情uu 
版块:
嵌入式操作系统 linux 发布时间:2020-10-12 21:49:54
20290
楼主
跳转到指定楼层
| 只看该作者 回帖奖励 |倒序浏览 |阅读模式
▋**1. 管道的概念**
管道,又名「无名管理」,或「匿名管道」,管道是一种非常基本,也是使用非常频繁的IPC方式。
1.1 管道本质

  • 管道的本质也是一种文件,不过是伪文件,实际上是一块内核缓冲区,大小4K;
  • 管道创建以后会产生两个文件描述符,一个是读端,另一个是写端;
  • 管道里的数据只能从写端被写入,从读端被读出;
1.2 管道原理
管道是内核的一块缓冲区,更具体一些,是一个环形队列。数据从队列的一端写入数据,另一端读出,如下图示:

1.3 管道的优点
简单
1.4 管道的缺点

  • 只能单向通信,如果需要双向通信则需要建立两个管道;
  • 只能应用于具有血缘关系的进程,如父子进程;
  • 缓冲区大小受限,通常为1页,即4k;
▋**2. 管道的创建**
管道创建三步曲:
a. 父进程调用pipe函数创建管道;
b. 父进程调用fork函数创建子进程;
c. 父进程关闭fd,子进程关闭fd;
具体如下图所示:

▋**3. 管道的读写行为**
a. 管道的缓冲区大小固定为4k,所以如果管道内数据已经写满,则无法再写入数据,进程的write调用将阻塞,直到有足够的空间再写入数据;
b. 管道的读动作比写动作要快,数据一旦被读走了,管道将释放相应的空间,以便后续数据的写入。当所有的数据都读完之后,进程的read调用将阻塞,直到有数据再次写入。
▋**4. 例程**
父子间通信:
1#include 2#include 3#include 4#include 56int main7{8 int fd;9 pid_t pid;10 char buf;11 char *data = "hello world!";1213 /* 创建管道 */14 if (pipe(fd) == -1) {15 printf("ERROR: pipe create failed!\n");16 return -1;17 }1819 pid = fork;20 if (pid == 0) {21 /* 子进程 */22 close(fd); // 子进程读取数据,关闭写端23 read(fd, buf, sizeof(buf)); // 从管道读数据24 printf("child process read: %s\n", buf);25 close(fd);26 } else if (pid > 0) {27 /* 父进程 */28 close(fd); //父进程写数据,关闭读端29 write(fd, data, strlen(data)); // 向管道写数据30 printf("parent process write: %s\n", data);31 close(fd);32 }3334 return 0;35}兄弟间通信:
1#include 2#include 3#include 4#include 5#include 67int main 8{9 int fd;10 int i = 0;11 pid_t pid;12 char buf;13 char *data = "hello world!";1415 /* 创建管道 */16 if (pipe(fd) == -1) {17 printf("ERROR: pipe create failed!\n");18 return -1;19 }2021 for (i = 0; i < 2; i++) {22 pid = fork;23 if (pid == -1) {24 printf("ERROR: fork error!\n");25 return -1;26 } else if (pid == 0) {27 break;28 }29 }3031 /* 通过i来判断创建的子进程及父进程 */32 if (i == 0) {33 /* 第一个子进程,兄进程 */34 close(fd); // 兄进程向弟进程写数据,关闭读端35 write(fd, data, strlen(data));36 printf("elder brother send: %s\n", data);37 close(fd);38 } else if (i == 1) {39 /* 第二个子进程,弟进程 */40 close(fd);41 read(fd, buf, sizeof(buf));42 printf("younger brother receive: %s\n", buf);43 close(fd);44 } else {45 /* 父进程 */46 close(fd);47 close(fd);48 for (i = 0; i < 2; i++) {49 wait(NULL);50 }51 }5253 return 0;54}
#### 看完的都是真爱,点个赞再走呗?您的「三连」就是良许持续创作的最大动力!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表