ImageVerifierCode 换一换
格式:DOCX , 页数:10 ,大小:19.46KB ,
资源ID:10484280      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/10484280.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(管道通信.docx)为本站会员(b****7)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

管道通信.docx

1、管道通信Linux的管道通信进程通信的实用例子之一是Unix系统的管道通信。Unix系统从SystemV开始提供有名管道和无名管道两种数据通信方式。无名管道为建立管道的进程及其子孙提供一条以比特流方式传送消息的通信 。该管道在逻辑上被看作管道文件,在物理上则由文件系统的高速缓冲区构成,而很少启动外设。有名管道可用于两个无关的进程之间的通信。管道是Linux支持的最初Unix IPC形式之一,在Linux中是一种使用非常频繁的通信机制。从本质上说,管道也是一种文件,但它又和一般的文件有所不同,管道可以克服使用文件进行通信的两个问题,具体表现为: 限制管道的大小。实际上,管道是一个固定大小的缓冲区

2、。在Linux中,该缓冲区的大小为1页,即4K字节,使得它的大小不象文件那样不加检验地增长。使用单个固定缓冲区也会带来问题,比如在写管道时可能变满,当这种情况发生时,随后对管道的write()调用将默认地被阻塞,等待某些数据被读取,以便腾出足够的空间供write()调用写。 读取进程也可能工作得比写进程快。当所有当前进程数据已被读取时,管道变空。当这种情况发生时,一个随后的read()调用将默认地被阻塞,等待某些数据被写入,这解决了read()调用返回文件结束的问题。注意:从管道读数据是一次性操作,数据一旦被读,它就从管道中被抛弃,释放空间以便写更多的数据。管道是单向的、先进先出的、无结构的、

3、固定大小的字节流,它把一个进程的标准输出和另一个进程的标准输入连接在一起。写进程在管道的尾端写入数据,读进程在管道的首端读出数据。数据读出后将从管道中移走,其它读进程都不能再读到这些数据。管道提供了简单的流控制机制。进程试图读空管道时,在有数据写入管道前,进程将一直阻塞。同样,管道已经满时,进程再试图写管道,在其它进程从管道中移走数据之前,写进程将一直阻塞。管道的创建#include int pipe(int fd2)函数int pipe(int fd2)创建一个管道,管道两端可分别用描述字fd0以及fd1来描述。需要注意的是,管道的两端是固定了任务的。即一端只能用于读,由描述字fd0表示,称

4、其为管道读端;另一端则只能用于写,由描述字fd1来表示,称其为管道写端。如果试图从管道写端读取数据,或者向管道读端写入数据都将导致错误发生。一般文件的I/O函数都可以用于管道,如close、read、write等等。使用管道通信时,可关闭某些不需要的读或写描述符,建立起单向的读或写管道,然后用read和write像操作文件一样去操作它:close(pipe_fd0);/*关闭读管道*/ close(pipe_fd1);/*关闭写管道*/发送进程利用文件系统的系统调用write( fd1, buf, size),把buf中长度为size字节的字符消息送入管道入口(即写入端)fd1,接收进程则使用

5、系统调用read( fd0, buf, size )从管道出口(即读出端)fd0读出size字节的字符消息放到buf中。这里,管道按FIFO方式传送消息,且只能单向传送消息。管道应用实例例1:管道可用于输入输出重定向,它将一个命令的输出直接定向到另一个命令的输入。比如,当在某个shell程序(Bourneshell或C shell等)键入whowc -l后,相应shell程序将创建who以及wc两个进程和这两个进程间的管道。考虑下面的命令行:$kill -l显示了当前系统支持的所有信号$kill -l | grep SIGRTMIN 例2:使用系统调用pipe()建立一条管道线,两个子进程p1

6、和p2分别向管道各写一句话:child1 is sending a message!和child2 is sending a message!,父进程则从管道中读出来自子进程的信息,并显示在屏幕上。#include #include main() int fd2; int pid1,pid2; char OutPipe100, InPipe100; pipe(fd); while(pid1=fork()=-1); if(pid1=0) printf(“child process1 %dn”,getpid(); lockf(fd1,1,0); /*加锁锁定写入端*/ sprintf(OutPip

7、e, “child1 is sending a message!”); write(fd1, OutPipe, 50); /*将buf中的50个字符写入管道*/ sleep(5); /*睡眠5秒,暂时放弃CPU*/ lockf(fd1,0,0); /*解锁释放写入端*/ exit(0); /*结束进程pid1 */else while(pid2=fork()=-1); if(pid2=0) printf(“child process2 %dn”,getpid()”); lockf(fd1,1,0); sprintf(OutPipe, “child2 is sending a message!”

8、); write(fd1, OutPipe, 50); sleep(5); lockf(fd1,0,0); exit(0);else printf(“parent process %dn”,getpid(); wait(0); read(fd0,InPipe,50); printf(“%sn”,InPipe); wait(0); read(fd0,InPipe,50); printf(“%sn”,InPipe); exit(0);这里,用到了文件锁函数lockf以实现互斥。其函数原型为:#include int lockf(int files, int function, long size)

9、;功能:用作锁定文件的某些段或整个文件参数:files是文件描述符;function是锁定和解锁,1表示锁定,0表示解锁;size是锁定和解锁的字节数,表示自fd文件的当前位置开始处理size个相连字节,若size值为0,则表示从调用lockf后开始锁定,锁定范围从文件的当前位置到文件尾。思考:程序例2中,文件锁是否是必需的例3:两个进程,如子进程向父进程发送数据,即使用子进程的fd1和父进程的fd0,同时关闭子进程的fd0和父进程的fd1。#include#include#include#include#include#includeintmain()char*msg=Iamchildpro

10、cess!; /*子进程发送的数据*/pid_tpid;charbuf100; /*用于读取*/intpi; /*创建管道时的返回值*/intfd2; /*创建管道的参数*/memset(buf,0,sizeof(buf); /*设置buf数组全为0,需*/pi=pipe(fd); /*要引入#include*/if(pi0) /*parentprocess*/ close(fd1); /*关闭写管道*/ sleep(2); /*休眠一下等待数据写入*/ if(read(fd0,buf,100)0)/*写入管道*/ printf(Messagefromthepipeis:%sn,buf); c

11、lose(fd0);/*关闭读管道*/ waitpid(pid,NULL,0);/*待pid进程退出,此处pid为子进程*/ exit(0);else perror(fork()error!); exit(0);管道的局限性管道的主要局限性正体现在它的特点上:只支持单向数据流;只能用于具有亲缘关系的进程之间;没有名字;管道的缓冲区是有限的(管道制存在于内存中,在管道创建时,为缓冲区分配一个页面大小);管道所传送的是无格式字节流,这就要求管道的读出方和写入方必须事先约定好数据的格式,比如多少字节算作一个消息(或命令、或记录)等等。有名管道普通管道只能用于一个进程家族之间的通信,如父子,兄弟之间,

12、而命名管道是有“名字”的管道,另外的进程可以看到并使用。普通管道在内存中,随着进程的结束而消失,命名管道在磁盘上,作为一个特殊的设备文件而存在,进程结束不消失。值得注意的是,FIFO严格遵循先进先出(first in first out),对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。它们不支持诸如lseek()等文件定位操作。有名管道可用于两个无关的进程之间的通信。它的实现函数是:#include #include int mkfifo(const char * pathname, mode_t mode)创建一个名为filename的管道,mode模式设置管道的权

13、限,如O_CREAT、O_EXCL、O_NONBLOCK等。返回:成功0,出错返回-1 错误存储在errno中有名管道比管道多了一个打开操作:open。int open( const char * pathname,int flags, mode_t mode);参数pathname指向欲打开的文件路径字符串;下列是参数flags 所能使用的旗标:O_RDONLY 以只读方式打开文件;O_WRONLY 以只写方式打开文件;O_RDWR 以可读写方式打开文件。上述三种旗标互斥,不可同时使用,但可与下列的旗标利用OR(|)运算符组合: O_CREAT:若欲打开的文件不存在则自动建立该文件; O_E

14、XCL:如果也设置了O_CREAT,此指令会去检查文件是否存在。若不存在则建立该文件,否则将导致打开文件错误。此外,若O_CREAT与O_EXCL同时设置,并且欲打开的文件为符号连接,则会打开文件失败;O_NOCTTY:打开文件为终端机设备时,不会将该终端机当成进程控制终端机;O_TRUNC:若文件存在并且以可写的方式打开时,此旗标会令文件长度清为0,而原来存于该文件的资料也会消失;O_APPEND:当读写文件时会从文件尾开始移动,也就是所写入的数据会以附加的方式加入到文件后面; O_NONBLOCK:以不可阻塞的方式打开文件,也就是无论有无数据读取或等待,都会立即返回进程之中; 参数mode

15、一般为0。返回:若所有欲核查的权限都通过了检查则返回0,表示成功;只要有一个权限被禁止则返回-1。注意,使用open()打开 FIFO文件时,使用O_NONBLOCK旗标时,必须先有进程以读的方式打开这个管道。例如执行语句int fp=open(FIFO,O_RDWR|O_NONBLOCK,0);后,语句read(fp,buf,20);将会立即返回读取的数据;如果没有O_NONBLOCK属性,读取将会处于阻塞状态,直到有数据写入该命名管道。例4:下面一个实例演示了mkfifo的使用。请先以超级用户身份登录系统,然后编辑/编译源程序(两个*.c程序),在图形终端上执行读程序,读程序执行后将陷入循

16、环;切换到字符终端1(ctrl+alt+f1),以超级用户身份登录并执行写程序,然后回到图形终端,观察读程序的输出变化。/*/#include #include #include #include #include #include #include #include #define FIFO /home/jkx/myfifo /*使用宏命名有名管道文件的路径*/ int main() int fd;/*指向命名管道*/ char buf100;/*存储数据*/ if(mkfifo(FIFO,O_CREAT|O_EXCL)0) /*创建管道*/ perror(Create error!n);

17、unlink(FIFO);/*清除管道*/ exit(0); fd=open(FIFO,O_RDONLY|O_NONBLOCK,0);/*打开管道*/ if(fd0)/*读取管道*/ printf(Get message:%sn,buf); else printf(Not accept any message!n); sleep(1);/*休眠*/ */*/#include #include #include #include #include #include #include #define FIFO /home/jkx/myfifo /*宏定义命名管道路径*/ int main() char *msg=Some message!;/*发送数据*/ int fd; fd=open(FIFO,O_WRONLY|O_NONBLOCK,0);/*打开*/ if(write(fd,msg,20)!=-1) /*发送信息*/ printf(Message have been send to FIFOn); exit(0);

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1