进程软中断通信实验

【预备知识】

进程软中断通信涉及的系统调用描述如下。

1.kill()

进程用kill()向一个进程或一组进程发送一个信号。系统调用格式为int kill(pid,sig)。其中,pid是一个或一组进程的标识符,sig是要发送的软中断信号。信号的发送分如下三种情况。

pid>0时,核心将信号发送给进程pid。

pid=0时,核心将信号发送给与发送进程同组的所用进程。

pid=-1时,核心将信号发送给所有用户标识符真正等于发送进程的有效用户标识号的进程。

2.signal(sig,function)

接收信号的程序用signal()来实现对处理方式的预置,允许调用进程控制软中断信号。系统调用格式为signal(sig function),此时需包含头文件signal.h。其中,sig用于指定信号的类型,sig为0则表示没有收到任何信号,其余类型如表所示。

调用函数使用如下头文件:

#include<signal.h>

参数定义如下:

signal (sig,function)

int sig;

void(*func) ();  

function是该进程中的一个函数地址,在核心返回用户态时,它以软中断信号的序号作为参数调用该函数,对除了信号SIGKILL、SIGTRAP和SIGPWR以外的信号,核心自动重新设置软中断信号处理程序的值为SIG_DFL,进程不能捕获SIGKILL信号。

function的解释如下:

(1)function=1时,进程对sig类信号不做任何处理便立即返回,亦即屏蔽该类型号。

(2)function=0时,默认值,进程收到sig信号后终止自己。

(3)function为非0、非1类整数时,执行用户设置的软中断处理程序。

(4)signal(SIGINT,SIG_IGN);来让进程忽略SIGINT信号.

信号的类型

名字

说明

01

SIGHUP

挂起(hangup)

02

SIGINT

中断,当用户从键盘按“^c”键或“^break”键时

03

SIGQUIT

退出,当用户从键盘按“quit“键时

04

SIGILL

非法指令

05

SIGTRAP

跟踪陷阱(trace trap)

06

SIGIOT

IOT指令

07

SIGEMT

EMT指令

08

SIGFPE

浮点运算溢出

09

SIGKILL

终止进程

10

SIGBUS

总线错误

11

SIGSEGV

段违例,进程试图去访问其虚地址空间以外的位置

12

SIGSYS

系统调用中参数错,如系统调用号非法

13

SIGPIPE

向某个非读管道中写入数据

14

SIGALRM

闹钟。当进程希望在某时间后接收信号时发此信号

15

SIGTERM

软件终止(software termination)

16

SIGUSR1

用户自定义信号1

17

SIGUSR2

用户自定义信号2

18

SIGCLD

某个子进程死

19

SIGPWR

电源故障

 

编程实现例<一>

【任务】

编程实现,父进程生成子进程,父进程发送信号并等待,子进程接收信号并完成某种功能,然后自我终止并唤醒父进程。

【程序】

#include <stdio.h>

#include <signal.h>

#include <unistd.h>

int func();

main()

{

int i,j;

signal(17,func);

if(i=fork())

{

printf(“Parent:  Signal  17  will  be  send t  to  Child! \n ”)

kill(i,17);

wait(0);

printf (“Parent: finished! \n”);

}

else

{

sleep(10);

printf(“Child: A signal  from  my  Parent  is  received !  \n”);

exit();

}

}

func()

{

printf(“It is  signal  17   processing  function !  \n”)

}

修改后的代码:

【运行结果】

【分析】

这是一个父子进程通信的例子。父进程生成子进程,发送信号给子进程,并等待子进程完成某种功能。子进程接收信号,并执行处理函数后自我终止,唤醒父进程。当父进程发送信号给子进程后,子进程会等待10秒钟后接收到信号,并执行信号处理函数,然后自我终止,唤醒父进程。父进程等待子进程结束后输出完成的消息。

编程实现例<二>

【任务】

编制一程,使用系统调用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上来的中断信号(即DEL键),当捕捉到中断信号后,父进程用系统调用kill()向两个子进程发出信号,子进程捕捉到信号后,分别输出下列信息后终止。

child process 1 is killed by parent!

child process 2 is killed by parent!

父进程等待两个子进程终止后,输出以下信息后终止。

Parent process is killed!

【程序】

#include <stdio.h>

#include <signal.h>

#include <unistd.h>

int waiting(),stop();

int wait_mark;

main()

{

int p1,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(“parent process is killed!\n”);

     exit(0)

    }

   else

    {

      printf(“p2\n”);

      wait_mark=1;

      signal(17,stop);

      signal(SIGINT,SIG_IGN);

      waiting();

      lockf(stdout,1,0);

      printf(“child process 2 is killed by parent!\n”);

      lockf(stdout,0,0);

      exit(0);

    }

}

else

    {

      printf(“p1\n”);

      wait_mark=1;

      signal(16,stop)

      signal(SIGINT,SIG_IGN);

      waiting();

      lockf(stdout,1,0);

      printf(“child process 1 is killed by parent!\n”);

      lockf(stdout,0,0);

      exit(0);

    }

}

void waiting()

 {

       while (wait_mark!=0);

   }

void stop()

{

Wait_mark=0;

}

修改后的代码:

【运行结果】

【分析】

这是一个父进程生成两个子进程的例子。父进程会等待子进程执行完毕后输出 "parent process is killed!" 的消息,并向子进程发送中断信号。子进程接收到中断信号后输出相应的消息。当父进程发送中断信号给子进程后,子进程会输出相应的消息。父进程会等待子进程执行完毕后输出 "parent process is killed!" 的消息

编程实现例<三>

【任务】

在上面程序中,增加语句signal(SIGINT,SIG_IGN)、signal(SIGQUIT,SIG_IGN),观察执行结果,并分析原因。

【程序】

#include <stdio.h>

#include <signal.h>

#include <unistd.h>

int pid1,pid2;

int endflag=0,pf1=0,pf2=0;

void intdelete()

{

  kill(pid1,16);

  kill(pid2,17);

  endflag=1;

}

void int1()

{

  printf(“child process 1 is killed by parent!\n”);

exit(0);

}

void int2()

{

  printf(“child process 2 is killed by parent!\n”);

exit(0);

}

main()

{

int exitpid;

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(“parent process is killed!\n”);

     exit(0)

 }

}

}

修改后的代码:

【运行结果】

【分析】

程序中增加了两个语句 signal(SIGINT, SIG_IGN) 和 signal(SIGQUIT, SIG_IGN),将 SIGINT 和 SIGQUIT 信号的处理方式设置为忽略。原因是,

SIGINT 是由终端发送的中断信号,通常由用户按下 Ctrl+C 触发。SIGQUIT 是由终端发送的退出信号,通常由用户按下 Ctrl+\ 触发。

通过将这两个信号的处理方式设置为忽略 (SIG_IGN),程序会忽略这两个信号,不执行默认的信号处理行为。因此,当用户按下对应的终端键时,程序中的子进程不会被杀死,也不会输出相应的消息。

  • 27
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值