操作系统实验——进程通信(信号机制)实验

一、实验目的:

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

五、实验心得和体会:

通过信号机制实现进程之间的通信比较简单,只需要声明头文件之后,按函数语法调用文件即可,还需注意函数放置的位置以及与其他函数配合使用,不过用信号机制这种方法通信的效率低,当通信数据量较大时一般不用此法。最关键的是需要进行相关设置使得子进程不要提前退出,输出想要的结果。

  • 58
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柚柚丰色tsy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值