在本例中,首先创建管道,之后父进程使用 fork()函数创建子进程,之后通过关闭父进程的读描述符和子
进程的写描述符,建立起它们之间的管道通信。
/* pipe.c */
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.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)
{
/* 子进程关闭写描述符,并通过使子进程暂停 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'
管道读写注意点
只有在管道的读端存在时,向管道写入数据才有意义。否则,向管道写入数据的进程将收到内核
传来的 SIGPIPE 信号(通常为 Broken pipe 错误)。 向管道写入数据时,Linux 将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图
专业始于专注 卓识源于远见
向管道写入数据。如果读进程不读取管道缓冲区中的数据,那么写操作将会一直阻塞。
父子进程在运行时,它们的先后次序并不能保证,因此,在这里为了保证父子进程已经关闭了相
应的文件描述符,可在两个进程中调用 sleep()函数,当然这种调用不是很好的解决方法,在后面
学到进程之间的同步与互斥机制之后,请读者自行修改本小节的实例程序。