操作系统实验报告(进程的管道及消息通信)
操作系统实验报告6
操作系统实验报告6一、实验目的本次操作系统实验的主要目的是深入了解和掌握操作系统中进程管理、内存管理、文件系统等核心概念和相关技术,通过实际操作和观察,增强对操作系统工作原理的理解,并提高解决实际问题的能力。
二、实验环境本次实验使用的操作系统为 Windows 10,实验工具包括 Visual Studio 2019 等。
三、实验内容(一)进程管理实验1、创建多个进程,并观察它们的运行状态和资源占用情况。
通过编写简单的C++程序,使用Windows API 函数创建多个进程。
在程序中,设置不同的进程优先级和执行时间,观察操作系统如何调度这些进程,以及它们对 CPU 使用率和内存的影响。
2、进程间通信实现了进程间的管道通信和消息传递。
通过创建管道,让两个进程能够相互交换数据。
同时,还使用了 Windows 的消息机制,使进程之间能够发送和接收特定的消息。
(二)内存管理实验1、内存分配与释放使用 C++的动态内存分配函数(如`malloc` 和`free`),在程序运行时动态申请和释放内存。
观察内存使用情况,了解内存碎片的产生和处理。
2、虚拟内存管理研究了 Windows 操作系统的虚拟内存机制,通过查看系统的性能监视器,观察虚拟内存的使用情况,包括页面文件的大小和读写次数。
(三)文件系统实验1、文件操作进行了文件的创建、读取、写入、删除等基本操作。
通过编写程序,对不同类型的文件(如文本文件、二进制文件)进行处理,了解文件系统的工作原理。
2、目录操作实现了目录的创建、删除、遍历等功能。
了解了目录结构在文件系统中的组织方式和管理方法。
四、实验步骤(一)进程管理实验步骤1、打开 Visual Studio 2019,创建一个新的 C++控制台项目。
2、在项目中编写代码,使用`CreateProcess` 函数创建多个进程,并设置它们的优先级和执行时间。
3、编译并运行程序,通过任务管理器观察进程的运行状态和资源占用情况。
操作系统实验报告
《操作系统》课程实验报告专业:软件工程班级:软件二班学号: 2220111350 姓名:韩培培序号: 14目录:实验一、进程的创建实验二、进程控制实验三、进程的管道通信实验四、消息通信实验五、进程调度实验六、FIFO页面调度实验七、LRU页面置换算法实验一进程的创建一.实验目的:进程的创建二.实验内容:编写一段程序,使用系统调用 FORK( )创建两个子进程。
当此程序运行时,在系统中有一个父进程和两个子进程活动。
让每一个进程在屏幕上显示一个字符:父进程显示字符“A”子进程分别显示字符“B”和“C”。
试观察记录屏幕上的显示结果,并分析原因。
三.实验代码:#include <stdio.h>Main(){ int p1,p2;While((p1=fork())==-1);If (p1==0)Putchar(ˊbˊ);else{While((p2=fork())==-1);If(p2==0)Putchar(ˊcˊ);else putchar(ˊaˊ);}}四.实验运行结果五.分析原因程序首先调用Fork()函数创建一个子进程1.当创建进程不成功,循环创建进程,直至进程创建成功。
如果Fork()返回值为0,表示当前进程是子进程1,显示字符B。
如果Fork()返回值大于0,则表示当前进程是父进程,表示当前的程序代码是父进程所要执行的。
父进程调用Fork()创建子进程2。
当创建进程不成功时,循环创建进程直至成功。
如果Fork()返回值为0,则表示当前进程是子进程2,显示字符C。
如果Fork()返回值大于0,则表示当前进程是父进程,输出字符A。
实验二:进程控制一.实验目的:进程控制二.实验内容:修改已编写的程序,将每个进程的输出由单个字符改为一个字符串,再观察程序的执行时屏幕上出现的现象,并分析原因三.实验代码:# include<stdio.h>Main(){ int p1,p2,i;While((p1=fork())== -1);If (p1 == 0)For (i=0;i<500;i++)Printf("child %d/n",i);else{While((p2 =fork()) == -1);if(p2 == 0)for (i= 0;i<500;i++)printf("son%d\n",i)elsefor(i = 0;i<500;i++)printf("daughter%d\n",i);}}四.分析原因:由于函数Printf()输出的字符串之间不会被中断,因此,字符串内部的字符顺序输出时不变。
《操作系统》实验报告
一、实验目的1. 理解进程的概念及其在操作系统中的作用。
2. 掌握进程的创建、调度、同步和通信机制。
3. 学习使用进程管理工具进行进程操作。
4. 提高对操作系统进程管理的理解和应用能力。
二、实验环境1. 操作系统:Windows 102. 软件环境:Visual Studio 20193. 实验工具:C++语言、进程管理工具(如Task Manager)三、实验内容1. 进程的创建与销毁2. 进程的调度策略3. 进程的同步与互斥4. 进程的通信机制四、实验步骤1. 进程的创建与销毁(1)创建进程使用C++语言编写一个简单的程序,创建一个新的进程。
程序如下:```cpp#include <iostream>#include <windows.h>int main() {// 创建进程STARTUPINFO si;PROCESS_INFORMATION pi;ZeroMemory(&si, sizeof(si));si.cb = sizeof(si);ZeroMemory(&pi, sizeof(pi));// 创建进程if (!CreateProcess(NULL, "notepad.exe", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {std::cout << "创建进程失败" << std::endl;return 1;}std::cout << "进程创建成功" << std::endl;// 等待进程结束WaitForSingleObject(pi.hProcess, INFINITE);// 销毁进程CloseHandle(pi.hProcess);CloseHandle(pi.hThread);return 0;}```(2)销毁进程在上面的程序中,通过调用`WaitForSingleObject(pi.hProcess, INFINITE)`函数等待进程结束,然后使用`CloseHandle(pi.hProcess)`和`CloseHandle(pi.hThread)`函数销毁进程。
操作系统实验报告(进程的管道及消息通信)
printf("\n Ihave wrote:%s",string); write(fd,string,45); string[0]+=1; } else { read(fd,buf,256); printf("\n The context by I have read is :!%s",buf); buf[0]='\0'; } } close(fd); } 运行结果:
char parent[]="A message to pipe'communication.\n";
main() {
int pid,chan1[2]; char buf[100]; pipe(chan1); pid=fork(); if(pid<0) {
printf("to create child error\n"); exit(1); } if(pid>0) { close(chan1[0]); printf("parent process sends a message to child.\n"); write(chan1[1],parent,sizeof(parent)); close(chan1[1]); printf("parent process waits the child to terminate\n"); wait(0); printf("parent process terminate\n"); } else { close(chan1[1]); read(chan1[0],buf,100); printf("The message read by child process from parent is :%s.\n",buf); close(chan1[0]); printf("child process terminates\n"); } } 运行结果:
操作系统进程通信报告
实验四:进程同步实验一、实验任务:1、熟悉操作系统进程通信原理2、设计程序,实现共享内存、管道通信、消息通信二、实验原理:1、进程间通信的几种方法简介(1)消息队列:消息队列是消息的链接表,包括Posix消息队列systemV消息队列。
有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。
(2)共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。
是针对其他通信机制运行效率较低而设计的。
往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
(3)无名管道(Pipe)及有名管道(named pipe):有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;无名管道可用于有亲缘关系的进程之间彼此的通信,进行通信时候必须有一定的机制保证对管道写和读的互斥:即在读是要关闭写的端口,而在写的时候也要保证读的一端是关闭的。
2、进程通信函数(1)消息队列有关系统调用函数a.创建消息队列使用msgget()函数:#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>int msgget(key_t key, int flag) ;该函数成功调用返回消息队列标识符。
其中的key是关键字,可以由ftok()函数得到:key=ftok(“.”,’a’);其中”.”可以是任何目录,’a’是任意字符,即所有群组标识。
flag是标识,IPC_CREAT位表示创建,一般由服务器程序创建消息队列时使用。
如果是客户程序,必须打开现存的消息队列,必须不使用IPC_CREAT。
发送和接收的消息都必须使用一个类似msgbuf的结构表示,msgbuf结构定义如下:struct msgbuf{long mtype;char mtext[1];}上面的定义,消息内容只有一个字节,是不实用的,一般我们需要重新定义一个结构:struct amsgbuf{long mtype;char mtext[200];}其中的mtype都是消息类型。
通信管道实验报告(3篇)
第1篇一、实验目的1. 理解通信管道的概念和作用。
2. 掌握管道的创建、使用和销毁方法。
3. 学习管道在进程间通信中的应用。
4. 熟悉管道的同步机制。
二、实验原理管道(Pipe)是UNIX系统中实现进程间通信(IPC)的一种古老且常用的方法。
它允许一个进程向另一个进程发送数据。
管道通常由两个端点组成:一个用于写入数据,另一个用于读取数据。
管道可以用于父子进程之间的通信,也可以用于兄弟进程之间的通信。
三、实验内容1. 创建管道:使用`pipe()`系统调用创建管道。
2. 写入数据:使用`write()`系统调用向管道写入数据。
3. 读取数据:使用`read()`系统调用从管道读取数据。
4. 管道的同步:使用`select()`或`poll()`等系统调用来实现管道的同步。
5. 管道的销毁:使用`close()`系统调用销毁管道。
四、实验步骤1. 创建管道:```cint pipefd[2];if (pipe(pipefd) == -1) {perror("pipe");exit(EXIT_FAILURE);}```2. 创建子进程:```cpid_t pid = fork();if (pid == -1) {perror("fork");exit(EXIT_FAILURE);}```3. 在子进程中写入数据:```cif (pid == 0) {close(pipefd[0]); // 关闭读端write(pipefd[1], "Hello, world!\n", 14); close(pipefd[1]); // 关闭写端exit(EXIT_SUCCESS);}```4. 在父进程中读取数据:```cclose(pipefd[1]); // 关闭写端char buffer[1024];read(pipefd[0], buffer, sizeof(buffer));printf("Received: %s\n", buffer);close(pipefd[0]); // 关闭读端```5. 同步管道:```cfd_set readfds;FD_ZERO(&readfds);FD_SET(pipefd[0], &readfds);select(pipefd[0] + 1, &readfds, NULL, NULL, NULL);```6. 销毁管道:```cclose(pipefd[0]);close(pipefd[1]);```五、实验结果1. 创建管道成功。
进程通信的实验报告
一、实验目的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. 理解进程的基本概念和进程控制块(PCB)的作用。
2. 掌握进程创建、调度、同步和通信的基本方法。
3. 熟悉进程状态转换及进程同步机制。
4. 提高编程能力,加深对操作系统进程管理的理解。
二、实验环境1. 操作系统:Windows 102. 编程语言:C/C++3. 开发环境:Visual Studio 2019三、实验内容1. 进程创建与销毁2. 进程调度3. 进程同步4. 进程通信四、实验步骤1. 进程创建与销毁(1)定义进程结构体```ctypedef struct {int pid; // 进程IDchar name[50]; // 进程名int status; // 进程状态struct PCB next; // 指向下一个进程的指针} PCB;```(2)创建进程```cPCB createProcess(char name) {PCB newProcess = (PCB )malloc(sizeof(PCB)); newProcess->pid = ...; // 分配进程IDstrcpy(newProcess->name, name);newProcess->status = ...; // 初始化进程状态 newProcess->next = NULL;// ... 其他初始化操作return newProcess;}```(3)销毁进程```cvoid destroyProcess(PCB process) {free(process);}```2. 进程调度(1)定义进程队列```ctypedef struct {PCB head; // 队列头指针PCB tail; // 队列尾指针} ProcessQueue;```(2)初始化进程队列```cvoid initProcessQueue(ProcessQueue queue) {queue->head = NULL;queue->tail = NULL;}```(3)入队```cvoid enqueue(ProcessQueue queue, PCB process) { if (queue->head == NULL) {queue->head = process;queue->tail = process;} else {queue->tail->next = process;queue->tail = process;}}(4)出队```cPCB dequeue(ProcessQueue queue) {if (queue->head == NULL) {return NULL;}PCB process = queue->head;queue->head = queue->head->next; if (queue->head == NULL) {queue->tail = NULL;}return process;}```3. 进程同步(1)互斥锁```ctypedef struct {int locked; // 锁的状态} Mutex;void initMutex(Mutex mutex) {mutex->locked = 0;void lock(Mutex mutex) {while (mutex->locked) {// 等待锁释放}mutex->locked = 1;}void unlock(Mutex mutex) {mutex->locked = 0;}```(2)信号量```ctypedef struct {int count; // 信号量值Mutex mutex; // 互斥锁} Semaphore;void initSemaphore(Semaphore semaphore, int count) { semaphore->count = count;initMutex(&semaphore->mutex);}void P(Semaphore semaphore) {lock(&semaphore->mutex);while (semaphore->count <= 0) {// 等待信号量}semaphore->count--;unlock(&semaphore->mutex);}void V(Semaphore semaphore) {lock(&semaphore->mutex);semaphore->count++;unlock(&semaphore->mutex);}```4. 进程通信(1)管道通信```cint pipe(int pipefd[2]) {// 创建管道}void writePipe(int pipefd[2], const void buf, size_t nbyte) { // 向管道写入数据}void readPipe(int pipefd[2], void buf, size_t nbyte) {// 从管道读取数据}```(2)消息队列通信```cint msgget(key_t key, int msgflg) {// 创建消息队列}void msgsnd(int msqid, const void msgp, size_t msgsz, int msgflg) {// 向消息队列发送消息}void msgrcv(int msqid, void msgp, size_t msgsz, long msgtype, int msgflg) {// 从消息队列接收消息}```五、实验结果与分析1. 进程创建与销毁:通过创建和销毁进程,验证了进程结构体的正确性。
进程的管道通信实验报告
进程的管道通信实验报告一、实验目的本实验旨在通过实际操作,深入理解进程间通信(IPC)的原理,掌握管道通信的实现方法,提高对操作系统进程管理的理解。
二、实验环境实验环境为Linux操作系统,使用Shell脚本进行进程的管道通信实验。
三、实验内容1. 创建两个Shell脚本文件,分别命名为sender.sh和receiver.sh。
2. 在sender.sh中,编写一个简单的程序,用于向管道中写入数据。
程序包括一个无限循环,每次循环中随机生成一个数字并写入管道。
3. 在receiver.sh中,编写一个简单的程序,用于从管道中读取数据。
程序同样包括一个无限循环,每次循环中从管道中读取一个数字并输出。
4. 使用Shell命令将sender.sh和receiver.sh链接起来,实现进程间的管道通信。
四、实验过程1. 打开两个终端窗口,分别用于运行sender.sh和receiver.sh。
2. 在第一个终端窗口中,输入命令“bash sender.sh”运行sender.sh脚本。
该脚本将创建一个无限循环,每次循环中随机生成一个数字并写入管道。
3. 在第二个终端窗口中,输入命令“bash receiver.sh”运行receiver.sh脚本。
该脚本将创建一个无限循环,每次循环中从管道中读取一个数字并输出。
4. 观察两个终端窗口的输出,可以看到sender.sh进程向管道中写入的数字被receiver.sh进程读取并输出。
五、实验总结通过本次实验,我们成功实现了进程间的管道通信。
在实验过程中,我们深入了解了进程间通信的原理和实现方法,掌握了管道通信的基本操作。
通过实际操作,我们更好地理解了操作系统中进程管理、进程间通信的相关知识。
同时,我们也发现了一些不足之处,例如在程序中没有添加异常处理机制等。
在今后的学习中,我们将继续深入探索进程间通信的相关知识,提高自己的编程技能和系统设计能力。
操作系统实验4 进程的管道通信
操作系统实验报告计算机0703班200729实验4 进程的管道通信1. 实验目的1)加深对进程概念的理解,明确进程和程序的区别。
2)进一步认识并发执行的实质。
3)分析进程争用资源的现象,学习解决进程互斥的方法。
4)学习解决进程同步的方法。
5)了解Linux系统中进程通信的基本原理。
进程是操作系统中最重要的概念,贯穿始终,也是学习现代操作系统的关键。
通过本次实验,要求理解进程的实质和进程管理的机制。
在Linux系统下实现进程从创建到终止的全过程,从中体会进程的创建过程、父进程和子进程之间的关系、进程状态的变化、进程之间的互斥、同步机制、进程调度的原理和以管道为代表的进程间的通信方式的实现。
2. 内容及要求:这是一个设计型实验,要求自行编制程序。
使用系统调用pipe()建立一条管道,两个子进程分别向管道写一句话:Child process1 is sending a message!Child process2 is sending a message!父进程从管道读出来自两个子进程的信息,显示在屏幕上。
要求:1)父进程先接收子进程1发来的消息,然后再接收子进程2发来的消息。
2)实现管道的互斥使用,当一个子进程正在对管道进行写操作时,另一子进程必须等待。
使用系统调用lockf(fd[1],1,0)实现对管道的加锁操作,用lockf(fd[1],0,0)解除对管道的锁定。
3)实现父子进程的同步,当子进程把数据写入管道后,便去睡眠等待;当父进程试图从一空管道中读取数据时,也应等待,直到子进程将数据写入管道后,才将其唤醒。
3.相关的系统调用1)fork() 用于创一个子进程。
格式:int fork();返回值:在子进程中返回0;在父进程中返回所创建的子进程的ID值;当返回-1时,创建失败。
2)wait() 常用来控制父进程与子进程的同步。
在父进程中调用wait(),则父进程被阻塞,进入等待队列,等待子进程结束。
进程的管道通信实验总结
进程的管道通信实验是一个非常有用的实验,它允许两个进程之间进行数据交换。
这个实验主要涉及到了管道、管道缓冲区以及进程之间的通信机制。
以下是对这个实验的总结:
1. 管道的概念和作用:
管道是一种用于进程间通信的机制,它允许两个进程之间进行数据交换。
在管道通信实验中,我们创建了一个管道,并使用它来在两个进程之间传递数据。
管道的作用是连接两个进程,使得它们可以相互发送和接收数据。
2. 管道缓冲区:
管道缓冲区是管道中的一个重要概念。
当一个进程向管道写入数据时,数据会被写入缓冲区中,等待另一个进程读取。
当缓冲区中的数据被读取后,缓冲区中的数据会被移除,为新的数据腾出空间。
3. 进程间的通信:
在管道通信实验中,我们创建了两个进程,并使用管道来在它们之间进行通信。
一个进程向管道写入数据,另一个进程从管道读取数据。
通过这种方式,两个进程可以相互发送和接收数据。
4. 实验中的问题和解决方案:
在实验中,我们遇到了一些问题,如管道中的数据读写错误、进程间的通信问题等。
为了解决这些问题,我们采取了一些措施,如检查数据的读写是否正确、确保进程间的通信畅通等。
5. 实验的意义和收获:
通过这个实验,我们深入了解了进程间通信的概念和机制,并掌握了管道通信的基本原理和方法。
此外,我们还学会了如何解决实验中遇到的问题,提高了我们的编程能力和解决问题的能力。
总之,进程的管道通信实验是一个非常有意义的实验,它让我们深入了解了进程间通信的原理和方法。
通过这个实验,我们不仅掌握了相关的知识和技能,还提高了我们的编程能力和解决问题的能力。
管道的系统实验报告(3篇)
一、实验目的1. 理解管道的概念和原理。
2. 掌握管道的创建、使用和关闭方法。
3. 熟悉管道在进程间通信中的应用。
4. 通过实验加深对管道系统调用的理解。
二、实验环境操作系统:Linux编程语言:C/C++开发环境:GCC三、实验原理管道(Pipe)是UNIX系统中实现进程间通信(IPC)的一种古老且有效的机制。
它允许两个有亲缘关系的进程(如父子进程)之间进行单向数据传输。
管道是一种半双工通信方式,即数据只能在一个方向上流动。
在Linux系统中,管道是通过系统调用`pipe()`创建的。
`pipe()`函数返回两个文件描述符,分别代表管道的两个端点:一个用于读操作,另一个用于写操作。
四、实验内容1. 创建管道。
2. 创建子进程。
3. 父进程向管道写数据。
4. 子进程从管道读数据。
5. 关闭管道。
五、实验步骤1. 创建管道include <stdio.h>include <unistd.h>include <sys/types.h>include <sys/wait.h>int main() {int pipe_fd[2];if (pipe(pipe_fd) == -1) {perror("pipe");return 1;}return pipe_fd[0]; // 返回管道的读端文件描述符}```2. 创建子进程```cinclude <stdio.h>include <unistd.h>include <sys/types.h>include <sys/wait.h>int main() {int pipe_fd[2];pid_t pid;if (pipe(pipe_fd) == -1) {perror("pipe");return 1;}pid = fork();if (pid == -1) {perror("fork");return 1;}if (pid == 0) {// 子进程close(pipe_fd[0]); // 关闭读端write(pipe_fd[1], "Hello, Parent!", 17); // 向管道写数据 close(pipe_fd[1]); // 关闭写端} else {// 父进程close(pipe_fd[1]); // 关闭写端char buffer[100];read(pipe_fd[0], buffer, sizeof(buffer)); // 从管道读数据 printf("Received from child: %s\n", buffer);close(pipe_fd[0]); // 关闭读端wait(NULL); // 等待子进程结束}return 0;}```3. 编译并运行程序```bashgcc -o pipe_example pipe_example.c./pipe_example```输出结果:```Received from child: Hello, Parent!```4. 分析实验结果实验结果显示,父进程成功从管道中读取了子进程写入的数据。
操作系统--进程通信实验报告
2.编辑结果如下。
3.编译和运行程序。
4. 运行解释结果
父进程创建一个子进程和一个无名管道fd。
父进程wait(0)等待子进程的终止信号,子进程向管道写入信息“This is a message。
”然后终止,父进程收到终止信号后从管道读出信息并显示在屏幕上后结束。
2.编辑结果如下。
3.编译和运行程序。
4. 运行解释结果
父进程先创建一个子进程1,子进程1往管道fd里写入信息,并输出parent的信息,父进程接着有创造了一个子进程2,子进程2也往fd管道fd里写入信息,父进程wait(0)等待两个子进程结束信号,等两个子进程都结束后,输出管道里的信息。
实现了父子进程之间的管道通信。
1.编辑源程序。
2.编辑结果如下。
3.编译和运行程序。
4. 运行解释结果
发送进程将要发送的信息从键盘输入,每输入一行就作为一条信息发送,用“end”作为结
束的信息,存入共享的内存区。
接收进程从信息队列逐个取出信息并显示输出。
1.编辑源程序。
2.编辑结果如下。
3.编译和运行程序。
4. 运行解释结果
发送进程将要发送的信息从键盘输入,每输入一行就作为一条信息发送,用“end”作为结束的信息,存入信息缓冲区。
接收进程从信息队列逐个取出信息并显示输出。
操作系统 进程的管道通信 实验报告
3、验证了lockf的加锁解锁作用,并验证了读写进程互斥。
4、进程中sleep(5)的作用是让所显示的内容休眠5秒钟,即等待5秒钟再显示。进程1和进程2也能对管道进行操作,因为他们同属于共同的管道,共同共享资源。
int j;
for(j=0;j<5;j++)
{
sprintf(OutPipe, "\n Child process %d is sending message!\n",j)eep(5);
}
lockf(fd[1], 0, 0);
exit(0);
进程的管道通信实验报告
学号
姓名
时间
2011年11月18日
专业
网络工程
班级
5班
实验题目:进程的管道通信实验
实验目的:
1、了解什么是管道
2、熟悉UNIX/LINUX支持的管道通信方式
3、通过进程多次的循环读写学习利用管道进行进程间的通信
4、验证lockf的加锁解锁作用
5、验证读写进程本身是否已经实现了互斥作用
}
else
{
printf("\nFather1\n");
int p;
for(p=0;p<5;p++)
{
read(fd[0], InPipe, 50);
printf("%s\n", InPipe);
}
printf("\nFather2\n");
int q;
for(q=0;q<5;q++)
实验一 进程通信——管道和信号实验报告
进程管理实验报告【姓名】…【学号】…【实验题目】进程管理【实验目的】a.加深对进程概念的理解,明确进程和程序的区别;b.进一步认识并发执行的实质;c.分析进程争用资源的现象,学习解决进程互斥的方法;d.了解Unix系统中进程通信的基本原理【实验预备知识】学习UNIX中有关进程创建、控制和通信的部分。
【实验方法】利用Unix系统提供的内部函数创建进程并管理进程,从而实现进程控制、进程间通信和进程的管道通信。
【实验内容】(1)进程的创建编写程序,创建两个子进程。
当此程序运行时,系统中有一个父进程和两个子进程。
父进程在屏幕上显示“Parent”,子进程分别在屏幕上显示“Child1”和“Child2”。
(2)进程控制如果在程序中使用系统调用lockf()来给每一个进程加锁,可以实现进程之间的互斥,观察并分析出现的现象。
(3)进程间通信①编制一个程序,使其实现进程的软中断通信。
要求:使用系统调用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上来的中断信号(即DEL键);当捕捉到中断信号后,父进程用系统调用kill()向两个进程发出信号,子进程捕捉到信号后分别输出下列信息后终止:Child Process 1 is Killed by Parent!Child Process 2 is Killed by Parent!父进程等待两个子进程终止后,输出如下信息后终止:Parent Process is killed!②在上面的程序中增加语句signal(SIGINT, SIG_IGN)和signal(SIGQUIT, SIG_IGN),观察执行结果,并分析原因。
(4)进程的管道通信编制一段程序,实现进程的通信。
使用系统调用pipe()建立一条管道;两个子进程P1和P2分别向管道各写一句话:Child 1 is sending a message!Child 2 is sending a message!而父进程则从管道中读出来自两个子进程的信息,显示在屏幕上。
操作系统实验三进程的管道通信
操作系统实验三进程的管道通信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]是管道的写端口,用于向管道写入数据。
进程通信实验报告
西安电子科技大学《操作系统原理》实验报告题目:进程通信实验报告班级: 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_)。
进程通信实验报告
进程通信实验报告进程通信实验报告概述进程通信是操作系统中非常重要的一个概念,它允许不同的进程之间进行数据的交换和共享。
在本次实验中,我们通过使用不同的进程通信机制,如管道、消息队列和共享内存,来实现进程之间的数据传输和通信。
本报告将详细介绍实验的背景、实验过程、结果分析以及对实验的总结。
实验背景进程通信是操作系统中的一个核心概念,它允许多个进程之间进行数据的交换和共享。
在现代操作系统中,进程通信是实现并发和协作的重要手段。
了解不同的进程通信机制以及它们的优缺点对于深入理解操作系统的原理和实现至关重要。
实验过程在本次实验中,我们使用了三种不同的进程通信机制:管道、消息队列和共享内存。
首先,我们创建了两个进程,一个作为发送方,一个作为接收方。
然后,我们分别使用了管道、消息队列和共享内存来实现进程之间的数据传输和通信。
管道是一种最简单的进程通信机制,它可以在父进程和子进程之间进行单向的通信。
我们通过创建一个管道,并将其连接到父进程和子进程的标准输入和标准输出,实现了父子进程之间的数据传输。
消息队列是一种更为灵活的进程通信机制,它可以实现多个进程之间的双向通信。
我们使用了系统提供的消息队列函数,创建了一个消息队列,并在发送方将消息发送到队列中,接收方则从队列中接收消息。
通过消息队列,我们实现了进程之间的异步通信。
共享内存是一种高效的进程通信机制,它允许多个进程共享同一块内存空间。
我们使用了共享内存函数,创建了一个共享内存区域,并将其映射到两个进程的虚拟地址空间中。
通过共享内存,我们实现了进程之间的数据共享和同步。
结果分析通过实验,我们发现不同的进程通信机制各有优缺点。
管道是最简单的一种机制,但只能实现单向通信,且只能用于具有亲缘关系的进程。
消息队列可以实现多个进程之间的双向通信,但消息的顺序可能会被打乱。
共享内存是最高效的一种机制,但需要额外的同步机制来保证数据的一致性。
总结进程通信是操作系统中非常重要的一个概念,它允许不同的进程之间进行数据的交换和共享。
基于管道的进程通信 操作系统实验报告2
}
else
{
wait(0);
if((r=read(fd[0],s,50))==-1)
printf("can not read pipe\n");
else printf("%s\n",s);
}
}
\\创建管道
\\创建子进程p1
\\p1抢上CPU
\\p1将字符串写入管道
\\撤销进程
\\父进程抢上CPU
内蒙古师大计算机与信息工程学院
《操作系统》课程实验报告
实习题目
实验二
基于管道的进程通信
指导教师
职称
学生姓名
学号
日期
实现工具
C语言
实现环境
Linux
实习内容(功能、目标)
内容:
编写一段程序,使用系统调用pipe()创建一无名管道,同时父进程创建一个子进程p1;并使子进程通过管道向父进程传递数据“p1 process is sending data to father.”,父进程通过管道接收到该字符串后输出。
char buf[50],s[50];
pipe(fd);
while((p1=fork())==-1);
if(p1==0)
{
sprintf(buf,"p1is sending data to father.");
printf("childp1!\n");
write(fd[1],buf,50);
sleep(5);
\\父进程从管道中读取字符串失败
\\读取成功输出字符串
结果分析(含实现中出错原因分析)
思考问题:
(1)为什么要在父进程与子进程之间通过管道同步传递数据?不同步而任意写入或读取数据结果如何?
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
while((fgets(line,MAXLINE,fpin))!=NULL) {
if(fputs(line,fpout)==EOF) {
fprintf(stderr,"fputs error to pipe. \n"); exit(1); } } if(ferror(fpin)) { fprintf(stderr,"fgets error. \n"); exit(1); } if(pclose(fpout)==-1) { fprintf(stderr,"pclose error. \n"); exit(1); } exit(0); } 运行结果:
3、有名管道的通信
有名管道使用的例子;代码如下: #include<sys/types.h> #include<sys/stat.h> #include<unistd.h> #include<fcntl.h> int mknod(const char *pathname,mode_t mode,dev_t dev); char string []="this is a example to show fifo communication";
二.消息缓冲机制
客户进程收到服务结果信息后,显示两者的通信过程,下面给出 客户进程和服务者进程通信示例的源程序: (1) 客户进程的通信过程 #include<sys/types.h> #include<sys/ipc.h> #include<sys/msg.h> #define SVKEY 75 #define REQ 1 struct msgform {
为读进程分配文件表项、为写进程分配文件表
项、分配用户文件描述符
4、读/写进程互斥:内核为地址设置一个读指针 和一个写指针,按先进先出顺序读、写。为使 读、写进程互斥地访问pipe文件,需使各进程互 斥地访问pipe文件索引结点中的直接地址项。因 此,每次进程在访问pipe文件前,都需检查该索 引文件是否已被上锁。若是,进程便睡眠等待, 否则,将其上锁,进行读/写。操作结束后解 锁,并唤醒因该索引结点上锁而睡眠的进程。
一、什么是管道:
所谓管道,是指能够连接一个写进程和一个读进 程的、并允许它们以生产者—消费者方式进行通 信的一个共享文件,又称为pipe文件。由写进程 从管道的写入端(句柄1)将数据写入管道,而 读进程则从管道的读出端(句柄0)读出数据。 二、管道的类型: 1、有名管道:一个可以在文件系统中长期存在 的、具有路径名的文件。用系统调用mknod( )建 立。它克服无名管道使用上的局限性,可让更多 的进程也能利用管道进行通信。因而其它进程可 以知道它的存在,并能利用路径名来访问该文 件。对有名管道的访问方式与访问其他文件一 样,需先用open( )打开。 2、无名管道:一个临时文件。利用pipe( )建立起 来的无名文件(无路径名)。只用该系统调用所 返回的文件描述符来标识该文件,故只有调用 pipe( )的进程及其子孙进程才能识别此文件描述 符,才能利用该文件(管道)进行通信。当这些 进程不再使用此管道时,核心收回其索引结点。 3、pipe文件的建立:分配磁盘和内存索引结点、
实验题 进程的管道及消息通 小组 否பைடு நூலகம்
目
信
合作
姓名
班级
学
号
一、实验目的
1、了解什么是管道
2、熟悉LINUX支持的管道通信方式
3、了解Linux系统中的进程间通信机制,包括共 享内存和信号量。
二.实验环境
安装了Linux虚拟机的Windows 系统的计算机一台
三、实验内容与步骤
一、管道通信 1、创建无名管道的格式
#include<sys/types.h> #include<ctype.h> #include<unistd.h> int pipe(int filedes[2]); 真确返回:0,错误返回:-1。无名管道pipe()的使用 例子:使用无名管道pipe(),进行父子进程之间的通信。源代码如下: #include<sys/types.h> #include<ctype.h> #include<unistd.h> int pipe(int filedes[2]);
msgrcv(msqid,&msg,256,REQ,0);//接受客户发送的消息 printf("server is doing the service for a client.\n"); pint = (int *)msg.mtext; pid = * pint;//获得客户pid,以便进行服务 printf("server receive client's service request is client's pid: '%d'.\n",pid); msg.mtype = pid; pid = getpid(); /*经服务进程的的pid发送给客户 msgsnd(msqid,&msg,sizeof(int),0); } } 运行结果:
long mtype;//消息类型 char mtext[256];//消息正文 } main() { struct msgform msg; int msqid,pid,* pint; msqid = msgget(SVKEY,0777);//创建消息队列 pid = getpid();//获得当前进程标识 pint = (int *)msg.mtext;//获得消息正文首地址 * pint = pid;//将客户进程的pid复制到消息缓冲区中 msg.mtype = REQ; msgsnd(msqid,&msg,sizeof(int),0);//发送消息 msgrcv(msqid,&msg,256,pid,0);//这里pid作为消息类型 printf("client receive server's service result is server's pid: %d \n",pid) ;
四、实验过程与分析
在1例子中: 1、pipe( )是建立一无名管道,系统调用格式为 pipe(filedes)参数定义是int pipe(filedes);int filedes[2];其中,filedes[1]是写入端,filedes[0]是读 出端。 2、read( )的系统调用格式是read(fd,buf,nbyte),参 数定义是int read(fd,buf,nbyte); int fd; char *buf; unsigned nbyte;它的功能是从fd所指示的文件中读 出nbyte个字节的数据,并将它们送至由指针buf 所指示的缓冲区中。如该文件被加锁,等待,直 到锁打开为止。 3、write( )系统调用格式是read(fd,buf,nbyte),它的 功能是把nbyte 个字节的数据,参数定义同read( ),而父进程则从管道中读出来自两个进程的信 息,显示在屏幕上。从buf所指向的缓冲区写到 由fd所指向的文件中。如文件加锁,暂停写入, 直至开锁。 五、实验总结
main(argc,argv) int argc; char *argv[]; {
int fd; char buf[256];
int i; mknod("fifo",010777,0); if(argc==2) {
fd=open("fifo",O_WRONLY); } else {
fd=open("fifo",O_RDONLY); } for(i=0;i<26;i++) {
fprintf(stderr,"usage:a.out<pathname>\n"); exit(1); } if((fpin=fopen(argv[1],"r"))==NULL) { fprintf(stderr,"can't open %s \n",argv[1]); exit(1); } if((fpout=popen("/mnt/usb/mldm/chcase.exe","w"))==NULL) { fprintf(stderr,"popen error\n"); exit(1); }
2、打开一个以命令行为参数的管理文件,完成
进程之间的通信进程
例子:以命令行为参数的管理文件的示例。 假设有一个的可执行程序chcase,从标准输出设备读字符,将小写 字母转换成大写字母并进行输出。 主程序使用popen创建管道,实现将某文件中的字母转换成大写字 母。其中的文本文件名作为参数传进来。源程序如下: #include<sys/wait.h> #include<stdio.h> #define MAXLINE 100 int main(int argc,char *argv[]) { char line[MAXLINE]; FILE *fpin,*fpout; if(argc!=2) {
char parent[]="A message to pipe'communication.\n";
main() {
int pid,chan1[2]; char buf[100]; pipe(chan1); pid=fork(); if(pid<0) {
printf("to create child error\n"); exit(1); } if(pid>0) { close(chan1[0]); printf("parent process sends a message to child.\n"); write(chan1[1],parent,sizeof(parent)); close(chan1[1]); printf("parent process waits the child to terminate\n"); wait(0); printf("parent process terminate\n"); } else { close(chan1[1]); read(chan1[0],buf,100); printf("The message read by child process from parent is :%s.\n",buf); close(chan1[0]); printf("child process terminates\n"); } } 运行结果: