进程间通信——管道
管道简介
常说的管道都是匿名半双工管道,匿名半双工管道在系统中是没有实名的,并不可以在文件系统中以任何方式看到该管道。它只是进程的一种资源,会随着进程的结束而被系统清除。管道通信是在UNIX系统中应用比较频繁的一种方式,例如使用grep查找:ls |grep ipc
顾名思义,匿名半双工管道没有名字,这个特性导致了它在应用方面的局限性:
1.只能在有具有公共祖先的进程间通信,即或是父子关系进程间、或是在兄弟关系进程间通信。
2.数据只能在一个方向上移动
管道创建
尽管这样,半双工管道还是Linux系统上最常见的通信方式。Linux系统用pipe函数创建一个半双工管道,期函数原型为:
include
int pipe(int fd[2]);
参数fd是一个长度为2的文件描述符,fd[1]为输入文件描述符,fd[1]为输出文件描述符;函数返回类型为int,0表示成功,-1表示失败。当成功返回时,则自动维护一个从fd[1]到fd[0]的同行管道。
管道操作
对管道进行读写,可以通过write和read进行:
write(fd[1], "create the pipe successfully !\n", 31 ); /*向管道写入端写入数据*/
char str[256];
read(fd[0], str, sizeof(str) ); /*从管道读出端读出数据*/
读写时,需要注意的问题:
1.当输出端关闭时,对输入端的写操作会产生信号SIGPIPE,说明管道读端已经关闭,并且write操作返回为–1,errno的值为EPIPE,对于SIGPIPE信号可以进行捕捉处理。
2.read返回0说明管道中没数据,但不能说明输入端是否关闭
操作流程
1.创建管道
2.利用fork创建子进程
3.控制管道流向
4.从fd[1]向管道写信息
5.通过fd[0]从管道渡信息
创建管道的标准库函数
#include
FILE *popen( const char * command, const char *mode );
int pclose ( FILE *stream );
示例
引用《Linux C程序设计大全》 中的例子
- #include <unistd.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #define BUFES PIPE_BUF /* PIPE_BUF管道默认一次性读写的数据长度*/
- int main ( void ) {
- int fd[2];
- char buf[BUFSZ];
- pid_t pid;
- int len;
- if ( (pipe(fd)) < 0 ){ /*创建管道*/
- perror ( "failed to pipe" );
- exit( 1 );
- }
- if ( (pid = fork()) < 0 ){ /* 创建一个子进程 */
- perror ( "failed to fork " );
- exit( 1 );
- }
- else if ( pid > 0 ){
- close ( fd[0] ); /*父进程中关闭管道的读出端*/
- write (fd[1], "hello my son!\n", 14 ); /*父进程向管道写入数据*/
- exit ( 0);
- }
- else {
- close ( fd[1] ); /*子进程关闭管道的写入端*/
- len = read (fd[0], buf, BUFS ); /*子进程从管道中读出数据*/
- if ( len < 0 ){
- perror ( "process failed when read a pipe " );
- exit( 1 );
- }
- else
- write(STDOUT_FILENO, buf, len); /*输出到标准输出*/
- exit(0);
- }
- }
阅读(1685) | 评论(0) | 转发(2) |