linux系统调用创建无名管道,无名管道系统调用

本文关键字: linux 管道通信,linux 进程通信方式,无名管道

1.管道创建与关闭说明

管道是基于文件描述符的通信方式,当一个管道建立时,它会创建两个文件描述符fd[0]和fd[1],其中fd[0]固定用于读管道,而fd[1]固定用于写管道,如图1所示,这样就构成了一个半双工的通道。

4f1d4b8b80b9fa088d7106ccaf116f49.png

图1 无名管道的读写机制

管道关闭时只需将这两个文件描述符关闭即可,可使用普通的close()函数逐个关闭各个文件描述符。

2.管道创建函数

创建管道可以通过调用pipe()来实现。表1列出了pipe()函数的语法要点。

表1 pipe()函数语法要点

所需头文件

#include

函数原型

int pipe(int fd[2])

函数传入值

fd[2]:管道的两个文件描述符,之后就可以直接操作这两个文件描述符

函数返回值

成功:0

出错:-1

3.管道读写说明

用pipe()函数创建的管道两端处于一个进程中,由于管道是主要用于在不同进程间通信的,因此在实际应用中没有太大意义。实际上,通常先是创建一个管道,再调用fork()函数创建一个子进程,该子进程会继承父进程所创建的管道,这时,父子进程管道的文件描述符对应关系如图2所示。

5b096047c380df5453d31982e79d6d64.png

图2 父子进程管道的文件描述符对应关系

此时的关系看似非常复杂,实际上却已经给不同进程之间的读写创造了很好的条件。父子进程分别拥有自己的读写通道,为了实现父子进程之间的读写,只需把无关的读端或写端的文件描述符关闭即可。例如,在图3中将父进程的写端fd[1]和子进程的读端fd[0]关闭。此时,父子进程之间就建立起了一条“子进程写入父进程读取”的通道。

d5557d61a07b39b7121525535c6dd2ef.png

图3 关闭父进程fd[1]和子进程fd[0]

同样,也可以关闭父进程的fd[0]和子进程的fd[1],这样就可以建立一条“父进程写入子进程读取”的通道。另外,父进程还可以创建多个子进程,各个子进程都继承了相应的fd[0]和fd[1]。这时,只需关闭相应端口就可以建立其各子进程间的通道。

4.管道读写注意点

管道读写需注意以下几点:

● 只有在管道的读端存在时,向管道写入数据才有意义。否则,向管道写入数据的进程将收到内核传来的SIGPIPE信号(通常为Broken pipe错误)。

● 向管道写入数据时,Linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。如果读进程不读取管道缓冲区中的数据,那么写操作将会一直阻塞。

● 父子进程在运行时,它们的先后次序并不能保证。因此,为了保证父子进程已经关闭了相应的文件描述符,可在两个进程中调用sleep()函数。当然这种调用不是很好的解决方法,在后面学到进程之间的同步机制与互斥机制后,请读者自行修改本小节的实例程序。

5.使用实例

在本例中,首先创建管道,之后父进程使用fork()函数创建子进程,后通过关闭父进程的读描述符和子进程的写描述符,建立起它们之间的管道通信。

/* pipe.c */

#include

#include

#include

#include

#include

#define MAX_DATA_LEN256

#define DELAY_TIME1

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) /* 创建一个子进程 */

{

/* 子进程关闭写描述符,并通过使子进程暂停1s等待父进程已关闭相应的读描述符 */

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);

}

}

将该程序交叉编译,下载到开发板上的运行结果如下:

$ ./pipe

Parent wrote 17 bytes : 'Pipe Test Program'

17 bytes read from the pipe is 'Pipe Test Program

热点链接:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值