linux系统管道知识,哈哈哈,好东西转给大家啦

原文链接地址:http://linchunai1212.blog.163.com/blog/static/35112143201111361543958/

前面在一段小程序中看到了mkfifo这样的一个函数,在baidu了一下之后对于进程间通信产生了一点兴趣,所以就小小的研究了一下。
在一个多进程操作系统所提供的运行环境下,可以通过两种不同的途径或者说采用两种不同的策略,来建立起复杂的大型应用系统。一种途径就是通过一个孤立的, 大型的,复杂的进程提供所需的全部服务,另外一种途径就是通过由若干相互联系的,小型的。相对简单的进程构成的组合来提供所需的功能。早期的操作系统往往 倾向与前者,而Unix以及其衍生的各种操作系统往往倾向于后者。相比之下,后者有着各种好处:1.模块化,2.各个进程都得到保护,在相当程度上排除了 相互干扰的可能性,3.灵活性更强。
当然这种好处也是要付出代价的,也有缺点,但是相比之下,这种途径的优点远远超出了其缺点。
Unix(从而Linux)向应用软件提供了一些进程间通信的手段,早期的Unix提供了:管道(pipe),信号(signal),跟踪(trace)。
这里我们只谈管道:父进程与子进程,或者两个兄弟进程之间,可以通过系统调用建立起一个单向的通信管道。但是,这种管道只能由父进程来建立,所以对于子进 程来说是静态的,与生俱来的。管道两端的进程各自将该管道视作一个文件。一个进程往通道中写的内容由另一个进程从通道读出,通过通道传递的内容遵循“先入 先出”(FIFO)的规则。每个通道都是单向的,需要双向通信时要建立起两个通道。
下面说一说进程间管道的建立,在这之前我们要说到fork()函数,在Linux系统中一个新的进程是由一个已经存在的进程“复制”出来的,而不是“创造”出来的(而所谓的“创建”实际上就是复制)。
管道机制的主体是系统调用pipe(),但是由pipe()所建立的管道的两端都在同一个进程中,这样的管道起不到进程间通信的作用。所以必须在fork()的配合下,才能在父子进程间或者两个子进程之间建立起进程间的通信管道。
下面就介绍一下怎样将管道用于进程间通信:
(1)进程A创建了一个管道,创建完成时代表管道两端的两个已打开文件都在进程A中。
Linux操作系统中的管道(pipe)使用方法 - 艾子 - linchunai1212的博客
Linux操作系统中的管道(pipe)使用方法 - 艾子 - linchunai1212的博客Linux操作系统中的管道(pipe)使用方法 - 艾子 - linchunai1212的博客
(2)进程A通过fork()创建出进程B,在fork()的过程中进程A的打开文件表按原样复制到进程B中。

Linux操作系统中的管道(pipe)使用方法 - 艾子 - linchunai1212的博客Linux操作系统中的管道(pipe)使用方法 - 艾子 - linchunai1212的博客
(3)进程A关闭管道的读端,而进程B关闭管道的写段。于是,管道的写段在进程A中而读端在进程B中,成为了父子进程之间的通信管道。

Linux操作系统中的管道(pipe)使用方法 - 艾子 - linchunai1212的博客 
(4)进程A又通过frok()创建进程C,而后关闭其管道写段而与管道脱离关系,使得管道的写段在进程C中而读端在进程B中,成为两个兄弟进程之间的管道。

Linux操作系统中的管道(pipe)使用方法 - 艾子 - linchunai1212的博客Linux操作系统中的管道(pipe)使用方法 - 艾子 - linchunai1212的博客 
人们在认识到管道机制也存在一些缺点和不足。由于管道是一种“无名”,“无形”的文件,它可以通过fork()的过程创建于“近亲” 的进程之间,而不能成为可以在任意两个进程之间建立通信的机制,更不可能成为一种一般的,通用的进程间通信模型,同时,管道机制的这种缺点本身强烈的暗示 着人们,只要用“有名”,“有形”的文件来实现管道,就能克服这种缺点。所以有了管道之后,“命名管道”的出现时必然的。
为了实现“命名管道”,在“普通文件”,“块设备文件”,“字符设备文件”之外,又设立了一种文件类型,称为FIFO文件。对这种文件的访问严格遵循“先进先出”的原则。这样就可以像在磁盘上建立一个文件一样建立一个命名管道,具体可以使用命令mknod来建立。例如:
% mknod mypipe   p
这里的参数“p”表示所建立的节点的类型。
我们从——help中可以看出:
b      create a block (buffered) special file
c, u   create a character (unbuffered) special file
p      create a FIFO

一个使用pipe编程的例子
表头文件 #include<unistd.h>
定义函数 int pipe(int filedes[2]);
函数说明
pipe()会建立管道,并将文件描述词由参数 filedes 数组返回。
filedes[0]为管道里的读取端,所以pipe用read调用的
filedes[1]则为管道的写入端。

返回值:  若成功则返回零,否则返回-1,错误原因存于 errno 中。
错误代码: 
EMFILE 进程已用完文件描述词最大量
ENFILE 系统已无文件描述词可用。
EFAULT 参数 filedes 数组地址不合法。

#include <unistd.h>
#include <stdio.h>

int main( void )
{
int filedes[2];
char buf[80];
pid_t pid;

pipe( filedes );

if ( (pid=fork()) > 0 )
{
printf( "This is in the father process,here write a string to the pipe.\n" );
char s[] = "Hello world , this is write by pipe.\n";
write( filedes[1], s, sizeof(s) );
close( filedes[0] );
close( filedes[1] );
}
else
{
printf( "This is in the child process,here read a string from the pipe.\n" );
read( filedes[0], buf, sizeof(buf) );
printf( "%s\n", buf );
close( filedes[0] );
close( filedes[1] );
}

waitpid( pid, NULL, 0 );

return 0;
}


[root@localhost src]# gcc pipe.c 
[root@localhost src]# ./a.out 
This is in the child process,here read a string from the pipe.
This is in the father process,here write a string to the pipe.
Hello world , this is write by pipe.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值