无名管道通信是指在进程间创建一个管道文件,一端读, 一端写, 实现通信。这个管道文件并不在磁盘上
, 而是在内存中, 进程结束后随即释放。
无名管道是半双工
通信, 在同一时刻, 一端只能读, 另一端只能写。
无名管道只能在亲缘进程之间
实现通信, 它依赖亲缘进程间相同的内存空间中的文件描述符。
管道通信方式类似队列数据结构, 先进先出
。
注意点:
- 读端关闭, 写端写入时, 触发管道破裂信号(
SIGPIPE
) - 写端关闭, 读端读取时, 读取数据完毕后立即返回, 不再阻塞
- 写端不写入, 读端读取时, 读完管道内的数据后, 读端阻塞
- 写端写入, 读端不读取时, 管道写满后, 写端阻塞
- 无名管道有固定的两端,
pipefds[0]
固定为读端,pipefds[1]
固定为写端 - 不能使用
lseek
在无名管道中偏移
代码示例 :
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#include <errno.h>
#include <stdlib.h>
#define BUF_SIZE 100
int main(int argc, const char *argv[])
{
// 创建无名管道文件描述符
// pipefds[0] 只读
// pipefds[1] 只写
int pipefds[2];
if (-1 == pipe(pipefds))
{
perror("pipe error");
return EXIT_FAILURE;
}
// 创建子进程
pid_t pid = fork();
if (-1 == pid)
{
perror("fork");
return EXIT_FAILURE;
}
// 子进程执行区
if (pid > 0)
{
// 子进程只读管道, 关闭写端文件描述符
close(pipefds[1]);
char buf[BUF_SIZE];
bzero(buf, sizeof(buf));
read(pipefds[0], buf, sizeof(buf) - 1);
printf("[thread son][read from pipe]: %s\n", buf);
close(pipefds[0]);
return EXIT_SUCCESS;
}
// 父进程执行区
// 父进程只写管道, 关闭读端文件描述符
close(pipefds[0]);
char buf[BUF_SIZE];
sprintf(buf, "hello, this is father speaking.");
write(pipefds[1], buf, sizeof(buf) - 1);
close(pipefds[1]);
return EXIT_SUCCESS;
}