实验四:软中断通信
***
大家好呀~~~今天是小白学操作系统系列第四篇。在开始之前,~~让我们先来摆烂
啊不,阅读一些材料。不了解没有办法做实验哦~
若觉文字太多,可直接阅读红体字
~~
【实验必读材料】:
一、信号的基本概念:
每个进程在运行时,都要通过信号机制来检查是否有信号到达。若有,便中断正在执行的程序,转向与该信号相对应的处理程序,以完成对该事件的处理;处理结束后再返回到原来的断点继续执行。
二、几个函数调用:
1、***Signal()**
预置对信号的处理方式,允许调用进程控制软中断信号。
系统调用格式:signal(sig,function)
头文件为: #include <signal.h>
由于不同系统的信号编号是不完全相同的,所以当前系统中,可以使用“kill -l”命令查看信号编号。
下表仅供参考,不同系统信号不一样哦~:
2.****kill()**
系统调用格式:int kill(pid,sig)
参数定义
int pid,sig;
其中,pid是一个或一组进程的标识符,参数sig是要发送的软中断信号。
(1)pid>0时,操作系统将信号发送给进程pid。
(2)pid=0时,操作系统将信号发送给与发送进程同组的所有进程。
(3)pid=-1时,操作系统将信号发送给所有用户标识符真正等于发送进程的有效用户标识号的进程。
3、****lockf()**
头文件:#include <unistd.h>
允许将文件区域用作信号量(监视锁),或用于控制对锁定进程的访问(强制模式记录锁定)。试图访问已锁定资源的其他进程将返回错误或进入休眠状态,直到资源解除锁定为止。当关闭文件时,将释放进程的所有锁定,即使进程仍然有打开的文件。当进程终止时,将释放进程保留的所有锁定。
lockf(fd,1,0)是给文件上锁; lockf(fd,0,0)是给文件解锁;**
4、***pause()
***
头文件:#include <unistd.h>
定义函数:int pause(void);
函数说明:pause()会令目前的进程暂停
(进入睡眠状态), 直到被信号(signal)所中断.
返回值:只返回-1
.****
5、***waitpid()**
头文件
#include<sys/types.h>
#include<sys/wait.h>
如果在调用 waitpid()时子进程已经结束,则 waitpid()会立即返回子进程结束状态值。 子进程的结束状态值会由参数 status 返回,而子进程的进程识别码也会一起返回。如果不在意结束状态值,则参数 status 可以设成 NULL。参数 pid 为欲等待的子进程识别码,其他数值意义如下:**
【实验目的】:
1.了解什么是信号,熟练掌握signal(),wait(),exit(),kill()函数。
2.熟悉并掌握Linux系统中进程之间采用软中断通信的基本原理。
【实验内容】:
一、编写一段程序,使用系统调用fork( )创建两个子进程,再用系统调用signal( )进行预置,让父进程捕捉由键盘发来的中断信号(即同时按下Ctrl+C键)。当系统捕捉到中断信号后,调用预置的stop函数,子进程捕捉到信号后,分别输出下列信息后终止:
Child process 1 is interrupted by parent!
Child process 2 is interrupted by parent!
父进程等待两个子进程终止后,输出以下信息后终止:
Parent process is interrupted!
参考代码:
# include<stdio.h> # include<signal.h> # include<unistd.h> # include<sys/wait.h> #include<stdlib.h> int wait_mark; void waiting() { while(wait_mark!=0); } void stop() { wait_mark=0; } int main() { int p1, p2; signal(SIGINT,stop); //signal()初始位置 while((p1=fork())==-1); if(p1>0) { while((p2=fork())==-1); if(p2>0) { wait_mark=1; waiting( ); wait(0); wait(0); printf("parent process is interrupted!\n"); exit(0); } else { wait_mark=1; waiting( ); lockf(1,1,0); printf("child process 2 is interrupted by parent!\n");//可以输出多条语句试试看是否能插入其他进程的输出语句 lockf(1,0,0); exit(0); } } else { wait_mark=1; waiting( ); lockf(1,1,0); printf("child process 1 is interrupted by parent!\n");//这里也可以输出多条语句试试看 lockf(1,0,0); exit(0); } }
运行结果:
yzy@yzy-virtual-machine:~/new$ ./a.out ^Cchild process 2 is interrupted by parent! child process 1 is interrupted by parent! parent process is interrupted!
分析结果:
1、系统调用signal( )进行预置,让父进程捕捉由键盘发来的中断信号,当系统捕捉到中断信号后,调用预置的stop函数,子进程捕捉到信号后,输出信息终止,(child1、child2输出顺序不定。)父进程等待两个子进程结束后,也输出信息终止。
2、父进程用了两个wait(0)的原因:等待2个子进程都结束再执行。
3、每个进程退出时都用了语句exit(0)的原因:正常运行程序并退出程序。为了保证每个进程执行完后,shell能及时回收资源。
二、修改并调试程序,增加语句signal(SIGINT,SIG_IGN)和语句signal(SIGQUIT,SIG_IGN),再观察程序执行时屏幕上出现的现象,并分析其原因。注意:实验前先用kill命令查询本机用户自定义信号的编号。
程序主要功能:子进程屏蔽外部中断信号(Ctrl-C);父进程接收用户按Ctrl-C产生的外部中断信号后,分别给两个子进程发信号(用户自定义信号)。
参考代码:
# include<stdio.h> # include<signal.h> # include<unistd.h> # include<sys/wait.h> #include<stdlib.h> int EndFlag,pid1,pid2; void IntSend() { kill(pid1,10);//向进程pid1发送用户自定义信号10 kill(pid2,12);// 向进程pid2发送用户自定义信号12 EndFlag=1; } void Print1() { printf("child process 1 is interrupted by parent !\n"); exit(0); } void Print2() { printf("child process 2 is interrupted by parent !\n"); exit(0); } int main() { int exitcode; signal(SIGINT,SIG_IGN); signal(SIGQUIT,SIG_IGN); while((pid1=fork())==-1); if(pid1==0) { signal(SIGUSR1, Print1); //用户自定义信号1 signal(SIGQUIT,SIG_IGN); pause(); exit(0); } else { while((pid2=fork())==-1); if(pid2==0) { signal(SIGUSR2, Print2); //用户自定义信号2 signal(SIGQUIT,SIG_IGN); pause(); exit(0); } else { signal(SIGINT, IntSend); waitpid(-1,&exitcode,0); printf("parent process is interrupted! \n"); exit(0); } }}
运行结果
yzy@yzy-virtual-machine:~/new$ ./b.out ^Cchild process 1 is interrupted by parent ! child process 2 is interrupted by parent ! parent process is interrupted!
分析结果:
子进程屏蔽外部中断信号,父进程接收用户按“Ctrl+C”产生的外部中断信号后,分别给两个子进程发信号(用户自定义信号)。系统调用signal( )进行预置,子进程接收自定义信号后,调用预置的print函数,打印输出。(child1、child2顺序不定)。语句‘waitpid(-1,&exitcode,0)’代表父进程等待任何子进程,接收子进程状态结束值。等待子进程结束后,父进程打印输出,结束。
【实验总结】:
软中断通信:
了解了基本知识,硬中断,操作系统系统外设状态的变化。为了满足实时系统的要求,中断处理应该是越快越好。linux为了实现这个特点,当中断发生的时候,硬中断处理那些短时间就可以完成的工作,而将那些处理事件比较长的工作,放到中断之后来完成,也就是软中断来完成。基本的思路是: 父进程生成子进程,父进程发送信号并等待,子进程接收信号,然后自我终止并唤醒父进程,父进程再自我终止。
心得体会:
通过本次实验我了解了软中断通信和管道通信进一步认识到了并发的实质,对Linux进程有了中断和通信更多的认识,学会了一些函数的应用,但是这只是很小一部分,我还需要课下多查阅资料,加强和巩固自己的学习。
**点赞的都是小可爱哦**~