操作系统实验三(进程通信)
操作系统实验,实验3, 进程管理 (1)
在图形界面上利用终端通过命令“su - ”切换到超级用户,编辑文件 “job”; 按组合键[Ctrl+Alt+F2]切换到第二个虚拟终端(超级用户); 输入命令“at –f job now+1 minute”,设置1分钟后执行at调度内容; 稍等后观察at调度的执行效果,再切换到第一个虚拟终端观察at调度 的执行效果;
切换到第一个虚拟终端观察at调度的执行效果(5分钟后系统将执行重 启调度任务)。
[操作要求2] 设置一个调度,要求1分钟后执行文件job中的作业。 文件job的内容为: find /home/jkx/ -name “*.c” > /home/jkx/fdresult wall user jkx, all code files have been searched out! Please check out. [操作步骤]
续表
守 护 进 程 innd Usenet新闻服务器 功 能 说 明
linuxconf
lpd named netfs network
允许使用本地WEB服务器作为用户接口来配置机器
打印服务器 DNS服务器 安装NFS、Samba和NetWare网络文件系统 激活已配置网络接口的脚本程序
nfsd
portmap postgresql routed sendmail
事件(例如xinetd和lpd)
启动守护进程有如下几种方法
在引导系统时启动 人工手动从shell提示符启动
系统启动script的执行期间 被启动(/etc/rc.d) 任何具有相应执行 权限的用户
使用crond守护进程启动
执行at命令启动
守护进程一般由系统在开机时通过脚本或root
操作系统实验3-进程控制
WORD wMajorReq=(WORD)(dwVerReq>16);
WORD wMinorReq=(WORD)(dwVerReq&0xffff);
::cout<<"Process ID:"<<dwIdThis<<",requires OS:"<<wMajorReq<<wMinorReq<<::endl;
{
//改变优先级
::SetPriorityClass(
::GetCurrentProcess(), //利用这一进程
HIGH_PRIORITY_CLASS); //改变为high
//报告给用户
::cout<<"Task Manager should indicate this "
"process is high priority."<<::endl;
//设置版本信息的数据结构,以便保存操作系统的版本信息
OSVERSIONINFOEX osvix;
::ZeroMemory(&osvix,sizeof(osvix));
osvix.dwOSVersionInfoSize=sizeof(osvix);
//提取版本信息和报告
::GetVersionEx(reinterpret_cast<LPOSVERSIONINFO>(&osvix));
Parent();
}
return 0;
}
分析:程序4-3.cpp说明了一个进程从“生”到“死”的整个一生,第一次执行时,它创建一个子进程,其行为如同“父亲”。在创建子进程之前,先创建一个互斥的内核对象,其行为对于子进程来说,如同一个“自杀弹”。当创建子进程时,就打开了互斥体并在其他线程中进行别的处理工作,同时等待着父进程使用ReleaseMutex()API发出“死亡”信号。然后用Sleep()API调用来模拟父进程处理其他工作,等完成时,指令子进程终止。
电大操作系统实验报告3_ 进程管理实验
电大操作系统实验报告3_ 进程管理实验电大操作系统实验报告 3 进程管理实验一、实验目的进程管理是操作系统的核心功能之一,本次实验的目的是通过实际操作和观察,深入理解进程的概念、状态转换、进程调度以及进程间的通信机制,掌握操作系统中进程管理的基本原理和方法,提高对操作系统的整体认识和实践能力。
二、实验环境本次实验使用的操作系统为 Windows 10,编程语言为 C 语言,开发工具为 Visual Studio 2019。
三、实验内容及步骤(一)进程的创建与终止1、编写一个 C 程序,使用系统调用创建一个子进程。
2、在父进程和子进程中分别输出各自的进程 ID 和父进程 ID。
3、子进程执行一段简单的计算任务,父进程等待子进程结束后输出结束信息。
以下是实现上述功能的 C 程序代码:```cinclude <stdioh>include <stdlibh>include <unistdh>int main(){pid_t pid;pid = fork();if (pid < 0) {printf("创建子进程失败\n");return 1;} else if (pid == 0) {printf("子进程:我的进程 ID 是%d,父进程 ID 是%d\n",getpid(), getppid());int result = 2 + 3;printf("子进程计算结果:2 + 3 =%d\n", result);exit(0);} else {printf("父进程:我的进程 ID 是%d,子进程 ID 是%d\n",getpid(), pid);wait(NULL);printf("子进程已结束\n");}return 0;}```编译并运行上述程序,可以观察到父进程和子进程的输出信息,验证了进程的创建和终止过程。
(二)进程的状态转换1、编写一个 C 程序,创建一个子进程,子进程进入睡眠状态一段时间,然后被唤醒并输出状态转换信息。
16207318邓嘉操作系统实验三
操作系统实验第三次实验进程同步实验指导老师:***学号:********姓名:***操作系统第三次实验进程同步实验指导老师:谭朋柳学生:16207318邓嘉4.1 实验目的加深对并发协作进程同步与互斥概念的理解,观察和体验并发进程同步与互斥操作的效果,分析与研究经典进程同步与互斥问题的实际解决方案。
了解Linux 系统中IPC 进程同步工具的用法,练习并发协作进程的同步与互斥操作的编程与调试技术。
4.2 实验说明在linux 系统中可以利用进程间通信(interprocess communication )IPC 中的3 个对象:共享内存、信号灯数组、消息队列,来解决协作并发进程间的同步与互斥的问题。
1)共享内存是OS 内核为并发进程间交换数据而提供的一块内存区(段)。
如果段的权限设置恰当,每个要访问该段内存的进程都可以把它映射到自己私有的地址空间中。
如果一进程更新了段中数据,那么其他进程立即会看到这一更新。
进程创建的段也可由另一进程读写。
linux 中可用命令ipcs -m 观察共享内存情况。
$ ipcs -m------ Shared Memory Segments --------key shmid owner perms bytes nattch status 0x00000000 327682 student 600 393216 2 dest0x00000000 360451 student 600 196608 2 dest 0x00000000 393220 student 600 196608 2 destkey 共享内存关键值shmid 共享内存标识owner 共享内存所由者(本例为student)perm 共享内存使用权限(本例为student 可读可写)byte 共享内存字节数nattch 共享内存使用计数status 共享内存状态上例说明系统当前已由student 建立了一些共享内存,每个都有两个进程在共享。
计算机操作系统03进程的同步与通信
用TS实现进程互斥: repeat while TS(lock) do skip; critical section lock:=false; remainder section until false;
第三章 进程的同步与通信
2. 利用Swap指令实现互斥 Swap指令: procedure (var a,b:Boolean) var temp:Boolean; begin temp:=a; a:=b; b:=temp end
计算机操作系统
第三章 进程的同步与通信
教学目的与要求: 1.掌握进程同步、进程通信、资源、信号量等
基本概念 2.了解解决进程同步问题的软件方法和硬件方
法 3.能用信号量和管程解决简单进程同步问题 4.了解OS/2操作系统的进程同步与通信机制
第三章 进程的同步与通信
重点与难点:
1. 同步、通信、资源、信号量等基本概念
第三章 进程的同步与通信
2 临界资源的定义 临界资源是指并发进程之间在某段时间内同
时提出访问请求的互斥型资源。 例:在A进程正在访问打印机的时候,B进程也提
出对打印机的访问请求,则打印机为临界资源。应 互斥使用临界资源。
三.临界区 1 临界区的定义 是指进程中访问临界资源的那段代码
第三章 进程的同步与通信
第三章 进程的同步与通信
算法3:与算法2相似,只是在flag[i]=ture时表示进 程P[i]要求进入临界区,若此时无其它进程有此要求, 则进程P[i]可进入临界区。对于进程Pi repeat flag[i]:=true; while flag[j] do no_op critical section flag[i]:=false; remainder section until false 该算法的缺点:违背了空闲让进和有限等待原则
进程通信的实验报告
一、实验目的1. 理解进程通信的概念和作用。
2. 掌握进程通信的常用方法,包括管道、消息队列、信号量等。
3. 通过编程实践,加深对进程通信机制的理解和应用。
二、实验环境操作系统:Linux开发环境:gcc三、实验内容1. 管道通信2. 消息队列通信3. 信号量通信四、实验步骤及分析1. 管道通信(1)实验步骤1)创建一个父进程和一个子进程;2)在父进程中创建一个管道,并将管道的读端和写端分别赋给父进程和子进程;3)在父进程中,通过管道的写端发送数据给子进程;4)在子进程中,通过管道的读端接收父进程发送的数据;5)关闭管道的读端和写端;6)结束进程。
(2)实验分析通过管道通信,实现了父进程和子进程之间的数据传递。
管道是半双工通信,数据只能单向流动。
在本实验中,父进程向子进程发送数据,子进程接收数据。
2. 消息队列通信(1)实验步骤1)创建一个消息队列;2)在父进程中,向消息队列中发送消息;3)在子进程中,从消息队列中接收消息;4)删除消息队列;5)结束进程。
(2)实验分析消息队列是一种进程间通信机制,允许不同进程之间传递消息。
消息队列的创建、发送、接收和删除等操作都是通过系统调用实现的。
在本实验中,父进程向消息队列发送消息,子进程从消息队列接收消息,实现了进程间的消息传递。
3. 信号量通信(1)实验步骤1)创建一个信号量;2)在父进程中,对信号量执行P操作,请求资源;3)在子进程中,对信号量执行V操作,释放资源;4)结束进程。
(2)实验分析信号量是一种用于实现进程同步的机制。
在进程通信中,信号量可以用来协调多个进程对共享资源的访问。
在本实验中,父进程和子进程通过信号量实现了对共享资源的同步访问。
五、实验结果1. 管道通信实验结果:父进程成功向子进程发送数据,子进程成功接收数据。
2. 消息队列通信实验结果:父进程成功向消息队列发送消息,子进程成功从消息队列接收消息。
3. 信号量通信实验结果:父进程成功获取资源,子进程成功释放资源。
进程通讯管理实验报告(3篇)
第1篇一、实验目的1. 理解进程通信的概念和原理;2. 掌握进程通信的常用机制和方法;3. 能够使用进程通信机制实现进程间的数据交换和同步;4. 增强对操作系统进程管理模块的理解。
二、实验环境1. 操作系统:Linux2. 编程语言:C3. 开发环境:GCC三、实验内容1. 进程间通信的管道机制2. 进程间通信的信号量机制3. 进程间通信的共享内存机制4. 进程间通信的消息队列机制四、实验步骤1. 管道机制(1)创建管道:使用pipe()函数创建管道,将管道文件描述符存储在两个变量中,分别用于读和写。
(2)创建进程:使用fork()函数创建子进程,实现父子进程间的通信。
(3)管道读写:在父进程中,使用read()函数读取子进程写入的数据;在子进程中,使用write()函数将数据写入管道。
(4)关闭管道:在管道读写结束后,关闭对应的管道文件描述符。
2. 信号量机制(1)创建信号量:使用sem_open()函数创建信号量,并初始化为1。
(2)获取信号量:使用sem_wait()函数获取信号量,实现进程同步。
(3)释放信号量:使用sem_post()函数释放信号量,实现进程同步。
(4)关闭信号量:使用sem_close()函数关闭信号量。
3. 共享内存机制(1)创建共享内存:使用mmap()函数创建共享内存区域,并初始化数据。
(2)映射共享内存:在父进程和子进程中,使用mmap()函数映射共享内存区域。
(3)读写共享内存:在父进程和子进程中,通过指针访问共享内存区域,实现数据交换。
(4)解除映射:在管道读写结束后,使用munmap()函数解除映射。
4. 消息队列机制(1)创建消息队列:使用msgget()函数创建消息队列,并初始化消息队列属性。
(2)发送消息:使用msgsnd()函数向消息队列发送消息。
(3)接收消息:使用msgrcv()函数从消息队列接收消息。
(4)删除消息队列:使用msgctl()函数删除消息队列。
进程控制与进程通信程序实验报告
进程控制与进程通信程序实验报告一、引言进程是计算机系统中最基本的概念之一,是操作系统中最小的资源管理单位。
进程控制与进程通信是操作系统中重要的内容,涉及到进程的创建、调度和终止,以及进程间的信息传递和同步管理。
本实验旨在通过编写进程控制与进程通信程序,加深对操作系统中进程管理和通信机制的理解。
二、实验目的1. 理解进程的概念和特点,掌握进程的创建、调度和终止方法。
2. 掌握进程通信的基本原理和方法,包括共享内存、管道、消息队列和信号量等。
3. 能够编写简单的进程控制和进程通信程序。
三、实验内容1. 进程控制实验:编写一个程序,实现进程的创建、调度和终止。
通过调用系统调用函数,创建多个子进程,并通过进程控制函数实现父子进程的协作与同步。
2. 进程通信实验:编写一个程序,实现进程间的信息传递和同步管理。
通过共享内存、管道、消息队列或信号量等机制,实现不同进程之间的数据交换和共享。
四、实验步骤1. 进程控制实验:(1)创建父进程和子进程:使用fork()函数创建子进程,并通过判断返回值来区分父子进程。
(2)调度子进程:使用wait()函数等待子进程的结束,以实现父子进程的同步。
(3)终止子进程:使用exit()函数终止子进程的运行。
2. 进程通信实验:(1)共享内存:使用shmget()函数创建共享内存段,使用shmat()函数映射共享内存到进程的地址空间,实现共享数据的读写。
(2)管道:使用pipe()函数创建管道,使用fork()函数创建子进程,通过读写管道实现进程间的数据传输。
(3)消息队列:使用msgget()函数创建消息队列,使用msgsnd()函数向消息队列发送消息,使用msgrcv()函数从消息队列接收消息,实现进程间的消息传递。
(4)信号量:使用semget()函数创建信号量,使用semop()函数对信号量进行P操作和V操作,实现进程间的同步和互斥。
五、实验结果通过实验,我们成功实现了进程的创建、调度和终止,以及进程间的信息传递和同步管理。
操作系统第3章-3 进程通信.
发送进程发消息时要指定接收进程的名字,反 过来,接收时要指明发送进程的名字;
发送原语:Send(receiver,message) 接收原语:Receiver(sender,message) * 对称形式:一对一 * 非对称形式:多对一 (顾客/服务员)
2019/7/13
信号量上的PV操作是最简单的进程通信。
2019/7/13
2
进程通信的类型
低级通信机制
交换信息量少,如P、V原语,软中断信号; 适用于集中式操作系统。
高级通信机制:交换信息量大
消息传递(message passing)通信机制; 共享内存(shared memory)通信机制; 管道(Pipe)通信:共享文件(shared file)通信机制; 既适用于集中式操作系统,又适用于分布式操作系统
确定对方的存在
发送者和接收者双方必须能够知道对方是否存在, 如果对方已经不存在,就没有必要再发送信息。
2019/7/13
16
信箱
存放信件的存储区域
构成
信箱特征(头):信箱容量、信件格式、信箱名称等;
信箱体:若干格子,用来存放信件;
分类
私用信箱 共享信箱 公用信箱
发送 Deposite 进程
A (m)
邮箱头 …邮箱体
Remove 接收
(m)
进程
B
信箱使用规则
邮箱通信结构
若发送信件时信箱已满,则发送进程被置为“等信箱”状态,直到信
发送进程返回到用户态继续执行;
在以后某个时刻,当接收进程执行到receive接收原语时,也产 生访管中断进入操作系统。
由操作系统将载有消息的缓冲区从消息链中取出,并把消息内容 copy到接收进程空间,之后收回缓冲区,如此就完成了消息的接 收,接收进程返回到用户态继续进行。
操作系统实验---进程通信——共享存储区和信号量
实验报告实验题目姓名:学号:课程名称:操作系统实验所在学院:信息科学与工程学院专业班级:计算机任课教师:实验项目名称进程通信——共享存储区和信号量一、实验目的与要求:1、了解和熟悉共享存储机制2、了解和熟悉信号量机制3、熟悉信号量机制中使用的数据结构和信号量机制的操作以及控制。
4、了解共享主存段机制,学会对共享主存段的系统调用。
二、实验设备及软件:1、PC机一台2、Linux操作系统三、实验方法(原理、流程图)一、共享存储区1、共享存储区机制的概念共享存储区(Share Memory)是 UNIX 系统中通信速度最高的一种通信机制。
该机制可使若干进程共享主存中的某一个区域,且使该区域出现(映射)在多个进程的虚地址空间中。
另一方面,一个进程的虚地址空间中又可连接多个共享存储区,每个共享存储区都有自己的名字。
当进程间欲利用共享存储区进行通信时,必须先在主存中建立一共享存储区,然后将它附接到自己的虚地址空间上。
此后,进程对该区的访问操作,与对其虚地址空间的其它部分的操作完全相同。
进程之间便可通过对共享存储区中数据的读、写来进行直接通信。
图示列出二个进程通过共享一个共享存储区来进行通信的例子。
其中,进程 A 将建立的共享存储区附接到自己的 AA’区域,进程 B 将它附接到自己的 BB’区域。
应当指出,共享存储区机制只为进程提供了用于实现通信的共享存储区和对共享存储区进行操作的手段,然而并未提供对该区进行互斥访问及进程同步的措施。
因而当用户需要使用该机制时,必须自己设置同步和互斥措施才能保证实现正确的通信。
二、涉及的系统调用1、shmget( )创建、获得一个共享存储区。
系统调用格式: shmid=shmget(key,size,flag)参数定义: int shmget(key,size,flag);key_t key;int size,flag;其中,key是共享存储区的名字;size是其大小(以字节计);flag是用户设置的标志,如IPC_CREAT。
实验三操作系统进程间通信
实验三操作系统进程间通信实验三进程间通信班级:计科f1406 姓名:王家平学号:201416010619一、实验目的:Linux系统的进程通信机构(IPC)允许在任意进程间大批量的交换数据。
本实验的目的是了解和熟悉Linux支持的通信机制、共享存储区机制及信号量机制。
二、实验预备内容:阅读Linux系统的msg.c sem.c shm.c等源码文件,熟悉Linux的三种通信机制。
三、实验内容:(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均退出后结束。
(5)四(实验代码1.#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消息队列*/ }exit(0);}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);exit(0);}void main(){while((i=fork())==-1);if(!i) SERVER();while((i=fork())==-1);if(!i) CLIENT();wait(0);wait(0);}2.#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;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消息队列*/ }exit(0);}main(){while((i=fork())==-1); if(!i) CLIENT();wait(0);}。
操作系统实验三进程的管道通信
操作系统实验三进程的管道通信操作系统中的进程通信是指进程之间通过一定机制进行信息传递和交换的过程。
而管道是常用的进程间通信(IPC)机制之一,它提供了一种半双工的通信方式,用于在具有亲缘关系的进程之间进行通信。
本实验以Linux系统为例,介绍进程的管道通信。
一、进程间通信(IPC)概述进程之间的通信是操作系统的重要功能之一,它使得不同进程能够共享信息、协调工作。
Linux系统提供了多种进程间通信的方式,如管道、消息队列、信号、共享内存等。
其中,管道是最简单、最常用的一种进程间通信方式。
二、管道的概念与原理1.管道的概念管道是一种特殊的文件,用于实现具有亲缘关系的进程之间的通信。
整个管道可以看作是一个字节流,其中写入的数据可以被读取。
管道通常是半双工的,即数据只能从一个进程流向另一个进程,而不能反向流动。
2.管道的原理管道的内部实现是通过操作系统的缓冲区来完成的。
当一个进程往管道写入数据时,数据被放置在写管道的缓冲区中。
另一个进程从管道中读取数据时,数据被从读管道的缓冲区中取出。
如果写管道的缓冲区为空,写操作将会阻塞,直到有数据被写入为止。
同样,如果读管道的缓冲区为空,读操作将会阻塞,直到有数据可读为止。
三、管道的使用步骤1.打开管道在Linux系统中,使用`pipe`系统调用来创建管道。
它接受一个包含两个整数的参数数组,返回0表示成功,负数表示失败。
成功创建管道后,会得到两个文件描述符,分别代表读管道和写管道。
2.进程间通信在有亲缘关系的进程中,可以使用`fork`系统调用来创建一个子进程。
父进程和子进程都可以使用管道进行读写操作。
父进程可以关闭写管道描述符,子进程关闭读管道描述符,即父进程只负责写入数据,子进程负责读取数据。
3.写入数据父进程在写管道描述符上调用`write`函数来向管道写入数据。
该函数的返回值为成功写入的字节数,返回-1表示写入失败。
4.读取数据子进程在读管道描述符上调用`read`函数来从管道读取数据。
操作系统实验报告三
操作系统实验报告三一、实验目的本次操作系统实验的目的在于深入了解操作系统的进程管理、内存管理和文件系统等核心功能,通过实际操作和观察,增强对操作系统原理的理解和掌握,提高解决实际问题的能力。
二、实验环境本次实验在 Windows 10 操作系统环境下进行,使用了 Visual Studio 2019 作为编程工具,并借助了相关的操作系统模拟软件和调试工具。
三、实验内容与步骤(一)进程管理实验1、创建多个进程使用 C++语言编写程序,通过调用系统函数创建多个进程。
观察每个进程的运行状态和资源占用情况。
2、进程同步与互斥设计一个生产者消费者问题的程序,使用信号量来实现进程之间的同步与互斥。
分析在不同并发情况下程序的执行结果,理解进程同步的重要性。
(二)内存管理实验1、内存分配与回收实现一个简单的内存分配算法,如首次适应算法、最佳适应算法或最坏适应算法。
模拟内存的分配和回收过程,观察内存的使用情况和碎片产生的情况。
2、虚拟内存管理了解 Windows 操作系统的虚拟内存机制,通过查看系统性能监视器观察虚拟内存的使用情况。
编写程序来模拟虚拟内存的页面置换算法,如先进先出(FIFO)算法、最近最少使用(LRU)算法等。
(三)文件系统实验1、文件操作使用 C++语言对文件进行创建、读写、删除等操作。
观察文件在磁盘上的存储方式和文件目录的结构。
2、文件系统性能测试对不同大小和类型的文件进行读写操作,测量文件系统的读写性能。
分析影响文件系统性能的因素,如磁盘碎片、缓存机制等。
四、实验结果与分析(一)进程管理实验结果1、创建多个进程在创建多个进程的实验中,通过任务管理器可以观察到每个进程都有独立的进程 ID、CPU 使用率、内存占用等信息。
多个进程可以并发执行,提高了系统的资源利用率。
2、进程同步与互斥在生产者消费者问题的实验中,当使用正确的信号量机制时,生产者和消费者能够协调工作,不会出现数据不一致或死锁的情况。
实验三_进程间的通信
本科实验报告专用纸课程名称操作系统原理成绩评定实验项目名称进程间的通信指导教师实验项目编号实验项目类型实验地点学生姓名学号学院系专业实验时间年月日上午~月日上午温度℃湿度一、实验目的和要求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:用来指明核心程序在队列没有数据的情况下所应采取的行动。
(完整word版)操作系统实验进程的通信
(操作系统原理和linux操作系统相结合的实验)实验二进程的通信一实验目的1 学会使用vi编辑器编辑C语言程序2 学会Linux环境下gcc的使用3 学会调试工具GDB的使用二实验原理1 利用linux提供的进程通信的系统调用设计进程通信程序,加深对进程通信概念的理解。
2 体会进程通信的方法和效果。
三实验环境PC机1台,Windows操作系统和其上的虚拟Linux操作系统。
四实验步骤1.管道通信(1)编写一个程序。
父进程创建一个子进程和一个无名管道fd,由子进程向管道写入信息“This is a message”,然后终止执行;父进程接收到子进程终止信号后从管道中读出并显示信息后结束。
#include<stdio.h>#include<unistd.h>main(){int p1,fd[2];char outpipe[50]; //定义读缓冲区char inpipe[50]="This is a message!"; //定义写缓冲区pipe(fd); //创建无名管道fdwhile((p1=fork())==-1);if (p1==0) //子进程返回{write(fd[1],inpipe,50); //写信息到管道exit(0);}else //父进程返回{wait(0); //等待子进程终止read(fd[0],outpipe,50); //从管道读信息到读缓冲区printf("%s\n",outpipe); //显示读到的信息exit(0);}}(2)父进程创建两个子进程,父子进程之间利用管道进行通信。
要求能显示父进程、子进程各自的信息,体现通信效果。
(源程序pipe_1.c)#include<stdio.h>main(){int I,r,j,k,l,p1,p2,fd[2];char buf[50],s[50];pipe(fd);while((p1=fork())==-1);if(p1==0){lockf(fd[1],1,0);sprintf(buf,"Child process p1 is sending message!\n");printf("Child process p1!\n");write(fd[1],buf,50);lockf(fd[1],0,0);sleep(5);j=getpid();k=getppid();printf("p1 %d is weakup.My parent process id is %d.\n",j,k);exit(0);}else{while((p2=fork())==-1);if(p2==0){lockf(fd[1],1,0);sprintf(buf,"Child process p2 is sending message!\n");printf("Child process p2!\n");write(fd[1],buf,50);lockf(fd[1],0,0);sleep(5);j=getpid();k=getppid();printf("p2 %d is weakup.My parent process id is %d.\n",j,k);exit(0);}else{I=getpid();wait(0);if(r=read(fd[0],s,50)==-1)printf("can’t read pip e.");elseprintf("Parent %d:%s\n",l,s);wait(0);if(r=read(fd[0],s,50)==-1)pr intf("can’t read pipe");elseprintf ( "Parent %d:%s\n",l,s);exit(0);}}}结果:2.共享内存通信。
进程通信实验报告
西安电子科技大学《操作系统原理》实验报告题目:进程通信实验报告班级: 030912姓名:王增祥学号: 03091168实验内容补充说明:一、分析和设计1.理论分析每个Windows进程都是由一个执行体进程块(EPROCESS)表示。
API函数CreatProcess 可以创建进程,采用管道技术可以实现进程间的相互通信。
建立pipe,进程以及其子进程就可以对该管道进程读写共享,管道读写操作利用,write、read、close进行。
父进程利用pipe 发送消息,子进程利用该pipe接收父进程发来的消息;子进程利用管道向父进程发送应答,父进程利用该pipe接受应答。
2.总体设计1、利用CreatProcess函数创建进程。
2、创建管道,实现进程间的通信二、详细实现1、创建界面,采用Botton、列表框等控件创建父子界面如下图:父进程界面:子进程界面:其中父进程各个空间创建类向导如图:子进程创建类向导如图:2.父进程编写(1)创建管道:(2)创建子进程:(3)消息发送(4)消息接受3.子进程编写(1)发送消息(2)读消息三、实验结果点击创建子进程按钮:在创建子进程之后进行进程间的通信如下图四、心得体会1、从试验的角度了解了进程间是怎样利用管道进行通信的,了解了进程间通信的实际过程2、进一步掌握了MFC的初步编程技巧,知道了怎样调试程序。
3进一步了解了,API函数的应用,明白了怎样进行界面编程。
4、进一步熟悉了在进行进程通信的编写过程中的各个细节。
六、附录Process_Father.cpp#include "stdafx.h"#include "Process_Father.h" //包含已编写的Process_Father.h头文件#include "Process_FatherDlg.h" //包含已编写的Process_FatherDlg.h头文件//进行宏定义#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif//创建父进程BEGIN_MESSAGE_MAP(CProcess_FatherApp, CWinApp)//{{AFX_MSG_MAP(CProcess_FatherApp)// NOTE - the ClassWizard will add and remove mapping macros here.// DO NOT EDIT what you see in these blocks of generated code!//}}AFX_MSGON_COMMAND(ID_HELP, CWinApp::OnHelp)END_MESSAGE_MAP()// CProcess_FatherApp constructionCProcess_FatherApp::CProcess_FatherApp(){// TODO: add construction code here,// Place all significant initialization in InitInstance}// The one and only CProcess_FatherApp objectCProcess_FatherApp theApp;// CProcess_FatherApp initializationBOOL CProcess_FatherApp::InitInstance(){AfxEnableControlContainer();#ifdef _AFXDLLEnable3dControls(); // Call this when using MFC in a shared DLL #elseEnable3dControlsStatic(); // Call this when linking to MFC statically #endifCProcess_FatherDlg dlg;m_pMainWnd = &dlg;int nResponse = dlg.DoModal();if (nResponse == IDOK){// TODO: Place code here to handle when the dialog is// dismissed with OK}else if (nResponse == IDCANCEL){// TODO: Place code here to handle when the dialog is// dismissed with Cancel}// Since the dialog has been closed, return FALSE so that we exit the// application, rather than start the application's message pump.return FALSE;}Process_FatherDlg.cpp// Process_FatherDlg.cpp : implementation file//#include "stdafx.h"#include "Process_Father.h"#include "Process_FatherDlg.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App Aboutclass CAboutDlg : public CDialog{public:CAboutDlg();// Dialog Data//{{AFX_DATA(CAboutDlg)enum { IDD = IDD_ABOUTBOX };//}}AFX_DATA// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CAboutDlg)protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL// Implementationprotected://{{AFX_MSG(CAboutDlg)//}}AFX_MSGDECLARE_MESSAGE_MAP()};CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD){//{{AFX_DATA_INIT(CAboutDlg)//}}AFX_DATA_INIT}void CAboutDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CAboutDlg)//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)//{{AFX_MSG_MAP(CAboutDlg)// No message handlers//}}AFX_MSG_MAPEND_MESSAGE_MAP()///////////////////////////////////////////////////////////////////////////// // CProcess_FatherDlg dialogCProcess_FatherDlg::CProcess_FatherDlg(CWnd* pParent /*=NULL*/) : CDialog(CProcess_FatherDlg::IDD, pParent){//{{AFX_DATA_INIT(CProcess_FatherDlg)//}}AFX_DATA_INIT// Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);}void CProcess_FatherDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CProcess_FatherDlg)DDX_Control(pDX, IDC_BT_CreateChildProcess, m_BT_CreateChildProcess);DDX_Control(pDX, IDC_Send, m_Send);DDX_Control(pDX, IDC_LISTBOX_Record, m_LISTBOX_Record);DDX_Control(pDX, IDC_EDIT_Message, m_EDIT_Message);//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CProcess_FatherDlg, CDialog)//{{AFX_MSG_MAP(CProcess_FatherDlg)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_BT_CreateChildProcess, OnBTCreateChildProcess)ON_BN_CLICKED(IDC_Send, OnSend)//}}AFX_MSG_MAPON_MESSAGE(WM_CHILD_SEND,OnReceiveMsg)END_MESSAGE_MAP()///////////////////////////////////////////////////////////////////////////// // CProcess_FatherDlg message handlersBOOL CProcess_FatherDlg::OnInitDialog(){CDialog::OnInitDialog();// Add "About..." menu item to system menu.// IDM_ABOUTBOX must be in the system command range.ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){CString strAboutMenu;strAboutMenu.LoadString(IDS_ABOUTBOX);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialogSetIcon(m_hIcon, TRUE); // Set big iconSetIcon(m_hIcon, FALSE); // Set small icon// TODO: Add extra initialization herereturn TRUE; // return TRUE unless you set the focus to a control}void CProcess_FatherDlg::OnSysCommand(UINT nID, LPARAM lParam){if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialog::OnSysCommand(nID, lParam);}}// If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework.void CProcess_FatherDlg::OnPaint(){if (IsIconic()){CPaintDC dc(this); // device context for paintingSendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);// Center icon in client rectangleint cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// Draw the icondc.DrawIcon(x, y, m_hIcon);}else{CDialog::OnPaint();}}// The system calls this to obtain the cursor to display while the user drags // the minimized window.HCURSOR CProcess_FatherDlg::OnQueryDragIcon(){return (HCURSOR) m_hIcon;}void CProcess_FatherDlg::OnBTCreateChildProcess(){//创建管道SECURITY_ATTRIBUTES sa;sa.nLength=sizeof(SECURITY_ATTRIBUTES);sa.lpSecurityDescriptor=NULL;sa.bInheritHandle=TRUE;::CreatePipe(&hPipeRead,&hPipeWrite,&sa,0);::CreatePipe(&hPipeRead2,&hPipeWrite2,&sa,0);//创建子进程STARTUPINFO StartupInfo;memset(&StartupInfo,0,sizeof(STARTUPINFO)) ;StartupInfo.cb=sizeof(STARTUPINFO);StartupInfo.dwFlags=STARTF_USESTDHANDLES;StartupInfo.hStdInput=hPipeRead;StartupInfo.hStdOutput=hPipeWrite;StartupInfo.hStdError=GetStdHandle(STD_ERROR_HANDLE);PROCESS_INFORMATION ProcessInfo;::CreateProcess("Process_Child.exe",NULL,NULL,NULL,TRUE,0,NULL,NULL,&Startu pInfo,&ProcessInfo);m_BT_CreateChildProcess.EnableWindow(FALSE);}void CProcess_FatherDlg::OnSend(){CString str;char ss[20]="Father:";m_EDIT_Message.GetWindowText(str);DWORD dwWritten;if(!WriteFile(hPipeWrite,str,40,&dwWritten,NULL)){MessageBox(TEXT("写错误"),"警告",MB_OK|MB_ICONWARNING);}CString strWinName = "Process_Child";CWnd *pWnd=CWnd::FindWindow(NULL,strWinName);if(pWnd){pWnd->SendMessage(WM_FATHER_SEND,0,0);strcat(ss,str);m_LISTBOX_Record.InsertString(-1,ss);m_EDIT_Message.SetWindowText("");}else{MessageBox("没有发现子进程","错误");}}void CProcess_FatherDlg::OnReceiveMsg(WPARAM wParam,LPARAM lParam){DWORD dwRead;TCHAR s[40];HANDLE hPipeRead2;hPipeRead2=GetStdHandle(STD_INPUT_HANDLE);if(!ReadFile(hPipeRead,s,40,&dwRead,NULL)){MessageBox(TEXT("读错误!"),"警告",MB_OK|MB_ICONWARNING);}char str[60]="Child: ";strcat(str,s);m_LISTBOX_Record.InsertString(-1,str);}Process_Father.h// Process_Father.h : main header file for the PROCESS_FATHER application//#if !defined(AFX_PROCESS_FATHER_H__1F9659A2_2B93_4C1E_89C5_5A88971D3DDA__INCLUD ED_)#define AFX_PROCESS_FATHER_H__1F9659A2_2B93_4C1E_89C5_5A88971D3DDA__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000#ifndef __AFXWIN_H__#error include 'stdafx.h' before including this file for PCH#endif#include "resource.h" // main symbols///////////////////////////////////////////////////////////////////////////// // CProcess_FatherApp:// See Process_Father.cpp for the implementation of this class//class CProcess_FatherApp : public CWinApp{public:CProcess_FatherApp();// Overrides// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CProcess_FatherApp)public:virtual BOOL InitInstance();//}}AFX_VIRTUAL// Implementation//{{AFX_MSG(CProcess_FatherApp)// NOTE - the ClassWizard will add and remove member functions here.// DO NOT EDIT what you see in these blocks of generated code !//}}AFX_MSGDECLARE_MESSAGE_MAP()};///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCATION}}// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif// !defined(AFX_PROCESS_FATHER_H__1F9659A2_2B93_4C1E_89C5_5A88971D3DDA__INCLUDE D_)Process_FatherDlg.h// Process_FatherDlg.h : header file//#if !defined(AFX_PROCESS_FATHERDLG_H__69E2942A_7A5F_413F_B4A3_AFB8C1F51DFE__INC LUDED_)#defineAFX_PROCESS_FATHERDLG_H__69E2942A_7A5F_413F_B4A3_AFB8C1F51DFE__INCLUDED_#define WM_FATHER_SEND WM_USER+100#define WM_CHILD_SEND WM_USER+101#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000///////////////////////////////////////////////////////////////////////////// // CProcess_FatherDlg dialogclass CProcess_FatherDlg : public CDialog{// Constructionpublic:CProcess_FatherDlg(CWnd* pParent = NULL); // standard constructor// Dialog Data//{{AFX_DATA(CProcess_FatherDlg)enum { IDD = IDD_PROCESS_FATHER_DIALOG };CButton m_BT_CreateChildProcess;CButton m_Send;CListBox m_LISTBOX_Record;CEdit m_EDIT_Message;//}}AFX_DATA// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CProcess_FatherDlg)protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL// Implementationprotected:HICON m_hIcon;// Generated message map functions//{{AFX_MSG(CProcess_FatherDlg)virtual BOOL OnInitDialog();afx_msg void OnSysCommand(UINT nID, LPARAM lParam);afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();afx_msg void OnReceiveMsg(WPARAM wParam, LPARAM lParam);afx_msg void OnBTCreateChildProcess();afx_msg void OnSend();//}}AFX_MSGDECLARE_MESSAGE_MAP()private:HANDLE hPipeWrite2;HANDLE hPipeRead2;HANDLE hPipeWrite;HANDLE hPipeRead;};//{{AFX_INSERT_LOCATION}}// Microsoft Visual C++ will insert additional declarations immediately before theprevious line.#endif// !defined(AFX_PROCESS_FATHERDLG_H__69E2942A_7A5F_413F_B4A3_AFB8C1F51DFE__INCL UDED_)子进程代码Process_Child.cpp// Process_Child.cpp : Defines the class behaviors for the application.//#include "stdafx.h"#include "Process_Child.h"#include "Process_ChildDlg.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/////////////////////////////////////////////////////////////////////////////// CProcess_ChildAppBEGIN_MESSAGE_MAP(CProcess_ChildApp, CWinApp)//{{AFX_MSG_MAP(CProcess_ChildApp)// NOTE - the ClassWizard will add and remove mapping macros here.// DO NOT EDIT what you see in these blocks of generated code!//}}AFX_MSGON_COMMAND(ID_HELP, CWinApp::OnHelp)END_MESSAGE_MAP()///////////////////////////////////////////////////////////////////////////// // CProcess_ChildApp constructionCProcess_ChildApp::CProcess_ChildApp(){// TODO: add construction code here,// Place all significant initialization in InitInstance}///////////////////////////////////////////////////////////////////////////// // The one and only CProcess_ChildApp objectCProcess_ChildApp theApp;///////////////////////////////////////////////////////////////////////////// // CProcess_ChildApp initializationBOOL CProcess_ChildApp::InitInstance(){AfxEnableControlContainer();// Standard initialization// If you are not using these features and wish to reduce the size// of your final executable, you should remove from the following// the specific initialization routines you do not need.#ifdef _AFXDLLEnable3dControls(); // Call this when using MFC in a shared DLL #elseEnable3dControlsStatic(); // Call this when linking to MFC statically #endifCProcess_ChildDlg dlg;m_pMainWnd = &dlg;int nResponse = dlg.DoModal();if (nResponse == IDOK){// TODO: Place code here to handle when the dialog is// dismissed with OK}else if (nResponse == IDCANCEL){// TODO: Place code here to handle when the dialog is// dismissed with Cancel}// Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump.return FALSE;}Process_ChildDlg.cpp// Process_ChildDlg.cpp : implementation file//#include "stdafx.h"#include "Process_Child.h"#include "Process_ChildDlg.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App Aboutclass CAboutDlg : public CDialog{public:CAboutDlg();// Dialog Data//{{AFX_DATA(CAboutDlg)enum { IDD = IDD_ABOUTBOX };//}}AFX_DATA// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CAboutDlg)protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL// Implementationprotected://{{AFX_MSG(CAboutDlg)//}}AFX_MSGDECLARE_MESSAGE_MAP()};CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD){//{{AFX_DATA_INIT(CAboutDlg)//}}AFX_DATA_INIT}void CAboutDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CAboutDlg)//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)//{{AFX_MSG_MAP(CAboutDlg)// No message handlers//}}AFX_MSG_MAPEND_MESSAGE_MAP()///////////////////////////////////////////////////////////////////////////// // CProcess_ChildDlg dialogCProcess_ChildDlg::CProcess_ChildDlg(CWnd* pParent /*=NULL*/): CDialog(CProcess_ChildDlg::IDD, pParent){//{{AFX_DATA_INIT(CProcess_ChildDlg)//}}AFX_DATA_INIT// Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);}void CProcess_ChildDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CProcess_ChildDlg)DDX_Control(pDX, IDC_Send, m_Send);DDX_Control(pDX, IDC_LISTBOX_Record, m_LISTBOX_Record);DDX_Control(pDX, IDC_EDIT_Message, m_EDIT_Message);//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CProcess_ChildDlg, CDialog)//{{AFX_MSG_MAP(CProcess_ChildDlg)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_Send, OnSend)//}}AFX_MSG_MAPON_MESSAGE(WM_FATHER_SEND,OnReceiveMsg)END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CProcess_ChildDlg message handlersBOOL CProcess_ChildDlg::OnInitDialog(){CDialog::OnInitDialog();// Add "About..." menu item to system menu.// IDM_ABOUTBOX must be in the system command range.ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){CString strAboutMenu;strAboutMenu.LoadString(IDS_ABOUTBOX);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}// Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialogSetIcon(m_hIcon, TRUE); // Set big iconSetIcon(m_hIcon, FALSE); // Set small icon// TODO: Add extra initialization herereturn TRUE; // return TRUE unless you set the focus to a control}void CProcess_ChildDlg::OnSysCommand(UINT nID, LPARAM lParam){if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialog::OnSysCommand(nID, lParam);}// If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework.void CProcess_ChildDlg::OnPaint(){if (IsIconic()){CPaintDC dc(this); // device context for paintingSendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);// Center icon in client rectangleint cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// Draw the icondc.DrawIcon(x, y, m_hIcon);}else{CDialog::OnPaint();}}// The system calls this to obtain the cursor to display while the user drags // the minimized window.HCURSOR CProcess_ChildDlg::OnQueryDragIcon(){return (HCURSOR) m_hIcon;}void CProcess_ChildDlg::OnSend(){char ss[20]="Child:";CString str;m_EDIT_Message.GetWindowText(str);DWORD dwWritten;hPipeWrite=GetStdHandle(STD_OUTPUT_HANDLE);if(!WriteFile(hPipeWrite,str,40,&dwWritten,NULL)) {MessageBox(TEXT("写错误"),"警告",MB_OK|MB_ICONWARNING);}CString strWinName = "Process_Father";CWnd *pWnd=CWnd::FindWindow(NULL,strWinName);if(pWnd){pWnd->SendMessage(WM_CHILD_SEND,0,0);strcat(ss,str);m_LISTBOX_Record.InsertString(-1,ss);m_EDIT_Message.SetWindowText("");}else{MessageBox("没有发现父进程","错误");}void CProcess_ChildDlg::OnReceiveMsg(WPARAM wParam,LPARAM lParam){DWORD dwRead;char s[40];HANDLE hPipeRead;hPipeRead=GetStdHandle(STD_INPUT_HANDLE);if(!ReadFile(hPipeRead,s,40,&dwRead,NULL)){MessageBox(TEXT("读错误!"),"警告",MB_OK|MB_ICONWARNING);}char str[60]="Father: ";strcat(str,s);m_LISTBOX_Record.InsertString(-1,str);}Process_Child.h// Process_Child.h : main header file for the PROCESS_CHILD application//#if !defined(AFX_PROCESS_CHILD_H__7416C60C_DD56_40CC_BD28_3DA310873DE7__INCLUDE#define AFX_PROCESS_CHILD_H__7416C60C_DD56_40CC_BD28_3DA310873DE7__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000#ifndef __AFXWIN_H__#error include 'stdafx.h' before including this file for PCH#endif#include "resource.h" // main symbols///////////////////////////////////////////////////////////////////////////// // CProcess_ChildApp:// See Process_Child.cpp for the implementation of this class//class CProcess_ChildApp : public CWinApp{public:CProcess_ChildApp();// Overrides// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CProcess_ChildApp)public:virtual BOOL InitInstance();//}}AFX_VIRTUAL// Implementation//{{AFX_MSG(CProcess_ChildApp)// NOTE - the ClassWizard will add and remove member functions here.// DO NOT EDIT what you see in these blocks of generated code !//}}AFX_MSGDECLARE_MESSAGE_MAP()};///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCATION}}// Microsoft Visual C++ will insert additional declarations immediately before theprevious line.#endif// !defined(AFX_PROCESS_CHILD_H__7416C60C_DD56_40CC_BD28_3DA310873DE7__INCLUDED _)Process_ChildDlg.h// Process_ChildDlg.h : header file//#if !defined(AFX_PROCESS_CHILDDLG_H__01C41D47_4973_4DCB_84FC_4B7C5A6C584A__INCL UDED_)#define AFX_PROCESS_CHILDDLG_H__01C41D47_4973_4DCB_84FC_4B7C5A6C584A__INCLUDED_ #define WM_FATHER_SEND WM_USER+100#define WM_CHILD_SEND WM_USER+101#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000///////////////////////////////////////////////////////////////////////////// // CProcess_ChildDlg dialogclass CProcess_ChildDlg : public CDialog{// Constructionpublic:CProcess_ChildDlg(CWnd* pParent = NULL); // standard constructor// Dialog Data//{{AFX_DATA(CProcess_ChildDlg)enum { IDD = IDD_PROCESS_CHILD_DIALOG };CButton m_Send;CListBox m_LISTBOX_Record;CEdit m_EDIT_Message;//}}AFX_DATA// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CProcess_ChildDlg)protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL// Implementationprotected:HICON m_hIcon;// Generated message map functions//{{AFX_MSG(CProcess_ChildDlg)virtual BOOL OnInitDialog();afx_msg void OnSysCommand(UINT nID, LPARAM lParam);afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();afx_msg void OnReceiveMsg(WPARAM wParam, LPARAM lParam);afx_msg void OnSend();//}}AFX_MSGDECLARE_MESSAGE_MAP()private:HANDLE hPipeWrite;};//{{AFX_INSERT_LOCATION}}// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif// !defined(AFX_PROCESS_CHILDDLG_H__01C41D47_4973_4DCB_84FC_4B7C5A6C584A__INCLU DED_)。
进程通信实验报告
进程通信实验报告进程通信实验报告概述进程通信是操作系统中非常重要的一个概念,它允许不同的进程之间进行数据的交换和共享。
在本次实验中,我们通过使用不同的进程通信机制,如管道、消息队列和共享内存,来实现进程之间的数据传输和通信。
本报告将详细介绍实验的背景、实验过程、结果分析以及对实验的总结。
实验背景进程通信是操作系统中的一个核心概念,它允许多个进程之间进行数据的交换和共享。
在现代操作系统中,进程通信是实现并发和协作的重要手段。
了解不同的进程通信机制以及它们的优缺点对于深入理解操作系统的原理和实现至关重要。
实验过程在本次实验中,我们使用了三种不同的进程通信机制:管道、消息队列和共享内存。
首先,我们创建了两个进程,一个作为发送方,一个作为接收方。
然后,我们分别使用了管道、消息队列和共享内存来实现进程之间的数据传输和通信。
管道是一种最简单的进程通信机制,它可以在父进程和子进程之间进行单向的通信。
我们通过创建一个管道,并将其连接到父进程和子进程的标准输入和标准输出,实现了父子进程之间的数据传输。
消息队列是一种更为灵活的进程通信机制,它可以实现多个进程之间的双向通信。
我们使用了系统提供的消息队列函数,创建了一个消息队列,并在发送方将消息发送到队列中,接收方则从队列中接收消息。
通过消息队列,我们实现了进程之间的异步通信。
共享内存是一种高效的进程通信机制,它允许多个进程共享同一块内存空间。
我们使用了共享内存函数,创建了一个共享内存区域,并将其映射到两个进程的虚拟地址空间中。
通过共享内存,我们实现了进程之间的数据共享和同步。
结果分析通过实验,我们发现不同的进程通信机制各有优缺点。
管道是最简单的一种机制,但只能实现单向通信,且只能用于具有亲缘关系的进程。
消息队列可以实现多个进程之间的双向通信,但消息的顺序可能会被打乱。
共享内存是最高效的一种机制,但需要额外的同步机制来保证数据的一致性。
总结进程通信是操作系统中非常重要的一个概念,它允许不同的进程之间进行数据的交换和共享。
操作系统实验报告实验3_1
操作系统实验报告实验3_1一、实验目的本次实验的主要目的是深入理解操作系统中进程管理的相关概念和原理,通过实际操作和观察,掌握进程的创建、调度、同步与互斥等关键机制,提高对操作系统内核工作原理的认知和实践能力。
二、实验环境本次实验在装有 Windows 10 操作系统的计算机上进行,使用了Visual Studio 2019 作为开发工具,编程语言为 C++。
三、实验内容与步骤(一)进程创建1、编写一个简单的 C++程序,使用系统调用创建一个新的进程。
2、在父进程和子进程中分别输出不同的信息,以区分它们的执行逻辑。
```cppinclude <iostream>include <windowsh>int main(){DWORD pid;HANDLE hProcess = CreateProcess(NULL, "childexe", NULL, NULL, FALSE, 0, NULL, NULL, NULL, &pid);if (hProcess!= NULL) {std::cout <<"Parent process: Created child process with PID "<< pid << std::endl;WaitForSingleObject(hProcess, INFINITE);CloseHandle(hProcess);} else {std::cerr <<"Failed to create child process" << std::endl;return 1;}return 0;}```(二)进程调度1、设计一个多进程并发执行的程序,通过设置不同的优先级,观察操作系统对进程的调度情况。
2、记录每个进程的执行时间和等待时间,分析调度算法的效果。
```cppinclude <iostream>include <windowsh>DWORD WINAPI ProcessFunction(LPVOID lpParam) {int priority =(int)lpParam;DWORD start = GetTickCount();std::cout <<"Process with priority "<< priority <<"started" << std::endl;for (int i = 0; i < 100000000; i++){//执行一些计算操作}DWORD end = GetTickCount();DWORD executionTime = end start;std::cout <<"Process with priority "<< priority <<" ended Execution time: "<< executionTime <<" ms" << std::endl;return 0;}int main(){HANDLE hThread1, hThread2;int priority1 = 1, priority2 = 2;hThread1 = CreateThread(NULL, 0, ProcessFunction, &priority1, 0, NULL);hThread2 = CreateThread(NULL, 0, ProcessFunction, &priority2, 0, NULL);if (hThread1!= NULL && hThread2!= NULL) {SetThreadPriority(hThread1, THREAD_PRIORITY_LOWEST);SetThreadPriority(hThread2, THREAD_PRIORITY_NORMAL);WaitForSingleObject(hThread1, INFINITE);WaitForSingleObject(hThread2, INFINITE);CloseHandle(hThread1);CloseHandle(hThread2);} else {std::cerr <<"Failed to create threads" << std::endl;return 1;}return 0;}```(三)进程同步与互斥1、实现一个生产者消费者问题的程序,使用信号量来实现进程之间的同步与互斥。
操作系统实验 进程通信
进程通信(实验二)【实验目的】:掌握用邮箱方式进行进程通信的方法,并通过设计实现简单邮箱理解进程通信中的同步问题以及解决该问题的方法。
【实验原理】:邮箱机制类似于日常使用的信箱。
对于用户而言使用起来比较方便,用户只需使用send()向对方邮箱发邮件receive()从自己邮箱取邮件,send()和receive()的内部操作用户无需关心。
因为邮箱在内存中实现,其空间有大小限制。
其实send()和receive()的内部实现主要还是要解决生产者与消费者问题。
【实验内容】:进程通信的邮箱方式由操作系统提供形如send()和receive()的系统调用来支持,本实验要求学生首先查找资料了解所选用操作系统平台上用于进程通信的系统调用具体形式,然后使用该系统调用编写程序进行进程间的通信,要求程序运行结果可以直观地体现在界面上。
在此基础上查找所选用操作系统平台上支持信号量机制的系统调用具体形式,运用生产者与消费者模型设计实现一个简单的信箱,该信箱需要有创建、发信、收信、撤销等函数,至少能够支持两个进程互相交换信息,比较自己实现的信箱与操作系统本身提供的信箱,分析两者之间存在的异同。
实验背景介绍进程间通信有如下目的:数据的传输,共享数据,通知事情,资源共享,进程控制。
进程间的通信机制(IPC),就是多进程相互通信,交换信息的方法。
Linux IPC机制包括,信号和管道是其中的两个,还支持传统的UNIX SYSTM-V 的IPC 机制。
信号主要用来通知进程异步事情的发生,最初信号设计的目的是为了处理错误,他们也用来作为最基本的IPC机制。
管道是单向的,先进先出,先入先出,无结构的,固定大小的数据流。
UNIX System V 机制中的三种进程间通信机制,它们是:消息队列:用于进程之间传递分类的格式化数据信号量:用于通信之间的同步控制。
信号量通常与共享存储器方式一起使用。
共享内存:使不同进程通过共享彼此的虚拟空间而达到相互对共享区操作和数据通信。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
暨南大学本科实验报告专用纸
一、实验目的
学习如何利用管道机制或消息缓冲队列进行进程间的通信,并加深对上述通信机制的理解。
提高学生分析问题和解决问题的能力,并学习撰写规范的科学研究报告。
二、实验环境及设备
(一)实验室名称:计算机实验室
(二)主要仪器设备:PC机、Linux操作系统环境
三、实验内容
编写一段程序,使用管道来实现父子进程之间的进程通信。
子进程项父进程发送自己的进程表示符,以及某字符串。
父进程则通过管道读出子进程发来的消息,将消息显示在屏幕上,然后终止。
四、实验调试分析
1、实验函数说明
(1)pipe
头文件:#include<unistd.h>
定义函数:int pipe(int pipedes[2]);
函数说明:
pipe()会建立管道,并将文件描述词由参数pipedes 数组返回。
pipedes[0]为管道里的读取端,所以pipe用read调用的
pipedes[1]则为管道的写入端。
头文件:#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所指的文件做各种锁定或解除锁定的动作。
此函数只能锁定整个文件,无法锁定文
件的某一区域。
参数 operation有下列四种情况:
LOCK_SH 建立共享锁定。
多个进程可同时对同一个文件作共享锁定。
LOCK_EX 建立互斥锁定。
一个文件同时只有一个互斥锁定。
LOCK_UN 解除文件锁定状态。
LOCK_NB 无法建立锁定时,此操作可不被阻断,马上返回进程。
通常与LOCK_SH 或LOCK_EX 做OR(|)组合。
单一文件无法同时建立共享锁定和互斥锁定,而当使用dup()或fork()时文件描述词不会继承此种锁定。
返回值返回0表示成功,若有错误则返回-1,错误代码存于errno。
2、实验调试
实验过程中,由于将字符串"is sending a message to parent!"以字符数组的形式存储的,故只申请了31个字符空间,没有多申请一个字符空间存储末尾的'\0',在程序运行时就会出现错误结果,错误结果如下图所示,理论上应该不会出现错误的,因为在write、read函数中都有限制向管道中写入、读出多少个字符的。
但在运行时却出乎意料的出错了,要是申请的空间大于字符个数,就不会出现错误了。
在实验过程中还遇到了另一个问题——字符串"is sending a message to parent!"被两次输出。
怀疑是该字符串被两次的写入了管道,因为查看程序时只发现一个地方有输出该字符串,该字符串是从管道读出的且只输出一次,该字符串在写入管道时也是只写了一次。
总之向管道中写入一次字符串,也读出一次,但是输入该字符串时且输出了两次连续的该字符串,由于实验过程中一直调试该错误程序,没有保留当时的程序,所以没有找到当时错误的原因。
五、实验结果
六、实验源程序
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[]) {
pid_t pid;
int temp,result;
int pipedes[2];
char s[50];
char d[50];
if((pipe(pipedes))==-1) /*创建管道*/
{
perror("pipe");
exit(EXIT_FAILURE);
}
if((pid=fork())==-1) /*创建新进程*/
{
perror("fork");
exit(EXIT_FAILURE);
}else if(pid == 0) /*子进程*/
{
sprintf(s,"%d is sending a message to parent!",getpid());
printf("now,write data to pipe\n");
flock(pipedes[1],1,0);
if((write(pipedes[1],s,50))==-1) /*将数据写入管道*/
{
perror("write");
exit(EXIT_SUCCESS);
}
flock(pipedes[1],0,0);
}else if(pid > 0) /*父进程*/
{
wait(0);
printf("now,read data form pipe\n");
if((read(pipedes[0],d,50))==-1) /*从管道中读取数据*/
{
perror("read");
exit(EXIT_FAILURE);
}
printf("the data from pipe is: %s\n",d);
}
return 0;
}
七、实验心得
通过调用管道了解了父子进程之间的进程通信,子进程项发出的消息,对父进程的影响,以及父进程对子进程所有的内容进行显示。