一、实验目的: 1、了解什么是信号 2、熟悉 LINUX 系统中进程之间软中断通信的基本原理
|
二、实验内容: 1、编写程序:用 fork( )创建两个子进程,再用系统调用 signal( )让父进程捕捉键盘上 来的中断信号(即按^c 键);捕捉到中断信号后,父进程用系统调用 kill( )向两个子进程发 出信号,子进程捕捉到信号后分别输出下列信息后终止: Child process1 is killed by parent! Child process2 is killed by parent! 父进程等待两个子进程终止后,输出如下的信息后终止: Parent process is killed! 2、分析利用软中断通信实现进程同步的机理 |
三、实验步骤及结果: //把实验运行过程和相关代码,或者实验结果等截图拷贝过来 1、了解实验涉及到的函数的使用方式 2、在系统中新建文本文档,编写程序代码 3、利用gcc进行调试并编译 报错原因: ①调用wait( )函数和exit( )函数前没有声明相应的头文件 ②创建进程时等于符号“= =”中间有空格,程序无法识别 【添加这三个头文件同时删除空格后编译成功】 4、运行程序,比较分析结果 【关键语法点:signal(SIGINT, SIG_IGN)】 该函数设置信号函数处理方式,当收到键盘发送键盘中断(如break键被按下)信号时将会忽略此信号,所以子程序不会直接退出,仍然会并发执行 (1)没有该语句时: (2)该语句放在进程1时: (3)该语句放在进程2时: (4)进程1和进程2同时有该语句时: 5、原因分析 (1)signal( )函数都放在一段程序的前面部位,而不是在其他接收信号处。这是 因为 signal( )的执行只是为进程指定信号值 16 或 17 的作用,以及分配相应的与 stop( )过程链接的指针。因而,signal( )函数必须在程序前面部分执行。 (2)当子进程前面没有“signal(SIGINT, SIG_IGN)”时,当“Ctrl+C”的时候,系统会给父进程及其两个子进程都发送 SIGINT 信号,对 bash 来说,这三个进程都是前台进程,所以都发送。 (3)对于父进程来说,收到signal信号则调用 stop 函数了,但是对于两个子进程来说,默认的对这个信号的处理就是退出(exit),所以看不到子进程的打印。 (4)进程接收到信号以后,可以有如下 3 种选择进行处理: ①接收默认处理:接收默认处理的进程通常会导致进程本身消亡。例如连接到终端的进程,用户按下 CTRL+c,将导致内核向进程发送一个 SIGINT 的信号,进程如果不对该信号做特殊的处理,系统将采用默认的方式处理该信号,即终止进程的执行; ②忽略信号:进程可以通过代码,显示地忽略某个信号的处理,例如:signal(SIGINT,SIGDEF);但是某些信号是不能被忽略的, ③捕捉信号并处理:进程可以事先注册信号处理函数,当接收到信号时,由信号处理函数自动捕捉并且处理信号。 6、软中断通信实现进程同步的机理: (1)软中断通信:是利用信号机制是对中断机制的一种模拟。 (2)信号:每个信号都对应一个正整数常量(称为 signal number,即信号编号。定义在系统头文件 <signal.h>中),代表同一用户的诸进程之间传送事先约定的信息的类型,用于通知某进程 发生了某异常事件。 (3)机理:每个进程在运行时,都要通过信号机制来检查是否有信号到达。若有, 便中断正在执行的程序,转向与该信号相对应的处理程序,以完成对该事件的处理;处理 结束后再返回到原来的断点继续执行。 |
四、实验作业(思考题): 1、该程序段前面部分用了两个 wait(0),它们起什么作用? 两个wait(0)函数均放在对父进程的处理中,用于实现进程同步,避免父进程先于子进程退出,避免子进程被初始进程收养,使得父进程在子进程结束之后再结束。 2、该程序段中每个进程退出时都用了语句 exit(0),为什么? exit(0)函数表示进程正常终止,调用exit函数能及时回收进程所占用的资源并减少父进程的干预,实现进程的自我终止。核心会为exit( )完成以下操作: 关闭软中断、回收资源、写记帐信息、置进程为“僵死状态”。 3、为何预期的结果并未显示出? 对于父进程来说,收到signal信号则调用 stop 函数了,但是对于两个子进程来说,默认的对这个信号的处理就是退出(exit),所以看不到子进程的打印。 需要设置语句“signal(SIGINT, SIG_IGN)”令子进程忽略停止的信号,才能显示预期结果。 4、程序该如何修改才能得到正确结果? 在进程1和进程2之前都设置语句“signal(SIGINT, SIG_IGN)”,则可以打印出子进程 5、不修改程序如何得到期望的输出? 可以单独向父进程发送 SIGINT 信号,这样即可避免子进程由于收到 SIGINT 信号执行默认操作而自我终止。 具体实现方法: ①首先让程序在后台运行,执行该命令后,会在后台生成 3 个进程,使用 ps 命令可以查看到它们的 PID (相对小的 PID 应该为父进程的 PID,原因是创建时间相对早)。 ②然后向后台的父进程发送 SIGINT 信号,命令:kill –SIGINT 父进程pid |
五、实验心得和体会: 通过信号机制实现进程之间的通信比较简单,只需要声明头文件之后,按函数语法调用文件即可,还需注意函数放置的位置以及与其他函数配合使用,不过用信号机制这种方法通信的效率低,当通信数据量较大时一般不用此法。最关键的是需要进行相关设置使得子进程不要提前退出,输出想要的结果。 |
操作系统实验——进程通信(信号机制)实验
最新推荐文章于 2024-05-22 12:59:31 发布