实验三,进程通信管道及其共享内存

合集下载

实验3 进程的管道通信实验

实验3 进程的管道通信实验

父进程和子进程间管道通信示例
• 例1:用C语言编写一个程序,建立一个 pipe,同时父进程生成一个子进程,子进向 pipe中写入一字符串,父进程从pipe中读出 该字符串。
程序
# include <stdio.h> main() { int x, fd[2]; char buf[30],s[30]; pipe(fd); /*创建管道*/ while((x=fork()) = = -1); /*创建子进程失败时,循环*/ if(x = = 0) { sprintf(buf, ”This is an example\n”); write(fd[1],buf,30); /*把buf中字符写入管道*/ exit(0); } else { wait(0); read(fd[0],s,30); /*父进程读管道中字符*/ printf(“%s”,s); } }
管道的实现原理(1)
• 利用linux提供的系统调用pipe,可建立一 条同步通信管道。其格式为: pipe(fd) int fd[2]; • fd[ห้องสมุดไป่ตู้]为写入端,fd[0]为读出端。
管道的实现原理(2)
• 通过文件系统的系统调用write和read进行管 道的写和读;
– 管道按FIFO(先进先出)方式传送消息 – 只能单向传送消息,进程间双向通信,通常需要 两个管道; – 只适用于父子进程之间或父进程安排的各个子进 程之间。
实验3 进程的管道通信实验
实验目的
• 1、了解什么是管道 • 2、熟悉UNIX/LINUX支持的管道通信 方式
实验内容
• 编写程序实现进程的管道通信。用系统调 用pipe( )建立一管道,二个子进程P1和P2 分别向管道各写一句话: Child 1 is sending a message! Child 2 is sending a message! 父进程从管道中读出二个来自子进程的信 息并显示(要求先接收P1,后P2)。

操作系统进程通信(信号,共享存储区,消息队列)

操作系统进程通信(信号,共享存储区,消息队列)
7/7
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;

操作系统实验三进程的管道通信

操作系统实验三进程的管道通信

实验三进程的管道通信一、实验目的:(1)加深对进程概念的理解,明确进程和程序的区别;(2)学习进程创建的过程,进一步认识并发执行的实质;(3)分析进程争用资源的现象,学习解决进程互斥的方法;(4)学习解决进程同步的方法;(5)掌握Linux系统进程间通过管道通信的具体实现方法。

二、实验内容及要求:(1)使用系统调用pipe()建立一条管道线,两个子进程分别向管道写一句话(写的内容自己定,但要有该进程的一些信息);(2)父进程从管道中读出来自两个子进程的消息,显示在屏幕上;(3)要求:父进程首先接收子进程p1发来的消息,然后再接收子进程p2发来的消息;(4)两个子进程要并发执行;(5)实现管道的互斥使用。

当一个子进程正在对管道进行写操作时,另一个欲写入管道的子进程必须等待。

使用系统调用lockf(fd[1],1,0)实现对管道的加锁操作,用lockf(fd[1],0,0)解除对管道的锁定;(6)实现父子进程的同步,当父进程试图从一空管道中读取数据时,便进入等待状态,直到子进程将数据写入管道返回后,才将其唤醒。

三、实现:相关的系统调用fork() 用于创一个子进程。

格式:int fork();返回值:在子进程中返回0;在父进程中返回所创建的子进程的ID值;当返回-1时,创建失败。

wait() 常用来控制父进程与子进程的同步。

在父进程中调用wait(),则父进程被阻塞,进入等待队列,等待子进程结束。

当子进程结束时,父进程从wait()返回继续执行原来的程序。

返回值:大于0时,为子进程的ID值;等于-1时,调用失败。

exit() 是进程结束时最常调用的。

格式:void exit( int status); 其中,status为进程结束状态。

pipe() 用于创建一个管道格式:pipe(int fd);其中fd是一个由两个数组元素fd[0]和fd[1]组成的整型数组,fd[0]是管道的读端口,用于从管道读出数据,fd[1]是管道的写端口,用于向管道写入数据。

进程实验-进程间通信(管道、消息、共享内存、软中断)

进程实验-进程间通信(管道、消息、共享内存、软中断)

进程实验3 Linux 进程间通信一、软中断信号的处理,实现同一用户的各进程之间的通信。

●相关的系统调用⏹kill(pid ,sig):发送信号⏹signal(sig, func):指定进程对信号sig的处理行为是调用函数func。

●程序清单#include <unistd.h>#include <stdio.h>#include <signal.h>void waiting();void stop();int wait_mark;main(){int p1,p2;while((p1=fork())==-1);if(p1>0){while((p2=fork())==-1);if(p2>0){ printf("parent\n");/*父进程在此完成某个操作、或接收到用户从键盘输入的特殊按键命令后发出下面的信号。

这里省略。

*/kill(p1,16);kill(p2,17);wait(0);wait(0);printf("parent process id killed! \n");exit(0);}else/* p2==0*/{printf("p2\n");wait_mark=1;signal(17,stop);waiting();printf("child process 2 is killed by parent! \n");exit(0);}}else/*p1==0*/{printf("p1\n");wait_mark=1;signal(16,stop);waiting();printf("child process 1 is kelled by parent! \n");exit(0);}}void waiting(){while(wait_mark!=0);}void stop(){wait_mark=0;}●输入并运行此程序,分析程序的运行结果。

操作系统进程通信报告

操作系统进程通信报告

实验四:进程同步实验一、实验任务: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)阅读以上父子进程利用管道进行通信的例子(例1),写出程序的运行结果并分析
实验代码:
#include<stdio.h>
main()
{ int x,fd[2];
char buf[30],s[30];
pipe(fd);
while ((x=fork())==-1);
if (x==0)
}
write(fe[1],s,30);
wait(0);
}
运行结果:
(3)阅读例2的程序,运行一次该程序,然后用ipcs命令查看系统中共享存储区的情况,再次执行该程序,再用ipcs命令查看系统中共享内存的情况,对两次的结果进行比较,并分析原因。最后用ipcrm命令删除自己建立的共享存储区。(有关ipcs和ipcrm介绍见后面一页)
addr=shmat(shmid,0,0);/*挂接,并得到共享区首地址*/
printf ("addr 0x%x\n",addr);
pint=(char *)addr;
for (i='a';i<='e';i++) *pint++=i;
pause();/*等待接收进程读*/
}
cleanup()
{
shmctl(shmid,IPC_RMID,0);
(2)每个同学登陆两个窗口,先在一个窗口中运行例3程序1(或者只登陆一个窗口,先在该窗口中以后台方式运行程序1),然后在另一个窗口中运行例3程序2,观察程序的运行结果并分析。运行结束后可以用ctrl+c结束程序1的运行。
(3)编写程序:使用系统调用shmget(),shmat(),shmdt(),shmctl(),编制程序。要求在父进程中生成一个30字节长的私有共享内存段。接下来,设置一个指向共享内存段的字符指针,将一串大写字母写入到该指针指向的存贮区。调用fork()生成子进程,让子进程显示共享内存段中的内容。接着,将大写字母改成小写,子进程修改共享内存中的内容。之后,子进程将脱接共享内存段并退出。父进程在睡眠5秒后,在此显示共享内存段中的内容(此时已经是小写字母)。

实验三进程通讯实验报告

实验三进程通讯实验报告

实验三进程通讯实验报告实验三进程通讯实验报告【姓名】【学号】【实验题目】进程通讯——消息队列与共享存储区【实验目的】(1)掌握进程间通讯的编程方法;(2)加深对进程并发执行的理解;(3)学习利用消息队列与共享存储区实现进程通信的方法。

【实验内容】设计一个多进程并发运行的程序,它由不同的进程完成下列工作:(1)接收键盘输入进程负责接收用户的键盘输入,并以适当的方式将由键盘获得的数据交给其它进程处理。

(2)显示进程负责全部数据显示任务,包括键盘输入数据的显示与提示信息的显示。

(3)分发数据进程将键盘输入的数据分为3类,即字母、数字与其它,并分别将字母写入文件letter、txt中,数字写入文件number、txt中,除字母与数字外其它数据丢弃。

【实验要求】1、程序能以适当的方式提示用户输入数据;2、提示用户有数据被丢弃;3、全部的显示任务必须由显示进程完成;4、整个程序能够连续处理多组输入数据,直到用户输入“quit”字符串,整个程序结束;5、进一步要求:同时采用共享存储区与消息2种方法实现进程之间的通信,并比较这2种通信方法的利弊。

【实验方法】1、利用fork()函数创建2个子进程,用一个父进程与两个子进程完成上面的三个实验任务,用子进程1实现分发数据任务,子进程2实现接受键盘输入任务,父进程实现全部的显示任务。

2、同时通过共享存储区与消息队列两种进程通讯方式实现上面三个进程之间的同步与互斥。

3、利用while()循环、kill()函数与signal()函数实现连续多组数据输入。

【程序结构】·数据结构:消息队列、字符数组;·程序结构:顺序结构、if-else分支结构与while循环结构;·主要算法:无特别算法【实验结果】1、有代表性的执行结果:[stud13@localhost stud13]$ cc ipc、c[stud13@localhost stud13]$ 、/a、outPlease input a line:∟operatingsystem01234-=,、Your message is:operatingsystem01234-=,、The characters deserted are:-=,、Please input a line:∟xushengju6651001!@#$%^&*()Your message is:xushengju6651001!@#$%^&*()The characters deserted are:!@#$%^&*()Please input a line:∟Hello123Your message is:Hello123Please input a line:∟quit[stud13@localhost stud13]$ cat letter、txtOperatingsystemxushengjuHello[stud13@localhoststud13]$ cat number、txt1123[stud13@localhost stud13]$2、结果分析及解释:在创建子进程1时,由于先返回子进程的ID 号,msgrcv(msgid,&msg,BUFSIZE,0,0)一直都就是非0值,故循环等待。

进程通讯管理实验报告(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()函数删除消息队列。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
int shmid;
main()
{
int i;
char *pint;
char *addr;
extern char * shmat ();
extern cleanup ();
for(i=0;i<20;i++) signal(i,cleanup);
shmid=shmget(SHMKEY,16*K,0777|IPC_CREAT); /*建立16K共享区SHMKEY */
printf("Parent Process!\n");
printf("%s\n",s);
count-=2;
for(left=0,right=count;left<=count/2;left++,right--){
temp=s[left];
s[left]=s[right];
s[right]=temp;
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHMKEY 208 /*在实际实验过程中,为了避免每个同学建立的共享存储区关键字一样而相互干扰,关键字请用学号末3位*/
#define K 1024
int shmid;
对两次的结果进行比较:两次运行结束后的第二个共享标识符是不一样的。在用ipcs查看时,共享内存段中的关键字,共享内存标识符,访问权限,字节等都是不一样的。
(4)每个同学登陆两个窗口,先在一个窗口中运行例3程序1(或者只登陆一个窗口,先在该窗口中以后台方式运行程序1),然后在另一个窗口中运行例3程序2,观察程序的运行结果并分析。运行结束后可以用ctrl+c结束程序1的运行。
for (i=0;i<256;i++)
printfΒιβλιοθήκη "%d\n",*pint++);/*打印共享区中的内容*/
}
运行结果:
分析:
例3_1程序后台运行时,该程序开始执行,系统调用shmget创建一个8*1024字节的共享内存段,再通过调用shmat挂接内存段,由系统选择挂接地址,最终输出转换后的挂接地址。
if ((shmid_1=shmget(key,1000,0644|IPC_CREAT))==-1){
perror("shmget shmid_1");exit(1);
}
printf("First shared memory identifier is %d\n",shmid_1);
if ((shmid_2=shmget(IPC_PRIVATE,20,0644))==-1){
main ()
{
int i,*pint;
char *addr;
extern char * shmat ();
shmid=shmget(SHMKEY,8*K,0777);/*取共享区SHMKEY的id */
addr=shmat(shmid,0,0);/*连接共享区*/
pint=(int *)addr;
}
write(fe[1],s,30);
wait(0);
}
运行结果:
(3)阅读例2的程序,运行一次该程序,然后用ipcs命令查看系统中共享存储区的情况,再次执行该程序,再用ipcs命令查看系统中共享内存的情况,对两次的结果进行比较,并分析原因。最后用ipcrm命令删除自己建立的共享存储区。(有关ipcs和ipcrm介绍见后面一页)
(2)每个同学登陆两个窗口,先在一个窗口中运行例3程序1(或者只登陆一个窗口,先在该窗口中以后台方式运行程序1),然后在另一个窗口中运行例3程序2,观察程序的运行结果并分析。运行结束后可以用ctrl+c结束程序1的运行。
(3)编写程序:使用系统调用shmget(),shmat(),shmdt(),shmctl(),编制程序。要求在父进程中生成一个30字节长的私有共享内存段。接下来,设置一个指向共享内存段的字符指针,将一串大写字母写入到该指针指向的存贮区。调用fork()生成子进程,让子进程显示共享内存段中的内容。接着,将大写字母改成小写,子进程修改共享内存中的内容。之后,子进程将脱接共享内存段并退出。父进程在睡眠5秒后,在此显示共享内存段中的内容(此时已经是小写字母)。
perror("shmget shmid_2");exit(2);
}
printf("Second shared memory identifier is %d\n",shmid_2);
exit(0);
}
运行结果:
Ipcs查看:
再次运行:
再次用ipcs查看:
Ipcrm删除
分析:
成功,返回共享内存段的标识符,内核中用于唯一的标识一个对象。对存在于内核存贮空间中的每个共享内存段,内核均为其维护着一个数据结构shmid_ds。
addr=shmat(shmid,0,0);/*挂接,并得到共享区首地址*/
printf ("addr 0x%x\n",addr);
pint=(char *)addr;
for (i='a';i<='e';i++) *pint++=i;
pause();/*等待接收进程读*/
}
cleanup()
{
shmctl(shmid,IPC_RMID,0);
addr=shmat(shmid,0,0);/*挂接,并得到共享区首地址*/
printf ("addr 0x%x\n",addr);
pint=(int *)addr;
for (i=0;i<256;i++) *pint++=i;
pause();/*等待接收进程读*/
}
cleanup()
{
shmctl(shmid,IPC_RMID,0);
exit ();
}
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHMKEY 208 /*在实际实验过程中,为了避免每个同学建立的共享存储区关键字一样而相互干扰,关键字请用学号末3位*/
#define K 1024
int shmid;
main ()
{
int i,*pint;
char *addr;
extern char * shmat ();
extern cleanup ();
for(i=0;i<20;i++) signal(i,cleanup);
shmid=shmget(SHMKEY,16*K,0777|IPC_CREAT); /*建立16K共享区SHMKEY */
{
close(fd[0]);
printf("Child Process!\n");
strcpy(buf,"This is an example\n");
write(fd[1],buf,30);
exit(0);
}
else{
close(fd[1]);
printf("Parent Process!\n");
需要指出的是,共享存储区机制只为通信进程提供了访问共享存储区的操作条件,而对通信的同步控制则要依靠信号量机制等才能完成。
(5)编写程序:使用系统调用shmget(),shmat(),shmdt(),shmctl(),编制程序。要求在父进程中生成一个30字节长的私有共享内存段。接下来,设置一个指向共享内存段的字符指针,将一串大写字母写入到该指针指向的存贮区。调用fork()生成子进程,让子进程显示共享内存段中的内容。接着,将大写字母改成小写,子进程修改共享内存中的内容。之后,子进程将脱接共享内存段并退出。父进程在睡眠5秒后,在此显示共享内存段中的内容(此时已经是小写字母)。
失败,返回-1,设置errno。
①第一个参数key(键值)用来创建IPC标识符,shmget()返回的标识符与key值一一对应,不同的key值返回不同的标识符。
②第二个参数size,决定了共享内存段的大小(若访问已存在的内存段,该参数可设为0)。有最大字节数的限制
③第三个参数shmflag,用于设置访问权限及标识创建条件。
int shmid;
main ()
{
int i;
char *pint;
char *addr;
extern char * shmat ();
shmid=shmget(SHMKEY,8*K,0777);/*取共享区SHMKEY的id */
操作系统实验报告
实验三、进程通信(一)
——管道及共享内存
一、实验目的
1)加深对管道通信的了解
2)掌握利用管道进行通信的程序设计
3)了解共享内存通信的程序设计方法
4)了解和熟悉Linux支持的共享存储区机制
二、实验内容
任务一、
(1)阅读以上父子进程利用管道进行通信的例子(例1),写出程序的运行结果并分析。
(2)编写程序:父进程利用管道将一字符串交给子进程处理。子进程读字符串,将里面的字符反向后再交给父进程,父进程最后读取并打印反向的字符串。
任务二、
(1)阅读例2的程序,运行一次该程序,然后用ipcs命令查看系统中共享存储区的情况,再次执行该程序,再用ipcs命令查看系统中共享内存的情况,对两次的结果进行比较,并分析原因。最后用ipcrm命令删除自己建立的共享存储区。(有关ipcs和ipcrm介绍见后面一页)
相关文档
最新文档