课程
实验四 进程通信 题目整理
实验四 进程通信 题目整理
本文件根据原始实验题目材料整理,已统一为适合 GitHub 提交的 Markdown 版本。
题目材料 1:实验四 进程通信
一、实验目的
以管道通信为例了解 Linux 系统中进程通信的基本原理。
二、预备知识
-
系统调用
lockf(fd, mode, size),对指定文件的指定区域(由size指示)进行加锁或解锁,以实现进程的同步与互斥。其中fd是文件描述字;mode是锁定方式,=1表示加锁,=0表示解锁,size是指定文件fd的指定区域,用0表示从当前位置到文件尾。 -
进程管道的通信。
建立进程间的管道,格式为:
pipe(fd);int fd[2];其中,fd[1]是写端,向管道中写入;fd[0]是读端,从管道中读出;本质上将其当作文件处理。进程间可通过管道,用write与read来传递数据,但write与read不可以同时进行,在管道中只能有 4096 字节的数据被缓冲。
写端 fd[1] --- pipe(fd) --- 读端 fd[0]
write(fd[1], buf, size) read(fd[0], buf, size)
write()写文件函数,把buf中的长度为size字符的消息送入管道入口fd[1]。read()读文件函数,从管道出口fd[0]读出size字符的消息置入buf中。- 系统调用
sleep(second)用于进程的同步与互斥,自变量是暂停秒数。其功能是使现行进程暂停执行由自变量规定的秒数。 sprintf()格式化输出到数组的函数。- 系统调用
exit()和wait()参考课本 238 页。
三、实验内容
1. 分析示例程序且编译执行
编写一个程序,建立一个 pipe,同时父进程产生一个子进程,子进程向 pipe 中写入一个字符串,父进程相隔 5 秒钟从该 pipe 中读出该字符串。
#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");
printf("child process running! \n");
write(fd[1], buf, 30); /* 把 buf 中的字符写入管道 */
sleep(5); /* 睡眠 5 秒,让父进程读 */
exit(0); /* 关闭 x,子进程自我中止 */
}
else
{
wait(0); /* 父进程挂起直到其某一子进程中止为止 */
read(fd[0], s, 30);
printf("%s", s);
}
}
2. 编写一段程序
使用系统调用 pipe() 建立一条管道线,同时父进程生成 2 个子进程分别向这条管道写一句话:child1 is sending a message! Child2 is sending a message! 父进程则循环从管道中读出信息,显示在屏幕上。(提示:两个子进程向管道中写入字符的时候要保持互斥,使用 lockf)
{
lockf(fd[1], 1, 0);
// ...
lockf(fd[1], 0, 0);
}
3. (选做) 编制一段程序,实现软中断通信
实验目的
- 了解什么是信号
- 熟悉 Linux 系统中进程之间软中断通信的基本原理
实验内容:
编制一段程序,实现软中断通信
使用系统调用
fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上来的中断信号,当父进程接受到这两个软中断的其中某一个后,父进程用系统调用kill()向两个子进程分别发送整数值为 16 和 17 软中断信号,子进程获得对应软中断信号后,分别输出下列信息后终止:
Child process 1 is killed by parent !!Child process 2 is killed by parent !!父进程调用
wait()函数等待两个子进程终止后,输出以下信息后终止:
Parent process is killed!!
多运行几次编写的程序,简略分析出现不同结果的原因。
软中断,是对硬中断的一种模拟,发送软中断就是向接收进程的 proc 结构中的相应项发送一个特定意义的信号。软中断必须等到接收进程执行时才能生效。
实验指导
一、信号
1、信号的基本概念
每个信号都对应一个正整数常量(称为 signal number,即信号编号。定义在系统头文件 <signal.h> 中),代表同一用户的诸进程之间传送事先约定的信息的类型,用于通知某进程发生了某异常事件。每个进程在运行时,都要通过信号机制来检查是否有信号到达。若有,便中断正在执行的程序,转向与该信号相对应的处理程序,以完成对该事件的处理;处理结束后再返回到原来的断点继续执行。实质上,信号机制是对中断机制的一种模拟,故在早期的 UNIX 版本中又把它称为软中断。
信号与中断的相似点:
- 采用了相同的异步通信方式
- 当检测出有信号或中断请求时,都暂停正在执行的程序而转去执行相应的处理程序
- 都在处理完毕后返回到原来的断点
- 对信号或中断都可进行屏蔽
信号与中断的区别:
- 中断有优先级,而信号没有优先级,所有的信号都是平等的
- 信号处理程序是在用户态下运行的,而中断处理程序是在核心态下运行
- 中断响应是及时的,而信号响应通常都有较大的时间延迟
信号机制具有以下三方面的功能:
- 发送信号。发送信号的程序用系统调用
kill()实现 - 预置对信号的处理方式。接收信号的程序用
signal()来实现对处理方式的预置 - 收受信号的进程按事先的规定完成对相应事件的处理
2、信号的发送
信号的发送,是指由发送进程把信号送到指定进程的信号域的某一位上。如果目标进程正在一个可被中断的优先级上睡眠,核心便将它唤醒,发送进程就此结束。一个进程可能在其信号域中有多个位被置位,代表有多种类型的信号到达,但对于一类信号,进程却只能记住其中的某一个。
进程用 kill() 向一个进程或一组进程发送一个信号。
3、对信号的处理
当一个进程要进入或退出一个低优先级睡眠状态时,或一个进程即将从核心态返回用户态时,核心都要检查该进程是否已收到软中断。当进程处于核心态时,即使收到软中断也不予理睬;只有当它返回到用户态后,才处理软中断信号。对软中断信号的处理分三种情况进行:
- 如果进程收到的软中断是一个已决定要忽略的信号(
function=1),进程不做任何处理便立即返回 - 进程收到软中断后便退出(
function=0) - 执行用户设置的软中断处理程序
二、所涉及的中断调用
1、kill()
系统调用格式:
int kill(pid, sig)
int pid, sig;
其中,pid 是一个或一组进程的标识符,参数 sig 是要发送的软中断信号。
pid>0时,核心将信号发送给进程pidpid=0时,核心将信号发送给与发送进程同组的所有进程pid=-1时,核心将信号发送给所有用户标识符真正等于发送进程的有效用户标识号的进程
2、signal()
预置对信号的处理方式,允许调用进程控制软中断信号。
系统调用格式:
signal(sig, function)
头文件为:
#include <signal.h>
参数定义:
signal(sig, function)
int sig;
void (*func)()
其中 sig 用于指定信号的类型,sig 为 0 则表示没有收到任何信号,余者如下表:
| 值 | 名字 | 说明 |
|---|---|---|
| 01 | SIGHUP | 挂起(hangup) |
| 02 | SIGINT | 中断,当用户从键盘按 ^c 键 |
| 03 | SIGQUIT | 退出,当用户从键盘按 quit 键时 |
| 04 | SIGILL | 非法指令 |
| 05 | SIGTRAP | 跟踪陷阱(trace trap),启动进程,跟踪代码的执行 |
| 06 | SIGIOT | IOT 指令 |
| 07 | SIGEMT | EMT 指令 |
| 08 | SIGFPE | 浮点运算溢出 |
| 09 | SIGKILL | 杀死、终止进程 |
| 10 | SIGBUS | 总线错误 |
| 11 | SIGSEGV | 段违例(segmentation violation),进程试图去访问其虚地址空间以外的位置 |
| 12 | SIGSYS | 系统调用中参数错,如系统调用号非法 |
| 13 | SIGPIPE | 向某个非读管道中写入数据 |
| 14 | SIGALRM | 闹钟。当某进程希望在某时间后接收信号时发此信号 |
| 15 | SIGTERM | 软件终止(software termination) |
| 16 | SIGUSR1 | 用户自定义信号 1 |
| 17 | SIGUSR2 | 用户自定义信号 2 |
| 18 | SIGCLD | 某个子进程死 |
| 19 | SIGPWR | 电源故障 |
function:在该进程中的一个函数地址,在核心返回用户态时,它以软中断信号的序号作为参数调用该函数,对除了信号 SIGKILL、SIGTRAP 和 SIGPWR 以外的信号,核心自动地重新设置软中断信号处理程序的值为 SIG_DFL,一个进程不能捕获 SIGKILL 信号。
function 的解释如下:
function=1时,进程对sig类信号不予理睬,亦即屏蔽了该类信号function=0时,缺省值,进程在收到sig信号后应终止自己function为非 0、非 1 类整数时,function的值即作为信号处理程序的指针
算法流程图如下:













