实验三、进程通信(一) ——管道及共享内存
操作系统实验三进程的管道通信

实验三进程的管道通信一、实验目的:(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_ 进程管理实验

电大操作系统实验报告3_ 进程管理实验电大操作系统实验报告 3 进程管理实验一、实验目的进程管理是操作系统的核心功能之一,本次实验的目的是通过实际操作和观察,深入理解进程的概念、状态转换、进程调度以及进程间的通信机制,掌握操作系统中进程管理的基本原理和方法,提高对操作系统的整体认识和实践能力。
二、实验环境本次实验使用的操作系统为 Windows 10,编程语言为 C 语言,开发工具为 Visual Studio 2019。
三、实验内容及步骤(一)进程的创建与终止1、编写一个 C 程序,使用系统调用创建一个子进程。
2、在父进程和子进程中分别输出各自的进程 ID 和父进程 ID。
3、子进程执行一段简单的计算任务,父进程等待子进程结束后输出结束信息。
以下是实现上述功能的 C 程序代码:```cinclude <stdioh>include <stdlibh>include <unistdh>int main(){pid_t pid;pid = fork();if (pid < 0) {printf("创建子进程失败\n");return 1;} else if (pid == 0) {printf("子进程:我的进程 ID 是%d,父进程 ID 是%d\n",getpid(), getppid());int result = 2 + 3;printf("子进程计算结果:2 + 3 =%d\n", result);exit(0);} else {printf("父进程:我的进程 ID 是%d,子进程 ID 是%d\n",getpid(), pid);wait(NULL);printf("子进程已结束\n");}return 0;}```编译并运行上述程序,可以观察到父进程和子进程的输出信息,验证了进程的创建和终止过程。
(二)进程的状态转换1、编写一个 C 程序,创建一个子进程,子进程进入睡眠状态一段时间,然后被唤醒并输出状态转换信息。
进程实验-进程间通信(管道、消息、共享内存、软中断)

进程实验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)

实验三线程控制和进程间通信一、实验目的通过Linux管道通信机制、消息队列通信机制的使用,加深对不同类型的进程通信方式的理解。
二、实验内容:1.熟悉Linux的管道通信机制2.熟悉Linux的消息队列通信机制三、思考1.有名管道和无名管道之间有什么不同?2.管道的读写与文件的读写有什么异同?3.Linux消息队列通信机制中与教材中的消息缓冲队列通信机制存在哪些异同?四、实验指导<一>Linux管道通信机制管道是所有UNIX都提供的一种进程间通信机制,它是进程之间的一个单向数据流,一个进程可向管道写入数据,另一个进程则可以从管道中读取数据,从而达到进程通信的目的。
1.无名管道无名管道通过pipe()系统调用创建,它具有如下特点:(1)它只能用于具有亲缘关系的进程(如父子进程或者兄弟进程)之间的通信。
(2)管道是半双工的,具有固定的读端和写端。
虽然pipe()系统调用返回了两个文件描述符,但每个进程在使用一个文件描述符之前仍需先将另一个文件描述符关闭。
如果需要双向的数据流,则必须通过两次pipe()建立起两个管道。
(3)管道可以看成是一种特殊的文件,对管道的读写与文件的读写一样使用普通的read、write等函数,但它不是普通的文件,也不属于任何文件系统,而只存在于内存中。
2.pipe系统调用(1)函数原型#include <unistd.h>int pipe(int filedes[2]);(2)参数filedes参数是一个输出参数,它返回两个文件描述符,其中filedes[0]指向管道的读端,filedes[1]指向管道的写端。
(3)功能pipe在内存缓冲区中创建一个管道,并将读写该管道的一对文件描述符保存在filedes所指的数组中,其中filedes[0]用于读管道,filedes[1]用于写管道。
(4)返回值成功返回0;失败返回-1,并在error中存入错误码。
(5)错误代码EMFILE:进程使用的文件描述符过多ENFILE :系统文件表已满EFAULT :非法参数filedes3.无名管道的阻塞型读写管道缓冲区有4096B的长度限制,因此,采用阻塞型读写方式时,当管道已经写满时,写进程必须等待,直到读进程取走信息为止。
实验三进程通讯实验报告

实验三进程通讯实验报告实验三进程通讯实验报告【姓名】【学号】【实验题目】进程通讯——消息队列与共享存储区【实验目的】(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篇)

第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. 管道:管道是一种基于文件描述符的通信方式,可以在父子进程之间或者兄弟进程之间传递数据。
管道有两种类型:有名管道和无名管道。
有名管道可以在不同的进程之间共享,而无名管道只能在具有亲缘关系的进程之间使用。
2. 共享内存:共享内存是指将一块内存空间映射到多个进程的地址空间中,这样多个进程就可以直接访问同一块内存数据。
共享内存的优点是速度快、数据共享直接,但同时也存在一些问题,如同步和互斥等。
3. 信号量:信号量是一种基于计数器的同步机制,用于进程之间的协调。
进程可以通过信号量来控制共享资源的访问,从而避免竞争条件和死锁等问题。
信号量通常需要与其他通信方式一起使用,如共享内存。
4. 消息队列:消息队列是一种先进先出的数据结构,可以在不同的进程之间传递消息。
进程可以将消息放入队列中,另一个进程可以从队列中读取这些消息。
消息队列的优点是可靠性高、数据传输有序,但同时也存在一些问题,如消息的格式和大小限制等。
总的来说,不同的进程间通信方式各有优缺点,我们需要根据
具体的需求和场景来选择最适合的通信方式。
实现进程间通信的实验原理

实现进程间通信的实验原理进程间通信(Inter-Process Communication,IPC)是指在操作系统中,不同的进程之间进行数据交换和共享的一种机制。
常见的进程间通信的方法有:1. 管道(Pipe):管道是一种半双工的通信机制,它可以实现父子进程之间的通信。
通常由操作系统创建,父进程创建一个管道后,可以通过fork系统调用创建子进程,从而共享管道。
子进程可以通过管道进行写入一端,父进程可以通过管道进行读取。
2. 命名管道(Named Pipe):命名管道也是一种管道,但它允许不相关的进程之间进行通信。
命名管道被创建时,通过指定一个路径名,从而使不同进程能够通过路径名来访问同一管道。
3. 信号量(Semaphore):信号量是一种计数器,用于控制多个进程对共享资源的访问。
进程可以通过特定的操作(比如P操作和V操作)来对信号量进行增加或减少操作。
同一时刻只允许一个进程对信号量进行P操作,其他进程需要等待。
4. 共享内存(Shared Memory):共享内存是一种进程之间共享数据的方式,它在物理内存中创建一块共享区域,多个进程可以将这块内存映射到各自的虚拟地址空间中。
进程可以直接读写共享内存,而无需进行数据拷贝。
5. 消息队列(Message Queue):消息队列是一种可以实现不同进程之间通过消息进行通信的机制。
进程可以通过特定的操作将消息发送到消息队列中,其他进程可以从消息队列中读取消息。
6. 套接字(Socket):套接字是一种网络编程中常用的进程间通信方式。
它可以在不同主机上的进程之间进行通信。
进程可以通过套接字进行网络数据的读取和写入。
以上是常见的几种进程间通信的方法,每种方法都有自己的优势和适用场景。
根据具体的需求,可以选择适合的方式进行进程间通信。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
(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秒后,在此显示共享内存段中的内容(此时已经是小写字母)。
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);
{
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");
pipe(fd);
pipe(fe);
printf("please input a line of char");
scanf("%s",buf);
while((x=fork())==-1);
if(x==0)
{
close(fd[0]);
close(fe[1]);
printf("Child Process!\n");
实验代码:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHMKEY 208 /*在实际实验过程中,为了避免每个同学建立的共享存储区关键字一样而相互干扰,关键字请用学号末3位*/
#define K 1024
操作系统实验报告
实验三、进程通信(一)
——管道及共享内存
一、实验目的
1)加深对管道通信的了解
2)掌握利用管道进行通信的程序设计
3)了解共享内存通信的程序设计方法
4)了解和熟悉Linux支持的共享存储区机制
二、实验内容
任务一、
(1)阅读以上父子进程利用管道进行通信的例子(例1),写出程序的运行结果并分析。
exit ();
}
运行结果:
分析:
首先系统通过调用shmctl对shmid指向的内存段进行删除操作,接着系统调用shmget创建一个16*1024字节的共享内存段,成功返回共享内存段的标识符给shmid,系统再次调用shmat连接内存段,返回该共享内存段连接到调用进程地址空间上的地址addr。
实验代码:
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
实验代码:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
main()
{
key_t key=208; /*在实际实验过程中,为了避免每个同学建立的共享存储区关键字一样而相互干扰,关键字请用学号末3位*/
int shmid_1,shmid_2;
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;
exit ();
}
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHMKEY 208 /*在实际实验过程中,为了避免每个同学建立的共享存储区关键字一样而相互干扰,关键字请用学号末3位*/
#define K 1024
perror("shmget shmid_2");exit(2);
}
printf("Second shared memory identifier is %d\n",shmid_2);
exit(0);
}
运行结果:
Ipcs查看:
再次运行:
再次用ipcs查看:
Ipcrm删除
分析:
成功,返回共享内存段的标识符,内核中用于唯一的标识一个对象。对存在于内核存贮空间中的每个共享内存段,内核均为其维护着一个数据结构shmid_ds。
int shmid;
main ()
{
int i;
char *pint;
char *addr;
extern char * shmat ();
shmid=shmget(SHMKEY,8*K,0777);/*取共享区SHMKEY的id */
read(fd[0],s,30);
printf("%s\n",s);
}
}
运行结果:
分析:
调用pipe(fd);创建一个管道后,接着调用fork()函数产生两个进程,首先开始执行子进程,关闭管道出口,通过管道入口向管道中写入内容。执行if语句后,进入else语句块内开始父进程,管道入口关闭,通过管道出口端从管道中读取之前写入内容,最后输出出来
对两次的结果进行比较:两次运行结束后的第二个共享标识符是不一样的。在用ipcs查看时,共享内存段中的关键字,共享内存标识符,访问权限,字节等都是不一样的。
(4)每个同学登陆两个窗口,先在一个窗口中运行例3程序1(或者只登陆一个窗口,先在该窗口中以后台方式运行程序1),然后在另一个窗口中运行例3程序2,观察程序的运行结果并分析。运行结束后可以用ctrl+c结束程序1的运行。
需要指出的是,共享存储区机制只为通信进程提供了访问共享存储区的操作条件,而对通信的同步控制则要依靠信号量机制等才能完成。
(5)编写程序:使用系统调用shmget(),shmat(),shmdt(),shmctl(),编制程序。要求在父进程中生成一个30字节长的私有共享内存段。接下来,设置一个指向共享内存段的字符指针,将一串大写字母写入到该指针指向的存贮区。调用fork()生成子进程,让子进程显示共享内存段中的内容。接着,将大写字母改成小写,子进程修改共享内存中的内容。之后,子进程将脱接共享内存段并退出。父进程在睡眠5秒后,在此显示共享内存段中的内容(此时已经是小写字母)。
int shmid;
main ()
{
int i,*pint;