博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
进程间通信-管道
阅读量:4212 次
发布时间:2019-05-26

本文共 3308 字,大约阅读时间需要 11 分钟。

1.什么是管道

管道是最初的Unix IPC(进程间通信)形式,局限于没有名字,从而只能由有亲缘关系的进程使用。

2.管道接口描述

#include
int pipe(int fd[2]);//返回:若成功则为0,若出错则为-1
该函数返回两个文件描述符:fd[0]和fd[1]。前者打开来读,后者打开来写。

管道的典型用途:为两个不同进程(父进程和子进程)间提供通信手段。

(1)提供一个单向数据流的方式:由一个进程(它将成为父进程)创建一个管道后调用fork派生一个自身的副本,父进程关闭管道的读出端,子进程关闭同一管道的写入端。

(2)提供一个双向数据流的方式:

步骤1:创建管道1(fd1[0]和fd1[1])和管道2(fd2[0]和fd2[1])

步骤2:fork;

步骤3:父进程关闭管道1的读出端(fd1[0])

步骤4:父进程关闭管道2的写入端(fd2[1])

步骤5:子进程关闭管道1的写入端(fd1[1])

步骤6:子进程关闭管道2的读出端(fd2[0])

程序实例:

#include	"unpipc.h"void	client(int, int), server(int, int);intmain(int argc, char **argv){	int		pipe1[2], pipe2[2];	pid_t	childpid;	Pipe(pipe1);	/* create two pipes */	Pipe(pipe2);	if ( (childpid = Fork()) == 0) {		/* child */		Close(pipe1[1]);		Close(pipe2[0]);		server(pipe1[0], pipe2[1]);		exit(0);	}		/* 4parent */	Close(pipe1[0]);	Close(pipe2[1]);	client(pipe2[0], pipe1[1]);	Waitpid(childpid, NULL, 0);		/* wait for child to terminate */	exit(0);}#include    "unpipc.h"voidclient(int readfd, int writefd){    size_t    len;    ssize_t    n;    char    buff[MAXLINE];        /* 4read pathname */    Fgets(buff, MAXLINE, stdin);    len = strlen(buff);        /* fgets() guarantees null byte at end */    if (buff[len-1] == '\n')        len--;                /* delete newline from fgets() */        /* 4write pathname to IPC channel */    Write(writefd, buff, len);        /* 4read from IPC, write to standard output */    while ( (n = Read(readfd, buff, MAXLINE)) > 0)        Write(STDOUT_FILENO, buff, n);}#include    "unpipc.h"voidserver(int readfd, int writefd){    int        fd;    ssize_t    n;    char    buff[MAXLINE+1];        /* 4read pathname from IPC channel */    if ( (n = Read(readfd, buff, MAXLINE)) == 0)        err_quit("end-of-file while reading pathname");    buff[n] = '\0';        /* null terminate pathname */    if ( (fd = open(buff, O_RDONLY)) < 0) {            /* 4error: must tell client */        snprintf(buff + n, sizeof(buff) - n, ": can't open, %s\n",                 strerror(errno));        n = strlen(buff);        Write(writefd, buff, n);    } else {            /* 4open succeeded: copy file to IPC channel */        while ( (n = Read(fd, buff, MAXLINE)) > 0)            Write(writefd, buff, n);        Close(fd);    }} 

3.popen和pclose函数

#include
FILE *popen(const char *command,const char *type);//返回:若成功则为文件指针,若出错则为NULLint pclose(FILE *stream);//返回:若成功则为shell的终止状态,若出错则为-1
标准I/O函数库提供了popen函数,它
创建一个管道
启动另外一个进程,该进程要么从该管道读出标准输入,要么往该管道写入标准输出。

pclose函数关闭由popen创建的标准I/O流,等待其中的命令终止,然后返回shell的终止状态

代码实例:

 

#include	"unpipc.h"intmain(int argc, char **argv){	size_t	n;	char	buff[MAXLINE], command[MAXLINE];	FILE	*fp;		/* 4read pathname */	Fgets(buff, MAXLINE, stdin);	n = strlen(buff);		/* fgets() guarantees null byte at end */	if (buff[n-1] == '\n')		n--;				/* delete newline from fgets() */	snprintf(command, sizeof(command), "cat %s", buff);	fp = Popen(command, "r");		/* 4copy from pipe to standard output */	while (Fgets(buff, MAXLINE, fp) != NULL)		Fputs(buff, stdout);	Pclose(fp);	exit(0);}

popen()函数实际上执行以下操作:

1.使用pipe()系统调用创建一个新管道

2.创建一个新进程,该进程又执行以下操作

       a.如果type是r,就把与管道的写通道相关的文件描述符拷贝到文件描述符1(标准输出);否则,如果type是w,就把与管道的读通道相关的文件描述符拷贝到文件描述符   0(标准输入)

       b.关闭pipe()返回的文件描述符

       c.调用execve()系统调用执行filename所指定的程序

3.如果type是r,就关闭与管道的写通道相关的文件描述符;否则,如果type是w,就关闭与管道的读通道相关的文件描述符

4.返回FILE文件指针所指向的地址,这个指针指向仍然打开的管道所涉及的任一文件描述符。

你可能感兴趣的文章
usb-otg-调试心得
查看>>
嵌入式开发指导博客-刘洪涛
查看>>
Linux启动流程-bootloader至kernel的过程--android系统启动流程
查看>>
USB2.0速度识别--区分低速-高速-全速
查看>>
NandFlash驱动超详细分析
查看>>
inf文件解析
查看>>
MOSFET结构及其工作原理详解
查看>>
android开源社区
查看>>
手机摄像头工作原理
查看>>
手机电容触摸屏技术简介
查看>>
led子系统 及 内核中led触发器实例
查看>>
Android USB Tethering的实现以及代码流程
查看>>
有关电池充电和LCD驱动的好地方
查看>>
USB规范浏览--设备和主机规范
查看>>
男人的品位--我们自己的最求
查看>>
Android (Linux) Suspend流程
查看>>
LINUX时间管理
查看>>
定时器的使用
查看>>
为Android加入busybox工具
查看>>
使用技巧busybox
查看>>