您好,欢迎访问三七文档
实验5观察进程通信二•一、实验目的–掌握有名管道的创建方法–熟悉消息队列的进程通信方法•二、实验内容–使用mknod()创建命名管道–利用open()打开命名管道,完成命名管道的通信。–使用msgget()函数创建消息队列–使用msgsend()函数和msgrev()发送和接收消息–使用msgctl()读取消息实验指导-有名管道•有名管道的创建方法–有名管道利用文件可实现不同用户进程之间的通信。–利用mknod()、open()、read()、write()系统调用来实现–mknod语法:•mknod(pathname,typeandpermissions,dev)–Pathname:文件名–typeandpermissions:文件访问权限–Dev:这里为0(为块或字符文件规定的主设备号和次设备号)实验指导-有名管道–使用mknod()创建有名管道,内核为管道文件分配一个索引节点并在索引节点设置该文件类型是有名管道–打开open()管道–语法:–Intopen(path,flags),返回文件描述符•Path:文件名•Flags:打开类型,按POSI标准分为:–O_RDONLY只读,O_WRONLY只写–O_RDWR读写,O_APPEND–O_CREAT,O_EXCL,O_NOCTTY–O_NONBLOCK–O_TRUNC实验指导-有名管道•有名管道的读写使用read()和write()•Close(filedes)关闭管道–Filedes:有名管道的文件描述符案例1•在同一进程中创建一个有名管道,然后向管道写入字符,再读出#includesys/stat.h#includefcntl.hCharfilename[]=“./myfifo”;Charstring[]=“welcometonamedpipe”;Main(argc,argv)Intargc;Char*argv[];{intfiledes[2];charbuf[256];if(mknod(filename,O_CREAT|S_IRUSR|S_IWUSR,0)==-1){perror(“mknoderror”);exit(1);}Filedes[0]=open(filename,O_RDONLY);Filedes[1]=open(filename,O_WRONLY);Write(filedes[1],string,21);Printf(“wrotemessage:[%s]\n”,string);Sleep(3);Memset(buf,0,sizeof(buf));Read(fileds[0],buf,21);Printf(“readmessage:[%s\n”,buf);Unlink(filename);Exit(0);}案例2-用管道实现客户/服务器•思想:–客户和服务器进程运行在同一个平台上–服务器在后台运行,客户在前台运行–客户进程接受用户的shell命令,该命令通过管道传送给服务器。–服务器接收到该命令并执行–服务器将命令执行的内容通过一个私有命名管道返回给客户,并有客户进程将内容显示在屏幕上–通信步骤如下:案例2-用管道实现客户/服务器•通信步骤如下:–服务器生成公共命名管道,对所有客户可见–客户生成自己的私有管道–客户进程提示输入信息,接受命名输入–客户将私有管道名和用户输入命令写到公共管道–服务器读取公共管道,得到私有管道名和命令–服务器使用popen-pclose序列来执行用户输入的命令,其输入经过私有管道送回客户进程,并在后面加上服务器当前的时间–客户显示命令的输出、服务器的时间和本地时间客户/服务器头文件mypub.h#includesys/stat.h#includefcntl.h#includestdio.h#includestdlib.h#includeunistd.h#includestring.h#includelimits.h#includetime.h#definePUBLICpipetest/PUBLIC“#defineB_SIZE(PIPE_BUF/2)/*传给公共FIFO消息的格式由struct语句说明*//*fifo_name:包含私有管道的名字*//*cmd_line:包含将要被服务器执行的命令*/structmessage{charfifo_name[B_SIZE];charcmd_line[B_SIZE];}服务器端进程-myService.c#includemyPub.h“voidmain(void){intn,done,dummyfifo,publicfifo,privatefifo;structmessagemsg;FILE*fin;staticcharbuffer[PIPE_BUF];time_tticks;charbuff[30];mknod(PUBLIC,S_IFIFO|0666,0);/*创建公共管道*/if((publicfifo=open(PUBLIC,O_RDONLY))==1||/*打开公共管道*/(dummyfifo=open(PUBLIC,O_WRONLY|O_NDELAY))==-1){perror(PUBLIC);exit(1);}while(read(publicfifo,(char*)&msg,sizeof(msg))0)/*从管道读数据*/{n=0;done=0;do{if((privatefifo=open(msg.fifo_name,O_WRONLY|O_NDELAY))==-1)/*以写方式打开私有,O_NDELAY防止OPEN产生死锁现象*/sleep(3);服务器端进程-myService.celse{fin=popen(msg.cmd_line,“r”);/*执行消息结构中传来的命令*/while((n=read(fileno(fin),buffer,PIPE_BUF))0){write(privatefifo,buffer,n);/*写入私有管道*/memset(buffer,0x0,PIPE_BUF);}pclose(fin);done=1;ticks=time(NULL);write(privatefifo,\ntheservertimeis:,20);sprintf(buffer,%.24s\r\n,ctime(&ticks));write(privatefifo,buff,strlen(buff));close(privatefifo);}}while((++n5)&&(!done));if(!done)write(fileno(stderr),\nNOTE:SERVER**NEVER**accessedprivateFIFO\n,48);}}客户端进程myClient.c#includemyPub.h“voidmain(void){intn,privatefifo,publicfifo;staticcharbuffer[PIPE_BUF];structmessagemsg;time_tticks;charbuff_local[30];/*生成私有管道的名字*/sprintf(msg.fifo_name,“pipetest/fifo%d”,getpid());printf(theprivatepipenameis%s\n,msg.fifo_name);if(mknod(msg.fifo_name,S_IFIFO|0666,0)0)/*创建对所有进程都有读写权限的私有管道*/{perror(msg.fifo_name);exit(1);}if((publicfifo=open(PUBLIC,O_WRONLY))==-1)/*打开公共管道*/{perror(PUBLIC);exit(2);}客户端进程myClient.cwhile(1){write(fileno(stdout),\ncommand,9);/*将存储命令结构成员置空,确保无多余字符*/memset(msg.cmd_line,0x0,B_SIZE);n=read(fileno(stdin),msg.cmd_line,B_SIZE);ticks=time(NULL);if(!strncmp(“quit”,msg.cmd_line,n-1))/*检查用户是否想退出*/break;write(publicfifo,(char*)&msg,sizeof(msg));/*写入公共管道*/if((privatefifo=open(msg.fifo_name,O_RDONLY))==-1){perror(msg.fifo_name);exit(3);}客户端进程myClient.cwhile((n=read(privatefifo,buffer,PIPE_BUF))0){write(fileno(stderr),buffer,n);}/*打印本地时间*/printf(theclienttimeis);sprintf(buff_local,%.24s\r\n,ctime(&ticks));printf(%s,buff_local);close(privatefifo);}close(privatefifo);unlink(msg.fifo_name);/*删除私有管道*/}进程间通信IPC:消息机制•一、实验目的–1.了解消息机制的相关函数。–2.了解消息队列的建立与使用。–3.能编写简单消息机制通信程序。•二、实验内容–1.建立消息队列–2.编写发送程序发送消息–3.编写接•三、预备知识–1.创建和访问一个消息队列•格式:intmsgget(key_tkey,intmsgflag);•返回值为对应消息的描述符(整型常量)。收程序接收消息进程间通信IPC:消息机制–2.发送消息(把一条消息添加到消息队列中去)•格式:intmsgsnd(intmsqid,constvoid*smg_ptr,size_tmsg_sz,intmsgflag);–3.接收消息•格式:intmsgrcv(intmsqid,void*msg_ptr,size_tmsg_sz,longintmsgtype,intmsgflag);–4.控制和删除消息•格式:intmsgctl(intmsqid,command,function);–注意:msgsnd()和msgrcv()和msgctl()命令若执行成功,则返回0,若不成功,则返回-1。•在两个不相关的进程间传递数据有许多种办法,消息队列是其中比较简单同时也比较高效的那一种。与命名管道相比,消息队列的优势在于它们既不依赖于发送进程,也不依赖于接收进程,它们可以独立存在,这就省掉了在打开和关闭命名管道时必不可少的同步与协调环节。进程间通信IPC:消息机制•四、实验步骤•1.新建一个发送消息的程序x1.c•程序目的:可提示用户进行键盘输入字符,直到用户输入”end”,才结束输入。将用户输入的内容存入消息队列,发送出去。#includestdlib.h#includestdio.h#includestring.h#includeerrno.h#includeunistd.h#includesys/types.h#includesys/ipc.h#includesys/msg.h#defineMAX_TEXT512structmform{longintmtype;charmtext[MAX_TEXT];};/*定义了消息的结构*/x1.c文件intmain(){intrunning=1;structmformmsg;intmsgid;charbuffer[BUFSIZ];msgid=msgget((key_t)1234,0666|IPC_CREAT);/*建立消息队列*/if(msgid==-1){/*若创建不成功,则显示出错信息,结束*/printf(“msggetfailed!\n”);exit(EXIT
本文标题:操作系统实验5
链接地址:https://www.777doc.com/doc-3352914 .html