当前位置:文档之家› 实验3 进程同步与通信实验

实验3 进程同步与通信实验

实验3 进程同步与通信实验
实验3 进程同步与通信实验

实验3 进程同步与通信实验

一、实验目的

1. 加深对进程概念的理解,明确进程和程序的区别

2. 进一步认识并发执行的实质

3. 分析进程争用资源的现象,学习解决进程互斥的方法

4. 了解Linux系统中进程通信的基本原理

5. 掌握Linux系统软中断通信的实现方法

6. 学会使用Linux系统中关于进程通信的实现方法

7. 掌握管道通信的使用

二、实验内容

1. 编制实现软中断通信的程序

使用系统调用fork()创建两个子进程,再用系统调用signal()让父进程捕捉定时器报警中断信号(SIGALRM),当父进程接收到该信号后,调用kill()向两个子进程发送终止信号,子进程分别输出下列信息后终止。

Child process 1 is killed by parent!!

Child process 2 is killed by parent!!

父进程调用wait()函数等待两个子进程终止后,输出以下信息后终止。

Parent process is killed!!

多运行几次编写的程序,简略分析出现不同结果的原因。

2. 编制实现进程的管道通信的程序(选作)

使用系统调用pipe()建立一条管道线,两个子进程分别向管道线各写一句话。

Child process 1 is sending a message!!

Child process 2 is sending a message!!

父进程从管道中读出来自于两个子进程的信息,显示屏幕上。

要求:父进程先接收子进程P1发来的消息,然后再接收子进程P2发来的消息。

三、实验结果

1. 编制实现软中断通信的程序

源代码:

#include

#include

#include

#include

void stop();

int waitFlag;

int main()

{

int pid1, pid2;

signal(3, stop);

while((pid1 = fork()) == -1)

;

if(pid1 > 0)

{

while((pid2 = fork()) == -1)

;

if(pid2 > 0)

{

waitFlag = 1;

sleep(1);

kill(pid1, 16);

kill(pid2, 17);

wait(0);

wait(0);

printf("Parent process is killed!!\n");

exit(0);

}

else

{

waitFlag = 1;

signal(17, stop);

printf("Child process 2 is killed by parent!!\n");

exit(0);

}

}

else

{

waitFlag = 1;

signal(16, stop);

printf("Child process 1 is killed by parent!!\n");

exit(0);

}

}

void stop()

{

waitFlag = 0;

}

运行结果:

2. 编制实现进程的管道通信的程序(选作)

源代码:

#include

#include

#include

int pid1,pid2;

main( )

{

int fd[2];

char OutPipe[100],InPipe[100];

pipe(fd);

while((pid1 = fork( )) == -1);

if(pid1 == 0)

{

lockf(fd[1],1,0);

sprintf(OutPipe,"Child process 1 is sending message!\n");

write(fd[1],OutPipe,50);

sleep(5);

lockf(fd[1],0,0);

exit(0);

}

else

{

while((pid2 = fork( )) == -1);

if(pid2 == 0)

{

lockf(fd[1],1,0);

sprintf(OutPipe,"Child process 2 is sending message!\n");

write(fd[1],OutPipe,50);

sleep(5);

lockf(fd[1],0,0);

exit(0);

}

else

{

wait(0);

read(fd[0],InPipe,50);

printf("%s\n",InPipe);

wait(0);

read(fd[0],InPipe,50);

printf("%s\n",InPipe);

exit(0);

}

}

}

运行结果:

Linux进程间通信(2)实验报告

实验六:Linux进程间通信(2)(4课时) 实验目的: 理解进程通信原理;掌握进程中信号量、共享内存、消息队列相关的函数的使用。实验原理: Linux下进程通信相关函数除上次实验所用的几个还有: 信号量 信号量又称为信号灯,它是用来协调不同进程间的数据对象的,而最主要的应用是前一节的共享内存方式的进程间通信。要调用的第一个函数是semget,用以获得一个信号量ID。 int semget(key_t key, int nsems, int flag); key是IPC结构的关键字,flag将来决定是创建新的信号量集合,还是引用一个现有的信号量集合。nsems是该集合中的信号量数。如果是创建新集合(一般在服务器中),则必须指定nsems;如果是引用一个现有的信号量集合(一般在客户机中)则将nsems指定为0。 semctl函数用来对信号量进行操作。 int semctl(int semid, int semnum, int cmd, union semun arg); 不同的操作是通过cmd参数来实现的,在头文件sem.h中定义了7种不同的操作,实际编程时可以参照使用。 semop函数自动执行信号量集合上的操作数组。 int semop(int semid, struct sembuf semoparray[], size_t nops); semoparray是一个指针,它指向一个信号量操作数组。nops规定该数组中操作的数量。 ftok原型如下: key_t ftok( char * fname, int id ) fname就是指定的文件名(该文件必须是存在而且可以访问的),id是子序号,虽然为int,但是只有8个比特被使用(0-255)。 当成功执行的时候,一个key_t值将会被返回,否则-1 被返回。 共享内存 共享内存是运行在同一台机器上的进程间通信最快的方式,因为数据不需要在不同的进程间复制。通常由一个进程创建一块共享内存区,其余进程对这块内存区进行读写。首先要用的函数是shmget,它获得一个共享存储标识符。 #include #include #include int shmget(key_t key, int size, int flag); 当共享内存创建后,其余进程可以调用shmat()将其连接到自身的地址空间中。 void *shmat(int shmid, void *addr, int flag); shmid为shmget函数返回的共享存储标识符,addr和flag参数决定了以什么方式来确定连接的地址,函数的返回值即是该进程数据段所连接的实际地

实验三 进程通信doc(DOC)

实验三进程通信(二) 实验目的: 1、理解进程通信原理和基本技术 2、了解linux系统进程间通信机构(IPC); 3、理解linux关于共享内存的概念; 4、掌握linux支持进程间共享内存的系统调用; 5、巩固进程同步概念。 实验内容: (一)闹钟。用c语言编程,实现进程间通过信号进行通信。 用fork()创建两个进程,子进程在等待5秒后用系统调用kill()向父进程发送SIGALRM 信号,父进程用系统调用signal()捕捉SIGALRM信号。参考程序如下: #include #include #include static int alarm_fired = 0; //闹钟未设置 //模拟闹钟 void ding(int sig) { alarm_fired = 1; //设置闹钟 } int main() { int pid; printf("alarm application starting\n"); if((pid = fork( )) == 0) { //子进程5秒后发送信号SIGALRM给父进程 sleep(5); kill(getppid(), SIGALRM); //exit(0); return 0; } //父进程安排好捕捉到SIGALRM信号后执行ding函数 printf("waiting for alarm to go off\n"); (void) signal(SIGALRM, ding); pause(); //挂起父进程,直到有一个信号出现 if (alarm_fired) printf("Ding!\n"); printf("done\n");

实验四父子进程通信

Linux进程通信 【实验程序及分析】 2. 父子进程同步 修改父进程创建子进程程序,使用exit()和wait()实现父子进程同步,其同步方式为父进程等待子进程的同步,即:子进程循环输出5次,然后父进程再循环输出5次。给出源程序代码和运行结果。 wait的函数原型是: #include /* 提供类型pid_t的定义 */ #include pid_t wait(int *status); 返回值:如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1。失败原因存于errno中。 进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程, wait 就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。 参数status用来保存被收集进程退出时的一些状态,它是一个指向int类型的指针。但如果我们对这个子进程是如何死掉的毫不在意,只想把这个僵尸进程消灭掉,(事实上绝大多数情况下,我们都会这样想),我们就可以设定这个参数为NULL,就象下面这样: pid = wait(NULL); 如果成功,wait会返回被收集的子进程的进程ID,如果调用进程没有子进程,调用就会失败,此时wait返回-1。 通过执行系统调用exit来终止一个进程。进程可以显示的调用exit系统调用来终止一个进程,也可以通过在程序结束时的return来实现。 调用exit方式如下: exit(status); status是返回给父进程的终止code。当一个进程exit后,这个进程处于zombie state。一般情况下exit(0)表示正常退出,exit(1),exit(-1)为异常退

Linux系统编程实验六进程间通信

实验六:进程间通信 实验目的: 学会进程间通信方式:无名管道,有名管道,信号,消息队列, 实验要求: (一)在父进程中创建一无名管道,并创建子进程来读该管道,父进程来写该管道(二)在进程中为SIGBUS注册处理函数,并向该进程发送SIGBUS信号(三)创建一消息队列,实现向队列中存放数据和读取数据 实验器材: 软件:安装了Linux的vmware虚拟机 硬件:PC机一台 实验步骤: (一)无名管道的使用 1、编写实验代码pipe_rw.c #include #include #include #include #include #include int main() { int pipe_fd[2];//管道返回读写文件描述符 pid_t pid; char buf_r[100]; char* p_wbuf; int r_num; memset(buf_r,0,sizeof(buf_r));//将buf_r初始化 char str1[]=”parent write1 “holle””; char str2[]=”parent write2 “pipe”\n”; r_num=30; /*创建管道*/ if(pipe(pipe_fd)<0) { printf("pipe create error\n"); return -1; } /*创建子进程*/ if((pid=fork())==0) //子进程执行代码 {

//1、子进程先关闭了管道的写端 close(pipe_fd[1]); //2、让父进程先运行,这样父进程先写子进程才有内容读sleep(2); //3、读取管道的读端,并输出数据 if(read(pipe_fd[0],buf_r, r_num)<0) { printf(“read error!”); exit(-1); } printf(“%s\n”,buf_r); //4、关闭管道的读端,并退出 close(pipe_fd[1]); } else if(pid>0) //父进程执行代码 { //1、父进程先关闭了管道的读端 close(pipe_fd[0]); //2、向管道写入字符串数据 p_wbuf=&str1; write(pipe_fd[1],p_wbuf,sizof(p_wbuf)); p_wbuf=&str2; write(pipe_fd[1],p_wbuf,sizof(p_wbuf)); //3、关闭写端,并等待子进程结束后退出 close(pipe_fd[1]); } return 0; } /*********************** #include #include #include #include #include #include int main() { int pipe_fd[2];//管道返回读写文件描述符 pid_t pid; char buf_r[100]; char* p_wbuf; int r_num;

实验三 进程通信(一)

操作系统实验报告 实验三、进程通信(一) ——管道及共享内存 一、实验目的 熟悉和掌握LINUX系统的管道通信和共享内存通信。 二、实验内容 (一)、管道通信 1、实验原理: 管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统。 数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。 利用系统调用pipe()可创建一个简单的管道。 int fd[2]; pipe(fd); 调用成功,fd[0]存放供读进程使用的文件描述符(管道出口),fd[1]存放供写程使用的文件描述符(管道入口)。 一个进程在由pipe()创建管道后,一般再fork()一个子进程,然后通过管道实现父子进程间的通信,子进程将从父进程那里继承所有打开的文件描述符。则父子两个进程都能访问组成管道的两个文件描述符,这样子进程可以向父进程发送消息(或者相反)。 发送进程利用文件系统的系统调用write(fd[1],buf,size),把buf中size个字符送入fd[1],接收进程利用read(fd[0],buf,size),把从fd[0]读出的size个字符置入buf中。这样管道按FIFO(先进先出)方式传送信息。 2、实验内容: #include main() { int x,fd[2]; char buf[30],s[30]; pipe(fd); while ((x=fork())==-1);

if (x==0) { close(fd[0]); printf("Child Process!\n"); strcpy(buf,"This is an example\n"); write(fd[1],buf,30); exit(0); } else{ close(fd[1]); printf("Parent Process!\n"); read(fd[0],s,30); printf("%s\n",s); printf("x value in Parent Process:%d!\n",x); } } (1)阅读上述父子进程利用管道进行通信的例子,写出程序的运行结果并分析。 程序运行x=fork()后,创建里一个子进程,在子进程里x的返回值为0,在父进程里x的返回值为7684,则子进程会执行if语句里的代码段,先关闭了管道的读入端,再在屏幕上输出“Child Process!”,然后将“This is an example\n”存入buf数组中,通过调用write()函数将buf数组的内容从管道的写入端写入,而父进程会执行else语句里的代码段,先关闭了管道的写入端,再在屏幕上输出“Parent Process!”,然后通过调用read ()函数将buf数组的内容从管道的读入端读入冰存储在s数组里,接着通过printf()函数将s数组里的内容输出到屏幕上,最后在屏幕上输出父进程中x的值。 (2)编写程序:父进程利用管道将一字符串交给子进程处理。子进程读字符串,将里面的字符反向后再交给父进程,父进程最后读取并打印反向的字符串。 #include main() { int i,x,fd[2]; char buf[20],s[20],cpy[20],m[20]; strcpy(buf,"This is an example\n"); pipe(fd); write(fd[1],buf,20);

进程间通信实验报告

进程间通信实验报告 班级:10网工三班学生姓名:谢昊天学号:1215134046 实验目的和要求: Linux系统的进程通信机构 (IPC) 允许在任意进程间大批量地交换数据。本实验的目的是了解和熟悉Linux支持的消息通讯机制及信息量机制。 实验内容与分析设计: (1)消息的创建,发送和接收。 ①使用系统调用msgget (), msgsnd (), msgrev (), 及msgctl () 编制一长度为1k 的消息的发送和接收程序。 ②观察上面的程序,说明控制消息队列系统调用msgctl () 在此起什么作用? (2)共享存储区的创建、附接和段接。 使用系统调用shmget(),shmat(),sgmdt(),shmctl(),编制一个与上述功能相同的程序。(3)比较上述(1),(2)两种消息通信机制中数据传输的时间。 实验步骤与调试过程: 1.消息的创建,发送和接收: (1)先后通过fork( )两个子进程,SERVER和CLIENT进行通信。 (2)在SERVER端建立一个Key为75的消息队列,等待其他进程发来的消息。当遇到类型为1的消息,则作为结束信号,取消该队列,并退出SERVER 。SERVER每接收到一个消息后显示一句“(server)received”。 (3)CLIENT端使用Key为75的消息队列,先后发送类型从10到1的消息,然后退出。最后的一个消息,既是 SERVER端需要的结束信号。CLIENT每发送一条消息后显示一句“(client)sent”。 (4)父进程在 SERVER和 CLIENT均退出后结束。 2.共享存储区的创建,附接和断接: (1)先后通过fork( )两个子进程,SERVER和CLIENT进行通信。 (2)SERVER端建立一个KEY为75的共享区,并将第一个字节置为-1。作为数据空的标志.等待其他进程发来的消息.当该字节的值发生变化时,表示收到了该消息,进行处理.然后再次把它的值设为-1.如果遇到的值为0,则视为结束信号,取消该队列,并退出SERVER.SERVER 每接收到一次数据后显示”(server)received”. (3)CLIENT端建立一个为75的共享区,当共享取得第一个字节为-1时, Server端空闲,可发送请求. CLIENT 随即填入9到0.期间等待Server端再次空闲.进行完这些操作后, CLIENT退出. CLIENT每发送一次数据后显示”(client)sent”. (4)父进程在SERVER和CLIENT均退出后结束。 实验结果: 1.消息的创建,发送和接收: 由 Client 发送两条消息,然后Server接收一条消息。此后Client Server交替发送和接收消息。最后一次接收两条消息。Client 和Server 分别发送和接收了10条消息。message 的传送和控制并不保证完全同步,当一个程序不再激活状态的时候,它完全可能继续睡眠,造成上面现象。在多次send message 后才 receive message.这一点有助于理解消息转送的实现机理。

实验一 和实验二

实验一熟悉Windows2000/XP中的进程和线程 一、实验目的 1、熟悉Windows2000/XP中任务管理器的使用。 2、通过任务管理器识别操作系统中的进程和线程的相关信息。 3、掌握利用spy++.exe来察看Windows中各个任务的更详细信息。 二、实验理论基础 1、实验理论基础: (1)操作系统中的进程和线程的概念; (2)进程PCB的各项指标含意; (3)操作系统中的进程和线程的概念; (4)进程的各种控制; 三、实验内容与步骤 1、启动操作系统自带的任务管理器: 方法:直接按组合键Ctrl+Alt+Del,或者是在点击任务条上的“开始”“运行”,并输入“taskmgr.exe”。如下图所示:

2、调整任务管理器的“查看”中的相关设置,显示关于进程的以下各项信息, 并完成下表(填满即可): 表一:统计进程的各项主要信息

3、从桌面启动办公软件“Word”,在任务管理器中找到该软件的登记,并将其结 束掉。再从任务管理器中分别找到下列程序:winlogon.exe、lsass.exe、csrss.exe、smss.exe,试着结束它们,观察到的反应是无法中止进程,原因是该程序为关键系统进程,任务管理器无法结束进程。 4、在任务管理器中找到进程“explorer.exe”,将之结束掉,并将桌面上你打开 的所有窗口最小化,看看你的计算机系统起来什么样的变化桌面所有的快捷图标消失,任务栏消失、得到的结论是这个进程用于显示桌面上的图标和开始菜单(说出explorer.exe进程的作用)。 5、运行“spy++.exe”应用软件,点击按钮“”,切换到进程显示栏上,查看进程“explorer.exe”的各项信息,并填写下表: 表二:统计线程的各项信息 进程:explorer.exe 中的各个线程

李建伟版实用操作系统第二版最新习题 3 进程同步与通信

李建伟版实用操作系统第二版最新习题 3 进程同步与通信 一、选择题 题号1 2 3 4 5 6 7 8 9 10 答案A D D C B C A B A A 题号11 12 答案D C 二、综合题 1、答:临界资源也称独占资源、互斥资源,它是指某段时间内只充许一个进程使用的资源。比如打印机等硬件资源,以及只能互斥使用的变量、表格、队列等软件资源。各个进程中访问临界资源的、必须互斥执行的程序代码段称为临界区,各进程中访问同一临界资源的程序代码段必须互斥执行。 为防止两个进程同时进入临界区,可采用软件解决方法或同步机构来协调它们。但是,不论是软件算法还是同步机构都应遵循下述准则: ①空闲让进。②忙则等待。③有限等待。④让权等待。 2、答:忙等待意味着一个进程正在等待满足一个没有闲置处理器的严格循环的条件。因为只有一个CPU 为多个进程服务,因此这种等待浪费了CPU 的时钟。 其他类型的等待:与忙等待需要占用处理器不同,另外一种等待则允许放弃处理器。如进程阻塞自己并且等待在合适的时间被唤醒。忙等可以采用更为有效的办法来避免。例如:执行请求(类似于中断)机制以及PV 信号量机制,均可避免“忙等待”现象的发生。 3、答: 在生产者—消费者问题中,Producer 进程中P(empty)和P(mutex)互换先后次序。先 执行P(mutex),假设成功,生产者进程获得对缓冲区的访问权,但如果此时缓冲池已满,没有空缓冲区可供其使用,后续的P(empty)原语没有通过,Producer 阻塞在信号量empty 上,而此时mutex 已被改为0,没有恢复成初值1。切换到消费者进程后,Consumer 进程执行P(full)成功,但其执行P(mutex)时由于Producer 正在访问缓冲区,所以不成功,阻塞在信号量mutex 上。生产者进程和消费者进程两者均无法继续执行,相互等待对方释放资源,会产生死锁。 在生产者和消费者进程中,V 操作的次序无关紧要,不会出现死锁现象。 4、答:

进程同步与通信作业习题与答案

第三章 一.选择题(50题) 1.以下_B__操作系统中的技术是用来解决进程同步的。 A.管道 B.管程 C.通道 2.以下_B__不是操作系统的进程通信手段。 A.管道 B.原语 C.套接字 D.文件映射 3.如果有3个进程共享同一程序段,而且每次最多允许两个进程进入该程序段,则信号量的初值应设置为_B__。 4.设有4个进程共享一个资源,如果每次只允许一个进程使用该资源,则用P、V操作管理时信号量S的可能取值是_C__。 ,2,1,0,-1 ,1,0,-1,-2 C. 1,0,-1,-2,-3 ,3,2,1,0 5.下面有关进程的描述,是正确的__A__。 A.进程执行的相对速度不能由进程自己来控制 B.进程利用信号量的P、V 操作可以交换大量的信息 C.并发进程在访问共享资源时,不可能出现与时间有关的错误 、V操作不是原语操作 6.信号灯可以用来实现进程之间的_B__。 A.调度 B.同步与互斥 C.同步 D.互斥 7.对于两个并发进程都想进入临界区,设互斥信号量为S,若某时S=0,表示_B__。 A.没有进程进入临界区 B.有1个进程进入了临界区 C. 有2个进程进入了临界区 D. 有1个进程进入了临界区并且另一个进程正等待进入 8. 信箱通信是一种_B__方式 A.直接通信 B.间接通信 C.低级通信 D.信号量 9.以下关于临界区的说法,是正确的_C__。

A.对于临界区,最重要的是判断哪个进程先进入 B.若进程A已进入临界区,而进程B的优先级高于进程A,则进程B可以 打断进程A而自己进入临界区 C. 信号量的初值非负,在其上只能做PV操作 D.两个互斥进程在临界区内,对共享变量的操作是相同的 10. 并发是指_C__。 A.可平行执行的进程 B.可先后执行的进程 C.可同时执行的进程 D.不可中断的进程 11. 临界区是_C__。 A.一个缓冲区 B.一段数据区 C.一段程序 D.栈 12.进程在处理机上执行,它们的关系是_C__。 A.进程之间无关,系统是封闭的 B.进程之间相互依赖相互制约 C.进程之间可能有关,也可能无关 D.以上都不对 13. 在消息缓冲通信中,消息队列是一种__A__资源。 A.临界 B.共享 C.永久 D.可剥夺 14. 以下关于P、V操作的描述正确的是__D_。 A.机器指令 B. 系统调用 C.高级通信原语 D.低级通信原语 15.当对信号量进行V源语操作之后,_C__。 A.当S<0,进程继续执行 B.当S>0,要唤醒一个就绪进程 C. 当S<= 0,要唤醒一个阻塞进程 D. 当S<=0,要唤醒一个就绪 16.对临界区的正确论述是__D_。 A.临界区是指进程中用于实现进程互斥的那段代码 B. 临界区是指进程中用于实现进程同步的那段代码 C. 临界区是指进程中用于实现进程通信的那段代码 D. 临界区是指进程中访问临界资源的那段代码 17. __A__不是进程之间的通信方式。 A.过程调用 B.消息传递 C.共享存储器 D.信箱通信 18. 同步是指进程之间逻辑上的__A__关系。

实验三 进程间通信

实验三进程间通信(2学时) 一、实验目的 (1)了解什么是信号。 (2)熟悉LINUX系统中进程之间软中断通信的基本原理。 (3)熟悉LINUX支持的管道通信方式。 二、实验内容 (1)编写一段程序,使其现实进程的软中断通信。 即:使用系统调用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上来的中断信号(即按 ctrl+c 键);当捕捉到中断信号后,父进程用系统调用kill( )向两个子进程发出信号,子进程捕捉到信号后,分别输出下列信息后终止: Child Process11 is killed by Parent! Child Process12 is killed by Parent! 父进程等待两个子进程终止后,输出如下的信息后终止 Parent Process is killed! 要求:运行以下参考程序并分析结果。 <参考程序> #include #include #include #include void waiting(),stop(),alarming(); int wait_mark; main() { int p1,p2; if(p1=fork()) /*创建子进程p1*/ { if(p2=fork()) /*创建子进程p2*/ { //父进程 wait_mark=1; signal(SIGINT,stop); /*接收到^c信号,转stop*/

signal(SIGALRM,alarming);/*接受SIGALRM*/ waiting(); kill(p1,16); /*向p1发软中断信号16*/ kill(p2,17); /*向p2发软中断信号17*/ wait(0); /*同步*/ wait(0); printf("parent process is killed!\n"); exit(0); //会暂时停止目前进程的执行,直到有信号来到或子进程结束。 } else { wait_mark=1; signal(17,stop); signal(SIGINT,SIG_IGN); /*忽略 ^c信号*/ while (wait_mark!=0); lockf(1,1,0); printf("child process2 is killed by parent!\n"); lockf(1,0,0); exit(0); } } else { wait_mark=1; signal(16,stop); signal(SIGINT,SIG_IGN); /*忽略^c信号*/ while (wait_mark!=0); lockf(1,1,0); printf("child process1 is killed by parent!\n"); lockf(1,0,0); exit(0); } } void waiting() { sleep(5); if (wait_mark!=0) kill(getpid(),SIGALRM); } void alarming()

第3章 进程同步与通信 练习题答案

第3章进程同步与通信练习题 (一)单项选择题 1.临界区是指( )。 A.并发进程中用于实现进程互斥的程序段 B.并发进程中用于实现进程同步的程序段 C.并发进程中用户实现进程通信的程序段 D.并发进程中与共享变量有关的程序段 2.相关临界区是指( )。 A.一个独占资源 B.并发进程中与共享变量有关的程序段 c.一个共享资源 D.并发进程中涉及相同变量的那些程序段 3.管理若干进程共享某一资源的相关临界区应满足三个要求,其中( )不考虑。 A一个进程可以抢占己分配给另一进程的资源 B.任何进程不应该无限地逗留在它的临界区中c.一次最多让一个进程在临界区执行 D.不能强迫一个进程无限地等待进入它的临界区4、( )是只能由P和v操作所改变的整型变量。 A共享变量 B.锁 c整型信号量 D.记录型信号量 5.对于整型信号量,在执行一次P操作时,信号量的值应( )。 A.不变 B.加1 C减1 D.减指定数值 6.在执行v操作时,当信号量的值( )时,应释放一个等待该信号量的进程。 A>0 B.<0 c.>=0 D.<=0 7.Pv操作必须在屏蔽中断下执行,这种不可变中断的过程称为( )。 A初始化程序 B.原语 c.子程序 D控制模块 8.进程间的互斥与同步分别表示了各进程间的( )。 A.竞争与协作 B.相互独立与相互制约 c.不同状态 D.动态性与并发性 9并发进程在访问共享资源时的基本关系为( )。 A.相互独立与有交往的 B.互斥与同步 c并行执行与资源共享 D信息传递与信息缓冲 10.在进程通信中,( )常用信件交换信息。 A.低级通信 B.高级通信 c.消息通信 D.管道通信 11.在间接通信时,用send(N,M)原语发送信件,其中N表示( )。 A.发送信件的进程名 B.接收信件的进程名 C信箱名 D.信件内容 12.下列对线程的描述中,( )是错误的。 A不同的线程可执行相同的程序 B.线程是资源分配单位 c.线程是调度和执行单位 D.同一 进程中的线程可共享该进程的主存空间 13.实现进程互斥时,用( )对应,对同一个信号量调用Pv操作实现互斥。 A.一个信号量与一个临界区 B.一个信号量与—个相关临界区 c.一个信号量与一组相关临界 区 D一个信号量与一个消息 14.实现进程同步时,每一个消息与一个信号量对应,进程( )可把不同的消息发送出去。 A.在同一信号量上调用P操作 B在不同信号量上调用P操作 c.在同一信号量上调用v操作D.在不同信号量上调用v操作 (二)填空题 1.目前使用的计算机的基本特点是处理器______执行指令。 2.进程的______是指进程在顺序处理器上的执行是按顺序进行的。 3.当一个进程独占处理器顺序执行时,具有______和______两个特性。 4.进程的封闭性是指进程的执行结果只取决于______,不受外界影响。 5 进程的可再现性是指当进程再次重复执行时,必定获得______的结果。 6.一个进程的工作在没有全部完成之前,另一个进程就可以开始工作,则称这些进程为______.

进程同步实验报告

实验三进程的同步 一、实验目的 1、了解进程同步和互斥的概念及实现方法; 2、更深一步的了解fork()的系统调用方式。 二、实验内容 1、预习操作系统进程同步的概念及实现方法。 2、编写一段源程序,用系统调用fork()创建两个子进程,当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示字符“a”;子进程分别显示字符“b”和字符“c”。程序的输出是什么?分析原因。 3、阅读模拟火车站售票系统和实现进程的管道通信源代码,查阅有关进程创建、进程互斥、进程同步的系统功能调用或API,简要解释例程中用到的系统功能或API的用法,并编辑、编译、运行程序,记录程序的运行结果,尝试给出合理的解释。 4、(选做)修改问题2的代码,使得父子按顺序显示字符“a”;“b”、“c”编辑、编译、运行。记录程序运行结果。 三、设计思想 1、程序框架 (1)创建两个子进程:(2)售票系统:

(3)管道通信: 先创建子进程,然后对内容加锁,将输出语句存入缓存,并让子进程自己进入睡眠,等待别的进程将其唤醒,最后解锁;第二个子进程也执行这样的过程。父进程等待子进程后读内容并输出。 (4)修改程序(1):在子进程的输出语句前加上sleep()语句,即等待父进程执行完以后再输出。 2、用到的文件系统调用函数 (1)创建两个子进程:fork() (2)售票系统:DWORD WINAPI Fun1Proc(LPVOID lpPartameter); CreateThread(NULL,0,Fun1Proc,NULL,0,NULL); CloseHandle(hThread1); (HANDLE)CreateMutex(NULL,FALSE,NULL); Sleep(4000)(sleep调用进程进入睡眠状态(封锁), 直到被唤醒); WaitForSingleObject(hMutex,INFINITE); ReleaseMutex(hMutex); (3)管道通信:pipe(fd),fd: int fd[2],其中: fd[0] 、fd[1]文件描述符(读、写); lockf( fd,function,byte)(fd: 文件描述符;function: 1: 锁定 0:解锁;byte: 锁定的字节数,0: 从当前位置到文件尾); write(fd,buf,byte)、read(fd,buf,byte) (fd: 文件描述符;buf : 信息传送的源(目标)地址;byte: 传送的字节数); sleep(5); exit(0); read(fd[0],s,50) (4)修改程序(1):fork(); sleep(); 四、调试过程 1、测试数据设计 (1)创建两个子进程:

操作系统进程创建及通信实验报告

武汉工程大学计算机科学与工程学院 《操作系统》实验报告[Ⅰ]

一、实验目的 创建进程,实现进程消息通信和共享内存通信,了解进程的创建、退出和获取进程信。了解什么是映像文件、管道通信及其作用,掌握通过内存映像文件和管道技术实现进程通信。 二、实验内容 本例用三种方法实现进程通信,仅用于示例目的,没有进行功能优化。 1、创建进程A和B后,在进程A中输入一些字符,点“利用 SendMessage发送消息”按钮可将消息发到进程B。 2、在进程A中输入一些字符,点“写数据到内存映像文件”按钮, 然后在进程B中点“从内存映像文件读数据”按钮可收到消息。其中在点“写数据到内存映像文件”时,要求创建映像文件,B进程在印象文件中读取数据。 3、先在进程B中点“创建管道并接收数据”按钮,然后在进程A 中输入一些字符,点“写数据到管道文件”按钮可将消息发到进程B。管道是连接读/写进程使他们进行通信的一个共享文件,目的是更好地实现进程间的通信。 三、实验思想 这次试验最主要的内容和核心思想就是学会创建进程并实现进程间的简单通信、创建映像文件和创建管道文件来通信,后两者是实现进程通信的高级通信机制中的两种。. 创建一个程序A和程序B,其中程序A和B各有一个主窗体,A主窗体上要求可以实现创建进程B(即调用函数B)、结束进程B、关闭进程A、向进程B发送数据、创建映像文件、创建管道文件等功能,进程B要求有从映像文件读取数据、创建管道并接收数据、结束进程B功能。最终让A、B进程相互通信。

四、设计分析: 首先设得设计A、B两个程序的操作界面,然后编写各个功能模块。对于A 程序窗体,在“利用SendMessage发送消息”按钮的消息响应函数中,主要是利用Windows API函数CWnd::FindWindow来找到接收消息的窗体,即进程B,找到进程B后,利用这个函数返回的窗体指针的SendMessage函数来发送消息。在“写数据到内存印象文件”按钮的消息响应函数中,主要是利用函数CreateFileMapping来创建一个印象文件,这个函数返回的是这个印象文件的句柄,然后将这个句柄和要发送的消息字符串传递到函数sprintf中,就可以所要发送的消息写入印象文件,在B程序窗体中有个“从内存印象文件读数据”按钮,在这个按钮的消息响应函数中读取父进程所创建的印象文件中的数据就可以实现通信了。在B程序窗体按钮“写数据到管道文件”的消息响应函数中,不能直接将要发送的消息发送到管道文件,因为管道必须先由子进程通过函数CreateNamedPipe创建,只有待子进程创建好管道后父进程才能根据管道创建管道文件,将消息写入管道文件并及时发送给子进程。而且这个管道只能使用一次,即每次发送完消息后那个管道不能在使用了,必须再由子进程创建一个管道,A 进程才能再次创建管道文件并向其中写入消息。这个程序也不一定要MFC实现,还可以用其他的技术和语言实现,比如说Java、VB等,外表构架可以不一样,但核心技术都是一样的,只是不同的调用形式和调用方法,比如说在VB中,实现进程间的一般通信就是使用动态数据交换DDE,实现起来就比较简单,但是要创建映像文件和管道文件就比较繁琐,可以根据不同的需求采用不同的语言。 五、程序部分源代码: 1.“利用SendMessage发送消息”按钮中的主要代码 //找到接收消息的窗口(窗口名为Receiver) CString str="进程B"; CWnd *pWnd=CWnd::FindWindow(NULL,str); if(pWnd) { COPYDATASTRUCT buf; char * s=new char[m_Msg1.GetLength()]; //m_Msg1为CString类型的变量 s=m_Msg1.GetBuffer(0);

操作系统实验-进程同步与互斥

实验四:进程的管道通信 实验题目 进程的管道通信 实验目的 加深对进程概念的理解,明确进程和程序的区别。学习进程创建的过程,进一步认识进程并发执行的实质。分析进程争用资源的现象,学习解决进程互斥的方法。学习解决进程同步的方法。掌握Linux系统中进程间通过管道通信的具体实现 实验内容 使用系统调用pipe()建立一条管道,系统调用fork()分别创建两个子进程,它们分别向管道写一句话,如: Child process1 is sending a message! Child process2 is sending a message! 父进程分别从管道读出来自两个子进程的信息,显示在屏幕上。 当然,仅仅通过屏幕上输出这两句话还不能说明实现了进程的管道通信,为了能够更好的证明和显示出进程的同步互斥和通信,在其中要加入必要的跟踪条件,如一定的输出语句等,来反映程序的并发执行情况 实验要求 这是一个设计型实验,要求自行、独立编制程序。两个子进程要并发执行。实现管道的互斥使用。当一个子进程正在对管道进行写操

作时,另一个欲写入管道的子进程必须等待。使用系统调用lockf(fd[1],1,0)实现对管道的加锁操作,用lockf(fd[1],0,0)解除对管道的锁定。实现父子进程的同步,当父进程试图从一空管道中读取数据时,便进入等待状态,直到子进程将数据写入管道返回后,才将其唤醒。 为了清楚的反应进程的同步,在子进程完成相应的操作后,调用sleep()函数睡眠一段时间(程序中定为3s)。父进程先执行wait()函数,当有子进程执行完毕后,会得到子进程的返回结果并清理子进程。若子进程没执行完,父进程一直执行wait()进行监听,知道有一个子进程执行完成为僵尸进程。 程序中用到的系统调用 因为程序时在linux系统上进行编写的,所以其中要利用到相关的linux提供的系统调用。 所用到的系统调用包含在如下头文件中。 #include #include #include #include #include #include fork() 用于创一个子进程。 格式:int fork();

操作系统实验Linux进程同步与通信操作系统二

操作系统课程实验二 年级2012 级 专业计算机科学与技术(应用型)指导教师黄玲 学号 姓名

实验二、Linux进程同步与通信 一、关键问题 1、实验目的 理解进程的高级通信;理解通过信号量实现进程的同步。 2、实验环境 Ubuntu 8.0或者以上,Eclipse集成开发环境 3、实验内容 3.1 观察Linux进程通信 下面代码实现两个进程之间通过共享内存通信。 3.2 Linux进程同步 实验要求:一个生产者向一个缓冲区发消息,每当发出一个消息后,要等待三个消费者都接收这条消息后,生产者才能发送新消息。用信号量和P、V操作,写出他们同步工作的程序。(提示:可以把缓冲区看作是三个缓冲块组成的缓冲区,生产者等到这三个缓冲块为空时,才发送新消息到这个缓冲区。每个消费者从一个缓冲块取走数据。) 二、设计修改思路 这是一个典型的生产者消费者问题可以基于信号灯解决,由于有3个消费者,一个生产者,共用同一个缓冲区,所以我们需要设置4个信号灯来控制4个进程的互斥。一个生产者进程不断向修改变量(写入10次),三个消费者进程从缓冲区中读取数据。创建了empty、full1、full2、full3四个信号量,供进程间同步访问临界区,同时建立两个虚存区:a用于生产者、消费者之间的共享数据,get 记录当前生产者进程和消费者进程的读写次数。 实现的算法如下: 生产者进程 { p(empty); p(empty); p(empty); 发送消息 v(full1); v(full2); v(full3); } 消费者A进程 { p(full1); 接受消息 v(empty); } 消费者B、C进程和A进程类似

实验报告三进程管理及进程通信

实验三进程管理及进程通信 实验环境: Linux操作系统 实验目的: (1)利用Linux提供的系统调用设计程序,加深对进程概念的理解。 (2)体会系统进程调度的方法和效果。 (3)了解进程之间的通信方式以及各种通信方式的使用。 实验方法: 用vi 编写c 程序(假定程序文件名为prog1.c)编 译程序 $ gcc -o prog1.o prog1.c 或 $ cc -o prog1.o prog1.c 运行 $./prog1.o 实验内容及步骤: 实验1 编写程序。显示进程的有关标识(进程标识、组标识、用户标识等)。经过5 秒钟后,执行另一个程序,最后按用户指示(如:Y/N)结束操作。 编程截图:

运行结果: 实验2 参考例程1,编写程序。实现父进程创建一个子进程。体会子进程与父进程分 别获得不同返回值,进而执行不同的程序段的方法。 例程1:利用fork()创建子进程 /* 用fork()系统调用创建子进程的例子*/ main() { int i; if (fork()) /*父进程执行的程序段*/ i=wait(); /* 等待子进程结束*/{ printf("It is parent process.\n"); printf("The child process,ID number %d, is finished.\n",i); } else{

Printf(“It is child process.\n”); Sleep(10); Exit(); } } 运行结果: 思考: 子进程是如何产生的?又是如何结束的?子进程被创建后它的运行环境是怎样建立的? 答:是由父进程用fock()函数创建形成的,通过exit()函数自我结束,子进程被创建后核心 将其分配一个进程表项和进程标识符,检查同时运行的进程数目,并且拷贝进程表项的数据,由子进程继承父进程所有文件。 实验3 参考例程2,编写程序。父进程通过循环语句创建若干子进程。探讨进程的家族树 以及子进程继承父进程的资源的关系。 例程2:循环调用fork()创建多个子进程。 /*建立进程树*/ #include main() { int i; printf(“My pid is %d, my father’s pid is %d\n”,getpid() ,getppid()); for(i=0; i<3; i++) if(fork()==0) printf(“%d pid=%d ppid=%d\n”, i,getpid(),getppid()); else { j=wait(0); Printf(“%d:The chile %d is finished.\n”,getpid(),j);

相关主题
文本预览
相关文档 最新文档