实验4 进程的管道通信
进程的管道通信实验说明书
*******************实践教学*******************兰州理工大学计算机与通信学院2011年秋季学期操作系统原理课程设计题目:进程的管道通信实验专业班级:09软件工程(1)班姓名:刘旭学号:09240201指导教师:王旭阳成绩:_______________目录摘要 (3)正文 (4)一.问题描述 (4)二. 设计目的 (4)三. 设计要求 (5)四. 详细设计 (5)1.程序流程图 (6)2.算法设计 (7)五. 结果分析 (9)设计总结 (10)参考文献 (11)致谢 (12)附件Ⅰ源程序代码 (13)摘要管道通信是发送进程和接收进程之间通过一个通道交流信息,管道是单向的,发送进程视管道为输出文件,即向管道写入数据,接收进程视管道为输入文件,即从中读取数据。
先写入的必定先读出,即管道通信的工作是单向的并以先进先出为顺序。
管道通信的实质是一个共享文件,数据以自然字符流的方式写入和读出。
在Linux系统中,进程在执行系统调用pipe()之后便创建了一个无名管道。
在管道通信实验中,可用父进程创建一个无名管道,子进程向其中写入信息,父进程从其中读取信息并显示。
关键词:父进程,子进程,管道,通信,文件正文一.问题描述:(1).了解UNIX的命令及使用格式,熟悉UNIX/LINUX的常用基本命令,练习并掌握UNIX提供的vi编辑器来编译C程序,学会利用gcc、gdb编译、调试C程序。
(2).编写程序实现进程的管道通信。
用系统调用pipe( )建立一管道,二个子进程P1和P2分别向管道各写一句话:Child 1 is sending a message!Child 2 is sending a message!父进程从管道中读出二个来自子进程的信息并显示(要求先接收P1,后P2)。
二.设计目的:通过该题目的设计过程,熟悉UNIX/LINUX支持的管道通信方式,了解该系统下进程管道通信机制,掌握进程管道通信程常用的系统函数,能够编写代码实现父子进程的管道通信。
实验四进程间管道通信
实验四进程间管道通信实验目的:使用使用系统调用pipe( )、close( )、write( )及read( )来编写一个父子进程通过管道传递信息的程序。
实验内容:进程的管道通信是UNIX系统中的一种通信方式,提供有名管道和无名管道两种数据通信方式,这里主要是采用无名管道通信。
无名管道为建立管道的进程及其子孙进程提供一条以比特流方式传送消息的通信管道。
该管道在逻辑上被看作管道文件,在物理上则由文件系统的高速缓冲区构成,而很少启动外设。
发送进程利用文件系统的系统调用write(fd[1],buf,size),把buf中的长度为size字符的消息送入管道入口fd[1],接收进程则使用系统调用read(fd[O],buf,size)从管道出口fd[0]读出size字符的消息置入buf中。
这里,管道按FIFO(先进先出)方式传送消息,且只能单向传送。
利用unix系统提供的系统调用pipe,可以建立一条同步的通信管道。
其格式为:pipe(fd)intfd[2]这里,fd[1]为写入端,fd[0]为读出端。
参考程序:用C语言编写一个程序,建立一个pipe,同时父进程生成一个子进程,子进程向pipe 中写入一个字符串,父进程从pipe 中读出该字符串。
//s4-3-1.c#include<stdio.h>main(){int x,fd[2];char buf[30],s[30];pipe(fd);/* 创建管道*/while((x=fork())==-1);/* 创建子进程失败时,循环*/if(x==0){sprintf(buf,"this is an example\n");write(fd[1],buf,30);/* 把buf 中字符写入管道*/exit(0);}else/* 父进程返回*/{wait(0);read(fd[0],s,30);/* 父进程读管道中字符*/printf("%s",s);}}编写一个程序,建立一个管道。
通信管道实验报告(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()函数删除消息队列。
进程的管道通信实验报告
进程的管道通信实验报告一、实验目的本实验旨在通过实际操作,深入理解进程间通信(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、设计程序,实现共享内存、管道通信、消息通信二、实验基本原理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都是消息类型。
进程之间的通信实验
实验:进程之间的通信管道1.Pipe函数与进程通信下面实验为使用管道进行父子进程间通信。
程序首先判断参数是否合法,因为输入的字符将从父进程通过发送到子进程中。
然后,调用pipe函数创建父子进程用于通信的管道。
使用fork函数创建子进程时,子进程会获得与父进程相同的资源,其中包括文件描述符信息。
因此,调用fork函数须在pipe函数调用前。
当父子进程通过管道进行通信时,files[1]为用于数据写入的文件描述符.因此,在子进程中,要读取管道中的数据可以调用read函数,而读取得文件描述符为files[0]。
对于父进程而言,写入数据需要调用write 函数,要写入的文件描述为files[1]。
#include <stdio.h>#include <unistd.h>int main(int argc,char* argv[]){int f_des[2];int pid;char msg[BUFSIZ];if(argc!=2){printf("Usage: %s message\n",argv[0]);return 1;}if(pipe(f_des)==-1){perror("cannot create the IPC pipe");return 1;}pid=fork();if(pid==-1){perror("cannot create new process");return 1;}else if(pid==0){close(f_des[1]);if(read(f_des[0],msg,BUFSIZ)==-1){perror("child process cannot read data from pipe");return 1;}elseprintf("in child process, receive message: %s\n",msg);_exit(0);}else {close(f_des[0]);if(write(f_des[1],argv[1],strlen(argv[1]))==-1){perror("parent process cannot write data to pipe");return 1;}elseprintf("in parent process, send message: %s\n",argv[1]);wait(NULL);_exit(0);}return 0;}2. Shell管道重订向的实现实现了在SHELL中的两个命令的组合。
管道通信实验
院系:计算机系
姓名:李
学号:10
专业:科学技术
年级:10级
实验题目:管道通信实验
一、实验目的(包括:实验内容、实验原理、实验目标)
1、了解管道的基本概念
2、掌握Linux支持的管道通信方式
二、实验设计(包括:设计思路、数据结构、程序流程图、关键代码说明)
本实验利用管道通信机制,实现输入字符串的自动分流操作。一共涉及3个管道,4个进程。P1:从键盘接受输入字符串,写入管道pipe1
{
close(d1[1]); //p1必须关闭写
read(d1[0],buff,sizeof(buff)); //p2从pipe1中读信息
if(strlen(buff)%2==1) //判断字符串长度,若为奇数
{
j=fork(); //创建子进程P3
if(j) //P3执行
}
}
三、实验结果(包括:运行结果、结果分析)
教师评语
成绩:教室签名:年月日
Please input a string: apple
P2 finishes writing to pipe2.
P3 pipe2 odd length string:apple
Please input a string: pear
P2 finishes writing to pipe3.
P4 pipe3 even length string:pear
P2:从pipe1接受字符串,若字符串的长度为偶数,则将其写入管道pipe2,负责写入管道pipe3.P3:从pipe2读出字符串,并显示pipe2:Even length string:偶长度字符串。P4:从pipe3读出字符串,并显示pipe3:Old length string:奇长度字符串。输入exit程序退出,示意图如下图1.1
操作系统实验报告进程的管道及消息通信
对观察到的内容做详细记录分析, 并写出实验报告。
对观察到的内容做详细记录分析,并写出实验报告。
四、实验过程与分析1.使用无名管道pipe(), 进行父子进程之间的通信。
编写的程序如下:运行结果如下:结果分析:父进程首先被调用时, 运行结果为:之后父进程阻塞等待子进程终止, 当系统调度子进程运行时, 输出如下的信息:之后父进程被唤醒, 调度运行, 输出如下结果后程序退出。
对于以上的结果: 首先父进程使用pipe(chan1)系统调用打开一个无名管道, 之后创建一个子进程。
子进程复制父进程的打开文件表。
为了正确通信, 父进程关闭读通道close(chan1[0]), 子进程关闭写通道close(chan1[1])。
父进程向管道写, 子进程从管道读。
完成一次通信之后, 父进程分别关闭自己的写/读通信, 管道文件消失。
2.以命名行为参数的管道文件的示例。
(假设有一个可执行程序chcase, 从标准输入设备读字符, 将小写字母转化成大写字母并输出。
主程序使用popen创建管道, 实现蒋某文本文件中的字幕转化成大写字母, 其中的文本文件名作为参数传进来。
)编写的程序如下:运行结果是:结果分析: 通过程序运行结果可知, 先打开文本文件, 如果文本打开失败, 则执行exit(1), 退出程序, 如果文本通过函数开成功, 则popen创建一个可写管道, 将命令行chcase的输入与管道的输入连接起来, 然后向管道输入数据, 此时命令行就可以通过管道接受文本文件的数据了,在从文件中读出数据时, 独处的内容放在line[]数组中,fpin表示从刚打开的文件里读出。
之后要编写字母大小写转化函数, 来实现小写字母转化成大写字母。
3.创建有名管道。
编写的程序如下:运行结果是:前台运行结果:后台运行结果:结果分析: 此程序是把管道和命令联系起来, read( )的系统调用格式是read(fd,buf,n), 参数定义是int read(fd,buf,n); int fd; char *buf; unsigned n;它的功能是从fd所指示的文件中读出n个字节的数据, 并将它们送至由指针buf所指示的缓冲区中。
实验四 进程管道通信
(2)读管道 在管道创建后,希望从管道中读取数据的进程使用 读文件描述符fd[0]作为参数,调用read( )系统调用。 #include <unistd.h> ssize_t read(int fd,void *buf,size_t nbytes); 返回:读到的字节数,若已到文件尾为0,若出错为-1。 (3)写管道 向管道中写入数据的进程使用写文件描述符fd[1]作 为参数,调用write( )系统调用。 #include <unistd.h> ssize_t write(int fd,const void *buf,size_t nbytes); 返回:若成功为已写的字节数,若出错为-1。
管道分为无名管道和有名管道。无名管道没有 名字,所以只能提供给进程家族中的父子进程间通 信使用,而有名管道则用于没有家族关系的任意两 个进程之间的通信。 实现无名管道的传统方法是利用文件系统机制, 把管道看作是一个打开的文件, 因此它有一个i节点和两个文件表项。 (1)创建一个管道 管道是由使用pipe系统调用而创建的。#include <unistd.h> int pipe(int fd[2]); 返回:成功为0,出错为-1 经由参数fd[]返回两个文件描述符:fd[0]为读端, fd[1]为写端。
操作系统实验指导 -以Linux系统为主
实验四 进程的管道通信
一、实验目的 (1)了解Linux系统中进程通信的基本原理。 (2)了解和掌握管道通信机制。 二、实验预备知识 管道是UNIX系统中最早为两个进程之间提供 的一种通信机制。管道是一种单向的、先入先出的、 无结构的、大小固定的通信通道。写进程在管道的 一端写入数据,读进程从管道的另一端读出数据。 如果两个或多个进程同时对一个进程进行读பைடு நூலகம்,那 么这些进程必须使用锁机制或者信号量机制对其进 行同步。
实验四 linux进程通信
2、进程的管道通信
3、信号量实现进程同步
特点
Unix早期版本
在进程间通信方面表现较弱,利用pipe来传递大量数据
Unix system V版本
由三部分组成:消息(用于进程之间传递分类的格式化数据)、共享存储器(使得不同进程通过共享彼此的虚拟空间而达到互相对共享区操作和数据通信的目的)、信号量(机制用于通信进程之间的同步控制。信号量通常与共享储存器方式一起使用。)
实验报告
姓名
学号
专业班级
课程名称
操作系统实验
实验日期
成绩
指导教师
批改日期Biblioteka 实验名称实验四linux进程通信
一、实验目的:
1、理解信号和管道的概念及实现进程间通信的原理。
2、掌握和使用消息对流实现进程间的通信。
3、掌握和使用信号量实现进程同步。
4、掌握使用共享主存实现进程间的通信。
二、实验要求:
IPC版本
Linux
完整继承了system V进程间通信IPC
三、实验内容和步骤:
1、利用信号机制实现进程软中断通信
经过以上步骤,查阅相关资料,我学习到两点知识:
1、警告与错误是两个概念,警告存在的情况下程序仍能编译通过,但有错误就不可以。
2、exit与return功能相似,但主要用于非main函数中,正常执行即返回0值。
用管道实现进程通信
操作系统实验报告用管道实现进程通信1. 实验目的(1)了解Windows系统环境下的进程通信机制。
(2)熟悉Windows系统提供的进程通信API。
2. 实验预备知识(1)根据《计算机操作系统实验指导》中相应内容填写(2)3. 实验内容一个基于有名管道的C/S模式应用,客户端发送命令到服务器,服务器执行命令,并将命令返回信息回传给客户端要求:A.客户端进程完成的工作1.建立私有有名管道2.打开服务端的共有有名管道3.等待用户输入命令4.将私有管道名和命令写入公有管道5.从私有管道中读服务端返回的结果B.服务端进程完成的工作1.建立服务端公有有名管道2.从公有有名管道中读取客户数据3.执行命令,并将结果写入客户私有管道4.实验代码服务器程序:// PipeClient.cpp : Defines the entrypoint for the console application.//#include "stdafx.h"#include "PipeClient.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endifCWinApp theApp;using namespace std;int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) {BOOL rc=0;char lpName[]="\\\\.\\pipe\\myPipe";char InBuffer[50]="";char OutBuffer[50]="";DWORD BytesRead;int nRetCode=0; int err=0;while(1){strcpy(InBuffer,"");strcpy(OutBuffer,"");printf("Input Data Please!\n");scanf("%s",InBuffer);rc=strcmp(InBuffer,"end");if(rc=0){rc=CallNamedPipe(lpName,InBuffer,sizeof(InBuffer) ,OutBuffer,sizeof(OutBuffer),&BytesRead,NMPWAIT_USE_DEFAULT_ WAIT);break;}rc=WaitNamedPipe(lpName,NMPWAIT_WAIT_FOREVER);if(rc==0){err=GetLastError();printf("Wait Pipe Fail!err=%d\n",err);exit(1);}else printf("Wait Pipe Success!\n");rc=CallNamedPipe(lpName,InBuffer,sizeof(InBuffer) ,OutBuffer,sizeof(OutBuffer),&BytesRead,NMPWAIT_USE_DEFAULT_W AIT);rc=strcmp(OutBuffer,"end");if(rc==0) break;if(rc==0){err=GetLastError();printf("Pipe Call Fail!err=%d\n",err);exit(1);}else printf("Pipe Call Success!\nData from Server is %s\n",OutBuffer);}printf("Now Client to be END\n");return nRetCode;}客户端程序:// 24.cpp : Defines the entry point for the console application.#include "stdafx.h"#include "PipeServer.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/////////////////////////////////////////////////// //////////////////////////// The one and only application objectCWinApp theApp;using namespace std;int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) {int nRetCode = 0;int err;BOOL rc;HANDLE hPipeHandle1;char lpName[]="\\\\.\\pipe\\myPipe";char InBuffer[50]="";char OutBuffer[50]="";DWORD BytesRead,BytesWrite;hPipeHandle1=CreateNamedPipe((LPCTSTR)lpName,PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED|WRITE_DAC ,PIPE_TYPE_MESSAGE|PIPE_READMODE_BYTE|PIPE_WAIT, 1,20,30,NMPWAIT_USE_DEFAULT_WAIT,(LPSECURITY_ATTRIBUTES)NULL);if((hPipeHandle1==INVALID_HANDLE_VALUE)||(hPipeHand le1==NULL)){err=GetLastError();printf("Server Pipe Create Fail!err=%d\n");exit(1);}else printf("Server Pipe Create Success!\n");while(1){//guangdaorc=ConnectNamedPipe(hPipeHandle1,(LPOVERLAPPED)NU LL);if(rc==0){err=GetLastError();printf("Server Pipe Conner Fail err=%d\n",err);exit(2);}else printf("Server Pipe Conner Success!\n");strcpy(InBuffer,"");strcpy(OutBuffer,"");//命名管道读数据rc=ReadFile(hPipeHandle1,InBuffer,sizeof(InBuffer ),&BytesRead,(LPOVERLAPPED)NULL);if(rc==0&&BytesRead==0){err=GetLastError();printf("Server Read Pipe Fail!err=%d\n",err);exit(3);}else{printf("Server Read Pipe Success!\nDATA from Client is=%s\n",InBuffer);}rc=strcmp(InBuffer,"end");if(rc==0) break;printf("Please Input Data to Send\n");scanf("%s",OutBuffer);//向管道写数据rc=WriteFile(hPipeHandle1,OutBuffer,sizeof(OutBuf fer),&BytesWrite,(LPOVERLAPPED)NULL);if(rc==0) printf("Server Write Pipe Fail!\n");else printf("Server Write Pipe Success!\n");DisconnectNamedPipe(hPipeHandle1);rc=strcmp(OutBuffer,"end");if(rc==0) break;}printf("Now Server be END!\n");CloseHandle(hPipeHandle1);return nRetCode;}。
实验四进程通信
实验四 进程间通信一、实验目的1. 掌握利用管道机制实现进程间的通信的方法2. 掌握利用消息缓冲队列机制实现进程间的通信的方法3. 掌握利用共享存储区机制实现进程间的通信的方法4. 了解Linux系统中进程软中断通信的基本原理二、实验学时2学时三、实验内容1.掌握实现进程间通信的系统调用的功能和方法进程通信,是指进程之间交换信息。
从这个意义上讲,进程之间的同步、互斥也是一种信息交换,也是一种通信。
但是,这里所说的“通信”是指进程之间交换较多的信息这样一种情况,特别是在由数据相关和有合作关系的进程之间,这种信息交换是十分必要和数量较大的。
进程间通信是协调解决多个进程之间的约束关系,实现进程共同进展的关键技术,是多道系统中控制进程并发执行必不可少的机制。
(1)进程的通信方式:a. 直接通信是指信息直接传递给接收方,如管道。
在发送时,指定接收方的地址或标识,。
在接收时,允许接收来自任也可以指定多个接收方或广播式地址, send(Receiver, message)。
意发送方的消息,并在读出消息的同时获取发送方的地址, receive(Sender,message)b. 间接通信:借助于收发双方进程之外的共享数据结构作为通信中转,如消息队列。
这种数据结构称为缓冲区或信箱。
通常收方和发方的数目可以是任意的。
(2)进程间通信的类型:a. 共享存储器系统:基于共享数据结构的通信方式:只能传递状态和整数值(控制信息),包括进程互斥和同步所采用的信号量机制。
速度快,但传送信息量小,编程复杂,属于低级通信;基于共享存储区的通信方式:能够传送任意数量的数据,属于高级通信。
b. 消息传递系统:在消息传递系统中,进程间的数据交换以消息为单位,用户直接利用系统提供的一组通信命令(原语)来实现通信。
c. 管道通信:管道是一条在进程间以字节流方式传送的通信通道。
它由OS 核心的缓冲区(通 常几十KB)来实现,是单向的;在实质上,是一个有OS 维护的特殊共享文件,常用于命令行所指定的输入输出重定向和管道命令。
实验四 进程的软中断通信和管道通信
实验四进程的软中断通信和管道通信一、实验目的1. 掌握Linux系统软中断通信的实现方法。
2. 掌握Linux系统软中断通信的基本原理。
3. 学会使用Linux系统中关于进程通信的一些系统调用。
4. 掌握管道通信的使用方法。
二、实验内容1. 软中断通信编写一段程序,使其实现进程的软中断通信。
使用系统调用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上来的中断信号(即按Del键),当捕捉到中断信号后,父进程用系统调用Kill()向两个子进程发出信号,子进程捕捉到信号后分别输出下列信息后终止:Child Processll is Killed by Parent!Child Processl2 is Killed by Parent!父进程等待两个子进程终止后,输出如下的信息后终止:Parent Process is Killed!2. 进程的管道通信编制一段程序,实现进程的管理通信。
使用系统调用pipe()建立一条管道线。
两个子进程P1和P2分别向管道中写一句话:Child 1 is sending a message!Child 2 is sending a message!而父进程则从管道中读出来自于两个子进程的信息,显示在屏幕上。
要求父进程先接收子进程P1发来的消息,然后再接收子进程P2发来的消息。
3. 管道编程练习编写一个程序,使用系统调用fork生成3个子进程,并使用系统调用pipe创建一个管道,使得这3个子进程和父进程共用同一个管道进行通信。
三、实验源程序[程序1] 软中断通信#include <stdio.h>#include <signal.h>#include<unistd.h>void waiting(),stop(); /引用函数声明/int wait_mark;main(){ int p1,p2;while((p1=fork())==-1); /创建进程p1/if(p1>0){while((p2=fork())==-1);if(p2>0){ wait_mark=1; /以下为主进程/signal(SIGINT,stop); /接受‘del’信号,并转stop/waiting(0);kill(p1,17); /向p1发中断信号17/kill(p2,17); /向p2发中断信号17/wait(0); /将当前进程挂起,直至子进程发出信号/ wait(0);printf(“parent process is killed!\n”);exit(0); /主进程终止自己/}else{ wait_mark=1; /以下为子进程p2/signal(17,stop);waiting();lockf(1,1,0); /加锁/printf(“child process 2 is killed by parent!\n”); lockf(1,0,0); /解锁/exit(0);}}else{ wait_mark=1; /进程p1/signal(17,stop);waiting();lockf(1,1,0);printf(“child process 1 is killed by parent!\n”); lockf(1,0,0);exit(0); /返回主进程,本进程自我终止/}}void waiting(){ while(wait_mark=0);}void stop(){ wait_mark=0;}运行时,从键盘输入中断信号‘del’键。
实验四、进程通信(二) ——消息通信
操作系统实验报告实验四、进程通信(二)——消息通信一、实验目的1)加深对管道通信的了解2)掌握利用管道进行通信的程序设计3)了解共享内存通信的程序设计方法4)了解和熟悉Linux支持的共享存储区机制二、实验内容任务:(1)每个同学登陆两个窗口,先在一个窗口中运行程序1(或者只登陆一个窗口,先在该窗口中以后台方式运行程序1),用ipcs命令查看系统中消息队列的情况,然后在另一个窗口中运行程序2,观察程序的运行结果并分析。
运行结束后可以用ctrl+c结束程序1的运行,再次用ipcs命令观察系统中消息队列的情况。
(2)使用系统调用msgget(),msgsnd(),msgrev()及msgctl()编制一长度为1K的消息的发送和接收程序。
①为了便于操作和观察结果,用一个程序作为“引子”,先后fork()两个子进程,SERVER和CLIENT,进行通信。
②SERVER端建立一个Key为学号末3位的消息队列,等待其他进程发来的消息。
当遇到类型为1的消息,则作为结束信号,取消该队列,并退出SERVER。
SERVER每接收到一个消息后显示一句“(server)received”。
③CLIENT端使用key为学号末3位的消息队列,先后发送类型从10到1的消息,然后退出。
最后的一个消息,即是SERVER端需要的结束信号。
CLIENT 每发送一条消息后显示一句“(client)sent”。
④父进程在SERVER和CLIENT均退出后结束。
三、代码及运行结果分析(1)每个同学登陆两个窗口,先在一个窗口中运行程序1(或者只登陆一个窗口,先在该窗口中以后台方式运行程序1),用ipcs命令查看系统中消息队列的情况,然后在另一个窗口中运行程序2,观察程序的运行结果并分析。
运行结束后可以用ctrl+c结束程序1的运行,再次用ipcs命令观察系统中消息队列的情况先在一个窗口中运行程序1程序1实验代码:#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#define MSGKEY 208 /*在实际实验过程中,为了避免每个同学建立的消息队列关键字一样而相互干扰,关键字请用学号末3位*/struct msgform{long mtype;char mtext [256];}msg;int msgqid;main (){int i ,pid, *pint;extern cleanup();for (i=0;i<20;i++)/*软中断处理*/signal (i,cleanup);msgqid = msgget (MSGKEY,0777|IPC_CREAT);/*建立与顾客进程相同的消息队列*/ for (;;){msgrcv (msgqid ,&msg,256,1,0);/*接收来自顾客进程的消息*/pint=(int * ) msg. mtext;pid = * pint;printf ("server:receive from pid %d\n",pid);msg.mtype=pid;*pint=getpid();msgsnd (msgqid,&msg ,sizeof (int) ,0) ;/*发送应答消息*/}}cleanup(){msgctl (msgqid ,IPC_RMID,0);exit();}运行结果:ipcs命令查看在另一个窗口中运行程序2程序2实验代码:#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#define MSGKEY 208 /*在实际实验过程中,为了避免每个同学建立的消息队列关键字一样而相互干扰,关键字请用学号末3位*/struct msgform{long mtype;char mtext [256];};main(){struct msgform msg;int msgqid,pid, *pint;msgqid=msgget(MSGKEY,0777);/*建立消息队列*/pid=getpid();pint=(int *)msg.mtext;*pint=pid;msg.mtype=1;/*指定消息类型*/msgsnd(msgqid,&msg,sizeof(int),0);/*往msgqid发送消息msg*/msgrcv(msgqid,&msg,256,pid,0);/*接收来自服务进程的消息*/printf("client : receive from pid%d\n",*pint);}运行结果:再次用ipcs命令观察系统中消息队列的情况分析:调用pipe(fd);创建一个管道后,接着调用fork()函数产生两个进程,首先开始执行子进程,关闭管道出口,通过管道入口向管道中写入内容。
第四次实验 进程的管道及消息通信
服务者进程接收到请求服务的消息后进行服务工作,完成服务后客户进程发送回一条消息,消息的类型为客户的标识pid,消息正文是服务者进程自己的标识pid。
buf[0]='\0';
}
}
close(fd);
}
二.消息缓冲机制
消息缓冲是unix系统进程之间进行大量数据交换的机制之一。消息缓冲是基于消息队列的,发送进程将消息挂入接收进程的消息队列,接收进程从消息队列中接收消息。消息是指具有类型和数量的一个数据。消息分为私有和公有的,如果消息是私有的,只能被创建消息队列的进程和其子进程访问;如果是公有的,可以被系统中知道消息队列名的所有进程访问。消息可以安类型访问,因此,不必按序访问。
}
main()
{
int msqid;
struct msgform msg;
int i,pid,* pint;
msqid = msgget(SVKEY,0777 | IPC_CREAT);//创建消息队列
for(;;)
{
msgrcv(msqid,&msg,256,REQ,0);//接受客户发送的消息
班级
2009级计本
学号
200981010142
一、实验目的
熟悉UNIX和linux操作系统进程通信的系统调用。
理解和掌握UNIX和LINUX进程通信系统的调用的功能,给出了进程通讯实现机制中的使用的系统调用命令的格式和如何利用系统调用命令进行进程通信编程,通过学习,提高对进程之间可通过系统的编程能力。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验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(),则父进程被阻塞,进入等待队列,等待子进程结束。
当子进程结束时,父进程从wait()返回继续执行原来的程序。
返回值:大于0时,为子进程的ID值;等于-1时,调用失败。
3)exit() 是进程结束时最常调用的。
格式:void exit( int status); 其中,status为进程结束状态。
4)pipe() 用于创建一个管道
格式:pipe(int fd);
其中fd是一个由两个数组元素fd[0]和fd[1]组成的整型数组,fd[0]是管道的读端口,用
于从管道读出数据,fd[1] 是管道的写端口,用于向管道写入数据。
返回值:0 调用成功;-1 调用失败。
5)sleep() 调用进程睡眠若干时间,之后唤醒。
格式:sleep(int t); 其中t为睡眠时间。
6)lockf() 用于对互斥资源加锁和解锁。
在本实验中,该调用的格式为:
lockf(fd[1],1,0);/* 表示对管道的写入端口加锁。
lockf(fd[1],0,0);/* 表示对管道的写入端口解锁。
7)write(fd[1],String,Length) 将字符串String的内容写入管道的写入口。
8)read(fd[0],String,Length) 从管道的读入口读出信息放入字符串String中。
4.程序流程
父进程:
1)创建管道;
2)创建子进程1;
3)创建子进程2;
4)等待从管道中读出子进程1写入的数据,并显示在屏幕上;
5)等待从管道中读出子进程2写入的数据,并显示在屏幕上;
6)退出。
子进程:
1)将管道的写入口加锁;
2)将信息“Child process n is sending message!”输入到变量OutPipe中,n=1,2;
3)将OutPipe中信息写入管道;
4)睡眠等待父进程从管道读出数据;
5)将管道的写入口解锁;
6)退出。
5.程序流程图
开始
创建管道
创建子进程
创建成功?N
Y
父进程返回?
N
锁定管道写端写信息入管道睡眠等待父进程
开锁
撤销子进程P1Y
创建子进程P2
创建成功?
N
Y
父进程返回?
Y
管道中是否有
消息
Y
读取管道消息
N
放弃处理机
锁定管道写端
向管道写入消息
睡眠等待父进程
锁定管道写端
撤销子进程P2
结束
N
6.程序源代码
#include <stdio.h>
#include <sys/types.h> #include <stdlib.h>
#include <sys/stat.h> #include <fcntl.h>
#include <error.h>
#include <wait.h>
#include <unistd.h>
int main()
{
int i,r,P1,P2,fd[2];//fd[1]写入端,fd[0]读取端
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 messages! \n");
printf("child process P1! \n");
write(fd[1],buf,50);
sleep(5);
lockf(fd[1],0,0);
exit(0);
}
else
{
while((P2=fork())==-1);
if(P2==0)
{
lockf(fd[1],1,0);
sprintf(buf,"child process P2 is sending messages! \n");
printf("child process P2! \n");
write(fd[1],buf,50);
sleep(5);
lockf(fd[1],0,0);
exit(0);
}
int pid;
pid=wait(0);
printf("%d\n",pid);
if(r=read(fd[0],s,50)==-1)
printf("can't read pipe! \n");
else
printf("%s\n",s);
pid=wait(0);
printf("%d\n",pid);
if(r=read(fd[0],s,50)==-1)
printf("can't read pipe! \n");
else
printf("%s\n",s);
exit(0);
}
}
7.运行结果及其说明
运行结果如下图所示。
8.回答以下问题
①指出父进程与两个子进程并发执行的顺序,并说明原因。
答:父进程先创建子进程P1,然后子进程P1执行,P1执行完以后父进程执行并创建子进程P2,接着P2执行,P2执行完以后返回父进程,程序结束。
这是由进
程的同步机制决定的,因为只有子进程向管道写入信息后,父进程才能从管道
中读取消息;否则父进程调用wait()阻塞自己,将处理机交由子进程
②若不对管道加以互斥控制,会有什么后果?
答:对管道进行互斥控制,是为防止两个子进程对管道资源进行争夺而产生信息丢失或覆盖。
如果不加控制,那么可能一个子进程写入的信息还没来得及被父
进程读出,另一个子进程又向管道写入信息,那么之前的进程写入的信息将被
覆盖,父进程也就读不到之前进程传递来的信息了。
③说明你是如何实现父子进程之间的同步的。
答:父进程读出之前确定管道中有数据,若管道中没有数据,则父进程调用wait()
函数阻塞自身。
当子进程结束时,管道中已经有数据,父进程才执行。
子进程在写入之前要确定管道中的数据已经被父进程读出,否则不能写
入或者阻塞自己。
可以通过进程间的互斥来间接的办到。
因为子进程间的互斥,所以每个子进程在执行开始都对管道pipe 加锁,那么这样同时就只能有一个子进程向管道写入数据,并且子进程在向管道中写入数据后还要调用sleep()系统调用睡眠若干时间,那么这样就可以保证父进程能够从管道中读出数据。
然后下一子进程才能写入。
那么这样就保证了开头所说的子进程在写入之前要确定管道中的数据已经被父进程读出,否则不能写入或者阻塞自己。