实验4 观察Linux进程间的通信一 实验目的 学习如何利用管道机制进行进程间的通信,以加深对通信机制的理解。 实验内容 ?了解系统调用pipe()的功能和实现过程。 编写程序实现进程的管道通信。用系统调用pipe( )建立一管道,二个子进程P1和P2分别向管道各写一句话: Child 1 is sending a message! Child 2 is sending a message! 父进程从管道中读出二个来自子进程的信息并显示(要求先接收P1,后P2)。 运行该程序,观察、记录并简单分析其运行结果。 实验指导 LINUX系统最重要的贡献之一便是首创了管道(pipe)。 管道是指能够连接一个写进程和一个读进程的、并允许它们以生产者—消费者方式进行通信的一个共享文件,又称为pipe文件 写进程从管道的写入端(句柄1)将数据写入管道 读进程从管道的读出端(句柄0)读出数据。 句柄fd[0] 句柄fd[1] 读出端 写入端 管道的类型 有名管道 一个可以在文件系统中长期存在的、具有路径名的文件 用系统调用mknod( )建立 克服无名管道使用上的局限性,可让更多的进程也能利用管道进行通信 其它进程可知它的存在,并利用路径名来访问该文件 对有名管道的访问方式与访问其他文件一样,需先用open( )打开。 无名管道 一个临时文件。利用pipe( )建立起来的无名文件(无路径名) 只用该系统调用所返回的文件描述符来标识该文件 只有调用pipe( )的进程及其子孙进程才能识别此文件描述符,才能利用该文件(管道)进行通信 当这些进程不再使用此管道时,核心收回其索引结点 二种管道的读写方式相同,本实验只讲无名管道 pipe文件的建立 分配磁盘和内存索引结点、为读进程分配文件表项、为写进程分配文件表项、分配用户文件描述符 读/写进程互斥 内核为地址设置一个读指针和一个写指针,按先进先出顺序读、写。 为使读、写进程互斥地访问pipe文件,需使各进程互斥地访问pipe文件索引结点中的直接地址项 每次进程访问pipe文件前,都需检查该索引文件是否已被上锁 若是,进程便睡眠等待,否则,将其上锁,进行读/写 操作结束后解锁,并唤醒因该索引结点上锁而睡眠的进程。 所涉及的系统调用 (1) pipe( ):建立一无名管道。 系统调用格式 pipe(filedes) 参数定义 int pipe(filedes); int filedes[2]; 其中,filedes[1]是写入端,filedes[0]是读出端。 该函数使用头文件 #include#inlcude#include所涉及的系统调用 (2) read( ) 系统调用格式 read(fd,buf,nbyte) 功能:从fd所指示的文件中读出nbyte个字节的数据,并将它们送至由指针buf所指示的缓冲区中 如该文件被加锁,等待,直到锁打开为止。 参数定义 int read(fd,buf,nbyte); int fd; char *buf; unsigned nbyte; (3) write( ) 系统调用格式 read(fd,buf,nbyte) 功能:把nbyte 个字节的数据,从buf所指向的缓冲区写到由fd所指向的文件中 如文件加锁,暂停写入,直至开锁。 参数定义同read( )。 参考程序 #include#include#includeint pid1,pid2; main( ) { int fd[2]; char outpipe[100],inpipe[100]; pipe(fd); /*创建一个管道*/ while ((pid1=fork( ))= =-1); if(pid1= =0) { lockf(fd[1],1,0); sprintf(outpipe,"child 1 process is sending message!"); /*把串放入数组outpipe中*/ write(fd[1],outpipe,50); /*向管道写长为50字节的串*/ sleep(5); /*自我阻塞5秒*/ lockf(fd[1],0,0); exit(0); } 参考程序 else { while((pid2=fork( ))= =-1); if(pid2= =0) { lockf(fd[1],1,0); /*互斥*/ sprintf(outpipe,"child 2 process is sending message!"); write(fd[1],outpipe,50); sleep(5); lockf(fd[1],0,0); exit(0); } else { wait(0); /*同步*/ read(fd[0],inpipe,50); /*从管道中读长为50字节的串*/ printf("%s\n",inpipe); wait(0); read(fd[0],inpipe,50); printf("%s\n",inpipe); exit(0); } } } 运行结果: 延迟5秒后显示:child 1 process is sending message! 再延迟5秒: child 2 process is sending message! 思考题 (1) 程序中的sleep(5)起什么作用? (2) 子进程1和2为什么也能对管道进行操作?