进程间通信之管道

无名管道(pipe)


1,管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道
2,只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);
3,单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中
4,数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。

管道创建:

管道由调用pipe函数而创建
   
   
#include <unistd.h>
int pipe(int fileds[2]); #返回值:若成功则返回0,若出错则返回-1
经由参数filedes返回两个文件描述符: fileds[0]为读而打开, fileds[1]为写而打开,fileds[1]的输出是fileds[0]的输入。
但是单个进程中的管道没有什么用处。一般都是调用pipe的进程接着调用fork创建子进程,这样管道也相同的复制了一份到子进程,就创建了从父进程到子进程的IPC通道,如下图:

数据流方向:

父进程到子进程的管道,则父进程关闭管道的读端(fd[0]),子进程则关闭写端(fd[1]),如下图:

子进程到父进程的管道,则父进程关闭写端,子进程关闭读端。
当管道的一端被关闭后,下列两条规则起作用:
1,当读一个写端已被关闭的管道时,在所有数据都被读取后,read返回0,以指示达到了文件结束处
2,如果写一个读端已关闭的管道,则产生信号SIGPIPE
注:在写管道时,常量PIPE_BUF规定了内核中管道缓冲区的大小。如果对管道调用write,而且要求写的字节数小于等于PIPE_BUF,则此操作不会与其他进程对同一管道的write操作穿插进行。(主要发生在后续要讲的FIFO),用pathconf或者fpathconf函数可以确定PIPE_BUF的值。
示例:
    
    
#include "apue.h"
 
int main(void)
{
int n;
int pipe_fd[2];
pid_t pid;
char r_buf[100];
char w_buf[4];
memset(r_buf,0,sizeof(r_buf));
memset(w_buf,0,sizeof(r_buf));
p_wbuf=w_buf;
if(pipe(pipe_fd)< 0)
err_sys("pipe error");
if((pid=fork()) < 0)
err_sys("fork error");
else if(pid > 0) //parent
{
close(pipe_fd[0]);//read
strcpy(w_buf,"111");
if(write(pipe_fd[1],w_buf,4)!=-1)
printf("parent write over\n");
}
else //child
{
close(pipe_fd[1]);//write
n = read(pipe_fd[0], r_buf, 100);
write(STDOUT_FILENO, line, n);
}
exit(0);
}

标准IO库函数:

在标准IO库中,为管道操作提供了两个函数(前面都是Unix环境下的库函数,标准库是跨平台的,在其他平台上仍能使用)
    
    
#include <stdio.h>
FILE *popen(const char *cmdstring, const char *type); #返回值:若成功则返回文件指针,若出错则返回NULL
int pclose(FILE *fp); #返回值:cmdstring的终止状态,若出错则返回-1
函数popen先执行fork,然后调用exec执行cmdstring,并且返回一个标准I/O文件指针。如果type是“r”,则文件指针连接到cmdstring的标准输出, 如果type是“w”,则文件指针连接到cmdstring的标准输入 。即执行popen,会先生成一个子进程来执行我们指定的程序,然后 type是“r”,则 子进程的标准输出会通过管道发送到原先进程, type是“w”,则原先进程通过管道发送给子进程的数据会成为子进程的标准输入。
 
       
而pclose函数则关闭标准IO流,等待命令执行结束,然后返回shell的终止状态。

命名管道(FIFO)


FIFO也是管道的一种,与无命名管道相比,FIFO可以用于不相关进程的数据交换。与前面提到pipe是一种文件一样,FIFO也是一种文件类型。
创建FIFO类似于创建文件,FIFO的路径名存在于文件系统中。( 操作时,把FIFO看作文件即可,不同进程可以通过对FIFO读写,从而来实现进程通信
    
    
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode); #返回值:若成功则返回0,出错则返回-1
参数说明:
pathname:是FIFO的路径名称。
mode:与open打开文件的模式一样,例如“r”、“w”等。
注:一般的文件I/O函数(open、close、read、write等)都可以用于已经创建的FIFO。另外,一个给定的FIFO有多个写进程是很常见的,这样则有可能出现多个进程的所写的数据互相穿插。为避免数据穿插,则需要考虑原子操作。如上面所说,常量PIPE_BUF说明了可被原子地写到FIFO的最大数据量。
FIFO的用途:
1),FIFO由shell命令使用以便将数据从一条管道线传送到另一条,为此无需创建中间临时文件。
2),FIFO用于客户进程-服务器进程应用程序中,以在客户进程和服务进程之间传递数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值