从零到负一

Linux编程基础2 - 进程间通信(匿名管道)

2020/06/21

管道(也叫匿名管道),可以在父进程和子进程之间进行通信。管道只能在单一方向上进行数据传输,且只能在父子进程间进行通信,要实现父子间双向数据传输,我们需要两个管道。

管道的创建

管道用函数pipe()进行创建,其函数原型如下:

1
2
// 成功返回0,否则返回-1
int pipe(int pipefd[2]);

pipe()函数创建一个管道,管道有两端,pipefd[0]固定是读取端,pipefd[1]固定是写入端。

管道的性质

除了只能进行单向数据传输,且只能在父子进程中使用外,管道还有如下这些性质:

  1. 读和写默认都是阻塞的,对空的管道进行读操作会阻塞进程;同理,对满的管道进行写操作也会阻塞进程;
  2. 要实现父子间双向的通信,需要至少两个管道;
  3. 同文件描述符一样,pipefd[0, 1]也有计数器。如果pipefd[1]的计数器为0,再从pipefd[0]读数据会收到0表示EOF;如果pipefd[0]的计数器为0,那么对pipefd[1]进行写操作将失败并收到SIGPIPE信号;
  4. 一个管道最多只能写入65535字节的数据。

管道在父子进程的通信

父进程在调用fork()后,之前创建的管道会复制一份给子进程(管道描述符计数器+1),如果我们想要父进程写,子进程读,那么就关闭父进程的pipefd[0]和子进程的pipefd[1];如果希望父进程读,子进程写,那么就关闭父进程的pipefd[1]和子进程的pipefd[0]

下面是一个简单的管道通信的例子(父进程写,子进程读),该例子来源于Linux下的进程通信方式: 管道通信详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_DATA_LEN 256
#define DELAY_TIME 1

int main()
{
pid_t pid;
int pipe_fd[2];
char buf[MAX_DATA_LEN];
const char data[] = "Pipe Test Program";
int real_read, real_write;
memset((void*)buf, 0, sizeof(buf));
/* 创建管道 */
if (pipe(pipe_fd) < 0)
{
printf("pipe create error\n");
exit(1);
}
if ((pid = fork()) == 0)
{
/* 子进程关闭写描述符,并通过使子进程暂停3s等待父进程已关闭相应的读描述符 */
close(pipe_fd[1]);
sleep(DELAY_TIME * 3);
/* 子进程读取管道内容 */
if ((real_read = read(pipe_fd[0], buf, MAX_DATA_LEN)) > 0)
{
printf("%d bytes read from the pipe is '%s'\n", real_read, buf);
}

/* 关闭子进程读描述符 */
close(pipe_fd[0]);
exit(0);
}
else if (pid > 0)
{
/* 父进程关闭读描述符,并通过使父进程暂停1s等待子进程已关闭相应的写描述符 */
close(pipe_fd[0]);
sleep(DELAY_TIME);

if((real_write = write(pipe_fd[1], data, strlen(data))) != -1)
{
printf("Parent wrote %d bytes : '%s'\n", real_write, data);
}

close(pipe_fd[1]); /*关闭父进程写描述符*/
waitpid(pid, NULL, 0); /*收集子进程退出信息*/
exit(0);
}
return 0;
}
————————————————
版权声明:本文为CSDN博主「好儿郎-志在四方」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/rl529014/java/article/details/51464363
CATALOG
  1. 1. 管道的创建
  2. 2. 管道的性质
  3. 3. 管道在父子进程的通信