没有合适的资源?快使用搜索试试~ 我知道了~
了解并掌握无名管道及有名管道; 重点是对基础及概念的把握; (非)阻塞写(读)打开规则; 读规则,写规则;
资源推荐
资源详情
资源评论
管道及有名管道
在本系列 序 中作者概述了 linux 进程间通信的几种主要手段。其中管道和有名管道是最早
的进程间通信机制之一 , 管道可用于具有亲缘关系进程间的通信 , 有名管道克服了管道没有
名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。 认
清管道和有名管道的读写规则是在程序中应用它们的关键 , 本文在详细讨论了管道和有名管
道的通信机制的基础上 , 用实例对其读写规则进行了程序验证 , 这样做有利于增强读者对读
写规则的感性认识,同时也提供了应用范例。
1
1
1
1 、 管道概述及相关 API
API
API
API 应用
1.1
1.1
1.1
1.1 管道相关的关键概念
管道是 Linux 支持的最初 Unix IPC 形式之一,具有以下特点:
• 管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管
道;
• 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);
• 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但
它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系
统,并且只存在与内存中。
• 数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的
内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。
1.2
1.2
1.2
1.2 管道的创建:
#include <unistd.h>
int pipe(int fd[2])
该函数创建的管道的两端处于一个进程中间 , 在实际应用中没有太大意义 , 因此 , 一个进程
在由 pipe() 创建管道后 , 一般再 fork 一个子进程 , 然后通过管道实现父子进程间的通信 ( 因
此也不难推出,只要两个进程中存在亲缘关系,这里的亲缘关系指的是具有共同的祖先 , 都
可以采用管道方式来进行通信)。
1.3
1.3
1.3
1.3 管道的读写规则:
无
名
管
道
的
特
点
管道两端可分别用描述字 fd[0] 以及 fd[1] 来描述,需要注意的是,管道的两端是固定了任务
的。即一端只能用于读,由描述字 fd[0] 表示,称其为管道读端;另一端则只能用于写,由
描述字 fd[1] 来表示,称其为管道写端。如果试图从管道写端读取数据,或者向管道读端写
入数据都将导致错误发生。一般文件的 I/O 函数都可以用于管道,如 close 、 read 、 write 等
等。
从管道中读取数据:
• 如果管道的写端不存在,则认为已经读到了数据的末尾,读函数返回的读出字节数
为 0 ;
• 当管道的写端存在时,如果请求的字节数目大于 PIPE_BUF ,则返回管道中现有的
数据字节数,如果请求的字节数目不大于 PIPE_BUF ,则返回管道中现有数据字节
数(此时,管道中数据量小于请求的数据量);或者返回请求的字节数(此时,管
道中数据量不小于请求的数据量)。注:( PIPE_BUF 在 include/linux/limits.h 中定
义 , 不同的内核版本可能会有所不同 。 Posix.1 要求 PIPE_BUF 至少为 512 字节 , red
hat 7.2 中为 4096 )。
关于管道的读规则验证:
/**************
* readtest.c *
**************/
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
main()
{
int pipe_fd[2];
pid_t pid;
char r_buf[100];
char w_buf[4];
char* p_wbuf;
int r_num;
int cmd;
memset(r_buf,0,sizeof(r_buf));
memset(w_buf,0,sizeof(r_buf));
p_wbuf=w_buf;
if(pipe(pipe_fd)<0)
{
printf("pipe create error\n");
return -1;
}
if((pid=fork())==0)
{
printf("\n");
close(pipe_fd[1]);
sleep(3);// 确保父进程关闭写端
r_num=read(pipe_fd[0],r_buf,100);
printf( "read num is %d the data read from the pipe is %d\n",r_num,atoi(r_buf));
close(pipe_fd[0]);
exit();
}
else if(pid>0)
{
close(pipe_fd[0]);//read
strcpy(w_buf,"111");
if(write(pipe_fd[1],w_buf,4)!=-1)
printf("parent write over\n");
close(pipe_fd[1]);//write
创建无名管道
创建子进程,父子通信
convert:string to int
多余
多余
多余
不能用:sizeof(w_buf)
可以用:strlen(w_buf)
w_buf的大小已经初始化,可以
使用memset,p_wbuf则不能,但
可以直接p_wbuf="hello"
printf("parent close fd[1] over\n");
sleep(10);
}
}
/**************************************************
* 程序输出结果:
* parent write over
* parent close fd[1] over
* read num is 4 the data read from the pipe is 111
* 附加结论:
* 管道写端关闭后,写入的数据将一直存在,直到读出为止 .
****************************************************/
向管道中写入数据:
• 向管道中写入数据时, linux 将不保证写入的原子性,管道缓冲区一有空闲区域 , 写
进程就会试图向管道写入数据。如果读进程不读走管道缓冲区中的数据,那么写操
作将一直阻塞。
注:只有在管道的读端存在时,向管道中写入数据才有意义。否则,向管道中写入
数据的进程将收到内核传来的 SIFPIPE 信号,应用程序可以处理该信号,也可以忽
略(默认动作则是应用程序终止)。
对管道的写规则的验证 1 :写端对读端存在的依赖性
#include <unistd.h>
#include <sys/types.h>
main()
{
int pipe_fd[2];
pid_t pid;
char r_buf[4];
char* w_buf;
int writenum;
int cmd;
memset(r_buf,0,sizeof(r_buf));
if(pipe(pipe_fd)<0)
{
剩余17页未读,继续阅读
资源评论
qrsforever
- 粉丝: 5
- 资源: 11
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功