实验三 进程通信(一)
实验3进程通信(1)
实验3 进程通信(一)UNIX/LINUX系统的进程间通信机构(IPC)允许在任意进程间大批量地交换数据。
本实验的目的是了解和熟悉LINUX支持的信号量机制、管道机制、消息通信机制及共享存储区机制。
一、信号量机制实验目的1、了解什么是信号2、熟悉LINUX系统中进程之间软中断通信的基本原理实验内容1、编写程序:用fork( )创建两个子进程,再用系统调用signal( )让父进程捕捉键盘上来的中断信号(即按^c键);捕捉到中断信号后,父进程用系统调用kill( )向两个子进程发出信号,子进程捕捉到信号后分别输出下列信息后终止:Child process1 is killed by parent!Child process2 is killed by parent!父进程等待两个子进程终止后,输出如下的信息后终止:Parent process is killed!2、分析利用软中断通信实现进程同步的机理实验指导(一)信号1、信号的基本概念每个信号都对应一个正整数常量(称为signal number,即信号编号。
定义在系统头文件<signal.h>中),代表同一用户的诸进程之间传送事先约定的信息的类型,用于通知某进程发生了某异常事件。
每个进程在运行时,都要通过信号机制来检查是否有信号到达。
若有,便中断正在执行的程序,转向与该信号相对应的处理程序,以完成对该事件的处理;处理结束后再返回到原来的断点继续执行。
实质上,信号机制是对中断机制的一种模拟,故在早期的UNIX版本中又把它称为软中断。
信号与中断的相似点:(1)采用了相同的异步通信方式;(2)当检测出有信号或中断请求时,都暂停正在执行的程序而转去执行相应的处理程序;(3)都在处理完毕后返回到原来的断点;(4)对信号或中断都可进行屏蔽。
信号与中断的区别:(1)中断有优先级,而信号没有优先级,所有的信号都是平等的;(2)信号处理程序是在用户态下运行的,而中断处理程序是在核心态下运行;(3)中断响应是及时的,而信号响应通常都有较大的时间延迟。
操作系统实验三进程的管道通信
实验三进程的管道通信一、实验目的:(1)加深对进程概念的理解,明确进程和程序的区别;(2)学习进程创建的过程,进一步认识并发执行的实质;(3)分析进程争用资源的现象,学习解决进程互斥的方法;(4)学习解决进程同步的方法;(5)掌握Linux系统进程间通过管道通信的具体实现方法。
二、实验内容及要求:(1)使用系统调用pipe()建立一条管道线,两个子进程分别向管道写一句话(写的内容自己定,但要有该进程的一些信息);(2)父进程从管道中读出来自两个子进程的消息,显示在屏幕上;(3)要求:父进程首先接收子进程p1发来的消息,然后再接收子进程p2发来的消息;(4)两个子进程要并发执行;(5)实现管道的互斥使用。
当一个子进程正在对管道进行写操作时,另一个欲写入管道的子进程必须等待。
使用系统调用lockf(fd[1],1,0)实现对管道的加锁操作,用lockf(fd[1],0,0)解除对管道的锁定;(6)实现父子进程的同步,当父进程试图从一空管道中读取数据时,便进入等待状态,直到子进程将数据写入管道返回后,才将其唤醒。
三、实现:相关的系统调用fork() 用于创一个子进程。
格式:int fork();返回值:在子进程中返回0;在父进程中返回所创建的子进程的ID值;当返回-1时,创建失败。
wait() 常用来控制父进程与子进程的同步。
在父进程中调用wait(),则父进程被阻塞,进入等待队列,等待子进程结束。
当子进程结束时,父进程从wait()返回继续执行原来的程序。
返回值:大于0时,为子进程的ID值;等于-1时,调用失败。
exit() 是进程结束时最常调用的。
格式:void exit( int status); 其中,status为进程结束状态。
pipe() 用于创建一个管道格式:pipe(int fd);其中fd是一个由两个数组元素fd[0]和fd[1]组成的整型数组,fd[0]是管道的读端口,用于从管道读出数据,fd[1]是管道的写端口,用于向管道写入数据。
进程实验-进程间通信(管道、消息、共享内存、软中断)
进程实验3 Linux 进程间通信一、软中断信号的处理,实现同一用户的各进程之间的通信。
●相关的系统调用⏹kill(pid ,sig):发送信号⏹signal(sig, func):指定进程对信号sig的处理行为是调用函数func。
●程序清单#include <unistd.h>#include <stdio.h>#include <signal.h>void waiting();void stop();int wait_mark;main(){int p1,p2;while((p1=fork())==-1);if(p1>0){while((p2=fork())==-1);if(p2>0){ printf("parent\n");/*父进程在此完成某个操作、或接收到用户从键盘输入的特殊按键命令后发出下面的信号。
这里省略。
*/kill(p1,16);kill(p2,17);wait(0);wait(0);printf("parent process id killed! \n");exit(0);}else/* p2==0*/{printf("p2\n");wait_mark=1;signal(17,stop);waiting();printf("child process 2 is killed by parent! \n");exit(0);}}else/*p1==0*/{printf("p1\n");wait_mark=1;signal(16,stop);waiting();printf("child process 1 is kelled by parent! \n");exit(0);}}void waiting(){while(wait_mark!=0);}void stop(){wait_mark=0;}●输入并运行此程序,分析程序的运行结果。
实验三、进程通信(一) ——管道及共享内存
(1)阅读以上父子进程利用管道进行通信的例子(例1),写出程序的运行结果并分析
实验代码:
#include<stdio.h>
main()
{ int x,fd[2];
char buf[30],s[30];
pipe(fd);
while ((x=fork())==-1);
if (x==0)
}
write(fe[1],s,30);
wait(0);
}
运行结果:
(3)阅读例2的程序,运行一次该程序,然后用ipcs命令查看系统中共享存储区的情况,再次执行该程序,再用ipcs命令查看系统中共享内存的情况,对两次的结果进行比较,并分析原因。最后用ipcrm命令删除自己建立的共享存储区。(有关ipcs和ipcrm介绍见后面一页)
addr=shmat(shmid,0,0);/*挂接,并得到共享区首地址*/
printf ("addr 0x%x\n",addr);
pint=(char *)addr;
for (i='a';i<='e';i++) *pint++=i;
pause();/*等待接收进程读*/
}
cleanup()
{
shmctl(shmid,IPC_RMID,0);
(2)每个同学登陆两个窗口,先在一个窗口中运行例3程序1(或者只登陆一个窗口,先在该窗口中以后台方式运行程序1),然后在另一个窗口中运行例3程序2,观察程序的运行结果并分析。运行结束后可以用ctrl+c结束程序1的运行。
(3)编写程序:使用系统调用shmget(),shmat(),shmdt(),shmctl(),编制程序。要求在父进程中生成一个30字节长的私有共享内存段。接下来,设置一个指向共享内存段的字符指针,将一串大写字母写入到该指针指向的存贮区。调用fork()生成子进程,让子进程显示共享内存段中的内容。接着,将大写字母改成小写,子进程修改共享内存中的内容。之后,子进程将脱接共享内存段并退出。父进程在睡眠5秒后,在此显示共享内存段中的内容(此时已经是小写字母)。
操作系统实验三(进程通信)
暨南大学本科实验报告专用纸课程名称《操作系统原理实验》成绩评定实验项目名称进程通信指导教师戴红实验项目编号0806002903 实验项目类型综合型实验地点学生姓名蔡高成学号2007052431学院国际商学院系企业管理专业信息管理与信息系统实验时间年月日下午温度℃湿度一、实验目的学习如何利用管道机制或消息缓冲队列进行进程间的通信,并加深对上述通信机制的理解。
提高学生分析问题和解决问题的能力,并学习撰写规范的科学研究报告。
二、实验环境及设备(一)实验室名称:计算机实验室(二)主要仪器设备:PC机、Linux操作系统环境三、实验内容编写一段程序,使用管道来实现父子进程之间的进程通信。
子进程项父进程发送自己的进程表示符,以及某字符串。
父进程则通过管道读出子进程发来的消息,将消息显示在屏幕上,然后终止。
四、实验调试分析1、实验函数说明(1)pipe头文件:#include<unistd.h>定义函数:int pipe(int pipedes[2]);函数说明:pipe()会建立管道,并将文件描述词由参数pipedes 数组返回。
pipedes[0]为管道里的读取端,所以pipe用read调用的pipedes[1]则为管道的写入端。
写进程A pipedes[1]返回值: 若成功则返回零,否则返回-1,错误原因存于errno 中。
错误代码:EMFILE 进程已用完文件描述词最大量ENFILE 系统已无文件描述词可用。
EFAULT 参数pipedes 数组地址不合法。
(2)sprintf函数功能:把格式化的数据写入某个字符串头文件:#include <stdio.h>函数原型:int sprintf( char *buffer, const char *format [, argument] … );返回值:字符串长度(strlen)(3)flock头文件: #include<sys/file.h>定义函数: int flock(int fd,int operation);函数说明: flock()会依参数operation所指定的方式对参数fd所指的文件做各种锁定或解除锁定的动作。
实验三进程间通信
实验三进程间通信班级: xxx 学号: xxx 姓名: xxx 分数:1、实验目的:Linux系统的进程通信机构(IPC)允许在任意进程间大批量的交换数据。
本实验的目的是了解和熟悉Linux支持的通信机制、共享存储区机制及信号量机制。
2、实验预备内容:阅读Linux系统的等源码文件,熟悉Linux的三种通信机制。
3、实验内容:(1)消息的创建,发送和接收(2)使用系统调用msgget(),msgsnd(),msgrev()及msgctl()编制一长度为1k的消息发送和接收程序。
<程序设计>(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均退出后结束。
4、源代码及运行截图:#include <>#include <sys/>#include <sys/>#include <sys/>#define MSGKEY 75struct msgform{long mtype;char mtext[1030];}msg;int msgqid,i;void CLIENT(){ int i;msgqid=msgget(MSGKEY,0777);for (i=10;i>=1;i--){=i;printf("(client)sent \n");msgsnd(msgqid,&msg,1024,0); /*发送消息msg入msgid消息队列*/}}void SERVER(){msgqid=msgget(MSGKEY,0777|IPC_CREAT); /*由关键字获得消息队列*/do{msgrcv(msgqid,&msg,1030,0,0); /*从msgid消息队列接收消息msg*/printf("(server)received \n");}while!=1); /*消息类型为1时,释放队列*/msgctl(msgqid,IPC_RMID,0);}void main(){while((i=fork())==-1);if(!i) SERVER();while((i=fork())==-1);if(!i) CLIENT();wait(0);wait(0);}5、实验感想本次实验的实验目的是了解和熟悉Linux支持的通信机制、共享存储机制及信号量机制。
操作系统实验三进程的管道通信精编版
操作系统实验三进程的管道通信精编版MQS system office room 【MQS16H-TTMS2A-MQSS8Q8-MQSH16898】实验三进程的管道通信一、实验目的:(1)加深对进程概念的理解,明确进程和程序的区别;(2)学习进程创建的过程,进一步认识并发执行的实质;(3)分析进程争用资源的现象,学习解决进程互斥的方法;(4)学习解决进程同步的方法;(5)掌握Linux系统进程间通过管道通信的具体实现方法。
二、实验内容及要求:(1)使用系统调用pipe()建立一条管道线,两个子进程分别向管道写一句话(写的内容自己定,但要有该进程的一些信息);(2)父进程从管道中读出来自两个子进程的消息,显示在屏幕上;(3)要求:父进程首先接收子进程p1发来的消息,然后再接收子进程p2发来的消息;(4)两个子进程要并发执行;(5)实现管道的互斥使用。
当一个子进程正在对管道进行写操作时,另一个欲写入管道的子进程必须等待。
使用系统调用lockf(fd[1],1,0)实现对管道的加锁操作,用lockf(fd[1],0,0)解除对管道的锁定;(6)实现父子进程的同步,当父进程试图从一空管道中读取数据时,便进入等待状态,直到子进程将数据写入管道返回后,才将其唤醒。
三、实现:相关的系统调用fork()用于创一个子进程。
格式:intfork();返回值:在子进程中返回0;在父进程中返回所创建的子进程的ID 值;当返回-1时,创建失败。
wait()常用来控制父进程与子进程的同步。
在父进程中调用wait(),则父进程被阻塞,进入等待队列,等待子进程结束。
当子进程结束时,父进程从wait()返回继续执行原来的程序。
返回值:大于0时,为子进程的ID值;等于-1时,调用失败。
exit()是进程结束时最常调用的。
格式:voidexit(intstatus);其中,status为进程结束状态。
pipe()用于创建一个管道格式:pipe(intfd);其中fd是一个由两个数组元素fd[0]和fd[1]组成的整型数组,fd[0]是管道的读端口,用于从管道读出数据,fd[1]是管道的写端口,用于向管道写入数据。
实验三_进程间通信 (1)
实验三线程控制和进程间通信一、实验目的通过Linux管道通信机制、消息队列通信机制的使用,加深对不同类型的进程通信方式的理解。
二、实验内容:1.熟悉Linux的管道通信机制2.熟悉Linux的消息队列通信机制三、思考1.有名管道和无名管道之间有什么不同?2.管道的读写与文件的读写有什么异同?3.Linux消息队列通信机制中与教材中的消息缓冲队列通信机制存在哪些异同?四、实验指导<一>Linux管道通信机制管道是所有UNIX都提供的一种进程间通信机制,它是进程之间的一个单向数据流,一个进程可向管道写入数据,另一个进程则可以从管道中读取数据,从而达到进程通信的目的。
1.无名管道无名管道通过pipe()系统调用创建,它具有如下特点:(1)它只能用于具有亲缘关系的进程(如父子进程或者兄弟进程)之间的通信。
(2)管道是半双工的,具有固定的读端和写端。
虽然pipe()系统调用返回了两个文件描述符,但每个进程在使用一个文件描述符之前仍需先将另一个文件描述符关闭。
如果需要双向的数据流,则必须通过两次pipe()建立起两个管道。
(3)管道可以看成是一种特殊的文件,对管道的读写与文件的读写一样使用普通的read、write等函数,但它不是普通的文件,也不属于任何文件系统,而只存在于内存中。
2.pipe系统调用(1)函数原型#include <unistd.h>int pipe(int filedes[2]);(2)参数filedes参数是一个输出参数,它返回两个文件描述符,其中filedes[0]指向管道的读端,filedes[1]指向管道的写端。
(3)功能pipe在内存缓冲区中创建一个管道,并将读写该管道的一对文件描述符保存在filedes所指的数组中,其中filedes[0]用于读管道,filedes[1]用于写管道。
(4)返回值成功返回0;失败返回-1,并在error中存入错误码。
(5)错误代码EMFILE:进程使用的文件描述符过多ENFILE :系统文件表已满EFAULT :非法参数filedes3.无名管道的阻塞型读写管道缓冲区有4096B的长度限制,因此,采用阻塞型读写方式时,当管道已经写满时,写进程必须等待,直到读进程取走信息为止。
实验三进程通讯实验报告
实验三进程通讯实验报告实验三进程通讯实验报告【姓名】【学号】【实验题目】进程通讯——消息队列与共享存储区【实验目的】(1)掌握进程间通讯的编程方法;(2)加深对进程并发执行的理解;(3)学习利用消息队列与共享存储区实现进程通信的方法。
【实验内容】设计一个多进程并发运行的程序,它由不同的进程完成下列工作:(1)接收键盘输入进程负责接收用户的键盘输入,并以适当的方式将由键盘获得的数据交给其它进程处理。
(2)显示进程负责全部数据显示任务,包括键盘输入数据的显示与提示信息的显示。
(3)分发数据进程将键盘输入的数据分为3类,即字母、数字与其它,并分别将字母写入文件letter、txt中,数字写入文件number、txt中,除字母与数字外其它数据丢弃。
【实验要求】1、程序能以适当的方式提示用户输入数据;2、提示用户有数据被丢弃;3、全部的显示任务必须由显示进程完成;4、整个程序能够连续处理多组输入数据,直到用户输入“quit”字符串,整个程序结束;5、进一步要求:同时采用共享存储区与消息2种方法实现进程之间的通信,并比较这2种通信方法的利弊。
【实验方法】1、利用fork()函数创建2个子进程,用一个父进程与两个子进程完成上面的三个实验任务,用子进程1实现分发数据任务,子进程2实现接受键盘输入任务,父进程实现全部的显示任务。
2、同时通过共享存储区与消息队列两种进程通讯方式实现上面三个进程之间的同步与互斥。
3、利用while()循环、kill()函数与signal()函数实现连续多组数据输入。
【程序结构】·数据结构:消息队列、字符数组;·程序结构:顺序结构、if-else分支结构与while循环结构;·主要算法:无特别算法【实验结果】1、有代表性的执行结果:[stud13@localhost stud13]$ cc ipc、c[stud13@localhost stud13]$ 、/a、outPlease input a line:∟operatingsystem01234-=,、Your message is:operatingsystem01234-=,、The characters deserted are:-=,、Please input a line:∟xushengju6651001!@#$%^&*()Your message is:xushengju6651001!@#$%^&*()The characters deserted are:!@#$%^&*()Please input a line:∟Hello123Your message is:Hello123Please input a line:∟quit[stud13@localhost stud13]$ cat letter、txtOperatingsystemxushengjuHello[stud13@localhoststud13]$ cat number、txt1123[stud13@localhost stud13]$2、结果分析及解释:在创建子进程1时,由于先返回子进程的ID 号,msgrcv(msgid,&msg,BUFSIZE,0,0)一直都就是非0值,故循环等待。
实验三、进程通信一 ——管道及共享内存
操作系统实验报告实验三、进程通信(一)——管道及共享存一、实验目的1)加深对管道通信的了解2)掌握利用管道进行通信的程序设计3)了解共享存通信的程序设计方法4)了解和熟悉Linux支持的共享存储区机制二、实验容任务一、(1)阅读以上父子进程利用管道进行通信的例子(例1),写出程序的运行结果并分析。
(2)编写程序:父进程利用管道将一字符串交给子进程处理。
子进程读字符串,将里面的字符反向后再交给父进程,父进程最后读取并打印反向的字符串。
任务二、(1)阅读例2的程序,运行一次该程序,然后用ipcs命令查看系统中共享存储区的情况,再次执行该程序,再用ipcs命令查看系统中共享存的情况,对两次的结果进行比较,并分析原因。
最后用ipcrm命令删除自己建立的共享存储区。
(有关ipcs和ipcrm介绍见后面一页)(2)每个同学登陆两个窗口,先在一个窗口中运行例3程序1(或者只登陆一个窗口,先在该窗口中以后台方式运行程序1),然后在另一个窗口中运行例3程序2,观察程序的运行结果并分析。
运行结束后可以用ctrl+c结束程序1的运行。
(3)编写程序:使用系统调用shmget(),shmat(),shmdt(),shmctl(),编制程序。
要求在父进程中生成一个30字节长的私有共享存段。
接下来,设置一个指向共享存段的字符指针,将一串大写字母写入到该指针指向的存贮区。
调用fork()生成子进程,让子进程显示共享存段中的容。
接着,将大写字母改成小写,子进程修改共享存中的容。
之后,子进程将脱接共享存段并退出。
父进程在睡眠5秒后,在此显示共享存段中的容(此时已经是小写字母)。
三、代码及运行结果分析(1)阅读以上父子进程利用管道进行通信的例子(例1),写出程序的运行结果并分析实验代码:#include<stdio.h>main(){ int x,fd[2];char buf[30],s[30];pipe(fd);while ((x=fork())==-1);if (x==0){close(fd[0]);printf("Child Process!\n");strcpy(buf,"This is an example\n");write(fd[1],buf,30);exit(0);}else{close(fd[1]);printf("Parent Process!\n");read(fd[0],s,30);printf("%s\n",s);}}运行结果:分析:调用pipe(fd);创建一个管道后,接着调用fork()函数产生两个进程,首先开始执行子进程,关闭管道出口,通过管道入口向管道中写入容。
实验三-进程通信
实验三进程通信一. 实验学时与类型学时:2,课外学时:自定实验类型:设计性实验二. 实验目的了解Linux 的软中断、管道、消息队列、共享存储区等进程间通信方式。
三. 实验内容1. 软中断通信机制(1) 请编写一个程序:循环输出“ how are you? ”,在按下Ctrl+C 后中断显示,输出“ Byebye! ”后退出程序。
#include<signal.h>#include<stdio.h>int k=1;void int_func(int sig) // 软中断处理函数{ k=0; }Int main(){ signal(SIGINT,int_func);// 预置软中断信号处理函数While(k==1) Printf( “ how are you?\n ” );Printf( “ byebye! ” );}I LO w arc y uu? how arc you? h<jw arc you? how arc you? h<)w arc y Ciu? Iw w are you?how arc y on?I LOW arc you? howarc you?h<jw arc you? howarc you?jb y ebye ! [ rOG t <J c a 1 h O s L z zw] # .(2)使用信号机制实现父子进程同步,父进程先输出 #in clude<sig nal.h>#in clude<stdio.h>int k=1;void fun c(i nt sig) { k=0; }main (){ int pid;pid=fork();if(pid>0){ printf( “ A\n ” );kill(pid,12);}else if(pid==0){ sig nal(12,fu nc);while(k==1)sleep(1);printf( “ B\n ”);}}[rao oca Iho s i zzw] , / 12A2. 管道机制(1)父子进程通过管道传送一串字符。
进程通信实验报告
操作系统实验报告(三)进程通信专业:软件工程姓名:XXX班级:XXX学号:XXX指导老师:XXX2013/12/3实验三:进程通信一.实验目的加深对进程通信的理解。
熟悉消息通信机制、共享存储器通信机制,进一步认识其与信号量通信的区别。
二.实验内容1)编程实现基于消息缓冲队列机制的进程通信数据结构和通信原语(创建消息、发送消息、接收消息);2)最后编写主函数对所做工作进行测试三.实验步骤(1)任务分析:实现进程通信,需要建立创建消息函数、发送消息函数、接收消息函数,需要用到进程中的Send和Receive原语(2)程序设计:a.总体设计:创建两个windows窗体应用程序,分别用于发送消息和接收消息,可以采用C#实现。
b.具体实现①创建应用程序Sendmessage,在windows窗体上放置一个文本框输入要发送的消息,一个按钮控件,单击按钮控件发送消息,编辑ButtonOnclick()事件,来编辑发送消息函数,发送后弹出消息发送成功对话框。
②创建应用程序Receivemessage,在windows窗口上放置一个文本框用于接收消息,放置一个Button按钮,并编辑ButtonOnclick()事件,来编辑接收消息函数,成功后弹出成功接收对话框。
③程序中的发送接收需要用到系统中的函数,将在实验代码中给与提示。
(4)调试与测试实验结果:发送消息:接收消息:四.实验总结进程通信实验主要是通过通信原语机制创建消息发送函数和消息接收函数来模拟实现进程间的通信,在实验过程中,一些通信机制不是太明确,通过在网上查找资料以及和同学们交流,最终完成了进程通信实验,通过这次实验,我对进程间的通信原理多了更深一步的了解,为学习操作系统知识建立了良好的实践基础。
五.附录①发送消息函数源码:using System;using System.Collections.Generic;using ponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using System.Runtime.InteropServices;namespace WindowsFormsApplication1{public partial class Form1 : Form{public Form1(){InitializeComponent();}[DllImport("User32.dll", EntryPoint = "SendMessage")] private static extern int SendMessage(int hWnd,int Msg,int wParam,ref COPYDATASTRUCT lParam);[DllImport("User32.dll", EntryPoint = "FindWindow")] private static extern int FindWindow(string lpClassName, string lpWindowName);public struct COPYDATASTRUCT{public IntPtr dwData;public int cbData;[MarshalAs(UnmanagedType.LPStr)]public string lpData;}const int WM_COPYDATA = 0x004A;private void button1_Click(object sender, EventArgs e){Sent();MessageBox.Show("信息发送成功|", "提示?", MessageBoxButtons.OK);}private void Sent(){int WINDOW_HANDLER = FindWindow(null, @"接受信息");if (WINDOW_HANDLER != 0){byte[] sarr =System.Text.Encoding.Default.GetBytes(this.textBox1.Text);int len = sarr.Length;COPYDATASTRUCT cds;cds.dwData = (IntPtr)100;cds.lpData = this.textBox1.Text;cds.cbData = len + 1;SendMessage(WINDOW_HANDLER, WM_COPYDATA, 0, ref cds); } }}}②接收消息函数源码:using System;using System.Collections.Generic;using ponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using System.Runtime.InteropServices;namespace WindowsFormsApplication2{public partial class Form1 : Form{string message;public Form1(){InitializeComponent();}public struct COPYDATASTRUCT{public IntPtr dwData;public int cbData;[MarshalAs(UnmanagedType.LPStr)]public string lpData;}const int WM_COPYDATA = 0x004A;private void button1_Click(object sender, EventArgs e) {Receive();}private void Receive(){textBox1.Text += "收到信息为"+ message + Environment.NewLine;MessageBox.Show("成功接收!");}protected override void DefWndProc(refSystem.Windows.Forms.Message m){switch (m.Msg){case WM_COPYDATA:COPYDATASTRUCT mystr = new COPYDATASTRUCT();Type mytype = mystr.GetType();mystr = (COPYDATASTRUCT)m.GetLParam(mytype); message = mystr.lpData;break;default:base.DefWndProc(ref m);break;}}}}。
操作系统实验三进程的管道通信
操作系统实验三进程的管道通信操作系统中的进程通信是指进程之间通过一定机制进行信息传递和交换的过程。
而管道是常用的进程间通信(IPC)机制之一,它提供了一种半双工的通信方式,用于在具有亲缘关系的进程之间进行通信。
本实验以Linux系统为例,介绍进程的管道通信。
一、进程间通信(IPC)概述进程之间的通信是操作系统的重要功能之一,它使得不同进程能够共享信息、协调工作。
Linux系统提供了多种进程间通信的方式,如管道、消息队列、信号、共享内存等。
其中,管道是最简单、最常用的一种进程间通信方式。
二、管道的概念与原理1.管道的概念管道是一种特殊的文件,用于实现具有亲缘关系的进程之间的通信。
整个管道可以看作是一个字节流,其中写入的数据可以被读取。
管道通常是半双工的,即数据只能从一个进程流向另一个进程,而不能反向流动。
2.管道的原理管道的内部实现是通过操作系统的缓冲区来完成的。
当一个进程往管道写入数据时,数据被放置在写管道的缓冲区中。
另一个进程从管道中读取数据时,数据被从读管道的缓冲区中取出。
如果写管道的缓冲区为空,写操作将会阻塞,直到有数据被写入为止。
同样,如果读管道的缓冲区为空,读操作将会阻塞,直到有数据可读为止。
三、管道的使用步骤1.打开管道在Linux系统中,使用`pipe`系统调用来创建管道。
它接受一个包含两个整数的参数数组,返回0表示成功,负数表示失败。
成功创建管道后,会得到两个文件描述符,分别代表读管道和写管道。
2.进程间通信在有亲缘关系的进程中,可以使用`fork`系统调用来创建一个子进程。
父进程和子进程都可以使用管道进行读写操作。
父进程可以关闭写管道描述符,子进程关闭读管道描述符,即父进程只负责写入数据,子进程负责读取数据。
3.写入数据父进程在写管道描述符上调用`write`函数来向管道写入数据。
该函数的返回值为成功写入的字节数,返回-1表示写入失败。
4.读取数据子进程在读管道描述符上调用`read`函数来从管道读取数据。
操作系统实验三进程的管道通信
操作系统实验三进程的管道通信Company number:【0089WT-8898YT-W8CCB-BUUT-202108】实验三进程的管道通信一、实验目的:(1)加深对进程概念的理解,明确进程和程序的区别;(2)学习进程创建的过程,进一步认识并发执行的实质;(3)分析进程争用资源的现象,学习解决进程互斥的方法;(4)学习解决进程同步的方法;(5)掌握Linux系统进程间通过管道通信的具体实现方法。
二、实验内容及要求:(1)使用系统调用pipe()建立一条管道线,两个子进程分别向管道写一句话(写的内容自己定,但要有该进程的一些信息);(2)父进程从管道中读出来自两个子进程的消息,显示在屏幕上;(3)要求:父进程首先接收子进程p1发来的消息,然后再接收子进程p2发来的消息;(4)两个子进程要并发执行;(5)实现管道的互斥使用。
当一个子进程正在对管道进行写操作时,另一个欲写入管道的子进程必须等待。
使用系统调用lockf(fd[1],1,0)实现对管道的加锁操作,用lockf(fd[1],0,0)解除对管道的锁定;(6)实现父子进程的同步,当父进程试图从一空管道中读取数据时,便进入等待状态,直到子进程将数据写入管道返回后,才将其唤醒。
三、实现:相关的系统调用fork() 用于创一个子进程。
格式:int fork();返回值:在子进程中返回0;在父进程中返回所创建的子进程的ID值;当返回-1时,创建失败。
wait() 常用来控制父进程与子进程的同步。
在父进程中调用wait(),则父进程被阻塞,进入等待队列,等待子进程结束。
当子进程结束时,父进程从wait()返回继续执行原来的程序。
返回值:大于0时,为子进程的ID值;等于-1时,调用失败。
exit() 是进程结束时最常调用的。
格式:void exit( int status); 其中,status为进程结束状态。
pipe() 用于创建一个管道格式:pipe(int fd);其中fd是一个由两个数组元素fd[0]和fd[1]组成的整型数组,fd[0]是管道的读端口,用于从管道读出数据,fd[1]是管道的写端口,用于向管道写入数据。
实验三_进程间的通信
本科实验报告专用纸课程名称操作系统原理成绩评定实验项目名称进程间的通信指导教师实验项目编号实验项目类型实验地点学生姓名学号学院系专业实验时间年月日上午~月日上午温度℃湿度一、实验目的和要求1.实验目的:1.学习如何利用管道机制或消息缓冲队列进行进程间的通信,并加深对上述通信机制的理解。
提高学生分析问题和解决问题的能力,并学习撰写规范的科学研究报告(论文)。
2.实验要求:了解系统pipe(),msgsnd(),msgrcv()的功能和实现过程。
二、实验原理和主要内容1.实验内容:(1)编写一段程序,使用管道来实现父子进程之间的进程通信。
子进程向父进程发送自己的进程表示符,以及某字符串。
父进程则通过管道读出子进程发来的消息,将消息显示在屏幕上,然后终止。
(2)编写一段程序,使其用消息缓冲队列来实现client和server 进程之间的通信。
2.实验原理:(使用的系统调用命令说明或算法及程序详细设计)3.实验函数说明(1)包含头文件#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>(2)msgsnd()函数int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);//将消息送入消息队列参数:msqid:消息队列的识别码。
msgp:指向消息缓冲区的指针,此位置用来暂时存储发送和接收的消息,是一个用户可定义的通用结构,形态如下struct msgbuf {long mtype; /* 消息类型,必须> 0 */char mtext[1]; /* 消息文本*/};msgsz:消息的大小。
msgtyp:从消息队列内读取的消息形态。
如果值为零,则表示消息队列中的所有消息都会被读取。
msgflg:用来指明核心程序在队列没有数据的情况下所应采取的行动。
实验3 进程通信
准备知识
掌握Socket通信的基本概念和工作原理; 掌握必要的网络知识,如TCP协议。
实验原理
Socket
Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程 ,可以用来进行网络方面的程序设计与开发。Socket(套接字)是通 过标准的Unix文件描述符和其它程序通信的一个方法。Socket数据传 输是一种特殊的输入输出,Socket套接字也是一种文件描述符。 Socket也具有一个类似于打开文件的创建函数Socket( ),该函数返回 一个整型的Socket描述符,随后的建立连接、消息传输等操作都是对 该描述符进行操作的。每一个套接字都用一个半相关描述:{协议, 本地地址、本地端口}来表示;一个完整的套接字则用一个相关描述 :{协议,本地地址、本地端口、远程地址、远程端口}。每一个套接 字都有一个本地的由操作系统分配的唯一的套接字号。
Socket的三种类型
(1)流式Socket(SOCK_STREAM) 流式套接字提供可靠的、面向连接的通信流;它使用TCP协议, 从而保证了数据传输的正确性和顺序性。 (2)数据报Socket(SOCK_DGRAM) 数据报套接字定义了一种无连接的服务,数据通过相互独立的报 文进行传输,是无序的,并且不保证可靠性、无差错。它使用数据报协 议UDP。 (3)原始Socket 原始套接字允许对底层协议如IP或ICMP直接访问,它功能强大 但使用较为不便,主要用于一些协议的开发。
实验3 进程通信
实验内容1 管道通信 实验内容12 Socket通信
管道通信
实 实 准 实 实
验 验 备 验 验
目 内 知 原 指
的 容 识 理 导
实验目的
计算机操作系统实验-进程通信(一)
进程通信(一)1 .实验目的学习如何利用管道机制、共享存储区机制进行进程间的通信,并加深对上述通信机制的理解。
2 .实验内容(1) 了解系统调用pipe()、shmget()、shmat()、shmdt()、shmctl()的功能和实现过程。
(2) 编写一段程序,使其用管道来实现父子进程之间的进程通信。
子进程向父进程发送自己的进程标识符,以及字符串“is sending a message to parent ! ”。
父进程则通过管道读出子进程发来的消息,将消息显示在屏幕上,然后终止。
(3) 编写一段程序,使其用共享存储区来实现父子进程之间的进程通信。
父进程创建一个长度为512 字节的共享内存空间,显示写入该共享内存的数据;子进程将共享内存也附加到自己的地址空间,并向共享内存中写入数据。
3 .实验步骤(1) 了解系统调用pipe()、shmget()、shmat()、shmdt()、shmctl()的功能和实现过程。
pipe()创建一条管道进行信息传输。
shmget()得到一个共享内存标识符或创建一个共享内存对象并返回共享内存标识符shmat()连接共享内存标识符为shmid的共享内存,连接成功后把共享内存区对象映射到调用进程的地址空间,随后可像本地空间一样访问shmdt()用来断开与共享内存附加点的地址,禁止本进程访问此片共享内存shmctl()共享内存管理,完成对共享内存的控制(2) 编写一段程序,使其用管道来实现父子进程之间的进程通信。
子进程向父进程发送自己的进程标识符,以及字符串“is sending a message to parent ! ”。
父进程则通过管道读出子进程发来的消息,将消息显示在屏幕上,然后终止。
程序代码:#include<stdio.h>#include<stdlib.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<unistd.h>int main(){int pid1,pid2;int fd[2];char out[512],in[512];pipe(fd);pid1=fork();if(pid1==0){sprintf(out,"%d is sending a message to parent!\n",getpid());printf("%s",out);write(fd[1],out,sizeof(out));}else{read(fd[0],in,sizeof(out));printf("%s",in);}return 0;}程序截图:运行结果:(3) 编写一段程序,使其用共享存储区来实现父子进程之间的进程通信。
实验三进程间通信
实验三进程间通信班级: xxx 学号: xxx 姓名: xxx 分数:1、实验目的:Linux系统的进程通信机构(IPC)允许在任意进程间大批量的交换数据。
本实验的目的是了解和熟悉Linux支持的通信机制、共享存储区机制及信号量机制。
2、实验预备内容:阅读Linux系统的msg.c sem.c shm.c等源码文件,熟悉Linux的三种通信机制。
3、实验内容:(1)消息的创建,发送和接收(2)使用系统调用msgget(),msgsnd(),msgrev()及msgctl()编制一长度为1k的消息发送和接收程序。
<程序设计>(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均退出后结束。
4、源代码及运行截图:#include <stdio.h>#include <sys/types.h>#include <sys/msg.h>#include <sys/ipc.h>#define MSGKEY 75struct msgform{long mtype;char mtext[1030];}msg;int msgqid,i;void CLIENT(){ int i;msgqid=msgget(MSGKEY,0777);for (i=10;i>=1;i--){msg.mtype=i;printf("(client)sent \n");msgsnd(msgqid,&msg,1024,0); /*发送消息msg入msgid消息队列*/}}void SERVER(){msgqid=msgget(MSGKEY,0777|IPC_CREAT); /*由关键字获得消息队列*/do{msgrcv(msgqid,&msg,1030,0,0); /*从msgid消息队列接收消息msg*/printf("(server)received \n");}while(msg.mtype!=1); /*消息类型为1时,释放队列*/msgctl(msgqid,IPC_RMID,0);}void main(){while((i=fork())==-1);if(!i) SERVER();while((i=fork())==-1);if(!i) CLIENT();wait(0);wait(0);}5、实验感想本次实验的实验目的是了解和熟悉Linux支持的通信机制、共享存储机制及信号量机制。
实验3 进程通信
实验三进程通信
1.实验类型:设计性实验
2.实验目的:
了解和熟悉LINUX的管道通信、软中断通信、SOCKET通信等
3.实验内容:
练习一三个子进程和父进程的管道通信。
(必做)
编写一个程序,建立一个管道。
同时,父进程生成子进程P1,P2,P3这三个子进程分别向管道中写入消息(消息由键盘输入),父进程将消息读出。
练习二软中断一(必做)
编写一个程序循环输出“how are you?”,当键盘输入Ctrl+C时终止,当输出次数不超过5000次时在此过程中使用Ctrl+C不能中断显示,5000次后才能用Ctrl+C中断显示,然后输出“Byebye”.
练习三软中断二(选做)
使用软中断实现父子进程同步,父进程先输出A,然后子进程输出B。
练习四编程实现基于SOCKET的进程间通信,实现网络中不同终端间可相互通信。
(选做)
要求:分别编写服务器端和客户端两个程序(使用线程),编译后分别在不同终端运行程序,二者间可相互进行通信。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
操作系统实验报告实验三、进程通信(一)——管道及共享内存一、实验目的熟悉和掌握LINUX系统的管道通信和共享内存通信。
二、实验内容(一)、管道通信1、实验原理:管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统。
数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。
利用系统调用pipe()可创建一个简单的管道。
int fd[2];pipe(fd);调用成功,fd[0]存放供读进程使用的文件描述符(管道出口),fd[1]存放供写程使用的文件描述符(管道入口)。
一个进程在由pipe()创建管道后,一般再fork()一个子进程,然后通过管道实现父子进程间的通信,子进程将从父进程那里继承所有打开的文件描述符。
则父子两个进程都能访问组成管道的两个文件描述符,这样子进程可以向父进程发送消息(或者相反)。
发送进程利用文件系统的系统调用write(fd[1],buf,size),把buf中size个字符送入fd[1],接收进程利用read(fd[0],buf,size),把从fd[0]读出的size个字符置入buf中。
这样管道按FIFO(先进先出)方式传送信息。
2、实验内容:#include<stdio.h>main(){ int x,fd[2];char buf[30],s[30];pipe(fd);while ((x=fork())==-1);if (x==0){close(fd[0]);printf("Child Process!\n");strcpy(buf,"This is an example\n");write(fd[1],buf,30);exit(0);}else{close(fd[1]);printf("Parent Process!\n");read(fd[0],s,30);printf("%s\n",s);printf("x value in Parent Process:%d!\n",x);}}(1)阅读上述父子进程利用管道进行通信的例子,写出程序的运行结果并分析。
程序运行x=fork()后,创建里一个子进程,在子进程里x的返回值为0,在父进程里x的返回值为7684,则子进程会执行if语句里的代码段,先关闭了管道的读入端,再在屏幕上输出“Child Process!”,然后将“This is an example\n”存入buf数组中,通过调用write()函数将buf数组的内容从管道的写入端写入,而父进程会执行else语句里的代码段,先关闭了管道的写入端,再在屏幕上输出“Parent Process!”,然后通过调用read ()函数将buf数组的内容从管道的读入端读入冰存储在s数组里,接着通过printf()函数将s数组里的内容输出到屏幕上,最后在屏幕上输出父进程中x的值。
(2)编写程序:父进程利用管道将一字符串交给子进程处理。
子进程读字符串,将里面的字符反向后再交给父进程,父进程最后读取并打印反向的字符串。
#include<stdio.h>main(){ int i,x,fd[2];char buf[20],s[20],cpy[20],m[20];strcpy(buf,"This is an example\n");pipe(fd);write(fd[1],buf,20);while ((x=fork())==-1);if (x==0){printf("Child Process!\n");read(fd[0],s,20);for(i=0;i<20;i++){cpy[i]=s[19-i];}write(fd[1],cpy,20);exit(0);}else{close(fd[1]);printf("Parent Process!\n");read(fd[0],m,20);printf("%s\n",m);}}(二)、共享内存通信1、实验原理:UNIXSystem V IPC软件包分三个组成部分:(1) 共享存储器(shared memory)方式可使得不同进程通过共享彼此的虚拟空间而达到互相对共享区操作和数据通信的目的。
(2) 消息(message)用于进程之间传递分类的格式化数据。
(3) 信号量(semaphore)机制用于通信进程之间往前推进时的同步控制。
信号量总是和共享存储器方式一起使用。
操纵共享内存共有4个系统调用:(1)shmget() :建立一个新的共享区或返回一个已存在的共享存储区描述字;int shmget(key_t key,int size,int shmflag);成功,返回共享内存段的标识符;失败,返回-1,设置errno。
①第一个参数key(键值),预定义的数据类型key_t,其类型是长整型。
用来创建IPC标识符,shmget()返回的标识符与key值一一对应,不同的key值返回不同的标识符。
②第二个参数size,决定了共享内存段的大小(若访问已存在的内存段,该参数可设为0)。
有最大字节数的限制,0x2000000=32M;③第三个参数shmflag,用于设置访问权限及标识创建条件。
#define IPC_PRIV ATE ((key_t)0)#define IPC_CREAT 00001000(八进制)#define IPC_EXCL 00002000(八进制)key值为IPC_PRIV ATE时,调用shmget()将生成一个新的共享内存段。
Shmflag为0666|IPC_CREAT时,如果key值是新的,返回新创建的内存段标识符。
若key值是旧的,返回已存在内核中的具有相同关键字值的内存段标识符。
(2)shmat():连接内存段,映射到自己的地址空间中;int shmat(int shmid,void *shmaddr,int shmflag);成功:返回该共享内存段连接到调用进程地址空间上的地址(指针)错误:返回-1。
第一个参数shmid,是一个有效的共享内存标识符;第二个参数shmaddr,非0,该值作为挂接的地址,设为0,则由系统来选择挂接地址;第三个参数shmflag,可指定挂接后的访问权限,(默认情况0)。
(3)shmdt() :当某个进程不需要一个共享内存段时,调用该系统调用,断开与该内存段的连接。
int shmdt(void *shmaddr);成功:返回0;错误:返回-1。
参数shmaddr指向一个已挂接的内存段。
(4)shmctl():用户对一个存在的共享内存段进行一系列的操作;int shmctl(int shmid,int cmd,struct shmid_ds *buf);成功:返回0;错误:返回-1,设置errno。
第一个参数shmid,前面shmget()调用返回的有效的共享内存标识符;第二个参数cmd,指明shmctl将要执行的操作;第三个参数buf,指向一个shmid_ds类的结构。
Cmd可执行的操作:(这些也是在/usr/include/linux/ipc.h中定义的)IPC_STAT:返回由shmid值指定的存贮段shmid_ds结构的当前值。
IPC_SET:修改shmid_ds结构中反问权限子结构的若干成员IPC_RMID:删除shmid指向的内存段(并非真正删除,只有当前连接到该内存段的最后一个进程正确地断开了与它的连接,实际的删除操作才会发生)。
附:1、ipcs命令的作用:用于查看系统中共享存储区,消息队列和信号量的情况。
2、ipcrm命令的作用:用于删除系统中存在的共享存储区,消息队列等。
如:ipcrm -M key 表示根据关键字删除共享存储区ipcrm -m id表示根据标识符删除共享存储区ipcrm -Q key表示根据关键字删除消息队列ipcrm -q id表示根据标识符删除消息队列2、实验内容:(1)阅读例2的程序,运行一次该程序,然后用ipcs命令查看系统中共享存储区的情况,再次执行该程序,再用ipcs命令查看系统中共享内存的情况,对两次的结果进行比较,并分析原因。
最后用ipcrm命令删除自己建立的共享存储区。
#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>main(){key_t key=69;int shmid_1,shmid_2;if ((shmid_1=shmget(key,1000,0644|IPC_CREAT))= = -1){perror("shmget shmid_1");exit(1);}printf("First shared memory identifier is %d\n",shmid_1);if ((shmid_2=shmget(IPC_PRIV ATE,20,0644))= = -1){perror("shmget shmid_2");exit(2);}printf("Second shared memory identifier is %d\n",shmid_2);exit(0);}key值为IPC_PRIV ATE时,调用shmget()将生成一个新的共享内存段。
(2)每个同学登陆两个窗口,先在一个窗口中运行例3程序1(或者只登陆一个窗口,先在该窗口中以后台方式运行程序1),然后在另一个窗口中运行例3程序2,观察程序的运行结果并分析。
运行结束后可以用ctrl+c结束程序1的运行。
例3:(程序1)#include <sys/types.h>#include <sys/ipc.h>#define SHMKEY 69#define K 1024int shmid;main (){int i,*pint;char *addr;extern char * shmat ();extern cleanup ();for(i=0;i<20;i++) signal(i,cleanup);shmid=shmget(SHMKEY,16*K,0777|IPC_CREAT); /*建立16K共享区SHMKEY */addr=shmat(shmid,0,0);/*挂接,并得到共享区首地址*/printf ("addr 0x%x\n",addr);pint=(int *)addr;for (i=0;i<256;i++) *pint++=i;pause();/*等待接收进程读*/}cleanup(){shmctl(shmid,IPC_RMID,0);exit ();}例3:(程序2)#include <sys/types.h>#include <sys/ipc.h>#define SHMKEY 69#define K 1024int shmid;main (){int i,*pint;char *addr;extern char * shmat ();shmid=shmget(SHMKEY,8*K,0777);/*取共享区SHMKEY的id */ addr=shmat(shmid,0,0);/*连接共享区*/pint=(int *)addr;for (i=0;i<256;i++)printf("%d ",*pint++);/*打印共享区中的内容*/}在后台运行的例3的程序1:首先系统通过调用shmctl()对shmid指向的内存段进行删除操作,接着系统调用shmget()创建一个16K的共享内存段,成功返回共享内存段的标识符给shmid,系统再次调用shmat()连接内存段,返回共享内存段连接到调用进程地址空间上的地址addr,最后向该共享内存段中写入数据;终端运行的例3的程序2:首先系统调用shmget()创建一个8K的共享内存段,由key与程序1相同,所以返回给shmid的值与程序1所创建的共享内存段的标识符相同,再通过调用shmat()挂接内存段,由shmid与程序1相同,所以挂接到程序1所创建的共享内存段,最后读取该共享内存段的数据并输出到屏幕上。