实验6 进程间通信
进程间通信实验报告
![进程间通信实验报告](https://img.taocdn.com/s3/m/e2f505e8f8c75fbfc77db2f5.png)
软件学院计算机课程实验报告册课程名称计算机操作系统实验学期 2011 年至 2012 年第 2 学期学生所在院(系)软件学院年级 11软件专业班级软工(1)班学生姓名朱水云学号 **********指导教师陈自刚实验最终成绩软件学院实验室制2012 年 4 月实验报告( 二 ) 实验名称:进程间通信实验时间:2012年4月18号实验性质应用性设计性综合性5,观察运行结果,并思考6,退出中断并写出实验报告调试过程:根据编译提示的错误进行修改四、实验结果:1消息的发送和接受运行结果:2.共享存储区的创建、附接和段接运行结果:五、疑难与小结:1.消息的创建,发送和接收小结:从理想的结果来说,应当是每当Client发送一个消息后,server 接收该消息,Client再发送下一条。
也就是说“(Client)sent”和“(server)received”的字样应该在屏幕上交替出现。
实际的结果大多是,先由 Client 发送两条消息,然后Server接收一条消息。
此后Client Server交替发送和接收消息.最后一次接收两条消息. Client 和Server 分别发送和接收了10条消息,与预期设想一致message的传送和控制并不保证完全同步,当一个程序不再激活状态的时候,它完全可能继续睡眠,造成上面现象,在多次send message 后才 receive message.这一点有助于理解消息转送的实现机理.2.共享存储区的创建、附接和段接运行的结果和预想的完全一样。
但在运行的过程中,发现每当client 发送一次数据后,server要等大约0.1秒才有响应。
同样,之后client又需要等待大约0.1秒才发送下一个数据。
出现上述的应答延迟的现象是程序设计的问题。
当client端发送了数据后,并没有任何措施通知server端数据已经发出,需要由client的查询才能感知。
此时,client端并没有放弃系统的控制权,仍然占用CPU的时间片。
Linux系统编程实验六进程间通信
![Linux系统编程实验六进程间通信](https://img.taocdn.com/s3/m/71779487453610661ed9f4fa.png)
实验六:进程间通信实验目的:学会进程间通信方式:无名管道,有名管道,信号,消息队列,实验要求:(一)在父进程中创建一无名管道,并创建子进程来读该管道,父进程来写该管道(二)在进程中为SIGBUS注册处理函数,并向该进程发送SIGBUS信号(三)创建一消息队列,实现向队列中存放数据和读取数据实验器材:软件:安装了Linux的vmware虚拟机硬件:PC机一台实验步骤:(一)无名管道的使用1、编写实验代码pipe_rw.c#include <unistd.h>#include <sys/types.h>#include <errno.h>#include <stdio.h>#include <string.h>#include <stdlib.h>int main(){int pipe_fd[2];//管道返回读写文件描述符pid_t pid;char buf_r[100];char* p_wbuf;int r_num;memset(buf_r,0,sizeof(buf_r));//将buf_r初始化char str1[]=”parent write1 “holle””;char str2[]=”parent write2 “pipe”\n”;r_num=30;/*创建管道*/if(pipe(pipe_fd)<0){printf("pipe create error\n");return -1;}/*创建子进程*/if((pid=fork())==0) //子进程执行代码{//1、子进程先关闭了管道的写端close(pipe_fd[1]);//2、让父进程先运行,这样父进程先写子进程才有内容读sleep(2);//3、读取管道的读端,并输出数据if(read(pipe_fd[0],buf_r, r_num)<0){printf(“read error!”);exit(-1);}printf(“%s\n”,buf_r);//4、关闭管道的读端,并退出close(pipe_fd[1]);}else if(pid>0) //父进程执行代码{//1、父进程先关闭了管道的读端close(pipe_fd[0]);//2、向管道写入字符串数据p_wbuf=&str1;write(pipe_fd[1],p_wbuf,sizof(p_wbuf));p_wbuf=&str2;write(pipe_fd[1],p_wbuf,sizof(p_wbuf));//3、关闭写端,并等待子进程结束后退出close(pipe_fd[1]);}return 0;}/***********************#include <unistd.h>#include <sys/types.h>#include <errno.h>#include <stdio.h>#include <string.h>#include <stdlib.h>int main(){int pipe_fd[2];//管道返回读写文件描述符pid_t pid;char buf_r[100];char* p_wbuf;int r_num;memset(buf_r,0,sizeof(buf_r));//将buf_r初始化char str1[]="holle";char str2[]="pipe";r_num=10;/*创建管道*/if(pipe(pipe_fd)<0){printf("pipe create error\n");return -1;}/*创建子进程*/if((pid=fork())==0) //子进程执行代码{close(pipe_fd[1]);//1、子进程先关闭了管道的写端//2、让父进程先运行,这样父进程先写子进程才有内容读//3、读取管道的读端,并输出数据if(read(pipe_fd[0],buf_r, r_num)<0){printf("read1 error!");exit(-1);}printf("\nparent write1 %s!",buf_r);sleep(1);if(read(pipe_fd[0],buf_r, r_num)<0){printf("read2 error!");exit(-1);}printf("\nparent write2 %s!",buf_r);close(pipe_fd[1]);//4、关闭管道的读端,并退出exit(1);//printf("child error!");}else if(pid>0) //父进程执行代码{close(pipe_fd[0]);//1、父进程先关闭了管道的读端p_wbuf=str1;//2、向管道写入字符串数据write(pipe_fd[1],p_wbuf,sizeof(str1));sleep(1);p_wbuf=str2;write(pipe_fd[1],p_wbuf,sizeof(str2));close(pipe_fd[1]);//3、关闭写端,并等待子进程结束后退出exit(1);//printf("father error!");}return 0;}**************************/2、编译应用程序pipe_rw.c3、运行应用程序子进程先睡两秒让父进程先运行,父进程分两次写入“hello”和“pipe”,然后阻塞等待子进程退出,子进程醒来后读出管道里的内容并打印到屏幕上再退出,父进程捕获到子进程退出后也退出4、由于fork函数让子进程完整地拷贝了父进程的整个地址空间,所以父子进程都有管道的读端和写端。
进程间通信
![进程间通信](https://img.taocdn.com/s3/m/6fc15288250c844769eae009581b6bd97e19bc51.png)
《操作系统》实验报告年级、专业、班级 姓名进程间通信实验题目实验时间 2014.11.21 实验地点 A主0410实验成绩 实验性质 □验证性 □设计性 □综合性 教师评价:□算法/实验过程正确; □源程序/实验内容提交 □程序结构/实验步骤合理;□实验结果正确; □语法、语义正确; □报告规范;其他:评价教师签名:一、实验目的1. 了解管道通信的特点,掌握管道通信的使用方法。
2. 了解消息队列通信机制及原理,掌握消息队列相关系统调用的使用方法及功能。
3. 了解Linux系统共享存储区的原理及使用方法。
二、实验项目内容1. 管道通信(1)父进程创建管道和两个子进程p1和p2。
(2)子进程p1打开给定文件(如果没有,则创建文件),并向文件中写数据,写完关闭文件,然后向管道写入一条消息“ok",目的是通知进程p2可以读取文件内容了。
(3)子进程p2通过管道读取消息,如果消息是“ok”,则打开文件,读取文件内容,并将其输出到屏幕上,关闭文件.2. 消息队列(1)父进程创建消息队列和两个子进程p1和p2。
(2)子进程p1打开给定文件(如果没有,则创建文件),并向文件中写数据,写完关闭文件,然后向消息队列写入一条消息“1",目的是通知进程p2可以读取文件内容了。
(3)子进程p2从消息队列读取消息,如果收到消息,则打开文件,读取文件内容,并将其输出道屏幕上,关闭文件。
3. 共享存储(1)由父进程建立一块共享存储区,并创建两个子进程p1,p2,父进程负责查询存储区状态,以及删除该存储区。
(2)子进程p1链接到该共享存储区,然后向存储区写入数据,写完断开链接。
(3)子进程p2链接到该共享存储区,从存储区读数据,然后断开链接。
注意:为了便于各进程对存储区访问的同步,这里使用信号量方法。
三、实验过程或算法1. 管道通信#include<unistd.h>#include<stdio.h>#include<string.h>#include<stdlib.h>int main() {int pipefd[2];pid_t pid;char buf[100];int n;为0memset(buf, 0, sizeof(buf));//clear bufif(pipe(pipefd) < 0) {perror("pipe");exit(0);}pid = fork();if(pid == 0) { //child process 1close(pipefd[0]);//close read fdchar *msg="Hello,I am a Pipe user.";write(pipefd[1], msg, 50);}else if(pid > 0) {pid = fork();if(pid == 0) { //child process 2close(pipefd[1]);//close write fdread(pipefd[0], buf, sizeof(buf));fprintf(stdout, "read from pipe is:%s\n", buf);}else if(pid > 0) exit(0);}}2.消息队列//发送消息,msqid是队列id,msg是要发送的消息void sendmsg(int msqid,mymesg msg){printf("msqid:%d,msg:%s\n",msqid,msg.mtext);if((msgsnd(msqid, &msg, sizeof(msg.mtext), IPC_NOWAIT)) != 0){//消息发送函数printf("pid_1:send msg error!\n");}else{printf("pid_1:send msg: %s succeed!\n", msg.mtext);}}//接收消息,msqid是队列idint rcvmsg(int msqid){mymesg msg={0};AIT);int msg_len = msgrcv(msqid, &msg, sizeof(msg.mtext), 0, IPC_NOW //接收消息函数if(msg_len < 0){printf("pid_2:receive msg error!\n");return 0;}printf("pid_2:recv msg: %s\n", msg.mtext);return 1;}3.共享存储创建共享存储区 shmid = shmget(IPC_PRIV A TE, SIZE, IPC_CREAT|0600 ) ;//{if ( shmid < 0 )perror("get shm ipc_id error") ;return -1 ;}pid = fork() ;子进程p1if ( pid == 0 ){ //printf("I'm child1 process,my pid is %d.\n",getpid());P操作sem_p(sem_id); //链接到存储区 shmaddr = (char *)shmat( shmid, NULL, 0 ) ;//if ( (int)shmaddr == -1 ){perror("shmat addr error") ;return -1 ;}向存储区写数据strcpy( shmaddr, "Hi,This is share memory!\n") ;//shmdt( shmaddr ) ;//断开链接V操作sem_v(sem_id); //父进程} else if ( pid > 0) {//printf("I'm father process,my pid is %d.\n",getpid());pid = fork();sleep(1);子进程2创建if(pid==0){//printf("I'm child2 process,my pid is %d.\n",getpid());P操作sem_p(sem_id); //读取存储区状态到buf中flag = shmctl( shmid, IPC_STAT, &buf) ;//{if ( flag == -1 )perror("shmctl shm error") ;return -1 ;}printf("shm_segsz =%d bytes\n", buf.shm_segsz ) ;printf("parent pid=%d, shm_cpid = %d \n", getppid(), buf.shm_cpid ) ;printf("chlid pid=%d, shm_lpid = %d \n",pid, buf.shm_lpid ) ;printf("shm_segsz =%d \n", buf.shm_perm.mode );shmaddr = (char *) shmat(shmid, NULL, 0 ) ;链接到存储区,读取其中数据if ( (int)shmaddr == -1 ){//perror("shmat addr error") ;return -1 ;}//打印数据到屏幕printf("%s", shmaddr) ;V操作sem_v(sem_id); //断开链接shmdt( shmaddr) ;//}else{perror("fork error.") ;shmctl(shmid, IPC_RMID, NULL) ;}删除该存储区shmctl(shmid, IPC_RMID, NULL) ;//return 0 ;}四、实验结果及分析和(或)源程序调试过程(包含程序使用方法、程序运行截图),实验过程中遇到的问题分析与心得体会。
进程实验-进程间通信(管道、消息、共享内存、软中断)
![进程实验-进程间通信(管道、消息、共享内存、软中断)](https://img.taocdn.com/s3/m/e273f54d3186bceb18e8bb57.png)
进程实验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;}●输入并运行此程序,分析程序的运行结果。
实验6 进程间通信
![实验6 进程间通信](https://img.taocdn.com/s3/m/c50d2d8584868762caaed587.png)
实验6 进程间通信一、实验目的:通过本实验了解和掌握进程间通讯的相关知识,(1)了解进程通信的基本原理。
(2)了解和熟悉管道通信,消息传送机制及共享存储机制。
二.实验内容1.进程的管道通信阅读下列程序,完成实验任务。
#include<unistd.h>#include<signal.h>#include<stdio.h>int pid1,pid2;main(){int fd[2];char outpipe[100],inpipe[100];pipe(fd); //将fd装入管道中while((pid1=fork())==-1); //如果进程没有创建成功,则一直循环if(pid1==0) //如果是子进程{lockf(fd[1],1,0);sprintf(outpipe,"chile 1 process a message!");//将字符串读入到oupipe中去write(fd[1],outpipe,50); //将outpipe写入到fd[1]中sleep(5); //睡眠5秒lockf(fd[1],0,0);exit(0);}else //是父进程{while((pid2=fork())==-1);if(pid2 == 0) //进程创建成功,并且是子进程{lockf(fd[1],1,0);sprintf(outpipe,"child 2 process is sending a message!");write(fd[1],outpipe,50);sleep(5);lockf(fd[1],0,0);exit(0);}else{wait(0); //等待进程read(fd[0],inpipe,50); //将inpipe读入fd[0]中去,printf("%s\n",inpipe); //打印出子进程2wait(0);read(fd[0],inpipe,50);printf("%s\n",inpipe); //打印出子进程1exit(0);}}}实验任务:(1),读懂上面的程序,编译执行,分析为什么会出现这样的结果。
操作系统实验报告(进程间的共享存贮区和信号量通信)
![操作系统实验报告(进程间的共享存贮区和信号量通信)](https://img.taocdn.com/s3/m/f4ef04d350e2524de5187efe.png)
case -1:perror("fork()");exit(0);case 0:do_child_loop(sem_set_id,FILE_NAME);exit(0);default:break;}}for(i = 0;i<10;i++){int child_status;wait(&child_status);}printf("main is done");fflush(stdout);return 0;}运行结果:二、共享主存段机制共享主存段为进程提供了直接通过主存进行通信的有效手段,不像消息缓存机制那样需要系统提供缓存,也不像pipe机制那样需要事先建立一个特殊文件,而是有通信双方直接访问某些共享虚拟存储器空间。
在系统V中,系统管理一组共享主存段控制块。
通信进程在使用共享主存段以前,首先提出申请,系统为止分配存储空间并返回共享主存段标识号。
一个共享段建立后,进程把它被附加到自己的虚拟存储空间中。
一个进程可以附加多个共享主存段。
一个主存段一旦被附加到进程的虚拟机空间后,对它的访问以其他虚拟机的访问完全相同。
但为了保证共享主存段数据完整性,通信的进程之间要互斥的进行访问。
当通信进程不再需要该共享主存段时,可使用命令将其与进程分离,从而使其进程的虚空间删除。
为了理解进程通过共享主存段的通信过程,下面举例,一个是进程向共享段写信息的例子:一个是进行从共享段读信息的例子。
代码如下:四、实验过程与分析一、信号量机制在第一个例子的程序中创建了5个并发子进程,互斥地对文件进行写操作,将自己的进程号写到文件中去,信号量的初值为1,当地一个进程执行update_file函数时首先将信号量值-1,(相当于P操作)致使其它进程等待无法操作文件,直到其结束后,将其值变为1后(相当于V操作),其它进程并发竞争对文件的写操作,并将自己的pid 写入文件中。
在linux中信号量机制的执行既步骤如下所示:(1)信号量的定义:struct semaphore {spinlock_t lock;unsigned int count;struct list_head wait_list;};在linux中,信号量用上述结构体表示,我们可以通过该结构体定义一个信号量。
进程通讯管理实验报告(3篇)
![进程通讯管理实验报告(3篇)](https://img.taocdn.com/s3/m/eeada26fbb1aa8114431b90d6c85ec3a87c28b8d.png)
第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()函数删除消息队列。
进程间通信实验.docx
![进程间通信实验.docx](https://img.taocdn.com/s3/m/17f02a493b3567ec102d8ad5.png)
进程间通信实验8000114134 欧阳为软工143Q1:使用无名管道pipe(),进行父子进程之间的通信。
A1:截图如下:分析:这段程序使用匿名管道,实现了同一进程组(父子进程间)的通信。
首先父进程使用函数pipe( )创建一个匿名管道,chan1[ ]被填入两个文件描述符,在该程序中chan[0]负责读操作,chan[1]负责写操作;创建匿名管道之后使用fork( )创建子进程,由于匿名管道是半双工的,即数据只能向一个方向流动,父进程写入数据,子进程读出,如果子进程一直不读出数据,写操作就会阻塞;程序为了保证正确通信,在父进程执行写操作时关闭读管道(close(chan1[0]));子进程读期间,关闭写管道。
Q2:以命名行为参数的管道文件的示例。
(假设有一个可执行程序chcase,从标准输入设备读字符,将小写字母转化成大写字母并输出。
主程序使用popen创建管道,实现蒋某文本文件中的字幕转化成大写字母,其中的文本文件名作为参数传进来。
)A2:截图如下:分析:在执行该程序之前,首先编译完成字符串大小写转变程序chcase以及文本文件chcase.txt。
在执行该程序时,文本文件需要作为参数传入;程序首先使用fopen()打开文本文件,若文本文件存在打开成功,则使用popen( )函数打开一个管道,popen( )函数用创建管道的方式启动一个进程,又因为管道是单向的,所以其type 参数只能定义成只读或者只写,如图:启动进程为只写,此时popen( )创建了一个只写管道,将命令行chcase 的输入与管道的输入连接,向管道输入数据,进程chcase 读出数据并将数据转化为大写。
Q3:创建有名管道A3:截图如下:分析:使用mknod()创建一个命名管道fifo,第一个参数是要创建的管道名,第二个参数指文件类型,第三个参数指设备号(普通文件设备号为0),命名管道遵循先进先出原则。
当输入命令的参数小于2时,进程为读数据而打开命名管道,而在之前并未因为写操作而打开管道,即管道中并没有数据,所以进程阻塞;输入命令参数等于2 ,进程打开管道写入数据,将字符串string的数据写入fifo 文件,最后输入小于2的命令行参数,进程读数据并输出。
进程之间的通信实验
![进程之间的通信实验](https://img.taocdn.com/s3/m/27693c3d0912a21614792915.png)
实验:进程之间的通信管道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中的两个命令的组合。
chapter06 进程间通信(IPC)
![chapter06 进程间通信(IPC)](https://img.taocdn.com/s3/m/a07a931cc5da50e2524d7f2a.png)
第6章 进程间通信(IPC)
主要内容:
进程间通信机制概述
信号处理 管道 System V IPC机制
精通Linux C编程
指多进程间相互通信、交换信息的方法。
一、进程间通信机制概述
1、信号
信号本质 信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程 收到一个信号与处理器收到一个中断请求可以说是一样的。信号是异步 的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不 知道信号到底什么时候到达。 信号是进程间通信机制中唯一的异步通信机制。信号机制经过 POSIX实时扩展后,功能更加强大,除了基本通知功能外,还可以传递 附加信息。 信号来源 信号事件的发生有两个来源:硬件来源(比如我们按下了键盘或者 其它硬件故障);软件来源,最常用发送信号的系统函数是kill, raise, alarm和setitimer以及sigqueue函数,软件来源还包括一些非法运算等 操作。
精通Linux C编程
二、信号处理
2、处理信号的系统函数
(2)高级信号处理
Linux系统还提供另一功能更强的系统调用sigaction: int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); 其中,参数signum指定要处理的信号(除SIGKILL和SIGSTOP之外)。act 和oldact都是指向信号动作结构的指针。
共享内存原理示意图
精通Linux C编程
二、信号处理
1、信号类型
精通Linux C编程
二、信号处理
1、信号类型
收到信号的进程对各种信号的处理方法有以下几种: (1)忽略某个信号,对该信号不做任何处理,就象未发生过一样。 但是有两个信号不能忽略:SIGSTOP和SIGKILL。
Linux进程间通信实验报告
![Linux进程间通信实验报告](https://img.taocdn.com/s3/m/3db8c6b5172ded630b1cb6db.png)
实验六:Linux进程间通信(2)(4课时)实验目的:理解进程通信原理;掌握进程中信号量、共享内存、消息队列相关的函数的使用。
实验原理:Linux下进程通信相关函数除上次实验所用的几个还有:信号量信号量又称为信号灯,它是用来协调不同进程间的数据对象的,而最主要的应用是前一节的共享内存方式的进程间通信。
要调用的第一个函数是semget,用以获得一个信号量ID。
int semget(key_t key, int nsems, int flag);key是IPC结构的关键字,flag将来决定是创建新的信号量集合,还是引用一个现有的信号量集合。
nsems是该集合中的信号量数。
如果是创建新集合(一般在服务器中),则必须指定nsems;如果是引用一个现有的信号量集合(一般在客户机中)则将nsems指定为0。
semctl函数用来对信号量进行操作。
int semctl(int semid, int semnum, int cmd, union semun arg);不同的操作是通过cmd参数来实现的,在头文件sem.h中定义了7种不同的操作,实际编程时可以参照使用。
semop函数自动执行信号量集合上的操作数组。
int semop(int semid, struct sembuf semoparray[], size_t nops);semoparray是一个指针,它指向一个信号量操作数组。
nops规定该数组中操作的数量。
ftok原型如下:key_t ftok( char * fname, int id )fname就是指定的文件名(该文件必须是存在而且可以访问的),id是子序号,虽然为int,但是只有8个比特被使用(0-255)。
当成功执行的时候,一个key_t值将会被返回,否则 -1 被返回。
共享内存共享内存是运行在同一台机器上的进程间通信最快的方式,因为数据不需要在不同的进程间复制。
通常由一个进程创建一块共享内存区,其余进程对这块内存区进行读写。
实验六进程间通信
![实验六进程间通信](https://img.taocdn.com/s3/m/49c7bfd9763231126edb11df.png)
信号处理程序在用户态下运行,而中断处理程序在核心态下运行
中断响应是及时的,而信号响应a 通常都有较大的时间延迟
10
1.2 进程软中断通信—信号机制的功能
❖ 发送信号
发送进程把信号送到指定进程信号域的某一位上,如目标进 程正在一个可被中断的优先级上睡眠,核心便将其唤醒
❖ 预置对信号的处理方式
进程处于核心态时,即使受到软中断也不予理睬;只有当它 返回到用户态后,才处理软中断信号
管道只能用于父子进程或兄弟进程之间
管道对于管道两端的进程而言就是一个文件,并单独构 成一种文件系统,存在于内存中
写管道的内容添加在管道缓冲区的末尾,读管道则从缓 冲区头部读出
❖ 有名管道在普通管道具备功能基础上,通过给管道
命名的方法变成管道文件,允许无亲缘关系进程间
通过访问管道文件进行通信
a
4
1.1 Linux进程间通信—信号
❖ 消息的发送:msgsnd(int msgqid, const void *msgp_ptr, size_t msg_sz, int msgflg);
❖ 消息的接收:msgrcv(int msgqid, void *msgp_ptr, size_t msg_sz, long int msgtype, int msgflg);
❖ 可以用流管道或套接口方式取代
a
6
1.1 Linux进程间通信—共享内存
❖ 在系统内核分配一块缓冲区,多个进程都可以访问 该缓冲区
❖ 效率高:进程可以直接读写内存,不需任何数据拷 贝,避免了内核空间与用户空间的切换
❖ 同步和协议都不受程序员控制,必须确保将句柄传 递给子进程和线程,需与其它通信机制结合使用, 来达到进程间的同步及互斥
进程控制与进程通信程序实验报告
![进程控制与进程通信程序实验报告](https://img.taocdn.com/s3/m/0adbb66d76232f60ddccda38376baf1ffc4fe3bf.png)
进程控制与进程通信程序实验报告1. 背景进程控制与进程通信是操作系统的重要概念之一,它们在现代计算机系统中起到了至关重要的作用。
进程控制是指操作系统对进程的创建、执行、中止和切换等各种操作的管理和控制,进程通信则是指进程之间通过各种方式传递信息和实现协作的机制。
在本次实验中,我们需要编写一个进程控制与进程通信程序。
通过实现进程的创建、执行和中止等基本操作,并通过进程通信机制进行信息传递,实现多个进程之间的协作。
本实验将帮助我们进一步理解和掌握进程控制与进程通信的原理和操作。
2. 分析2.1 实验要求本次实验要求我们编写一个进程控制与进程通信程序,实现以下功能:1.创建一个主进程和多个子进程,并实现进程的执行和切换;2.子进程之间通过进程通信机制传递信息;3.实现多个子进程之间的协作,完成指定的任务。
2.2 系统设计为了满足实验的要求,我们可以按照以下步骤设计我们的系统:1.创建主进程和多个子进程:使用操作系统提供的进程创建函数,创建一个主进程和多个子进程。
主进程将负责协调子进程的执行和协作。
2.进程执行和切换:使用操作系统提供的进程执行和切换函数,实现进程的执行和切换操作。
主进程可以通过改变进程的状态和优先级来控制进程的执行和切换。
3.进程通信机制:使用操作系统提供的进程通信机制,如消息队列、共享内存等,实现子进程之间的信息传递。
可以定义统一的消息格式,并使用相应的函数进行消息的发送和接收。
4.进程协作:根据实验要求,设计子进程之间的协作方式。
可以使用信号量、条件变量等机制来实现多个子进程之间的同步和互斥。
2.3 实验结果实验的结果将是一个能够创建多个子进程,并通过进程通信进行协作的程序。
程序将实现以下功能:1.主进程创建多个子进程,并通过改变进程的状态和优先级来控制进程的执行;2.子进程通过进程通信机制传递信息,完成指定的任务;3.子进程之间通过协作实现同步和互斥,保证任务的正确执行。
3. 实验步骤3.1 创建进程首先,我们需要创建主进程和多个子进程。
操作系统实验---进程通信
![操作系统实验---进程通信](https://img.taocdn.com/s3/m/e5a026dd77232f60dccca153.png)
实验报告实验题目姓名:学号:课程名称:操作系统实验所在学院:信息科学与工程学院专业班级:计算机任课教师:五、实验数据(现象)处理分析信号机制实验建立文件和可执行文件:信号机制实验运行结果:屏幕上无反应,按下^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 支持的信号量机制、管道机制、消息通信机制及共享存储区机制的基本原理和基本概念。
对信号和中断有了进一步的理解,能够分辨出两者的区别和相似点。
观察实验现象知道了信号的发送方式和处理方式。
掌握了信号的发送,是指由发送进程把信号送到指定进程的信号域的某一位上。
如果目标进程正在一个可被中断的优先级上睡眠,核心便将它唤醒,发送进程就此结束。
一个程可能在其信号域中有多个位被置位,代表有多种类型的信号到达,但对于一类信号,进程却只能记住其中的某一个。
通过本次实验最终目的还是全面了解进程的各种机制以及处理方法。
进程通信实验报告
![进程通信实验报告](https://img.taocdn.com/s3/m/e4cf8a1fa300a6c30c229fae.png)
西安电子科技大学《操作系统原理》实验报告题目:进程通信实验报告班级: 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_)。
进程控制与进程间通信操作系统实验报告
![进程控制与进程间通信操作系统实验报告](https://img.taocdn.com/s3/m/4166ebbe87c24028905fc362.png)
工程大学实验报告专业班级:姓名:学号:课程名称:操作系统实验成绩:指导教师:蔡敦波实验名称:进程控制与进程间通信一、实验目的:1、掌握进程的概念,明确进程和程序的区别。
2、认识和了解并发执行的实质。
3、了解什么是信号。
4、熟悉LINUX系统中进程之间软中断通信的基本原理。
二、实验内容:1、进程的创建(必做题)编写一段程序,使用系统调用fork( )创建两个子进程,在系统中有一个父进程和两个子进程活动。
让每个进程在屏幕上显示一个字符;父进程显示字符“a”,子进程分别显示字符“b”和“c”。
试观察记录屏幕上的显示结果,并分析原因。
<参考程序>运行的结果是bca. 首先创建进程p1,向子进程返回0,输出b.又创建进程p2,向子进程返回0,输出c,同时向父进程返回子进程的pid,输出a2、修改已编写的程序,将每个进程的输出由单个字符改为一句话,再观察程序执行时屏幕上出现的现象,并分析其原因。
(必做题)<参考程序># include<stdio.h>int main(){ int p1, p2, i;while((p1=fork())= = -1);if(p1= =0)for(i=0;i<500;i++)printf(“child%d\n”,i);else{ while((p2=fork())= =-1);If(p2= =0)for(i=0;i<500;i++)printf(“son%d\n”,i);elsefor(i=0;i<500;i++)printf(“daughter%d\n”,i);}}运行的结果是如上图所示. 首先创建进程p1,向子进程返回0,并for语句循环输出child +i字符串.又创建进程p2,向子进程返回0,输出字符串son+i,同时向父进程返回子进程的pid,输出字符串duaghter +i ,各打印5次。
3、编写程序创建进程树如图1和图2所示,在每个进程中显示当前进程识别码和父进程识别码。
进程间通信实验资料
![进程间通信实验资料](https://img.taocdn.com/s3/m/fc2d4b1fb52acfc788ebc90f.png)
进程间通信(1)调试以下程序给出运行结果并分析其程序原理:#include <stdio.h>#include <unistd.h>#include <wait.h>#include <signal.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>(1)编写两个程实现进程的无名管道和有名管道通信。
要求分别调用pipe()、close()、write()、read()、popen()、pclose()、mknod()、mkfifo()、open()实现多个进程间的通信。
1.使用无名管道pipe(),进行父子进程之间的通信。
编写的程序如下:fork函数执行完毕后,返回值pid<0,则子进程创建失败,pid>0,则运行父进程,关闭读操作,进行写操作,将信息写进管道,写完后关闭写操作,父进程挂起。
Pid=0,运行子程序,关闭写操作,进行读操作,读完信息关闭读操作,子进程运行结束,父进程继续运行。
2.以命名行为参数的管道文件的示例。
(假设有一个可执行程序chcase,从标准输入设备读字符,将小写字母转化成大写字母并输出。
主程序使用popen创建管道,实现蒋某文本文件中的字幕转化成大写字母,其中的文本文件名作为参数传进来。
)命令行数量不为2时,输出结果如图所示;创建一个可执行程序chcase,此程序从标准输入设备读字符,将小写字母转化成大写字母并输出。
主程序使用popen()创建一个管道。
再创建一个文本文件,输入将要转换成大写字母的小写字母。
Popen创建的管道一头与文本文件相连,获取文本文件中的信息,将此信息通过管道传送给与管道另一端相连的可执行程序chcase,chcase获取文本文件中的小写字母后,将小写字母转换成大写字母输出。
操作系统实验报告 进程间通信
![操作系统实验报告 进程间通信](https://img.taocdn.com/s3/m/3768f3c058f5f61fb736668c.png)
《计算机操作系统》实验报告(二)学号:030702412 姓名:陈楠学院:数计学院专业:计算机类年级:2007级班级:4班实验时间:2009-2010学年第一学期指导教师:丁善镜、黄志华目录1、实验题目 (3)2、实验目的 (3)3、实验环境 (3)4、实验原理 (3)5、实验内容 (3)5.1、fork()函数机理探索...........................................................错误!未定义书签。
5.1.1、原始代码段................................................................错误!未定义书签。
5.1.2、代码段修改一............................................................错误!未定义书签。
5.1.3、结论(1) .......................................................................错误!未定义书签。
5.1.4、fock()函数原理...........................................................错误!未定义书签。
5.1.5、代码段修改二............................................................错误!未定义书签。
5.2、并发执行测猜测................................................................错误!未定义书签。
5.2.1、并发执行改进............................................................错误!未定义书签。
Linux系统编程实验六进程间通信
![Linux系统编程实验六进程间通信](https://img.taocdn.com/s3/m/cffea4dff605cc1755270722192e453610665b1e.png)
Linux系统编程实验六进程间通信实验六:进程间通信●实验目的:学会进程间通信方式:无名管道,有名管道,信号,消息队列,●实验要求:(一)在父进程中创建一无名管道,并创建子进程来读该管道,父进程来写该管道(二)在进程中为SIGBUS注册处理函数,并向该进程发送SIGBUS信号(三)创建一消息队列,实现向队列中存放数据和读取数据●实验器材:软件:安装了Linux的vmware虚拟机硬件:PC机一台●实验步骤:(一)无名管道的使用1、编写实验代码pipe_rw.c#include#include#include#include#include#includeint main(){int pipe_fd[2];//管道返回读写文件描述符pid_t pid;char buf_r[100];char* p_wbuf;int r_num;memset(buf_r,0,sizeof(buf_r));//将buf_r初始化char str1[]=”parent write1 “holle””;char str2[]=”parent write2 “pipe”\n”;r_num=30;/*创建管道*/if(pipe(pipe_fd)<0){printf("pipe create error\n");return -1;}/*创建子进程*/if((pid=fork())==0) //子进程执行代码{//1、子进程先关闭了管道的写端close(pipe_fd[1]);//2、让父进程先运行,这样父进程先写子进程才有内容读sleep(2);//3、读取管道的读端,并输出数据if(read(pipe_fd[0],buf_r, r_num)<0){printf(“read error!”);exit(-1);}printf(“%s\n”,buf_r);//4、关闭管道的读端,并退出close(pipe_fd[1]);}else if(pid>0) //父进程执行代码{//1、父进程先关闭了管道的读端close(pipe_fd[0]);//2、向管道写入字符串数据p_wbuf=&str1write(pipe_fd[1],p_wbuf,sizof(p_wbuf));p_wbuf=&str2write(pipe_fd[1],p_wbuf,sizof(p_wbuf));//3、关闭写端,并等待子进程结束后退出close(pipe_fd[1]);}return 0;}/***********************#include#include#include#include#include#includeint main(){int pipe_fd[2];//管道返回读写文件描述符pid_t pid;char buf_r[100];char* p_wbuf;int r_num;memset(buf_r,0,sizeof(buf_r));//将buf_r初始化char str1[]="holle";char str2[]="pipe";r_num=10;/*创建管道*/if(pipe(pipe_fd)<0){printf("pipe create error\n");return -1;}/*创建子进程*/if((pid=fork())==0) //子进程执行代码{close(pipe_fd[1]);//1、子进程先关闭了管道的写端//2、让父进程先运行,这样父进程先写子进程才有内容读//3、读取管道的读端,并输出数据if(read(pipe_fd[0],buf_r, r_num)<0){printf("read1 error!");exit(-1);}printf("\nparent write1 %s!",buf_r);sleep(1);if(read(pipe_fd[0],buf_r, r_num)<0){printf("read2 error!");exit(-1);}printf("\nparent write2 %s!",buf_r);close(pipe_fd[1]);//4、关闭管道的读端,并退出exit(1);//printf("child error!");}else if(pid>0) //父进程执行代码{close(pipe_fd[0]);//1、父进程先关闭了管道的读端p_wbuf=str1;//2、向管道写入字符串数据write(pipe_fd[1],p_wbuf,sizeof(str1));sleep(1);p_wbuf=str2;write(pipe_fd[1],p_wbuf,sizeof(str2));close(pipe_fd[1]);//3、关闭写端,并等待子进程结束后退出exit(1);//printf("father error!");}return 0;}**************************/2、编译应用程序pipe_rw.c3、运行应用程序子进程先睡两秒让父进程先运行,父进程分两次写入“hello”和“pipe”,然后阻塞等待子进程退出,子进程醒来后读出管道里的内容并打印到屏幕上再退出,父进程捕获到子进程退出后也退出4、由于fork函数让子进程完整地拷贝了父进程的整个地址空间,所以父子进程都有管道的读端和写端。
实验六 进程间通信
![实验六 进程间通信](https://img.taocdn.com/s3/m/1b6da23b3968011ca3009163.png)
实验进程间通信
一、实验目的
1.理解管道机制、消息缓冲队列、共享存储区机制进行进程间的通信。
2.理解通信机制。
二、实验内容
1.使用管道来实现父进程之间的进程通信。
2.使用消息缓冲队列来实现Client进程和server进程之间的通信。
3.使用共享存储区来实现两个进程之间的进程通信。
三、参考代码
1.使用管道来实现父子进程之间的进程通信。
#include<unistd.h>
#include<signal.h>
#include<stdio.h>
int pid;
main()
{
int fd[2];
char OutPipe[300],InPipe[300];
pipe(fd);
while((pid=fork())==-1);
if(pid==0)
{
lockf(fd[1],1,0);
sprintf(OutPipe,"child's PID=%d\n%s",getpid(),"is sending a message to parent!\n");
write(fd[1],OutPipe,50);
sleep(5);
lockf(fd[1],0,0);
exit(0);
}
else
{
wait(0);
read(fd[0],InPipe,50);
printf("%s\n",InPipe);
exit(0);
}
}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验6 进程间通信一、实验目的:通过本实验了解和掌握进程间通讯的相关知识,(1)了解进程通信的基本原理。
(2)了解和熟悉管道通信,消息传送机制及共享存储机制。
二.实验内容1.进程的管道通信阅读下列程序,完成实验任务。
#include<unistd.h>#include<signal.h>#include<stdio.h>int pid1,pid2;main(){int fd[2];char outpipe[100],inpipe[100];pipe(fd); //将fd装入管道中while((pid1=fork())==-1); //如果进程没有创建成功,则一直循环if(pid1==0) //如果是子进程{lockf(fd[1],1,0);sprintf(outpipe,"chile 1 process a message!");//将字符串读入到oupipe中去write(fd[1],outpipe,50); //将outpipe写入到fd[1]中sleep(5); //睡眠5秒lockf(fd[1],0,0);exit(0);}else //是父进程{while((pid2=fork())==-1);if(pid2 == 0) //进程创建成功,并且是子进程{lockf(fd[1],1,0);sprintf(outpipe,"child 2 process is sending a message!");write(fd[1],outpipe,50);sleep(5);lockf(fd[1],0,0);exit(0);}else{wait(0); //等待进程read(fd[0],inpipe,50); //将inpipe读入fd[0]中去,printf("%s\n",inpipe); //打印出子进程2wait(0);read(fd[0],inpipe,50);printf("%s\n",inpipe); //打印出子进程1exit(0);}}}实验任务:(1),读懂上面的程序,编译执行,分析为什么会出现这样的结果。
答:分别将子进程1,2写入fd[1]中去,然后在fd[0]中打印出来。
(2),解释程序中sleep(5)语句的作用。
答:主要是起休眠作用。
如果去掉的话,两条语句一下子就打印到屏幕上,没法体现管道传送的过程。
实验截图如上。
2.共享存储区的创建,附接合断接。
使用系统调用shmget(),shmat(),shmdt()合shmct1(),编制一个长度为1kb的消息发送和接收程序。
源代码如下。
#include<sys/types.h>#include<sys/shm.h>#include<sys/ipc.h>#include<errno.h>#include<unistd.h>#include<stdio.h>#include<stdlib.h>#define SHMKEY 75int shmid,i;int *addr;int p1,p2;CLIENT() //客户端{int i;shmid =shmget(SHMKEY,1024,0777); //创建一个共享区SHMKEY为共享区区的名字,1024字节,0777为设置的标志。
addr = shmat(shmid,NULL,0); //shmat 共享存储区的附接。
将一个共享区附接到一个虚拟的地址空间上。
Shmid为连接共享区的标志,addr连接地址(区间),0表示返回的地址。
for(i = 10;i>=1;i--){while(*addr!=-1); //如果没有连接好地址,则一直循环printf("(client)sent:%d\n",i); //如果连接成功,输入i的值*addr = i; //将i的值赋给连接的地址}exit(0);}SERVER() //服务器{shmid = shmget(SHMKEY,1024,0777|IPC_CREAT);addr=(int*)shmat(shmid,NULL,0);do{*addr = -1;while(*addr == -1);printf("(server)received:%d\n",(*addr));//输出连接好的地址信息}while(*addr);shmctl(shmid,IPC_RMID,0);exit(0);}main(){p1 = fork();if(p1)SERVER();system("ipcs -m");p2=fork();if(p2)CLIENT();}实验任务:分析程序运行机制和过程,写出并分析程序运行结果。
实验截图如上。
3.消息的创建、发送和接收。
实验任务:使用系统调用msgget()、msgsnd()、msgrcv()及msgct1()编写一个内容与2(共享存储区,如上)功能相同的程序,并分析程序运行结果。
#include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<sys/types.h>#include<sys/msg.h>#include<sys/ipc.h>#include<sys/wait.h>#include<string.h>#define MSGKEY 75struct msgform{long mtype;char mtext[1030];}msg;int msgqid,i;void CLIENT(){msgqid = msgget(MSGKEY,0777);msg.mtype = 1;strcpy (msg.mtext,"hello,world\n");printf("(client)sent\n");msgsnd(msgqid,&msg,1024,0);}void SERVER(){msgqid = msgget(MSGKEY,0777|IPC_CREAT);msgrcv(msgqid,&msg,1030,1,0);printf("(server)receiver:%s\n",msg.mtext);msgctl(msgqid,IPC_RMID,0);}main(){system("ipcs -q");if(fork())SERVER();else CLIENT();wait(0);wait(0);}四、信号机制实验任务:在Linux 下编程,主进程用fork()创建两个子进程,主进程重复显示一首歌词,期间当程序收到窗口传来的kill命令信号时(如使用Ctrl + C传进来的中断信号),显示“我是机器不止九条命!!!”然后继续显示歌词,并向两个子进程分别发送中断信号,子进程1受到中断信号后,显示“。
”,并结束运行,子进程2收到中断信号后,显示“。
”,并结束运行,主进程等待两个进程均结束后,输出“。
”,后终止运行。
#include <stdio.h>#include <stdlib.h>#include <signal.h>int p1,p2,i;void methodfunc(){printf("\n我是机器猫,我有九条命!\n");kill(p1,160);kill(p2,170);// exit(0);}void child1(){printf("\n我是大儿子,我生的伟大\n");exit(0);}void child2(){printf("\n我是小儿子,我死的光荣\n");exit(0);}main(){p1=fork();if(p1==0){while(1){sleep(1);signal(160,child1);signal(SIGINT,child1);}p2 = fork();}else{p2 = fork();if(p2==0){while(1){sleep(1);signal(170,child2);signal(SIGINT,child2);}}for(i=0;i<10;i++){sleep(1);printf("\n一个像秋天,一个像夏天\n");signal(SIGINT,methodfunc);}}printf("\n我是父亲,啊,伤心再见!!\n");}五、实验心得在此次试验中,感触最深的是还是子进程创建试验,虽然逻辑很简单,但是对fork ()函数不是很了解,导致试验做了很长时间,还有就是发送kill命令是,要子进程接收到,也是一个问题,通过长时间的测试,终于将试验中如何创建两个子进程,一个父进程,父进程首先接收到中断命令后,发送kill命令,然后子进程受到kill命令,作出反应,然后继续跳转到主进程中,等待程序结束,最终打印出“我是父亲,伤心啊,再见。
”程序便结束掉。