操作系统实验进程通信
《Linux操作系统设计实践》实验二:进程通信

《Linux操作系统设计实践》实验二:进程通信实验目的:进一步了解和熟悉 Linux 支持的多种 IPC 机制,包括信号,管道,消息队列,信号量,共享内存。
实验环境: redhat实验内容:(1)进程间命名管道通信机制的使用:使用命名管道机制编写程序实现两个进程间的发送接收信息。
(2)进程间消息队列通信机制的使用:使用消息队列机制自行编制有一定长度的消息(1k 左右)的发送和接收程序。
(3)进程间共享存储区通信机制的使用:使用共享内存机制编制一个与上述(2)功能相同的程序。
并比较分析与其运行的快慢。
实验代码验证:(1).使用命名管道机制编写程序实现两个进程间的发送接收信息。
#include <stdio.h>#include <stdlib.h>#define FIFO_FILE "MYFIFO"int main(int argc, char *argv[]){FILE *fp;int i;if (argc<=1){printf("usage: %s <pathname>\n",argv[0]); exit(1);}if ((fp = fopen(FIFO_FILE, "w")) == NULL) {printf("open fifo failed. \n");exit(1);}for (i = 1; i < argc; i++){if (fputs(argv[i],fp) == EOF){printf("write fifo error. \n");exit(1);}if (fputs(" ",fp) == EOF){printf("write fifo error. \n"); exit(1);}}fclose(fp);return 0;}#include <stdio.h>#include <stdlib.h>#include <sys/stat.h>#include <unistd.h>#include <linux/stat.h>#define FIFO_FILE "MYFIFO"int main(){FILE *fp;char readbuf[80];if ((fp = fopen(FIFO_FILE, "r")) == NULL) {umask(0);mknod(FIFO_FILE, S_IFIFO | 0666, 0);}else{fclose(fp);}while (1){if ((fp = fopen(FIFO_FILE, "r")) == NULL) {printf("open fifo failed. \n");exit(1);}if (fgets(readbuf, 80, fp) != NULL){printf("Received string :%s \n", readbuf); fclose(fp);}else{if (ferror(fp)){printf("read fifo failed.\n");exit(1);}}}return 0;}实验结果:Server.c将client.c写入的字符输出。
操作系统进程通信(信号,共享存储区,消息队列)

letter.txt 内容为:operatingsystemlixin numbet.txt 内容为:12342007202314 ·结果分析及解释
1.首先输出提示信息 Enter some text: ,提示输入文本。 2.首先输入 operating system 1234 [][]\] ,包括字母数字和无效字符。 3.再次输出提示信息 Enter some text: 。 4.输入 lixin2007202314 5.再次输出提示信息 Enter some text: 后输入 quit 退出。 6.输出提示信息 Distributed over! (7)问题分析
strcpy(msg.text,"Enter some text:\n"); msgsnd(msgid,&msg,MAXSIZE,IPC_NOWAIT);//发送提示信息 kill(pid1,SIGUSR1);//向子进程 1 发送信号,以显示提示信息 sleep(1); 6.父进程使用 fgets()函数读入一行输入,fgets()函数读入结束时的回车符 并自动添加字符串结束符。 7.对于输入 “quit” 退出的解决,一开始使用函数 strncmp(buf,”quit”,4);但后 来考虑到输入诸如”quitxy”等字符床也会退出,因此将 strncmp 改为 strcmp 函数,具 体代码为: if(strcmp(buf,"quit\n. 共享存储区: 主要实现语句: shmid=shmget(key,size,flag); shmat(shmid,addr,flag); shmdt(addr); shmctl(shmid,cmd,buf)。 2. 消息队列: 主要实现语句: struct my_msg { long int my_msg_type;
操作系统实验报告(进程的管道及消息通信)

printf("\n Ihave wrote:%s",string); write(fd,string,45); string[0]+=1; } else { read(fd,buf,256); printf("\n The context by I have read is :!%s",buf); buf[0]='\0'; } } close(fd); } 运行结果:
char parent[]="A message to pipe'communication.\n";
main() {
int pid,chan1[2]; char buf[100]; pipe(chan1); pid=fork(); if(pid<0) {
printf("to create child error\n"); exit(1); } if(pid>0) { close(chan1[0]); printf("parent process sends a message to child.\n"); write(chan1[1],parent,sizeof(parent)); close(chan1[1]); printf("parent process waits the child to terminate\n"); wait(0); printf("parent process terminate\n"); } else { close(chan1[1]); read(chan1[0],buf,100); printf("The message read by child process from parent is :%s.\n",buf); close(chan1[0]); printf("child process terminates\n"); } } 运行结果:
操作系统进程通信报告

实验四:进程同步实验一、实验任务:1、熟悉操作系统进程通信原理2、设计程序,实现共享内存、管道通信、消息通信二、实验原理:1、进程间通信的几种方法简介(1)消息队列:消息队列是消息的链接表,包括Posix消息队列systemV消息队列。
有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。
(2)共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。
是针对其他通信机制运行效率较低而设计的。
往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
(3)无名管道(Pipe)及有名管道(named pipe):有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;无名管道可用于有亲缘关系的进程之间彼此的通信,进行通信时候必须有一定的机制保证对管道写和读的互斥:即在读是要关闭写的端口,而在写的时候也要保证读的一端是关闭的。
2、进程通信函数(1)消息队列有关系统调用函数a.创建消息队列使用msgget()函数:#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>int msgget(key_t key, int flag) ;该函数成功调用返回消息队列标识符。
其中的key是关键字,可以由ftok()函数得到:key=ftok(“.”,’a’);其中”.”可以是任何目录,’a’是任意字符,即所有群组标识。
flag是标识,IPC_CREAT位表示创建,一般由服务器程序创建消息队列时使用。
如果是客户程序,必须打开现存的消息队列,必须不使用IPC_CREAT。
发送和接收的消息都必须使用一个类似msgbuf的结构表示,msgbuf结构定义如下:struct msgbuf{long mtype;char mtext[1];}上面的定义,消息内容只有一个字节,是不实用的,一般我们需要重新定义一个结构:struct amsgbuf{long mtype;char mtext[200];}其中的mtype都是消息类型。
进程通信的实验报告

一、实验目的1. 理解进程通信的概念和作用。
2. 掌握进程通信的常用方法,包括管道、消息队列、信号量等。
3. 通过编程实践,加深对进程通信机制的理解和应用。
二、实验环境操作系统:Linux开发环境:gcc三、实验内容1. 管道通信2. 消息队列通信3. 信号量通信四、实验步骤及分析1. 管道通信(1)实验步骤1)创建一个父进程和一个子进程;2)在父进程中创建一个管道,并将管道的读端和写端分别赋给父进程和子进程;3)在父进程中,通过管道的写端发送数据给子进程;4)在子进程中,通过管道的读端接收父进程发送的数据;5)关闭管道的读端和写端;6)结束进程。
(2)实验分析通过管道通信,实现了父进程和子进程之间的数据传递。
管道是半双工通信,数据只能单向流动。
在本实验中,父进程向子进程发送数据,子进程接收数据。
2. 消息队列通信(1)实验步骤1)创建一个消息队列;2)在父进程中,向消息队列中发送消息;3)在子进程中,从消息队列中接收消息;4)删除消息队列;5)结束进程。
(2)实验分析消息队列是一种进程间通信机制,允许不同进程之间传递消息。
消息队列的创建、发送、接收和删除等操作都是通过系统调用实现的。
在本实验中,父进程向消息队列发送消息,子进程从消息队列接收消息,实现了进程间的消息传递。
3. 信号量通信(1)实验步骤1)创建一个信号量;2)在父进程中,对信号量执行P操作,请求资源;3)在子进程中,对信号量执行V操作,释放资源;4)结束进程。
(2)实验分析信号量是一种用于实现进程同步的机制。
在进程通信中,信号量可以用来协调多个进程对共享资源的访问。
在本实验中,父进程和子进程通过信号量实现了对共享资源的同步访问。
五、实验结果1. 管道通信实验结果:父进程成功向子进程发送数据,子进程成功接收数据。
2. 消息队列通信实验结果:父进程成功向消息队列发送消息,子进程成功从消息队列接收消息。
3. 信号量通信实验结果:父进程成功获取资源,子进程成功释放资源。
进程通讯管理实验报告(3篇)

第1篇一、实验目的1. 理解进程通信的概念和原理;2. 掌握进程通信的常用机制和方法;3. 能够使用进程通信机制实现进程间的数据交换和同步;4. 增强对操作系统进程管理模块的理解。
二、实验环境1. 操作系统:Linux2. 编程语言:C3. 开发环境:GCC三、实验内容1. 进程间通信的管道机制2. 进程间通信的信号量机制3. 进程间通信的共享内存机制4. 进程间通信的消息队列机制四、实验步骤1. 管道机制(1)创建管道:使用pipe()函数创建管道,将管道文件描述符存储在两个变量中,分别用于读和写。
(2)创建进程:使用fork()函数创建子进程,实现父子进程间的通信。
(3)管道读写:在父进程中,使用read()函数读取子进程写入的数据;在子进程中,使用write()函数将数据写入管道。
(4)关闭管道:在管道读写结束后,关闭对应的管道文件描述符。
2. 信号量机制(1)创建信号量:使用sem_open()函数创建信号量,并初始化为1。
(2)获取信号量:使用sem_wait()函数获取信号量,实现进程同步。
(3)释放信号量:使用sem_post()函数释放信号量,实现进程同步。
(4)关闭信号量:使用sem_close()函数关闭信号量。
3. 共享内存机制(1)创建共享内存:使用mmap()函数创建共享内存区域,并初始化数据。
(2)映射共享内存:在父进程和子进程中,使用mmap()函数映射共享内存区域。
(3)读写共享内存:在父进程和子进程中,通过指针访问共享内存区域,实现数据交换。
(4)解除映射:在管道读写结束后,使用munmap()函数解除映射。
4. 消息队列机制(1)创建消息队列:使用msgget()函数创建消息队列,并初始化消息队列属性。
(2)发送消息:使用msgsnd()函数向消息队列发送消息。
(3)接收消息:使用msgrcv()函数从消息队列接收消息。
(4)删除消息队列:使用msgctl()函数删除消息队列。
实验一 进程通信操作系统实验报告

验
内
容
2.用pipe()创建一个管道,然后用fork()创建两个生产进程和两个消费进程,它们之间能过pipe()传递信息。
实
验
结果
遇到问题及解决方法
int i,pid,status;
for(i=0;i<4;i++) pid=wait(*status); i,pid,status;
实
验
结果
遇到问题及解决方法
retval=clone((void*)producer,&(stack[4095]),clone_flag, (void*&arg);此语句void*后缺少),正确语句应为:
retval=clone((void*)producer,&(stack[4095]),clone_flag, (void*)&arg);
for(i=0;i<4;i++) pid=wait(&status);
if(id==1) stcopy(w_buf,"ccc\0");
else strcpy(w_buf,"ddd\0");
此语句中stcopy词语写错,应改为strcpy,即
if(id==1) strcpy(w_buf,"ccc\0");
学年第学期
操作系统课程
实验报告
学院:
专业:
班级:
姓名:
学号:
任课教师:
实验日期:2017年4月11日
实验题目
实验一进程通信
实验地点
实验目的
1.理解Linux系统的进程通信机构(IPC)允许在任意进程间大批量地交换数据的过程。
操作系统实验报告2-进程间通信

msg.mtype=1;
msgsnd(msgqid,&msg,sizeof(int),0);
msgrcv(msgqid,&msg,256,pid,0);
printf("client:receive from pid %d\n",*pint);
exit(0);
}
#include<sys/types.h>
信号本质:信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。信号是进程间通信机制中唯一的异步通信机制,可以看作是异步通知,通知接收信号的进程有哪些事情发生了。信号机制经过POSIX实时扩展后,功能更加强大,除了基本通知功能外,还可以传递附加信息。进程用kill( )向一个进程或一组进程发送一个信号;当一个进程要进入或退出一个低优先级睡眠状态时,或一个进程即将从核心态返回用户态时,核心都要检查该进程是否已收到软中断
signal(17,stop); /*接收到软中断信号17,转stop*/
waiting( );
lockf(stdout,1,0);
printf("Child process 2 is killed by parent!\n");
lockf(stdout,0,0);
exit(0);
}
}
else
{
wait_mark=1;
signal(16,stop); /*接收到软中断信号16,转stop*/
waiting( );
lockf(stdout,1,0);
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
进程通信(实验二)【实验目的】:掌握用邮箱方式进行进程通信的方法,并通过设计实现简单邮箱理解进程通信中的同步问题以及解决该问题的方法。
【实验原理】:邮箱机制类似于日常使用的信箱。
对于用户而言使用起来比较方便,用户只需使用send()向对方邮箱发邮件receive()从自己邮箱取邮件,send()和receive()的内部操作用户无需关心。
因为邮箱在内存中实现,其空间有大小限制。
其实send()和receive()的内部实现主要还是要解决生产者与消费者问题。
【实验内容】:进程通信的邮箱方式由操作系统提供形如send()和receive()的系统调用来支持,本实验要求学生首先查找资料了解所选用操作系统平台上用于进程通信的系统调用具体形式,然后使用该系统调用编写程序进行进程间的通信,要求程序运行结果可以直观地体现在界面上。
在此基础上查找所选用操作系统平台上支持信号量机制的系统调用具体形式,运用生产者与消费者模型设计实现一个简单的信箱,该信箱需要有创建、发信、收信、撤销等函数,至少能够支持两个进程互相交换信息,比较自己实现的信箱与操作系统本身提供的信箱,分析两者之间存在的异同。
实验背景介绍进程间通信有如下目的:数据的传输,共享数据,通知事情,资源共享,进程控制。
进程间的通信机制(IPC),就是多进程相互通信,交换信息的方法。
Linux IPC机制包括,信号和管道是其中的两个,还支持传统的UNIX SYSTM-V 的IPC 机制。
信号主要用来通知进程异步事情的发生,最初信号设计的目的是为了处理错误,他们也用来作为最基本的IPC机制。
管道是单向的,先进先出,先入先出,无结构的,固定大小的数据流。
UNIX System V 机制中的三种进程间通信机制,它们是:消息队列:用于进程之间传递分类的格式化数据信号量:用于通信之间的同步控制。
信号量通常与共享存储器方式一起使用。
共享内存:使不同进程通过共享彼此的虚拟空间而达到相互对共享区操作和数据通信。
它们之间有一个共同的特点,就是它们使用相同的认证方法,一个进程只有通过系统调用想内核传递一个唯一的引用标识符才能访问这些资源。
实验环境: ubuntu linux 操作系统实验原理分析:进程A 和进程B 共享内存C和D,并通过用P,V原理来控制它们对共享内存的读写。
共享内存通过PV控制读写。
信号量S0,S1,S2,S3 其中S0,S1控制C,S2,S3控制D。
其中S0表示内存中有几个信息,S1表示内存还可以存几个信息。
同理可得S2,S3.PV 简略图:进程A:发送信息......P(S1)Send ()V(S0)……接受消息……P(S2)Receive()V(S3)…….. 进程B:发送信息......P(S3)Send ()V(S2)……接受消息……P(S0)Receive()V(S1)……..函数调用分析:共享内存的创建,读,写,删除相当于信箱的创建,收信,发信,撤销等。
共享内存区域是被多个进程共享的一部分物理内存,进程可以把这些区域映射到它们地址空间的任一适合的虚拟地址范围。
这些地址范围对每一个进程来说都是不同的,映射后这些区域就可以像任何其他内存位置那样被访问,而不需要对它们使用读写调用。
进程向共享内存中写入数据,那么这个区域的所有进程可以立即看见共享区的新内容。
shmget(key_t key, size_t size, int shmflg);key标识共享内存的键值: 0/IPC_PRIVATE。
当key的取值为IPC_PRIVATE,则函数shmget()将创建一块新的共享内存;如果key的取值为0,而参数shmflg中设置了IPC_PRIVATE这个标志,则同样将创建一块新的共享内存。
size是要建立共享内存的长度。
shmflg主要和一些标志有关。
其中有效的包括IPC_CREAT和IPC_EXCL,它们的功能与open()的O_CREAT和O_EXCL相当。
IPC_CREAT 如果共享内存不存在,则创建一个共享内存,否则打开操作。
IPC_EXCL 只有在共享内存不存在的时候,新的共享内存才建立,否则就产生错误。
成功返回共享内存的标识符;不成功返回-1,errno储存错误原因。
例如:shmid=shmget(SHMKEY,256,IPC_CREAT|0600);创建了一个key=SHMKEY,大小为256的共享内存。
并把值给了shmid.shmat( int shmid , char *shmaddr , int shmflag );shmat()是用来允许本进程访问一块共享内存的函数。
int shmid是那块共享内存的ID。
char *shmaddr是共享内存的起始地址int shmflag是本进程对该内存的操作模式。
如果是SHM_RDONLY的话,就是只读模式。
其它的是读写模式成功时,这个函数返回共享内存的起始地址。
失败时返回-1例如:addr=(char *) shmat(shmid,NULL,0);内存地址映射把id为shmid共享内存的首地址给了addr,因此我们可以通过addr来访问共享内存,相当于,我们知道了数组的首地址,然后在对数组进行操作一样。
shmdt(Shared Memory Detach)函数与该共享内存块脱离。
将由shmat 函数返回的地址传递给这个函数。
成功共时返回0,不成功返回1,注意共享内存并未删除它,只是使该共享进程当前,进程不再可用。
如果当释放这个内存块的进程是最后一个使用该内存块的进程,则这个内存块将被删除。
例如:shmdt(addr);我们有了共享内存的首地址之后,对共享内存的读写就相当于对一个数组的读写。
写:strcpy(addr,"linux"); 就把linux字符放进了共享内存。
读:printf(“%s\n”,addr);综上所得,我们就很容易理解共享内存的一些操作;例:pid=shmget(Key,buffersize,IPC_CREAT|0600);//创建共享内存char *addr;addr=(char *)shmat(pid,NULL,0);//映射首地址strcpy(addr," This is the message which the parent have sent!");//写共享内存shmdt(addr);//释放共享内存信号量:是为了控制进程对资源的使用而发明的。
信号量是具有整数值的对象,它的工作原理如下;它支持两种原子操作P和V,P操作减少信号量的值,如果某一个信号量的值小于0,则操作阻塞,V操作增加信号量的值,如果结果值大于或等于0,V操作就要唤醒一个等待进程。
想要获得资源时使用P操作,每次请求成功,它都要减少信号量的值,信号量的值减至0时,下一个P操作将被阻塞,释放资源的时候使用V操作,它增加信号量的值,同时唤醒被阻塞的进程。
semget( semkey, count, flag);其中semkey 和flag 类似于建立消息和共享存储区域,semkey是用户指定的关键字,count 是指定信号量数组的长度。
Semid=(senkey ,4,0777|IPC_CREAT);创建了一个关键字为semkey的含有4个元素的信号量数组。
注意信号量数组序号是从0才是编址。
`semop(semid, struct sembuf semoparray[], size_t nops );函数中参数semid是一个通过semget函数返回的一个信号量标识符,参数nops标明了参数semoparray所指向数组中的元素个数。
参数semoparray 是一个struct sembuf结构类型的数组指针,结构sembuf来说明所要执行的操作,其定义如下:struct sembuf{unsigned short sem_num; //信号量集中的某一个信号量short sem_op; // sem_op指明所要执行的操作(1表示V操作,-1表示P操作)short sem_flg;}例:Int P(int semid){struct sembuf p;P.sem_num=1;/对第二个信号量; P.sem_op=-1;//p操作;P.sem_flag=SEM_UNDO;semop(semid,&p,1);} Int V(int semid){struct sembuf p;P.sem_num=2;//对第三个信号量; P.sem_op=1;//V操作;P.sem_flag=SEM_UNDO;semop(semid,&p,1);}对信号量进行控制semctl(int semid,int num,int cmd,union arg);系统调用semctl()的semid参数是关键字值。
第二个参数是信号量数目。
参数cmd中可以使用的命令中SETVAL设置信号量集中的一个单独的信号量的值。
返回值:如果成功,则为一个正数。
如果失败,则为-1 union semun {int val;struct semid_ds *buf;unsigned short *array;} sem;sem.val=0;//设置初值为0;semctl(sem_id,0,SETVAL,sem);//对第一个信号量设置初值为0;综上所得涉及到我们需要了全部调用函数,只要将这些函数合理的组合在一起,就得到了我们想要的实验效果了。
实验调试过程:创建共享内存和信号量以及初始状态A发送信息到共享内存C,相当于A给B发送邮件B从共享内存C中读取信息,相当于接受了邮件并查看了同理可得实验扩展:由实验的PV控制可知,当进程A的发送信息被挂起时,下面的进程B 收信息也被挂起时。
不符合常理,若调用了fork()函数,进程A又分为父进程和子进程与题意不符。
故可引进线程,线程1为收信息,线程2为发信息。
调用函数:int pthread_creat(pthread_t *thread, pthread_attr_t *attr,void *(*start_routine)(void*),void *arg);//创建线程void pthread_exit(void * retval);//结束线程int pthread_join(pthread_t th,void ** thread_return) //线程挂起附:mailA代码。