实验五进程间通信

合集下载

进程间通信

进程间通信

《操作系统》实验报告年级、专业、班级 姓名进程间通信实验题目实验时间 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 ;}四、实验结果及分析和(或)源程序调试过程(包含程序使用方法、程序运行截图),实验过程中遇到的问题分析与心得体会。

实验5 进程间通信实验

实验5 进程间通信实验

实验五进程间通信实验一、实验目的1、了解什么是信号。

2、熟悉LINUX系统中进程之间软中断通信的基本原理。

3、了解什么是管道4、熟悉UNIX/LINUX支持的管道通信方式二、实验内容1、编写一段程序,使用系统调用fork( )创建两个子进程,再用系统调用signal( )让父进程捕捉键盘上来的中断信号(即按ctrl+c键),当捕捉到中断信号后,父进程用系统调用kill( )向两个子进程发出信号,子进程捕捉到信号后,分别输出下列信息后终止:Child process 1 is killed by parent!Child process 2 is killed by parent!父进程等待两个子进程终止后,输出以下信息后终止:Parent process is killed!<参考程序>#include<stdio.h>#include<signal.h>#include<unistd.h>#include<sys/types.h>#include<sys/wait.h>int wait_mark;void waiting(),stop();void main(){int p1, p2;signal(SIGINT,stop);while((p1=fork())==-1);if(p1>0) /*在父进程中*/{while((p2=fork())==-1);If(p2>0) /*在父进程中*/{wait_mark=1;waiting(0);kill(p1,10);kill(p2,12);wait( );wait( );printf("parent process is killed!\n");exit(0);}else /*在子进程2中*/{wait_mark=1;signal(12,stop);waiting();lockf(1,1,0);printf("child process 2 is killed by parent!\n");lockf(1,0,0);exit(0);}}else /*在子进程1中*/{wait_mark=1;signal(10,stop);waiting();lockf(1,1,0);printf("child process 1 is killed by parent!\n");lockf(1,0,0);exit(0);}}void waiting(){while(wait_mark!=0);}void stop(){wait_mark=0;}实验要求:⑴运行程序并分析结果。

实验五 进程通信

实验五  进程通信

(2)读管道 在管道创建后,希望从管道中读取数据的进程使 用读文件描述符fd[0]作为参数,调用read( )系统调用。 #include <unistd.h> ssize_t read(int fd,void *buf,size_t nbytes); 返回:读到的字节数,若已到文件尾为0,若出错 为-1。 (3)写管道 向管道中写入数据的进程使用写文件描述符fd[1] 作为参数,调用write( )系统调用。 #include <unistd.h> ssize_t write(int fd,const void *buf,size_t nbytes); 返回:若成功为已写的字节数,若出错为-1。
2. 管道是UNIX系统中最早为两个进程之间提 供的一种通信机制。管道是一种单向的、先入 先出的、无结构的、大小固定的通信通道。写 进程在管道的一端写入数据,读进程从管道的 另一端读出数据。如果两个或多个进程同时对 一个进程进行读写,那么这些进程必须使用锁 机制或者信号量机制对其进行同步。 管道分为无名管道和有名管道。无名管道 没有名字,所以只能提供给进程家族中的父子 进程间通信使用,而有名管道则用于没有家族 关系的任意两个进程之间的通信。
wait(0); read(fd[0], inpipe, 50); printf(“%s\n”, inpipe); wait(0); read(fd[0], inpipe, 50); printf(“%s\n”, inpipe); exit(0);
}
} }Байду номын сангаас四. 试验总结
1. 写出试验报告。 2. 为程序添加注释。 3. 分析信号通信和管道通信各自的特点。

2. 编写一段程序,实现进程的管道通信。 使用系统调用pipe( )建立一条管道,创建两个子进程 P1和P2。 让P1和P2分别向管道各写一句话: Child 1 is sending a message! Child 2 is sending a message! 父进程则从管道中读出来自于两个子进程的信息, 显示在屏幕上。要求:父进程先接受子进程P1发来的 消息,然后再接受子进程P2发来的消息。 参考程序如下:

实验五:进程间通信

实验五:进程间通信

实验五:进程间通信●实验目的:学会进程间通信方式:无名管道,有名管道,信号,共享内存●实验要求:(一)在父进程中创建一无名管道,并创建子进程来读该管道,父进程来写该管道(二)在进程中为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));/*创建管道*/if(pipe(pipe_fd)<0){printf("pipe create error\n");return -1;}/*创建子进程*/if((pid=fork())==0) //子进程执行代码{//1、子进程先关闭了管道的写端//2、让父进程先运行,这样父进程先写子进程才有内容读//3、读取管道的读端,并输出数据//4、关闭管道的读端,并退出}else if(pid>0) //父进程执行代码{//1、父进程先关闭了管道的读端//2、向管道写入字符串数据//3、关闭写端,并等待子进程结束后退出}return 0;}2、编译应用程序pipe_rw.c3、运行应用程序子进程先睡两秒让父进程先运行,父进程分两次写入“hello”和“pipe”,然后阻塞等待子进程退出,子进程醒来后读出管道里的内容并打印到屏幕上再退出,父进程捕获到子进程退出后也退出4、由于fork函数让子进程完整地拷贝了父进程的整个地址空间,所以父子进程都有管道的读端和写端。

实验5 进程间通信:消息机制

实验5 进程间通信:消息机制

实验九进程间通信IPC:消息机制一、实验目的1.了解消息机制的相关函数。

2.了解消息队列的建立与使用。

3.能编写简单消息机制通信程序。

二、实验内容1. 建立消息队列2. 编写发送程序发送消息3. 编写接收程序接收消息三、预备知识1.创建和访问一个消息队列格式:int msgget(key_t key,int msgflag);返回值为对应消息的描述符(整型常量)。

2.发送消息(把一条消息添加到消息队列中去)格式:int msgsnd(int msqid,const void *smg_ptr,size_t msg_sz,int msgflag);3.接收消息格式:int msgrcv(int msqid,void *msg_ptr,size_t msg_sz,long int msgtype,int msgflag);4.控制和删除消息格式:int msgctl(int msqid,command,function);注意:msgsnd()和msgrcv()和msgctl()命令若执行成功,则返回0,若不成功,则返回-1。

四、实验步骤1.新建一个发送消息的程序x1.c$vi x1.c程序目的:可提示用户进行键盘输入字符,直到用户输入”end”,才结束输入。

将用户输入的内容存入消息队列,发送出去。

内容:#include<stdlib.h>#include<stdio.h>#include<string.h>#include<errno.h>#include<unistd.h>#include<sys/types.h>#include<sys/ipc.h>#include<sys/msg.h>#define MAX_TEXT 512struct mform{long int mtype;char mtext[MAX_TEXT];}; /*定义了消息的结构*/int main(){int running=1;struct mform msg;int msgid;char buffer[BUFSIZ];msgid=msgget((key_t)1234,0666|IPC_CREAT);/*建立消息队列*/if(msgid==-1){/*若创建不成功,则显示出错信息,结束*/ printf(“msgget failed!\n”);exit(EXIT_FAILURE);}while(running)/*当创建消息队列成功后,则循环接收用户从键盘输入的字符,直到消息内容中出现“end”为止。

进程间通信实验报告

进程间通信实验报告

进程间通信实验报告班级:10网工三班学生姓名:谢昊天学号:1215134046实验目的和要求:Linux系统的进程通信机构 (IPC) 允许在任意进程间大批量地交换数据。

本实验的目的是了解和熟悉Linux支持的消息通讯机制及信息量机制。

实验内容与分析设计:(1)消息的创建,发送和接收。

①使用系统调用msgget (), msgsnd (), msgrev (), 及msgctl () 编制一长度为1k 的消息的发送和接收程序。

②观察上面的程序,说明控制消息队列系统调用msgctl () 在此起什么作用?(2)共享存储区的创建、附接和段接。

使用系统调用shmget(),shmat(),sgmdt(),shmctl(),编制一个与上述功能相同的程序。

(3)比较上述(1),(2)两种消息通信机制中数据传输的时间。

实验步骤与调试过程:1.消息的创建,发送和接收:(1)先后通过fork( )两个子进程,SERVER和CLIENT进行通信。

(2)在SERVER端建立一个Key为75的消息队列,等待其他进程发来的消息。

当遇到类型为1的消息,则作为结束信号,取消该队列,并退出SERVER 。

SERVER每接收到一个消息后显示一句“(server)received”。

(3)CLIENT端使用Key为75的消息队列,先后发送类型从10到1的消息,然后退出。

最后的一个消息,既是 SERVER端需要的结束信号。

CLIENT每发送一条消息后显示一句“(client)sent”。

(4)父进程在 SERVER和 CLIENT均退出后结束。

2.共享存储区的创建,附接和断接:(1)先后通过fork( )两个子进程,SERVER和CLIENT进行通信。

(2)SERVER端建立一个KEY为75的共享区,并将第一个字节置为-1。

作为数据空的标志.等待其他进程发来的消息.当该字节的值发生变化时,表示收到了该消息,进行处理.然后再次把它的值设为-1.如果遇到的值为0,则视为结束信号,取消该队列,并退出SERVER.SERVER 每接收到一次数据后显示”(server)received”.(3)CLIENT端建立一个为75的共享区,当共享取得第一个字节为-1时, Server端空闲,可发送请求. CLIENT 随即填入9到0.期间等待Server端再次空闲.进行完这些操作后, CLIENT退出. CLIENT每发送一次数据后显示”(client)sent”.(4)父进程在SERVER和CLIENT均退出后结束。

实验五 Linux进程间通信05010501

实验五  Linux进程间通信05010501
lockf(fd[1],1,0); sprintf(OutPipe, "child 2 process is sending message!"); 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); wait(0); read(fd[0],InPipe,50); printf("%s\n",InPipe); exit(0); } } } 实验要求:运行程序并分析结果,将上面程序修改成,在父进程中用 pipe()建立一条管道, 往管道里写字符串,两个子进程分别接收父进程往管道里写的字符串。
lockf(fd[1],1,0); sprintf(OutPipe, "child 1 process is sending message!"); write(fd[1],OutPipe,50); sleep(5); lockf(fd[1],0,0); exit(0); } else{
while((pid2=fork())== -1); if(pid2 == 0) {
//printf("child2 exit status is %d\n", WEXITSTATUS(status2));
printf("parent process is killed!\n");
exit(0);
} else{
/*在子进程 2 中*/
wait_mark=1; signal(12,stop); //捕捉到中断信号 12 后,调用 stop 函数

实验五进程间通信实验

实验五进程间通信实验

实验五进程间通信实验(二)实验目的:1.通过基础实验,基本掌握无名管道、有需管道的程序设计。

2.通过编写程序,使读者掌握信号处理程序设计方法。

实验内容:1.无名管道程序设计:在父进程中创建一个无名管逍,并创建子进程:在父进程中写该管道,并用子进程将内容读出。

2.有名管道程序设计:创建两个进程,在A进程中创建一个有飲管道,并向英写入数据,通过B进程从有统管道中读出数据。

3.信号处理程序设计:在进程中为SIGBUS注册处理函数,并向该进程发送SIGBUS信号来触发信号处理函数。

实验过程:(一)无名管道程序设计实验代码:/* */#include <>#include <sys/>#include o#include o#include o#include o #(lefine MAX_DATA_LEN 256#define DELAY.TIMElint inain(){pid_t pid;int pipe_f(i[2];char buf[MAX_DATA_LEN];const char data[] = "Pipe Test Program"; int real_read, real_write;memset((void*)buf, 0, sizeof(buf));/*创建管道*/if (pipe(pipe_fd) < 0)printf(M pipe create error\n M);exit(l);}/*创建一子进程*/if ((pid = fork()) == 0){/*子进程关闭写描述符,并通过使子进程暂停1秒等待父进程已关闭相应的读描述符*/close(pipe_fd[l]);sleep(DELAY_TIME * 3);/*子进程读取管道内容*/if ((real_read = read(pipe_fd[O], buf, MAX_DATA_LEN)) > 0){printf(u%d bytes read from the pipe is ’%s'\n”, real_read, buf);}/*关闭子进程读描述符*/close(pipe_fd[OJ);exit(O);}else if (pid > 0){/*父进程关闭读描述符,并通过使父进程暂停1秒等待子进程已关闭相应的写描述符*/close(pipe_fd(0]); s!eep(DELAY_TIME);/*父进程向管道中写入字符串*/if((real_write = write(pipe_fd[l], data, strlen((const char*)data))) !=・1) {printf(u Parent wrote %d bytes : real_write, data);}/*关闭父进程写描述符*/close(pipe_fd[l]);/*收集子进程退出信息*/waitpid(pid9 NULL, 0);exit(O);}}将该程序编译,运行。

进程通信的实验报告

进程通信的实验报告

一、实验目的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篇)

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

进程间通信实验.docx

进程间通信实验.docx

进程间通信实验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的命令行参数,进程读数据并输出。

实现进程间通信的实验原理

实现进程间通信的实验原理

实现进程间通信的实验原理进程间通信(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函数与进程通信下面实验为使用管道进行父子进程间通信。

程序首先判断参数是否合法,因为输入的字符将从父进程通过发送到子进程中。

然后,调用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中的两个命令的组合。

实验五_Linux进程间通信

实验五_Linux进程间通信

实验五 Linux 进程间通信1. 实验目的1)熟悉在C 语言源程序中使用Linux 所提供的系统调用界面的方法;2)掌握Linux 中子进程的创建方法以及调度执行情况,理解进程与程序的区别; 3)掌握软中断信号的使用,了解使用软中断通信实现异步事件的方法;4)掌握父子进程使用管道进行通信的方法,了解管道通信的特点和上的限制。

2. 实验内容1) 父进程创建子进程(1) 实现父进程创建一个子进程,返回后父子进程都分别循环输出字符串“I am parent.”或“I am child.”5次,每输出1次后使用sleep(1)延时1秒,然后再进入下一循环。

(2) 在源程序中连续使用4个fork(),而不用if()进行返回值的判断,在4个fork()语言后面输出字符“A ”,观察并分析该程序编译连接执行后的输出结果。

(3) 由父进程创建一个子进程,子进程的功能史输出26个英文字母,使用execl()加载子进程的程序。

(1)(2)结果:(3)2)软中断的使用(1)编写一个程序循环显示“How are you?”,当键盘输入Ctrl+C的组合键后中断循环显示,执行软中断程序,软中断程序的功能是修改循环变量的值终止循环,然后输出“Byebye”。

输出显示结果:3)管道的使用:(1)编写一个程序,实现:父进程使用系统调用pipe()创建一个无名管道;(2)创建2个子进程,分别向管道各发下面中1条信息后结束:Child 1 is sending a message to parent!Child 2 is sending a message to parent!(1)结果:(2)输出结果:3.实验思考1)如果连续创建多个子进程而不使用条件进行各自空间的分隔,会出现什么情况?2)对实验内容2)进行改进,先输出10次“How are you?”,在此过程中使用Ctrl+C不能中断循环显示,10次以后使用Ctrl+C可以中断循环,应该做那些修改?3)管道通信与软中断通信在信息量的大小上有何区别?4)共享同一个管道进行通信的读写进程之间必须满足什么关系,为什么?。

Linux进程间通信实验报告

Linux进程间通信实验报告

实验六: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 被返回。

共享内存共享内存是运行在同一台机器上的进程间通信最快的方式,因为数据不需要在不同的进程间复制。

通常由一个进程创建一块共享内存区,其余进程对这块内存区进行读写。

实验五-进程间通信

实验五-进程间通信

实验五进程间通信UNIX/LINUX系统的进程间通信机构(IPC)允许在任意进程间大批量地交换数据。

本实验的目的是了解和熟悉LINUX支持的信号机制、管道机制、消息队列通信机制及共享存储区机制。

5.1信号机制实验(一)【实验目的】1.了解什么是信号。

2.熟悉LINUX系统中进程之间软中断通信的基本原理。

【实验原理】利用signal来实现发送信号和接受信号的原理【实验内容】1.编写一段程序,使用系统调用fork( )创建两个子进程,再用系统调用signal( )让父进程捕捉键盘上来的中断信号(即按ctrl+c键),当捕捉到中断信号后,父进程用系统调用kill( )向两个子进程发出信号,子进程捕捉到父进程发来的信号后,分别输出下列信息后终止:Child process 1 is killed by parent!Child process 2 is killed by parent!父进程等待两个子进程终止后,输出以下信息后终止:Parent process is killed!<参考程序># include<stdio.h># include<signal.h># include<unistd.h>int wait_mark;void waiting(),sto p();void main(){ int p1, p2;signal(SIGINT,stop);while((p1=fork())==-1);if(p1>0) /*在父进程中*/{ ①while((p2=fork())= =-1);If(p2>0) /*在父进程中*/{ ②wait_mark=1;waiting(0);kill(p1,10);kill(p2,12);wait( );wait( );printf(“parent process is killed!\n”);exit(0);}else /*在子进程2中*/{wait_mark=1;signal(12,stop);waiting();lockf(1,1,0);printf(“child process 2 is killed by parent!\n”);lockf(1,0,0);exit(0);}}else /*在子进程1中*/{wait_mark=1;signal(10,stop);waiting();lockf(1,1,0);printf(“child process 1 is killed by parent!\n”);lockf(1,0,0);exit(0);}}void waiting(){while(wait_mark!=0);}void stop(){wait_mark=0;}实验要求:⑴运行程序并分析结果。

进程通信实验报告

进程通信实验报告

西安电子科技大学《操作系统原理》实验报告题目:进程通信实验报告班级: 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_)。

进程通信实验

进程通信实验

实验报告的基本内容及要求1.实验预习在实验前每位同学都需要对本次实验进行认真的预习,并写好预习报告,在预习报告中要写出实验目的、要求,需要用到的仪器设备、物品资料以及简要的实验步骤,形成一个操作提纲。

对实验中的安全注意事项及可能出现的现象等做到心中有数,但这些不要求写在预习报告中。

设计性实验要求进入实验室前写出实验方案。

2.实验记录学生开始实验时,应该将记录本放在近旁,将实验中所做的每一步操作、观察到的现象和所测得的数据及相关条件如实地记录下来。

实验记录中应有指导教师的签名。

3.实验总结主要内容包括对实验数据、实验中的特殊现象、实验操作的成败、实验的关键点等内容进行整理、解释、分析总结,回答思考题,提出实验结论或提出自己的看法等。

实验报告学院: 专业: 班级:姓名 学号 实验组 实验时间 指导教师 成绩实验项目名称进程通信实验实验目的 了解管道的基本概念。

掌握Linux支持的管道通信方式。

实验要求 1)查阅相关资料理解管道的基本概念和相关知识。

2)了解Linux支持的管道通信方式。

实验原理 1管道的概念及特点管道是Linux进程通信的手段之一。

存在两个进程:一个进程从管道的一端把数据输入进去,另一个进程可以从另一端读取这些数据。

Linux使用的管道分为两种:无名管道和有名管道。

两种管道在内部结构上是一致的,但使用方法不同。

无名管道可用于具有亲缘关系的进程间的通信,名通道可在任意进程中使用。

管道具有以下特点。

管道是半双工的,同一时间,数据只能单向流动;若两进程之间需要相互通信,则需建立两个管道。

Linux系统中把管道看作是一种特殊文件,采用文件管理的方法对管道进行管理且只存在内存中。

数据的读出和写入都是单向的,不能从管道写端读取数据,也不能向管道读端写入数据。

2管道的创建在程序设计中管道的创建是由系统调用pipe()函数实现的,其原型定义如下: #include<unisted.h>Int pipe(int fds[2]);要用管道机制实现父子进程之间的进程,则需要先由pipe()创建管道,由系统调用fork()创建一个新的子进程,然后通过管道在两个进程间进行数据的传送,实现进程间的相互通信。

进程间通信实验资料

进程间通信实验资料

进程间通信(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获取文本文件中的小写字母后,将小写字母转换成大写字母输出。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验五进程间通信UNIX/LINUX系统的进程间通信机构(IPC)允许在任意进程间大批量地交换数据。

本实验的目的是了解和熟悉LINUX支持的信号机制、管道机制、消息队列通信机制及共享存储区机制。

信号机制实验(一)【实验目的】1.了解什么是信号。

2.熟悉LINUX系统中进程之间软中断通信的基本原理。

【实验原理】利用signal来实现发送信号和接受信号的原理【实验内容】1.编写一段程序,使用系统调用fork( )创建两个子进程,再用系统调用signal( )让父进程捕捉键盘上来的中断信号(即按ctrl+c键),当捕捉到中断信号后,父进程用系统调用kill( )向两个子进程发出信号,子进程捕捉到父进程发来的信号后,分别输出下列信息后终止:Child process 1 is killed by parent!Child process 2 is killed by parent!父进程等待两个子进程终止后,输出以下信息后终止:Parent process is killed!<参考程序># include<># include<># include<>int wait_mark;void waiting(),sto p();void main(){ int p1, p2;signal(SIGINT,stop);while((p1=fork())==-1);if(p1>0) /*在父进程中*/{ ①while((p2=fork())= =-1);If(p2>0) /*在父进程中*/{ ②wait_mark=1;waiting(0);kill(p1,10);kill(p2,12);wait( );wait( );printf(“parent process is killed!\n”);exit(0);}else /*在子进程2中*/{wait_mark=1;signal(12,stop);waiting();lockf(1,1,0);printf(“child process 2 is killed by parent!\n”);lockf(1,0,0);exit(0);}}else /*在子进程1中*/{wait_mark=1;signal(10,stop);waiting();lockf(1,1,0);printf(“child process 1 is killed by parent!\n”);lockf(1,0,0);exit(0);}}void waiting(){while(wait_mark!=0);}void stop(){wait_mark=0;}实验要求:⑴运行程序并分析结果。

⑵如果把signal(SIGINT,stop)放在①号和②号位置,结果会怎样并分析原因。

⑶该程序段前面部分用了两个wait(0),为什么?⑷该程序段中每个进程退出时都用了语句exit(0),为什么?信号机制实验(二)【实验目的】学习signal的函数的使用【实验原理】利用signal的函数的机制来实习我们发送截获信号的功能【实验内容】修改上面的程序,增加语句signal(SIGINT,SIG_IGN)和语句signal(SIGQUIT,SIG_IGN),再观察程序执行时屏幕上出现的现象,并分析其原因。

<参考程序># include<># include<># include<>int pid1, pid2;int EndFlag=0;pf1=0;pf2=0;void IntDelete(){kill(pid1,10);kill(pid2,12);EndFlag=1;}void Int1(){printf(“child process 1 is killed by parent !\n”);exit(0);}void Int2(){printf(“child process 2 is killed by parent !\n”);exit(0);}main(){int exitcode;signal(SIGINT,SIG_IGN);signal(SIGQUIT,SIG_IGN);while((pid1=fork())==-1);if(pid1==0){signal(SIGUSR1,Int1);signal(SIGINT,SIG_IGN);pause();exit(0);}elsewhile((pid2=fork())= =-1);if(pid2==0){signal(SIGUSR2,Int2);signal(SIGINT,SIG_IGN);pause();exit(0);}else{signal(SIGINT,IntDelete);waitpid(-1,&exitcode,0); /*等待任何子进程中断或结束*/printf(“parent process is killed \n”);exit(0);}}}实验要求:运行程序并分析结果。

⑶司机售票员问题(选做题)编程用fork()创建一个子进程代表售票员,司机在父进程中,再用系统调用signal()让父进程(司机)捕捉来自子进程(售票员)发出的中断信号,让子进程(售票员)捕捉来自(司机)发出的中断信号,以实现进程间的同步运行。

管道通信实验(一)【实验目的】1、了解什么是管道2、熟悉UNIX/LINUX支持的管道通信方式【实验内容】编写程序实现进程的管道通信。

用系统调用pipe( )建立一管道,二个子进程P1和P2分别向管道各写一句话:Child 1 is sending a message!Child 2 is sending a message!父进程从管道中读出二个来自子进程的信息并显示(要求先接收P1,后P2)。

参考程序#include <>#include <>#include <>main( ){int fd[2];char outpipe[100],inpipe[100];pipe(fd); /*创建一个管道*/while ((pid1=fork( ))= =-1);if(pid1= =0){lockf(fd[1],1,0);sprintf(outpipe,"child 1 process is sending message!");/*把串放入数组outpipe中*/write(fd[1],outpipe,50); /*向管道写长为50字节的串*/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 message!");write(fd[1],outpipe,50);sleep(5);lockf(fd[1],0,0);exit(0);}else{ wait(0); /*同步*/read(fd[0],inpipe,50); /*从管道中读长为50字节的串*/printf("%s/n",inpipe);wait(0);read(fd[0],inpipe,50);printf("%s/n",inpipe);exit(0);}}}五、运行结果延迟5秒后显示child 1 process is sending message!再延迟5秒child 2 process is sending message!管道通信实验(二)【实验目的】1、掌握有名管道的创建和读写方式2、熟悉UNIX/LINUX支持的有名管道通信方式【实验内容】1.创建有名管道2.本进程执行循环等待数据被写入到管道中并读有名管道3.打开有名管道并写数据到名管道参考代码:.);if ((fd = open(argv[1], O_RDONLY)) < 0){fprintf(stderr, "open fifo %s for reading failed: %s\n", argv[1], strerror(errno));exit(1);}fprintf(stdout, "open fifo %s for reading successed.\n", argv[0]);char buffer[BUFFER_SIZE];ssize_t n;while (1){again:n");break;}else{buffer[n] = '\0';fprintf(stdout, "read %d bytes from fifo: %s\n", n, buffer);}}return 0;}.);if ((fd = open(argv[1], O_WRONLY)) < 0){fprintf(stderr, "open fifo %s for writting failed: %s\n", argv[1], strerror(errno));exit(1);}fprintf(stdout, "open fifo %s for writting successed.\n", argv[0]);char buffer[BUFFER_SIZE];ssize_t n;n");}else{fprintf(stderr, "Error: open file failed: (errno = %d)%s\n", errno, strerror(errno));}exit(1);}off_t offset;offset = 1024;On error, the value MAP_FAILED (that is, (void*) -1) is returned, and errno is set appropriately. On success, munmap returns 0, on failure -1, and errno is set (probably to EINVAL).*//*PROT_EXEC Pages may be executed.PROT_READ Pages may be read.PROT_WRITE Pages may be written.PROT_NONE Pages may not be accessed.*/void *p;;On error, the value MAP_FAILED (that is, (void*) -1) is returned, and errno is set appropriately. On success, munmap returns 0, on failure -1, and errno is set (probably to EINVAL).*//*PROT_EXEC Pages may be executed.PROT_READ Pages may be read.PROT_WRITE Pages may be written.PROT_NONE Pages may not be accessed.*/void *p;1L3L4L4L2L3L4L3L1L3L4L2LserverReceive client1 message: i 'am client AReceive client2 message: ok! I have recieved your msg,I'm client B Receive client1 message: x[root@localhost root]#客户端A的运行结果如下:[root@localhost root]# ./client1input the msg to client2:i 'am client AReceive from client2, message: ok! I have recieved your msg,I'm client B input the msg to client2:xclient1 will quit![root@localhost root]#客户端B的运行结果如下:[root@localhost root]# ./client2Receive from client1, message: i 'am client Ainput the msg to client1: ok! I have recieved your msg,I'm client Bclient2 will quit![root@localhost root]#。

相关文档
最新文档