操作系统实验教程(6)

2018-12-17 15:09

4.2 管道通信

管道有两种:命名管道和无名管道。pipe为无名管道,两个父子进程之间可

以利用pipe机构传送大量信息。其中一个进程利用write向管道写数据,另一个进程利用read读管道中的数据。 利用pipe建立管道: int pipe_fd[2]; pipe(pipe_fd);

其中在pipe_fd[0]中返回pipe读通道打开的文件号,在pipe_fd[1]中返回pipe写通道打开的文件号。一般情况下,进程定义pipe后,会创建一个或几个子进程,父子进程利用pipe进行通信,于是pipe被父子进程共享,其中一个进程只利用它的发送端,另一个只用它的接收端。利用发送端的进程就应当关闭其接收端,利用接收端的进程应当关闭其发送端。管道通信要加头文件unistd.h。 例1:父子进程利用pipe通信。父进程利用一个pipe发送消息,子进程利用该pipe接收父进程发来的信息;子进程利用另一个pipe向父进程发送应答,父进程利用该pipe接收应答。

#include #include

char father[]={“the message from father.\\n”}; char child[]={“the message from child.\\n”}; main() {

int chan1[2],chan2[2]; char buff[50]; pipe(chan1); pipe(chan2); if(fork()) {

close(chan1[0]);

close(chan2[1]);

write(chan1[1],father,strlen(farther)); close(chan1[1]);

read(chan2[0],buff,50);

printf(“father process:%s\\n”,buff); }else{ close(chan1[1]); close(chan2[0]); read(chan1[0],buff,50);

24

printf(“child process:%s\\n”,buff); write(chan2[1],child,strlen(child)); close(chan2[1]);

} }

运行结果:

child process:the message from father. father process:the message from child.

例2:编制一段程序,实现进程的管道通信。使用系统调用pipe()建立一条管道先。两个子进程p1和分别向管道各写一句话: Child 1 process is sending a message! Child 2 process is sending a message!

而父进程则从管道中读出来自于两个子进程的信息并显示在屏幕上。

#include #include #include int pid1,pid2; main() {

int fd[2];

char outpipe[100],inpipe[100]; pipe(fd);

while ((pid1=fork())= =-1); if (pid1= =0) {

printf”p1\\n”); lockf(fd[1],1,0);

sprintf(outpipe,”child 1 process is sending a message!”); write(fd[1],outpipe,50); sleep(1); //自我阻塞1秒 lockf(fd[1],0,0); exit(0);

} else {

while ((pid2=fork())= =-1); if (pid2= =0) {

printf(“p2\\n”); lockf(fd[1],1,0);

sprintf(outpipe,”child 2 process is sending a message!”); write(fd[1],outpipe,50);

25

sleep(1);

lockf(fd[1],0,0); exit(0); } else {

printf(“parent\\n”); wait(0); //同步

read(fd[0],inpipe,50); //从管道中读 printf(“%s\\n”,inpipe); wait(0);

read(fd[0],inpipe,50); printf(“%s\\n”,inpipe); exit(0); } } }

运行结果:

child 1 process is sending a message! child 2 process is sending a message!

4.3消息通信 1、msgget(key,flag):

获得一个消息的描述符,该描述符指定一个消息队列以便用于其他系统调

用。

该函数使用偷文件如下: #include #include #include 参数定义

int msgget(key,flag) key_tkey; int flag;

语法格式:msgqid=msgget(key,flag)

其中:msgid是该系统调用返回的描述符,失败则返回-1;flag 本身由操作

允许权和控制命令值相“或”得到。

如:IP_CREAT|0400 是否该队列应被创建;

26

IP_EXCL |0400 是否该队列的创建应是互斥的;等。

2、msgsnd(id,msgp,size,flag):

发送一消息。

该函数是用头文件如下: #include #include #include 参数定义

int msgnd(id,msgp,size,flag) int id,size,flag; struct msgbuf * msgp;

其中:id是返回消息队列的描述符;msgp是指向用户存储区的一个构造体

指针,size指示由msgp指向的数据结构中字符数组的长度;即消息的长度。这个数组的最大值由MSG-MAX系统可调用参数来确定。flag规定当核心用尽内部缓冲空间时应执行的动作;若在标志flag中末设置IPC_NOWAIT位,则当该消息队列中字节数超过一最大值时,或系统范围的消息数超过某一最大值时,调用msgsnd进程睡眠。若是设置IPC_NOWAIT,则在此情况下,msgsnd立即返回。

3、msgrcv(id,msgp,size,type,flag):

接受一消息。

该函数调用使用头文件如下: #include #include #include 参数定义

int msgrcv(id,msgp,size,type,flag) int id,size,type,flag; struct msgbuf * msgq;

struct sgbuf{long mtpe;chat mtext[];};

27

语法格式:

count=msgrcv(id,msgp,size,type,flag)

其中:id是用来存放欲接收消息的拥护数据结构的地址;size是msgp中数

据数组的大小; type是用户要读的消息类型:

type为0:接收该队列的第一个消息; type为正:接收类型type的第一个消息;

type为负:接收小于或等于type绝对值的最低类型的第一个消息。 flag规定倘若该队列无消息,核心应当做什么事,如果此时设置了

IPC_NOWAIT标志,则立即返回,若在flag中设置了MSG_NOERROR,且所接收的消息大小大于size,核心截断所接受的消息。

count是返回消息正文的字节数。

4、msgctl(id,cmd,buf):

查询一个消息描述符的状态,设置它的状态及删除一个消息描述符。 调用该函数使用头文件如下: #include #include #include 参数定义

int msgctl(id,cmd,buf) int id,cmd;

struct msgbuf * msgq; struct msqid_ds * buf;

其中:函数调用成功时返回0,调用不成功时返回-1。id用来识别该消息的

描述符;cmd规定命令的类型。

IPC_START将与id相关联的消息队列首标读入buf。

IPC_SET为这个消息序列设置有效的用户和小组标识及操作允许权和字节

的数量。

IPC_RMID删除id的消息队列。

buf是含有控制参数或查询结果的用户数据结构的地址。

28


操作系统实验教程(6).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:2013白蒲中学高一数学教案:函数:27

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: