进程软中断通信.docx
《进程软中断通信.docx》由会员分享,可在线阅读,更多相关《进程软中断通信.docx(10页珍藏版)》请在冰点文库上搜索。
进程软中断通信
集团文件版本号:
(M928-T898-M248-WU2669-I2896-DQ586-M1988)
进程软中断通信
进程软中断通信
【预备知识】
进程软中断通信涉及的系统调用描述如下。
1.kill()
进程用kill()向一个进程或一组进程发送一个信号。
系统调用格式为intkill(pid,sig)。
其中,pid是一个或一组进程的标识符,sig是要发送的软中断信号。
信号的发送分如下三种情况。
pid>0时,核心将信号发送给进程pid。
pid=0时,核心将信号发送给与发送进程同组的所用进程。
pid=-1时,核心将信号发送给所有用户标识符真正等于发送进程的有效用户标识号的进程。
2.signal(sig,function)
接收信号的程序用signal()来实现对处理方式的预置,允许调用进程控制软中断信号。
系统调用格式为signal(sigfunction),此时需包含头文件signal.h。
其中,sig用于指定信号的类型,sig为0则表示没有收到任何信号,其余类型如表所示。
调用函数使用如下头文件:
#include
参数定义如下:
signal(sig,function)
intsig;
void(*func)();
function是该进程中的一个函数地址,在核心返回用户态时,它以软中断信号的序号作为参数调用该函数,对除了信号SIGKILL、SIGTRAP和SIGPWR以外的信号,核心自动重新设置软中断信号处理程序的值为SIG_DFL,进程不能捕获SIGKILL信号。
function的解释如下:
(1)function=1时,进程对sig类信号不做任何处理便立即返回,亦即屏蔽该类型号。
(2)function=0时,默认值,进程收到sig信号后终止自己。
(3)function为非0、非1类整数时,执行用户设置的软中断处理程序。
信号的类型
值
名字
说明
01
SIGHUP
挂起(hangup)
02
SIGINT
中断,当用户从键盘按“^c”键或“^break”键时
03
SIGQUIT
退出,当用户从键盘按“quit“键时
04
SIGILL
非法指令
05
SIGTRAP
跟踪陷阱(tracetrap)
06
SIGIOT
IOT指令
07
SIGEMT
EMT指令
08
SIGFPE
浮点运算溢出
09
SIGKILL
终止进程
10
SIGBUS
总线错误
11
SIGSEGV
段违例,进程试图去访问其虚地址空间以外的位置
12
SIGSYS
系统调用中参数错,如系统调用号非法
13
SIGPIPE
向某个非读管道中写入数据
14
SIGALRM
闹钟。
当进程希望在某时间后接收信号时发此信号
15
SIGTERM
软件终止(softwaretermination)
16
SIGUSR1
用户自定义信号1
17
SIGUSR2
用户自定义信号2
18
SIGCLD
某个子进程死
19
SIGPWR
电源故障
编程实现例<一>
【任务】
编程实现,父进程生成子进程,父进程发送信号并等待,子进程接收信号并完成某种功能,然后自我终止并唤醒父进程。
【程序】
#include
#include
#include
intfunc();
main()
{
inti,j;
signal(17,func);
if(i=fork())
{
printf(“Parent:
Signal17willbesendttoChild!
\n”)
kill(i,17);
wait(0);
printf(“Parent:
finished!
\n”);
}
else
{
sleep(10);
printf(“Child:
AsignalfrommyParentisreceived!
\n”);
exit();
}
}
func()
{
printf(“Itissignal17processingfunction!
\n”)
}
【运行结果】
【分析】
编程实现例<二>
【任务】
编制一程,使用系统调用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上来的中断信号(即DEL键),当捕捉到中断信号后,父进程用系统调用kill()向两个子进程发出信号,子进程捕捉到信号后,分别输出下列信息后终止。
childprocess1iskilledbyparent!
childprocess2iskilledbyparent!
父进程等待两个子进程终止后,输出以下信息后终止。
Parentprocessiskilled!
【程序】
#include
#include
#include
intwaiting(),stop();
intwait_mark;
main()
{
intp1,p2;
while((p1=fork())==-1);
if(p1>0)
{
while((p2=fork())==-1);
if(p2>0)
{
printf(“parent\n”);
wait_mark=1;
signal(SIGINT,stop);/*接收DEL信号,并转stop()*/
waiting();
kill(p1,16);/*向P1发中断信号16*/
kill(p2,17);/*向P2发中断信号17*/
wait(0);
wait(0);
printf(“parentprocessiskilled!
\n”);
exit(0)
}
else
{
printf(“p2\n”);
wait_mark=1;
signal(17,stop)
waiting();
lockf(stdout,1,0);
printf(“childprocess2iskilledbyparent!
\n”);
lockf(stdout,0,0);
exit(0);
}
}
else
{
printf(“p1\n”);
wait_mark=1;
signal(16,stop)
waiting();
lockf(stdout,1,0);
printf(“childprocess1iskilledbyparent!
\n”);
lockf(stdout,0,0);
exit(0);
}
}
voidwaiting()
{
while(wait_mark!
=0);
}
voidstop()
{
Wait_mark=0;
}
【运行结果】
childprocess1iskilledbyparent!
childprocess2iskilledbyparent!
Parentprocessiskilled!
【分析】
使用系统调用signal()都放在一段程序的前面部分,而不是在其他接收信号处。
这是因为signal()的执行只是为进程指定信号量16或17的作用,以及分配相应的stop()过程连接的指针,从而,signal()函数必须在程序前面部分执行。
编程实现例<三>
【任务】
在上面程序中,增加语句signal(SIGINT,SIG_IGN)、signal(SIGQUIT,SIG_IGN),观察执行结果,并分析原因。
【程序】
#include
#include
#include
intpid1,pid2;
intendflag=0,pf1=0,pf2=0;
voidintdelete()
{
kill(pid1,16);
kill(pid2,17);
endflag=1;
}
voidint1()
{
printf(“childprocess1iskilledbyparent!
\n”);
exit(0);
}
voidint2()
{
printf(“childprocess2iskilledbyparent!
\n”);
exit(0);
}
main()
{
intexitpid;
signal(SIGINT,SIG_IGN);
signal(SIGQUIT,SIG_IGN);
while((pid1=fork())==-1);
if(pid1==0)
{
printf(“p1\n”);
signal(SIGUSER1,int1);
signal(16,SIG_IGT)
pause();
exit(0);
}
else
{
while((pid2=fork())==-1);
if(pid==0)
{
printf(“p2\n”);
signal(SIGUSER2,int2);
signal(17,SIG_IGT)
pause();
exit(0);
}
else
{
printf(“parent\n”);
signal(SIGINT,intdelete);/*接收DEL信号,并转intdelete()*/
waitpid(-1,&exitpid,0);
printf(“parentprocessiskilled!
\n”);
exit(0)
}
}
}
【运行结果】
【分析】
由于忽略了中断与退出信号,程序会一直保持阻塞状态而无法退出。