实验八 进程通信应用
进程间通信的方式及应用场景
进程间通信的⽅式及应⽤场景开头 每个进程的⽤户地址空间都是独⽴的,进程与进程之间,内部空间是隔离的,进程 A 不可能直接使⽤进程 B 的变量名的形式得到进程B 中变量的值。
但内核空间是每个进程都共享的,所以进程之间要通信必须通过内核。
实现进程与进程之间的通信,常⽤的⽅式主要有:管道、消息队列、共享内存、信号量、信号、socket等等。
⼀、管道 在 Linux 命令中,常见的“|”符号就是⼀种管道。
⽐如:ps auxf | grep mysql 上⾯的命令中,“|”的功能是将前⼀个命令(ps auxf)的输出,作为后⼀个命令(grep mysql)的输⼊。
这种管道没有名字,匿名管道,⽤完就销毁。
命名管道也被叫做 FIFO,因为数据的传输⽅式是先进先出(first in first out)。
管道传输数据是单向的,如果想相互通信,需要创建两个管道才⾏。
管道创建、写⼊、读取创建mkfifo myPipe myPipe 是新创建的管道的名称,基于 Linux ⼀切皆⽂件的理念,管道也是以⽂件的⽅式存在,可以⽤ ls 看到⽂件类型是 p,也就是pipe(管道)的意思:$ ls -lprw-r--r--. 1 root root 0 Jul 1702:45 myPipeecho "hello" > myPipe # 将数据写进管道。
程序会阻塞,只有当管道⾥的数据被读完后,程序才会正常继续。
管道写⼊数据cat < myPipe # 读取管道⾥的数据# hello管道读取数据管道的优缺点 缺点:管道的通信⽅式效率低,不适合进程间频繁地交换数据。
优点:简单。
⼆、消息队列 前⾯说到管道的通信⽅式效率很低,因此管道不适合进程间频繁地交换数据。
对于这个问题,消息队列可以解决。
⽐如,A 进程要给 B 进程发送消息,A 进程将数据存⼊消息队列,B 进程只需要读取数据即可。
反之亦如此。
消息队列的本质是保存在内核中的⼀种消息链表,在发送数据时,会分成独⽴的数据单元,也就是消息体(数据块)。
操作系统实验 进程与进程通信
计算机工程学院实验报告课程名称:操作系统实验班级实验成绩:指导教师:姓名:实验项目名称:进程与进程通信学号:上机实践日期:2009-11-13实验项目编号:实验二组号:上机实践时间:2学时一、目的1、深刻理解进程和线程的概念;2、掌握线程和进程的差别以及与之相适应的通信方式;3、掌握在Linux环境下创建进程: fork()的应用;4、了解用fork()创建进程、以及整个程序的运行过程;5、掌握多进程的程序设计与进程之间通信的方法;6、掌握共享内存、信号灯集实现进程通信的方法;7、理解、掌握Linux下文件系统,以及其安装与卸载过程。
二、实验内容1、在Linux环境下,用fork()创建多个进程,分别运行不同的函数;2、一部分进程代表读者,一部分进程代表写者;用共享内存、信号灯集机制实现各个读者、写者进程之间的通信;3、掌握shmget()、shmat()、shmctl()以及semget()、semctl()、semop()等函数在进程通信中的使用方法;4、用信号灯加PV操作实现进程间的互斥与同步。
三、实验环境1、操作系统:Red Hat Linux四、实验原理1、枚举数据类型,在信号灯集初始化时使用。
该结构在sys/sem.h中没有定义,必须程序设计者自行定义。
其中:semid—已经创建的信号灯集ID,sn—操作的元素的IDunion semun{int val;struct semid_ds *buf;ushort *array;};2、对信号灯集中的某个元素进行P操作。
首先要定义一个sembuf 类型的变量(该类型已经在sys/sem.h中预定义,可以直接引用),然后对该变量的各个元素进行赋值,注意进行P操作,主要是sem_op元素赋值为 -1。
其中:semid—已经创建的信号灯集ID,sn—操作的元素的IDvoid down(int semid,int sn){/* define P operating*/struct sembuf op;op.sem_num=sn;op.sem_op=-1;op.sem_flg=0;semop(semid,&op,1);}3、对信号灯集中的某个元素进行V操作。
进程通信的实验报告
一、实验目的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()函数删除消息队列。
进程控制与进程通信程序实验报告
进程控制与进程通信程序实验报告一、引言进程是计算机系统中最基本的概念之一,是操作系统中最小的资源管理单位。
进程控制与进程通信是操作系统中重要的内容,涉及到进程的创建、调度和终止,以及进程间的信息传递和同步管理。
本实验旨在通过编写进程控制与进程通信程序,加深对操作系统中进程管理和通信机制的理解。
二、实验目的1. 理解进程的概念和特点,掌握进程的创建、调度和终止方法。
2. 掌握进程通信的基本原理和方法,包括共享内存、管道、消息队列和信号量等。
3. 能够编写简单的进程控制和进程通信程序。
三、实验内容1. 进程控制实验:编写一个程序,实现进程的创建、调度和终止。
通过调用系统调用函数,创建多个子进程,并通过进程控制函数实现父子进程的协作与同步。
2. 进程通信实验:编写一个程序,实现进程间的信息传递和同步管理。
通过共享内存、管道、消息队列或信号量等机制,实现不同进程之间的数据交换和共享。
四、实验步骤1. 进程控制实验:(1)创建父进程和子进程:使用fork()函数创建子进程,并通过判断返回值来区分父子进程。
(2)调度子进程:使用wait()函数等待子进程的结束,以实现父子进程的同步。
(3)终止子进程:使用exit()函数终止子进程的运行。
2. 进程通信实验:(1)共享内存:使用shmget()函数创建共享内存段,使用shmat()函数映射共享内存到进程的地址空间,实现共享数据的读写。
(2)管道:使用pipe()函数创建管道,使用fork()函数创建子进程,通过读写管道实现进程间的数据传输。
(3)消息队列:使用msgget()函数创建消息队列,使用msgsnd()函数向消息队列发送消息,使用msgrcv()函数从消息队列接收消息,实现进程间的消息传递。
(4)信号量:使用semget()函数创建信号量,使用semop()函数对信号量进行P操作和V操作,实现进程间的同步和互斥。
五、实验结果通过实验,我们成功实现了进程的创建、调度和终止,以及进程间的信息传递和同步管理。
实现进程间通信的实验原理
实现进程间通信的实验原理进程间通信(Inter-Process Communication,IPC)是指在操作系统中,不同的进程之间进行数据交换和共享的一种机制。
常见的进程间通信的方法有:1. 管道(Pipe):管道是一种半双工的通信机制,它可以实现父子进程之间的通信。
通常由操作系统创建,父进程创建一个管道后,可以通过fork系统调用创建子进程,从而共享管道。
子进程可以通过管道进行写入一端,父进程可以通过管道进行读取。
2. 命名管道(Named Pipe):命名管道也是一种管道,但它允许不相关的进程之间进行通信。
命名管道被创建时,通过指定一个路径名,从而使不同进程能够通过路径名来访问同一管道。
3. 信号量(Semaphore):信号量是一种计数器,用于控制多个进程对共享资源的访问。
进程可以通过特定的操作(比如P操作和V操作)来对信号量进行增加或减少操作。
同一时刻只允许一个进程对信号量进行P操作,其他进程需要等待。
4. 共享内存(Shared Memory):共享内存是一种进程之间共享数据的方式,它在物理内存中创建一块共享区域,多个进程可以将这块内存映射到各自的虚拟地址空间中。
进程可以直接读写共享内存,而无需进行数据拷贝。
5. 消息队列(Message Queue):消息队列是一种可以实现不同进程之间通过消息进行通信的机制。
进程可以通过特定的操作将消息发送到消息队列中,其他进程可以从消息队列中读取消息。
6. 套接字(Socket):套接字是一种网络编程中常用的进程间通信方式。
它可以在不同主机上的进程之间进行通信。
进程可以通过套接字进行网络数据的读取和写入。
以上是常见的几种进程间通信的方法,每种方法都有自己的优势和适用场景。
根据具体的需求,可以选择适合的方式进行进程间通信。
进程间通信方式及应用场景
进程间通信方式及应用场景进程间通信是操作系统中的一个重要概念,它指的是不同进程之间进行数据交换和共享的一种方式。
进程间通信可以通过多种机制来实现,每种机制都有其优缺点和适用场景。
1. 管道(Pipe):管道是进程间通信中最简单的一种方式,它是一个字节流的通道。
管道可以分为匿名管道和命名管道两种形式。
匿名管道通常是单向的、存在于父子进程之间,并且不能用于无关联的进程之间通信。
匿名管道适用于需要父子进程之间的双向通信,如进程的输入输出重定向。
命名管道是一种特殊的文件,允许无关联进程之间进行通信,可以用于多个进程之间的双向通信。
命名管道适用于多个进程之间进行数据交换,如服务器和客户端之间的通信。
2. 消息队列(Message Queue):消息队列是一种先进先出的消息传递机制。
消息队列在内核中创建,用于进程间传递数据。
消息队列可以通过消息标识符来寻址,而不是进程标识符。
消息队列适用于多个进程之间的数据传递,具有较大的灵活性和可靠性,可以避免数据丢失。
它可以实现进程之间的异步通信,提高系统性能,如网络数据包的传输、进程间的任务交换等。
3. 信号量(Semaphore):信号量是一种非负整数变量,用于多个进程之间的同步和互斥操作。
它可以用来实现进程之间的互斥和资源的共享。
信号量可以通过P操作(等待信号量)和V操作(释放信号量)来实现进程之间的同步。
P操作会将信号量值减一,如果信号量值为负,则进程进入等待状态。
V操作会将信号量值加一,并唤醒等待的进程。
信号量适用于需要多个进程之间的同步和互斥操作,如进程的互斥访问、控制资源的分配等。
4. 共享内存(Shared Memory):共享内存是进程间通信中最快、最高效的一种方式,它允许多个进程共享同一块物理内存空间。
共享内存通过将一段虚拟内存区域映射到多个进程的地址空间来实现。
共享内存适用于大量数据的高速传输和共享,比如图像处理、音视频编码、数据库等需要高速数据交换和共享的应用场景。
操作系统--进程通信实验报告
2.编辑结果如下。
3.编译和运行程序。
4. 运行解释结果
父进程创建一个子进程和一个无名管道fd。
父进程wait(0)等待子进程的终止信号,子进程向管道写入信息“This is a message。
”然后终止,父进程收到终止信号后从管道读出信息并显示在屏幕上后结束。
2.编辑结果如下。
3.编译和运行程序。
4. 运行解释结果
父进程先创建一个子进程1,子进程1往管道fd里写入信息,并输出parent的信息,父进程接着有创造了一个子进程2,子进程2也往fd管道fd里写入信息,父进程wait(0)等待两个子进程结束信号,等两个子进程都结束后,输出管道里的信息。
实现了父子进程之间的管道通信。
1.编辑源程序。
2.编辑结果如下。
3.编译和运行程序。
4. 运行解释结果
发送进程将要发送的信息从键盘输入,每输入一行就作为一条信息发送,用“end”作为结
束的信息,存入共享的内存区。
接收进程从信息队列逐个取出信息并显示输出。
1.编辑源程序。
2.编辑结果如下。
3.编译和运行程序。
4. 运行解释结果
发送进程将要发送的信息从键盘输入,每输入一行就作为一条信息发送,用“end”作为结束的信息,存入信息缓冲区。
接收进程从信息队列逐个取出信息并显示输出。
进程之间的通信实验
实验:进程之间的通信管道1.Pipe函数与进程通信下面实验为使用管道进行父子进程间通信。
程序首先判断参数是否合法,因为输入的字符将从父进程通过发送到子进程中。
然后,调用pipe函数创建父子进程用于通信的管道。
使用fork函数创建子进程时,子进程会获得与父进程相同的资源,其中包括文件描述符信息。
因此,调用fork函数须在pipe函数调用前。
当父子进程通过管道进行通信时,files[1]为用于数据写入的文件描述符.因此,在子进程中,要读取管道中的数据可以调用read函数,而读取得文件描述符为files[0]。
对于父进程而言,写入数据需要调用write 函数,要写入的文件描述为files[1]。
#include <stdio.h>#include <unistd.h>int main(int argc,char* argv[]){int f_des[2];int pid;char msg[BUFSIZ];if(argc!=2){printf("Usage: %s message\n",argv[0]);return 1;}if(pipe(f_des)==-1){perror("cannot create the IPC pipe");return 1;}pid=fork();if(pid==-1){perror("cannot create new process");return 1;}else if(pid==0){close(f_des[1]);if(read(f_des[0],msg,BUFSIZ)==-1){perror("child process cannot read data from pipe");return 1;}elseprintf("in child process, receive message: %s\n",msg);_exit(0);}else {close(f_des[0]);if(write(f_des[1],argv[1],strlen(argv[1]))==-1){perror("parent process cannot write data to pipe");return 1;}elseprintf("in parent process, send message: %s\n",argv[1]);wait(NULL);_exit(0);}return 0;}2. Shell管道重订向的实现实现了在SHELL中的两个命令的组合。
实验八进程通信
实验八进程通信一.实验引子:进程之间的信息交换称为进程通信。
进程通信因其交换的信号量多少又可分为低级通信和高级通信。
每次交换的信息量较少,甚至只是一个状态值,如进程的同步与互斥,这样的通信叫低级通信;若进程之间交换的信息量比较大,这样的通信叫作高级通信。
管道通信就是其中的一种高级通信机制。
从本质上说,管道就是一种用于连接读进程和写进程,以实现它们之间通信的共享文件。
向管道提供输入数据的发送进程(写进程)以字符流的形式将大量的数据送入管道,而接收进程则从管道中接收数据。
本实验中,Client为发送方,Server为接收方。
二.实验目的:通过该实验,让学生体会操作系统提供的进程通信机制之一——管道通信。
三.实验过程:按照实验指导的要求,分别建立一个Client工程、一个Server工程。
待两个工程都编译通过没有错误之后,分别打开两个工程下的Debug文件夹,执行其中的可执行程序。
进而观察两个进程之间的通信。
要求:写出实验过程,给出实验结果。
编辑框——右击建立类向导——Member Variables——Add Variables——m_msg——ok ——确定编辑框——右击建立类向导——Member Variables——Add V ariables——m_list——ok——确定将client文件夹和server文件夹下的Debug文件夹打开,分别运行client.exe和server.exe四.实验小结:管道是用来连接读进程和写进程的,实现通信间共享文件。
Client即向管道提供输入数据的发送进程以字符流的形式将大量的数据送入管道,而Server即接收进程则从管道中接收数据。
实现进程之间的高级通信。
进程控制与进程通信程序实验报告
进程控制与进程通信程序实验报告进程控制与进程通信程序实验报告本次实验主要涉及进程控制和进程通信两个方面。
进程控制是指操作系统对进程的管理和控制,包括创建、撤销、挂起、恢复等操作。
进程通信是指进程之间进行信息交换的过程,包括共享内存、管道、消息队列等方式。
在本次实验中,我们使用了C语言编写了两个程序,一个是父进程程序,一个是子进程程序。
父进程程序通过fork()函数创建子进程,然后通过wait()函数等待子进程结束。
子进程程序则通过exec()函数执行另一个程序。
这个程序是一个简单的计算器程序,可以进行加减乘除运算。
在进程通信方面,我们使用了共享内存的方式进行进程间通信。
共享内存是指多个进程共享同一块内存空间,可以实现进程间的数据共享。
在本次实验中,我们使用了shmget()函数创建共享内存,shmat()函数将共享内存映射到进程的地址空间中,shmdt()函数将共享内存从进程的地址空间中分离,shmctl()函数控制共享内存的状态。
在父进程程序中,我们使用了共享内存来传递两个操作数和操作符。
父进程程序首先创建共享内存,然后将两个操作数和操作符写入共享内存中。
子进程程序通过共享内存读取这些数据,并进行相应的计算。
计算结果再通过共享内存传递回父进程程序,父进程程序读取共享内存中的结果并输出。
本次实验的结果表明,进程控制和进程通信是操作系统中非常重要的概念。
掌握了这些概念,可以更好地理解操作系统的工作原理,也可以更好地编写高效的程序。
同时,共享内存是一种非常实用的进程通信方式,可以在多个进程之间实现数据共享,提高程序的效率。
总之,本次实验让我们更深入地了解了进程控制和进程通信的概念和实现方式。
通过编写程序,我们掌握了fork()、wait()、exec()、shmget()、shmat()、shmdt()、shmctl()等函数的使用方法,也更好地理解了操作系统的工作原理。
进程控制与进程通信程序实验报告
进程控制与进程通信程序实验报告1. 背景进程控制与进程通信是操作系统的重要概念之一,它们在现代计算机系统中起到了至关重要的作用。
进程控制是指操作系统对进程的创建、执行、中止和切换等各种操作的管理和控制,进程通信则是指进程之间通过各种方式传递信息和实现协作的机制。
在本次实验中,我们需要编写一个进程控制与进程通信程序。
通过实现进程的创建、执行和中止等基本操作,并通过进程通信机制进行信息传递,实现多个进程之间的协作。
本实验将帮助我们进一步理解和掌握进程控制与进程通信的原理和操作。
2. 分析2.1 实验要求本次实验要求我们编写一个进程控制与进程通信程序,实现以下功能:1.创建一个主进程和多个子进程,并实现进程的执行和切换;2.子进程之间通过进程通信机制传递信息;3.实现多个子进程之间的协作,完成指定的任务。
2.2 系统设计为了满足实验的要求,我们可以按照以下步骤设计我们的系统:1.创建主进程和多个子进程:使用操作系统提供的进程创建函数,创建一个主进程和多个子进程。
主进程将负责协调子进程的执行和协作。
2.进程执行和切换:使用操作系统提供的进程执行和切换函数,实现进程的执行和切换操作。
主进程可以通过改变进程的状态和优先级来控制进程的执行和切换。
3.进程通信机制:使用操作系统提供的进程通信机制,如消息队列、共享内存等,实现子进程之间的信息传递。
可以定义统一的消息格式,并使用相应的函数进行消息的发送和接收。
4.进程协作:根据实验要求,设计子进程之间的协作方式。
可以使用信号量、条件变量等机制来实现多个子进程之间的同步和互斥。
2.3 实验结果实验的结果将是一个能够创建多个子进程,并通过进程通信进行协作的程序。
程序将实现以下功能:1.主进程创建多个子进程,并通过改变进程的状态和优先级来控制进程的执行;2.子进程通过进程通信机制传递信息,完成指定的任务;3.子进程之间通过协作实现同步和互斥,保证任务的正确执行。
3. 实验步骤3.1 创建进程首先,我们需要创建主进程和多个子进程。
实验八进程通信应用
实验八进程通信应用实验目的1. 掌握命名管道的原理和应用2. 掌握文件映射共享内存的原理3、掌握基于进程通信的程序设计方法实验内容1.(1)命令行下创建有名管道myfifo,ls –l查看,分别在两个终端运行cat < myfifo 和echo hello >myfifo 分析执行情况,将cat在后台运行,echo在前台运行,执行情况如何分析FIFO的打开规则。
(2)设计两个程序,要求用命名管道FIFO,实现文本文件复制功能,即实现copy file1 file2的功能,file1是已经存在的文件,file2可以不存在,如果存在就清空原来的内容,通过建立的有名管道实现file1的内容复制到file2。
一、 FIFO1.有名管道的创建#include <sys/>#include <sys/>int mkfifo(const char * pathname, mode_t mode)该函数的第一个参数是一个普通的路径名,也就是创建后FIFO的名字。
第二个参数与打开普通文件的open()函数中的mode 参数相同。
2. 有名管道的打开有名管道创建成功后并没有打开,需要使用系统调用open( )将对应的文件打开。
open(const char*pathname,oflg)其中,参数pathname是要打开的有名管道的路径名,oflg是文件打开时的存取方式。
必须指定的互斥模式: O_RDONLY, O_WRONLY, O_NONBLOCKO_RDONLY:若无进程写方式打开FIFO,open阻塞O_RDONLY |O_NONBLOCK:若无进程写方式打开FIFO,open立即返回O_WRONLY:若无进程读方式打开FIFO,open阻塞O_WRONLY| O_NONBLOCK:若无进程读方式打开FIFO,open返回ENXIO错误,-1FIFO的打开规则:(1)如果当前打开操作是为读而打开FIFO时,若已经有相应进程为写而打开该FIFO,则当前打开操作将成功返回;否则,可能阻塞直到有相应进程为写而打开该FIFO(当前打开操作设置了阻塞标志);或者,成功返回(当前打开操作没有设置阻塞标志)。
操作系统实验---进程通信
实验报告实验题目姓名:学号:课程名称:操作系统实验所在学院:信息科学与工程学院专业班级:计算机任课教师:五、实验数据(现象)处理分析信号机制实验建立文件和可执行文件:信号机制实验运行结果:屏幕上无反应,按下^C 后,显示Parent process is killed!进程的管道通信可执行文件:管道通信实验运行结果:延迟5 秒后显示child 1 process is sending message!再延迟5 秒child 2 process is sending message!附加问题:在不修改程序的情况下要输出期望的结果,可以单独向父进程发送SIGINT 信号,这样即可避免子进程由于收到SIGINT 信号执行默认操作而自我终止,具体实现方法:(该实验中程序名为:demo2)首先让程序在后台运行,命令:./demo2&执行该命令后,会在后台生成3 个进程,使用ps 命令可以查看到它们的PID (相对小的PID 应该为父进程的PID,原因是创建时间相对早)。
然后向后台的父进程发送SIGINT 信号,命令:kill –SIGINT 28664 (其中28664为父进程的PID)运行结果如下所示:进程通信消息机制实验可执行文件:进程通信消息机制实验运行结果1:进程通信消息机制实验运行结果2:六、实验结论通过实验了解和熟悉了LINUX 支持的信号量机制、管道机制、消息通信机制及共享存储区机制的基本原理和基本概念。
对信号和中断有了进一步的理解,能够分辨出两者的区别和相似点。
观察实验现象知道了信号的发送方式和处理方式。
掌握了信号的发送,是指由发送进程把信号送到指定进程的信号域的某一位上。
如果目标进程正在一个可被中断的优先级上睡眠,核心便将它唤醒,发送进程就此结束。
一个程可能在其信号域中有多个位被置位,代表有多种类型的信号到达,但对于一类信号,进程却只能记住其中的某一个。
通过本次实验最终目的还是全面了解进程的各种机制以及处理方法。
(完整word版)操作系统实验进程的通信
(操作系统原理和linux操作系统相结合的实验)实验二进程的通信一实验目的1 学会使用vi编辑器编辑C语言程序2 学会Linux环境下gcc的使用3 学会调试工具GDB的使用二实验原理1 利用linux提供的进程通信的系统调用设计进程通信程序,加深对进程通信概念的理解。
2 体会进程通信的方法和效果。
三实验环境PC机1台,Windows操作系统和其上的虚拟Linux操作系统。
四实验步骤1.管道通信(1)编写一个程序。
父进程创建一个子进程和一个无名管道fd,由子进程向管道写入信息“This is a message”,然后终止执行;父进程接收到子进程终止信号后从管道中读出并显示信息后结束。
#include<stdio.h>#include<unistd.h>main(){int p1,fd[2];char outpipe[50]; //定义读缓冲区char inpipe[50]="This is a message!"; //定义写缓冲区pipe(fd); //创建无名管道fdwhile((p1=fork())==-1);if (p1==0) //子进程返回{write(fd[1],inpipe,50); //写信息到管道exit(0);}else //父进程返回{wait(0); //等待子进程终止read(fd[0],outpipe,50); //从管道读信息到读缓冲区printf("%s\n",outpipe); //显示读到的信息exit(0);}}(2)父进程创建两个子进程,父子进程之间利用管道进行通信。
要求能显示父进程、子进程各自的信息,体现通信效果。
(源程序pipe_1.c)#include<stdio.h>main(){int I,r,j,k,l,p1,p2,fd[2];char buf[50],s[50];pipe(fd);while((p1=fork())==-1);if(p1==0){lockf(fd[1],1,0);sprintf(buf,"Child process p1 is sending message!\n");printf("Child process p1!\n");write(fd[1],buf,50);lockf(fd[1],0,0);sleep(5);j=getpid();k=getppid();printf("p1 %d is weakup.My parent process id is %d.\n",j,k);exit(0);}else{while((p2=fork())==-1);if(p2==0){lockf(fd[1],1,0);sprintf(buf,"Child process p2 is sending message!\n");printf("Child process p2!\n");write(fd[1],buf,50);lockf(fd[1],0,0);sleep(5);j=getpid();k=getppid();printf("p2 %d is weakup.My parent process id is %d.\n",j,k);exit(0);}else{I=getpid();wait(0);if(r=read(fd[0],s,50)==-1)printf("can’t read pip e.");elseprintf("Parent %d:%s\n",l,s);wait(0);if(r=read(fd[0],s,50)==-1)pr intf("can’t read pipe");elseprintf ( "Parent %d:%s\n",l,s);exit(0);}}}结果:2.共享内存通信。
进程通信实验报告
西安电子科技大学《操作系统原理》实验报告题目:进程通信实验报告班级: 030912姓名:王增祥学号: 03091168实验内容补充说明:一、分析和设计1.理论分析每个Windows进程都是由一个执行体进程块(EPROCESS)表示。
API函数CreatProcess 可以创建进程,采用管道技术可以实现进程间的相互通信。
建立pipe,进程以及其子进程就可以对该管道进程读写共享,管道读写操作利用,write、read、close进行。
父进程利用pipe 发送消息,子进程利用该pipe接收父进程发来的消息;子进程利用管道向父进程发送应答,父进程利用该pipe接受应答。
2.总体设计1、利用CreatProcess函数创建进程。
2、创建管道,实现进程间的通信二、详细实现1、创建界面,采用Botton、列表框等控件创建父子界面如下图:父进程界面:子进程界面:其中父进程各个空间创建类向导如图:子进程创建类向导如图:2.父进程编写(1)创建管道:(2)创建子进程:(3)消息发送(4)消息接受3.子进程编写(1)发送消息(2)读消息三、实验结果点击创建子进程按钮:在创建子进程之后进行进程间的通信如下图四、心得体会1、从试验的角度了解了进程间是怎样利用管道进行通信的,了解了进程间通信的实际过程2、进一步掌握了MFC的初步编程技巧,知道了怎样调试程序。
3进一步了解了,API函数的应用,明白了怎样进行界面编程。
4、进一步熟悉了在进行进程通信的编写过程中的各个细节。
六、附录Process_Father.cpp#include "stdafx.h"#include "Process_Father.h" //包含已编写的Process_Father.h头文件#include "Process_FatherDlg.h" //包含已编写的Process_FatherDlg.h头文件//进行宏定义#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif//创建父进程BEGIN_MESSAGE_MAP(CProcess_FatherApp, CWinApp)//{{AFX_MSG_MAP(CProcess_FatherApp)// NOTE - the ClassWizard will add and remove mapping macros here.// DO NOT EDIT what you see in these blocks of generated code!//}}AFX_MSGON_COMMAND(ID_HELP, CWinApp::OnHelp)END_MESSAGE_MAP()// CProcess_FatherApp constructionCProcess_FatherApp::CProcess_FatherApp(){// TODO: add construction code here,// Place all significant initialization in InitInstance}// The one and only CProcess_FatherApp objectCProcess_FatherApp theApp;// CProcess_FatherApp initializationBOOL CProcess_FatherApp::InitInstance(){AfxEnableControlContainer();#ifdef _AFXDLLEnable3dControls(); // Call this when using MFC in a shared DLL #elseEnable3dControlsStatic(); // Call this when linking to MFC statically #endifCProcess_FatherDlg dlg;m_pMainWnd = &dlg;int nResponse = dlg.DoModal();if (nResponse == IDOK){// TODO: Place code here to handle when the dialog is// dismissed with OK}else if (nResponse == IDCANCEL){// TODO: Place code here to handle when the dialog is// dismissed with Cancel}// Since the dialog has been closed, return FALSE so that we exit the// application, rather than start the application's message pump.return FALSE;}Process_FatherDlg.cpp// Process_FatherDlg.cpp : implementation file//#include "stdafx.h"#include "Process_Father.h"#include "Process_FatherDlg.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App Aboutclass CAboutDlg : public CDialog{public:CAboutDlg();// Dialog Data//{{AFX_DATA(CAboutDlg)enum { IDD = IDD_ABOUTBOX };//}}AFX_DATA// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CAboutDlg)protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL// Implementationprotected://{{AFX_MSG(CAboutDlg)//}}AFX_MSGDECLARE_MESSAGE_MAP()};CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD){//{{AFX_DATA_INIT(CAboutDlg)//}}AFX_DATA_INIT}void CAboutDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CAboutDlg)//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)//{{AFX_MSG_MAP(CAboutDlg)// No message handlers//}}AFX_MSG_MAPEND_MESSAGE_MAP()///////////////////////////////////////////////////////////////////////////// // CProcess_FatherDlg dialogCProcess_FatherDlg::CProcess_FatherDlg(CWnd* pParent /*=NULL*/) : CDialog(CProcess_FatherDlg::IDD, pParent){//{{AFX_DATA_INIT(CProcess_FatherDlg)//}}AFX_DATA_INIT// Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);}void CProcess_FatherDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CProcess_FatherDlg)DDX_Control(pDX, IDC_BT_CreateChildProcess, m_BT_CreateChildProcess);DDX_Control(pDX, IDC_Send, m_Send);DDX_Control(pDX, IDC_LISTBOX_Record, m_LISTBOX_Record);DDX_Control(pDX, IDC_EDIT_Message, m_EDIT_Message);//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CProcess_FatherDlg, CDialog)//{{AFX_MSG_MAP(CProcess_FatherDlg)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_BT_CreateChildProcess, OnBTCreateChildProcess)ON_BN_CLICKED(IDC_Send, OnSend)//}}AFX_MSG_MAPON_MESSAGE(WM_CHILD_SEND,OnReceiveMsg)END_MESSAGE_MAP()///////////////////////////////////////////////////////////////////////////// // CProcess_FatherDlg message handlersBOOL CProcess_FatherDlg::OnInitDialog(){CDialog::OnInitDialog();// Add "About..." menu item to system menu.// IDM_ABOUTBOX must be in the system command range.ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){CString strAboutMenu;strAboutMenu.LoadString(IDS_ABOUTBOX);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialogSetIcon(m_hIcon, TRUE); // Set big iconSetIcon(m_hIcon, FALSE); // Set small icon// TODO: Add extra initialization herereturn TRUE; // return TRUE unless you set the focus to a control}void CProcess_FatherDlg::OnSysCommand(UINT nID, LPARAM lParam){if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialog::OnSysCommand(nID, lParam);}}// If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework.void CProcess_FatherDlg::OnPaint(){if (IsIconic()){CPaintDC dc(this); // device context for paintingSendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);// Center icon in client rectangleint cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// Draw the icondc.DrawIcon(x, y, m_hIcon);}else{CDialog::OnPaint();}}// The system calls this to obtain the cursor to display while the user drags // the minimized window.HCURSOR CProcess_FatherDlg::OnQueryDragIcon(){return (HCURSOR) m_hIcon;}void CProcess_FatherDlg::OnBTCreateChildProcess(){//创建管道SECURITY_ATTRIBUTES sa;sa.nLength=sizeof(SECURITY_ATTRIBUTES);sa.lpSecurityDescriptor=NULL;sa.bInheritHandle=TRUE;::CreatePipe(&hPipeRead,&hPipeWrite,&sa,0);::CreatePipe(&hPipeRead2,&hPipeWrite2,&sa,0);//创建子进程STARTUPINFO StartupInfo;memset(&StartupInfo,0,sizeof(STARTUPINFO)) ;StartupInfo.cb=sizeof(STARTUPINFO);StartupInfo.dwFlags=STARTF_USESTDHANDLES;StartupInfo.hStdInput=hPipeRead;StartupInfo.hStdOutput=hPipeWrite;StartupInfo.hStdError=GetStdHandle(STD_ERROR_HANDLE);PROCESS_INFORMATION ProcessInfo;::CreateProcess("Process_Child.exe",NULL,NULL,NULL,TRUE,0,NULL,NULL,&Startu pInfo,&ProcessInfo);m_BT_CreateChildProcess.EnableWindow(FALSE);}void CProcess_FatherDlg::OnSend(){CString str;char ss[20]="Father:";m_EDIT_Message.GetWindowText(str);DWORD dwWritten;if(!WriteFile(hPipeWrite,str,40,&dwWritten,NULL)){MessageBox(TEXT("写错误"),"警告",MB_OK|MB_ICONWARNING);}CString strWinName = "Process_Child";CWnd *pWnd=CWnd::FindWindow(NULL,strWinName);if(pWnd){pWnd->SendMessage(WM_FATHER_SEND,0,0);strcat(ss,str);m_LISTBOX_Record.InsertString(-1,ss);m_EDIT_Message.SetWindowText("");}else{MessageBox("没有发现子进程","错误");}}void CProcess_FatherDlg::OnReceiveMsg(WPARAM wParam,LPARAM lParam){DWORD dwRead;TCHAR s[40];HANDLE hPipeRead2;hPipeRead2=GetStdHandle(STD_INPUT_HANDLE);if(!ReadFile(hPipeRead,s,40,&dwRead,NULL)){MessageBox(TEXT("读错误!"),"警告",MB_OK|MB_ICONWARNING);}char str[60]="Child: ";strcat(str,s);m_LISTBOX_Record.InsertString(-1,str);}Process_Father.h// Process_Father.h : main header file for the PROCESS_FATHER application//#if !defined(AFX_PROCESS_FATHER_H__1F9659A2_2B93_4C1E_89C5_5A88971D3DDA__INCLUD ED_)#define AFX_PROCESS_FATHER_H__1F9659A2_2B93_4C1E_89C5_5A88971D3DDA__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000#ifndef __AFXWIN_H__#error include 'stdafx.h' before including this file for PCH#endif#include "resource.h" // main symbols///////////////////////////////////////////////////////////////////////////// // CProcess_FatherApp:// See Process_Father.cpp for the implementation of this class//class CProcess_FatherApp : public CWinApp{public:CProcess_FatherApp();// Overrides// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CProcess_FatherApp)public:virtual BOOL InitInstance();//}}AFX_VIRTUAL// Implementation//{{AFX_MSG(CProcess_FatherApp)// NOTE - the ClassWizard will add and remove member functions here.// DO NOT EDIT what you see in these blocks of generated code !//}}AFX_MSGDECLARE_MESSAGE_MAP()};///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCATION}}// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif// !defined(AFX_PROCESS_FATHER_H__1F9659A2_2B93_4C1E_89C5_5A88971D3DDA__INCLUDE D_)Process_FatherDlg.h// Process_FatherDlg.h : header file//#if !defined(AFX_PROCESS_FATHERDLG_H__69E2942A_7A5F_413F_B4A3_AFB8C1F51DFE__INC LUDED_)#defineAFX_PROCESS_FATHERDLG_H__69E2942A_7A5F_413F_B4A3_AFB8C1F51DFE__INCLUDED_#define WM_FATHER_SEND WM_USER+100#define WM_CHILD_SEND WM_USER+101#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000///////////////////////////////////////////////////////////////////////////// // CProcess_FatherDlg dialogclass CProcess_FatherDlg : public CDialog{// Constructionpublic:CProcess_FatherDlg(CWnd* pParent = NULL); // standard constructor// Dialog Data//{{AFX_DATA(CProcess_FatherDlg)enum { IDD = IDD_PROCESS_FATHER_DIALOG };CButton m_BT_CreateChildProcess;CButton m_Send;CListBox m_LISTBOX_Record;CEdit m_EDIT_Message;//}}AFX_DATA// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CProcess_FatherDlg)protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL// Implementationprotected:HICON m_hIcon;// Generated message map functions//{{AFX_MSG(CProcess_FatherDlg)virtual BOOL OnInitDialog();afx_msg void OnSysCommand(UINT nID, LPARAM lParam);afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();afx_msg void OnReceiveMsg(WPARAM wParam, LPARAM lParam);afx_msg void OnBTCreateChildProcess();afx_msg void OnSend();//}}AFX_MSGDECLARE_MESSAGE_MAP()private:HANDLE hPipeWrite2;HANDLE hPipeRead2;HANDLE hPipeWrite;HANDLE hPipeRead;};//{{AFX_INSERT_LOCATION}}// Microsoft Visual C++ will insert additional declarations immediately before theprevious line.#endif// !defined(AFX_PROCESS_FATHERDLG_H__69E2942A_7A5F_413F_B4A3_AFB8C1F51DFE__INCL UDED_)子进程代码Process_Child.cpp// Process_Child.cpp : Defines the class behaviors for the application.//#include "stdafx.h"#include "Process_Child.h"#include "Process_ChildDlg.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/////////////////////////////////////////////////////////////////////////////// CProcess_ChildAppBEGIN_MESSAGE_MAP(CProcess_ChildApp, CWinApp)//{{AFX_MSG_MAP(CProcess_ChildApp)// NOTE - the ClassWizard will add and remove mapping macros here.// DO NOT EDIT what you see in these blocks of generated code!//}}AFX_MSGON_COMMAND(ID_HELP, CWinApp::OnHelp)END_MESSAGE_MAP()///////////////////////////////////////////////////////////////////////////// // CProcess_ChildApp constructionCProcess_ChildApp::CProcess_ChildApp(){// TODO: add construction code here,// Place all significant initialization in InitInstance}///////////////////////////////////////////////////////////////////////////// // The one and only CProcess_ChildApp objectCProcess_ChildApp theApp;///////////////////////////////////////////////////////////////////////////// // CProcess_ChildApp initializationBOOL CProcess_ChildApp::InitInstance(){AfxEnableControlContainer();// Standard initialization// If you are not using these features and wish to reduce the size// of your final executable, you should remove from the following// the specific initialization routines you do not need.#ifdef _AFXDLLEnable3dControls(); // Call this when using MFC in a shared DLL #elseEnable3dControlsStatic(); // Call this when linking to MFC statically #endifCProcess_ChildDlg dlg;m_pMainWnd = &dlg;int nResponse = dlg.DoModal();if (nResponse == IDOK){// TODO: Place code here to handle when the dialog is// dismissed with OK}else if (nResponse == IDCANCEL){// TODO: Place code here to handle when the dialog is// dismissed with Cancel}// Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump.return FALSE;}Process_ChildDlg.cpp// Process_ChildDlg.cpp : implementation file//#include "stdafx.h"#include "Process_Child.h"#include "Process_ChildDlg.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App Aboutclass CAboutDlg : public CDialog{public:CAboutDlg();// Dialog Data//{{AFX_DATA(CAboutDlg)enum { IDD = IDD_ABOUTBOX };//}}AFX_DATA// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CAboutDlg)protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL// Implementationprotected://{{AFX_MSG(CAboutDlg)//}}AFX_MSGDECLARE_MESSAGE_MAP()};CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD){//{{AFX_DATA_INIT(CAboutDlg)//}}AFX_DATA_INIT}void CAboutDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CAboutDlg)//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)//{{AFX_MSG_MAP(CAboutDlg)// No message handlers//}}AFX_MSG_MAPEND_MESSAGE_MAP()///////////////////////////////////////////////////////////////////////////// // CProcess_ChildDlg dialogCProcess_ChildDlg::CProcess_ChildDlg(CWnd* pParent /*=NULL*/): CDialog(CProcess_ChildDlg::IDD, pParent){//{{AFX_DATA_INIT(CProcess_ChildDlg)//}}AFX_DATA_INIT// Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);}void CProcess_ChildDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CProcess_ChildDlg)DDX_Control(pDX, IDC_Send, m_Send);DDX_Control(pDX, IDC_LISTBOX_Record, m_LISTBOX_Record);DDX_Control(pDX, IDC_EDIT_Message, m_EDIT_Message);//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CProcess_ChildDlg, CDialog)//{{AFX_MSG_MAP(CProcess_ChildDlg)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_Send, OnSend)//}}AFX_MSG_MAPON_MESSAGE(WM_FATHER_SEND,OnReceiveMsg)END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CProcess_ChildDlg message handlersBOOL CProcess_ChildDlg::OnInitDialog(){CDialog::OnInitDialog();// Add "About..." menu item to system menu.// IDM_ABOUTBOX must be in the system command range.ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){CString strAboutMenu;strAboutMenu.LoadString(IDS_ABOUTBOX);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}// Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialogSetIcon(m_hIcon, TRUE); // Set big iconSetIcon(m_hIcon, FALSE); // Set small icon// TODO: Add extra initialization herereturn TRUE; // return TRUE unless you set the focus to a control}void CProcess_ChildDlg::OnSysCommand(UINT nID, LPARAM lParam){if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialog::OnSysCommand(nID, lParam);}// If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework.void CProcess_ChildDlg::OnPaint(){if (IsIconic()){CPaintDC dc(this); // device context for paintingSendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);// Center icon in client rectangleint cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// Draw the icondc.DrawIcon(x, y, m_hIcon);}else{CDialog::OnPaint();}}// The system calls this to obtain the cursor to display while the user drags // the minimized window.HCURSOR CProcess_ChildDlg::OnQueryDragIcon(){return (HCURSOR) m_hIcon;}void CProcess_ChildDlg::OnSend(){char ss[20]="Child:";CString str;m_EDIT_Message.GetWindowText(str);DWORD dwWritten;hPipeWrite=GetStdHandle(STD_OUTPUT_HANDLE);if(!WriteFile(hPipeWrite,str,40,&dwWritten,NULL)) {MessageBox(TEXT("写错误"),"警告",MB_OK|MB_ICONWARNING);}CString strWinName = "Process_Father";CWnd *pWnd=CWnd::FindWindow(NULL,strWinName);if(pWnd){pWnd->SendMessage(WM_CHILD_SEND,0,0);strcat(ss,str);m_LISTBOX_Record.InsertString(-1,ss);m_EDIT_Message.SetWindowText("");}else{MessageBox("没有发现父进程","错误");}void CProcess_ChildDlg::OnReceiveMsg(WPARAM wParam,LPARAM lParam){DWORD dwRead;char s[40];HANDLE hPipeRead;hPipeRead=GetStdHandle(STD_INPUT_HANDLE);if(!ReadFile(hPipeRead,s,40,&dwRead,NULL)){MessageBox(TEXT("读错误!"),"警告",MB_OK|MB_ICONWARNING);}char str[60]="Father: ";strcat(str,s);m_LISTBOX_Record.InsertString(-1,str);}Process_Child.h// Process_Child.h : main header file for the PROCESS_CHILD application//#if !defined(AFX_PROCESS_CHILD_H__7416C60C_DD56_40CC_BD28_3DA310873DE7__INCLUDE#define AFX_PROCESS_CHILD_H__7416C60C_DD56_40CC_BD28_3DA310873DE7__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000#ifndef __AFXWIN_H__#error include 'stdafx.h' before including this file for PCH#endif#include "resource.h" // main symbols///////////////////////////////////////////////////////////////////////////// // CProcess_ChildApp:// See Process_Child.cpp for the implementation of this class//class CProcess_ChildApp : public CWinApp{public:CProcess_ChildApp();// Overrides// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CProcess_ChildApp)public:virtual BOOL InitInstance();//}}AFX_VIRTUAL// Implementation//{{AFX_MSG(CProcess_ChildApp)// NOTE - the ClassWizard will add and remove member functions here.// DO NOT EDIT what you see in these blocks of generated code !//}}AFX_MSGDECLARE_MESSAGE_MAP()};///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCATION}}// Microsoft Visual C++ will insert additional declarations immediately before theprevious line.#endif// !defined(AFX_PROCESS_CHILD_H__7416C60C_DD56_40CC_BD28_3DA310873DE7__INCLUDED _)Process_ChildDlg.h// Process_ChildDlg.h : header file//#if !defined(AFX_PROCESS_CHILDDLG_H__01C41D47_4973_4DCB_84FC_4B7C5A6C584A__INCL UDED_)#define AFX_PROCESS_CHILDDLG_H__01C41D47_4973_4DCB_84FC_4B7C5A6C584A__INCLUDED_ #define WM_FATHER_SEND WM_USER+100#define WM_CHILD_SEND WM_USER+101#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000///////////////////////////////////////////////////////////////////////////// // CProcess_ChildDlg dialogclass CProcess_ChildDlg : public CDialog{// Constructionpublic:CProcess_ChildDlg(CWnd* pParent = NULL); // standard constructor// Dialog Data//{{AFX_DATA(CProcess_ChildDlg)enum { IDD = IDD_PROCESS_CHILD_DIALOG };CButton m_Send;CListBox m_LISTBOX_Record;CEdit m_EDIT_Message;//}}AFX_DATA// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CProcess_ChildDlg)protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL// Implementationprotected:HICON m_hIcon;// Generated message map functions//{{AFX_MSG(CProcess_ChildDlg)virtual BOOL OnInitDialog();afx_msg void OnSysCommand(UINT nID, LPARAM lParam);afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();afx_msg void OnReceiveMsg(WPARAM wParam, LPARAM lParam);afx_msg void OnSend();//}}AFX_MSGDECLARE_MESSAGE_MAP()private:HANDLE hPipeWrite;};//{{AFX_INSERT_LOCATION}}// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif// !defined(AFX_PROCESS_CHILDDLG_H__01C41D47_4973_4DCB_84FC_4B7C5A6C584A__INCLU DED_)。
进程通信实验报告
进程通信实验报告进程通信实验报告概述进程通信是操作系统中非常重要的一个概念,它允许不同的进程之间进行数据的交换和共享。
在本次实验中,我们通过使用不同的进程通信机制,如管道、消息队列和共享内存,来实现进程之间的数据传输和通信。
本报告将详细介绍实验的背景、实验过程、结果分析以及对实验的总结。
实验背景进程通信是操作系统中的一个核心概念,它允许多个进程之间进行数据的交换和共享。
在现代操作系统中,进程通信是实现并发和协作的重要手段。
了解不同的进程通信机制以及它们的优缺点对于深入理解操作系统的原理和实现至关重要。
实验过程在本次实验中,我们使用了三种不同的进程通信机制:管道、消息队列和共享内存。
首先,我们创建了两个进程,一个作为发送方,一个作为接收方。
然后,我们分别使用了管道、消息队列和共享内存来实现进程之间的数据传输和通信。
管道是一种最简单的进程通信机制,它可以在父进程和子进程之间进行单向的通信。
我们通过创建一个管道,并将其连接到父进程和子进程的标准输入和标准输出,实现了父子进程之间的数据传输。
消息队列是一种更为灵活的进程通信机制,它可以实现多个进程之间的双向通信。
我们使用了系统提供的消息队列函数,创建了一个消息队列,并在发送方将消息发送到队列中,接收方则从队列中接收消息。
通过消息队列,我们实现了进程之间的异步通信。
共享内存是一种高效的进程通信机制,它允许多个进程共享同一块内存空间。
我们使用了共享内存函数,创建了一个共享内存区域,并将其映射到两个进程的虚拟地址空间中。
通过共享内存,我们实现了进程之间的数据共享和同步。
结果分析通过实验,我们发现不同的进程通信机制各有优缺点。
管道是最简单的一种机制,但只能实现单向通信,且只能用于具有亲缘关系的进程。
消息队列可以实现多个进程之间的双向通信,但消息的顺序可能会被打乱。
共享内存是最高效的一种机制,但需要额外的同步机制来保证数据的一致性。
总结进程通信是操作系统中非常重要的一个概念,它允许不同的进程之间进行数据的交换和共享。
城院操作系统 实验报告_实验八
浙江大学城市学院实验报告课程名称操作系统原理实验实验项目名称实验八进程通信——管道学生姓名专业班级学号实验成绩指导老师(签名)日期注意:●务请保存好各自的源代码,已备后用。
●请上传到BB平台。
一. 实验目的和要求1.了解Linux系统的进程间通信机构(IPC);2.理解Linux关于管道的概念;3.掌握Linux支持管道的系统调用和管道的使用;4.巩固进程同步概念。
二、实验内容用系统调用pipe( )创建管道,实现父子进程间的通信。
三、实验步骤1、并发进程的无管道通信1)编译运行给出的pipe1.c,观察运行结果。
执行前:执行:执行后:2)思考:观察程序运行结果,比较新旧文件的内容是否有差异,并分析原因。
有。
程序将f1中的内容按字符逐个读出,并逐个写入到了f2中。
2、多进程的管道通信,编译并运行给出的代码pipe3.c,观察并理解多进程通过管道通信。
3、编写程序:(来自第三章习题)假定系统有三个并发进程read,move和print共享缓冲器B1和B2。
进程read负责从输入设备上读信息,每读出一个记录后把它存放到缓冲器B1中。
进程move从缓冲器B1中取出一个记录,加工后存入缓冲器B2。
进程print将B2中的记录取出打印输出。
缓冲器B1和B2每次只能存放一个记录。
要求三个进程协调完成任务,使打印出来的与读入的记录的个数,次序完全一样。
试创建三个进程,用pipe( )打开两个管道,如错误!未找到引用源。
所示,实现三个进程之间的同步。
程序源码:#include <unistd.h>#include <signal.h>#include <stdio.h>#include <semaphore.h>#include <fcntl.h>int pid1,pid2;/*sem_t *S1;sem_t *S2;sem_t *S3;sem_t *S4;*///sem_t S1;//sem_t S2;//sem_t S3;//sem_t S4;int valp;main( ){/* S1=sem_open("A",O_CREAT,0644,1);S2=sem_open("B",O_CREA T,0644,0);S3=sem_open("C",O_CREA T,0644,0);S4=sem_open("D",O_CREAT,0644,1);*/// sem_init(&S1,0,1);// sem_init(&S2,0,0);// sem_init(&S3,0,0);// sem_init(&S4,0,1);int fd1[2];int fd2[2];char pipe1[100],pipe2[100],pipe3[100];pipe(fd1); /*创建一个管道*/pipe(fd2);while ((pid1=fork( )) == -1);if(pid1 == 0){while ((pid2=fork( )) == -1);if(pid2==0){while(1){// S1=sem_open("A",O_EXCL);// sem_wait(S1);lockf(fd1[1],1,0);/*把输出串放入数组outpipe中*/printf("process1 is sending message to pipe1\n");sprintf(pipe1,"%d",rand());write(fd1[1],pipe1,50); /*向管道写长为50字节的串*/lockf(fd1[1],0,0);// printf("1111111111\n");// S2=sem_open("B",O_EXCL);// sem_post(S2);// printf("22222222222\n");}}else{while(1){//sem_open(const char *name,int oflag,mode_t mode,unsigned int value);// printf("33333333333\n");// S2=sem_open("B",O_EXCL);// sem_wait(S2);// printf("44444444444\n");// S4=sem_open("D",O_EXCL);// sem_wait(S4);printf("process2 is reading message from pipe1\n");read(fd1[0],pipe2,50);printf("process2 had received the message:%s\n",pipe2);lockf(fd2[1],1,0);printf("process2 is sending message to pipe2\n");write(fd2[1],pipe2,50);lockf(fd2[1],0,0);// S1=sem_open("A",O_EXCL);// sem_post(S1);// S3=sem_open("C",O_EXCL);// sem_post(S3);}}}else{while(1){// S3=sem_open("C",O_EXCL);// sem_wait(S3);printf("process3 is reading message from pipe2\n");read(fd2[0],pipe3,50);printf("process3 had received the message:%s\n",pipe3);// S4=sem_open("D",O_EXCL);// sem_post(S4);}}}程序运行结果:程序分析:程序实现了read,move和print的模拟。
进程通信实验
实验报告的基本内容及要求
1.实验预习
在实验前每位同学都需要对本次实验进行认真的预习,并写好预习报告,在预习报告中要写出实验目的、要求,需要用到的仪器设备、物品资料以及简要的实验步骤,形成一个操作提纲。
对实验中的安全注意事项及可能出现的现象等做到心中有数,但这些不要求写在预习报告中。
设计性实验要求进入实验室前写出实验方案。
2.实验记录
学生开始实验时,应该将记录本放在近旁,将实验中所做的每一步操作、观察到的现象和所测得的数据及相关条件如实地记录下来。
实验记录中应有指导教师的签名。
3.实验总结
主要内容包括对实验数据、实验中的特殊现象、实验操作的成败、实验的关键点等内容进行整理、解释、分析总结,回答思考题,提出实验结论或提出自己的看法等。
实验报告学院:专业:班级:
注:各学院可根据教学需要对以上栏木进行增减。
表格内容可根据内容扩充。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验八进程通信应用
实验目的
1. 掌握命名管道的原理和应用
2. 掌握文件映射共享内存的原理
3、掌握基于进程通信的程序设计方法
实验内容
1.(1)命令行下创建有名管道myfifo,ls –l查看,分别在两个终端运行cat < myfifo 和echo hello >myfifo分析执行情况,将cat在后台运行,echo在前台运行,执行情况如何?分析FIFO的打开规则。
(2)设计两个程序,要求用命名管道FIFO,实现文本文件复制功能,即实现copy file1 file2的功能,file1是已经存在的文件,file2可以不存在,如果存在就清空原来的内容,通过建立的有名管道实现file1的内容复制到file2。
一、 FIFO
1.有名管道的创建
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char * pathname, mode_t mode)
该函数的第一个参数是一个普通的路径名,也就是创建后FIFO的名字。
第二个参数与打开普通文件的open()函数中的mode 参数相同。
2. 有名管道的打开
有名管道创建成功后并没有打开,需要使用系统调用open( )将对应的文件打开。
open(const char*pathname,oflg)
其中,参数pathname是要打开的有名管道的路径名,oflg是文件打开时的存取方式。
必须指定的互斥模式:
O_RDONLY, O_WRONLY, O_NONBLOCK
O_RDONLY:若无进程写方式打开FIFO,open阻塞
O_RDONLY |O_NONBLOCK:若无进程写方式打开FIFO,open立即返回
O_WRONLY:若无进程读方式打开FIFO,open阻塞
O_WRONLY| O_NONBLOCK:若无进程读方式打开FIFO,open返回ENXIO错误,-1
FIFO的打开规则:
(1)如果当前打开操作是为读而打开FIFO时,若已经有相应进程为写而打开该FIFO,则当前打开操作将成功返回;否则,可能阻塞直到有相应进程为写而打开该FIFO(当前打开操作设置了阻塞标志);或者,成功返回(当前打开操作没有设置阻塞标志)。
(2)如果当前打开操作是为写而打开FIFO时,如果已经有相应进程为读而打开该FIFO,则当前打开操作将成功返回;否则,可能阻塞直到有相应进程为读而打开该FIFO(当前打开操作设置了阻塞标志);或者,返回ENXIO错误(当前打开操作没有设置阻塞标志)。
3.有名管道的读写
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
返回值: 读到的字节数,若已到文件尾为0,若出错为-1
ssize_t write(int fd, const void *buf, size_t count);
返回值: 若成功为已写的字节数,若出错为-1
从FIFO中读取数据read
以阻塞方式打开的FIFO,read调用:
①当前FIFO内没有数据,read调用将一直阻塞。
②当前FIFO内有数据,但有其它进程在读这些数据
解除阻塞的原因则是FIFO中有新的数据写入,不论信写入数据量的大小,也不论读操作请求多少数据量。
●以非阻塞方式打开的FIFO,read调用:
当前FIFO内没有数据,立即返回-1,当前errno值为EAGAIN,提醒以后再试。
向FIFO中写入数据write
●对于设置了阻塞标志的写操作:
当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。
如果此时管道空闲缓冲区不足以容纳要写入的字节数,则进入睡眠,直到当缓冲区中能够容纳要写入的字节数时,才开始进行一次性写操作。
当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。
FIFO缓冲区一有空闲区域,写进程就会试图向管道写入数据,写操作在写完所有请求写的数据后返回。
●对于没有设置阻塞标志的写操作:
当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。
如果当前FIFO 空闲缓冲区能够容纳请求写入的字节数,写完后成功返回;如果当前FIFO空闲缓冲区不能够容纳请求写入的字节数,则返回EAGAIN错误,提醒以后再写;
当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。
在写满所有FIFO空闲缓冲区后,写操作返回。
4.有名管道删除
有名管道和普通文件一样,存在于磁盘中。
但是有名管道不能直接存储文件,其存储的通讯信息在通信的两个进程结束后自动丢失。
与无名管道不同,通信的两个进程结束后,有名管道文件依然存在。
需要使用系统调用unlink( )删除有名管道文件。
头文件:
#include <unistd.h>
系统调用格式:
int unlink(const char *pathname);
unlink( )会删除参数pathname指定的文件。
二、 mmap
Linux提供了内存映射函数mmap, 它把文件内容映射到一段内存上, 通过对这段内存的读取和修改, 实现对文件的读取和修改。
头文件:<unistd.h> <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offsize);
返回值: 成功则返回映射区起始地址, 失败则返回MAP_FAILED(-1).
参数:
addr: 指定映射的起始地址, 通常设为NULL, 由系统指定.
length: 将文件的多大长度映射到内存.
prot: 映射区的保护方式, 可以是:
PROT_EXEC: 映射区可被执行.
PROT_READ: 映射区可被读取.
PROT_WRITE: 映射区可被写入.
PROT_NONE: 映射区不能存取.
flags: 映射区的特性, 可以是:
MAP_SHARED: 对映射区域的写入数据会复制回文件, 且允许其他映射该文件的进程共
享.
MAP_PRIVATE: 对映射区域的写入操作会产生一个映射的复制(copy-on-write), 对此区域所做的修改不会写回原文件.
MAP_ANONYMOUS:采取匿名映射。
fd: 由open返回的文件描述符, 代表要映射的文件,匿名映射时指定为-1。
offset: 以文件开始处的偏移量, 必须是分页大小的整数倍, 通常为0, 表示从文件头开始映射.
内存映射的步骤:
用open系统调用打开文件, 并返回描述符fd.
用mmap建立内存映射, 并返回映射首地址指针start.
对映射(文件)进行各种操作, 显示(printf), 修改(sprintf).
用munmap(void *start, size_t lenght)关闭内存映射.
用close系统调用关闭文件fd.
在修改映射的文件时, 只能在原长度上修改, 不能增加文件长度, 因为内存是已经分配好的。