linux 信号

来源:互联网 发布:java linux cpu使用率 编辑:程序博客网 时间:2024/06/05 08:55

原创:http://blog.sina.com.cn/u/2312748742

一、1、信号是一种软中断,2、信号只是用来通知某进程发生了什么事件,并不给该进程传递任何数据,3、收到信号的进程对各种信号有不同的处理方法。4、进程通过系统调用signal来指定进程对某个信号的处理行为。

二、信号 值 处理动作 发出信号的原因 :
SIGHUP 1 A 终端挂起或者控制进程终止
SIGINT 2 A 键盘中断(如break键被按下)
SIGQUIT 3 C 键盘的退出键被按下
SIGILL 4 C 非法指令
SIGABRT 6 C 由abort(3)发出的退出指令
SIGFPE 8 C 浮点异常
SIGKILL 9 AEF Kill信号
SIGSEGV 11 C 无效的内存引用
SIGPIPE 13 A 管道破裂: 写一个没有读端口的管道
SIGALRM 14 A 由alarm(2)发出的信号
SIGTERM 15 A 终止信号
SIGUSR1 30,10,16 A 用户自定义信号1
SIGUSR2 31,12,17 A 用户自定义信号2
SIGCHLD 20,17,18 B 子进程结束信号
SIGCONT 19,18,25 进程继续(曾被停止的进程)
SIGSTOP 17,19,23 DEF 终止进程
SIGTSTP 18,20,24 D 控制终端(tty)上按下停止键
SIGTTIN 21,21,26 D 后台进程企图从控制终端读
SIGTTOU 22,22,27 D 后台进程企图从控制终端写

三、信号的安装处理:

void (*signal(int signum, void (*handler))(int)))(int);

该函数有两个参数, signum指定要安装的信号, handler指定信号的处理函数.

该函数的返回值是一个函数指针, 指向上次安装的handler

四、例子:

#include<stdio.h>
#include<signal.h>
int counts=0;
void signal_callback(int nums)
{
 counts++;
 printf("Ctrl_C Press numbers:%d\n",counts);
}

int main()
{
 int c;
 signal(SIGINT,signal_callback);
 while((c=getchar())!='\n');
 return 0;
}
当运行该程序时,按CTRL+C,则会调用回调函数。

 五、屏蔽信号
所谓屏蔽, 并不是禁止递送信号, 而是暂时阻塞信号的递送,
解除屏蔽后, 信号将被递送, 不会丢失. 相关API为
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signum);
int sigdelset(sigset_t *set, int signum);
int sigismember(const sigset_t *set, intsignum);//sigismember()用来测试参数signum代表的信号是否已加入至参数set信号集里。如果信号集里已有该信号则返回1,否则返回0。

//信号的屏蔽:

int  sigprocmask(int how,  const  sigset_t *set,sigset_t *oset));

sigprocmask()函数能够根据参数how来实现对信号集的操作,

1)how操作主要有三种:

* SIG_BLOCK 在进程当前阻塞信号集中添加set指向信号集中的信号 mask=mask|set

* SIG_UNBLOCK 如果进程阻塞信号集中包含set指向信号集中的信号,则解除

   对该信号的阻塞 mask=mask & ~set

* SIG_SETMASK 更新进程阻塞信号集为set指向的信号集  mask =set

2)set:如果是非空指针,则更改进程的信号屏蔽字。


3)oset如果是非空指针,则读取进程的当前信号屏蔽字通过oset参数传出。

返回0表示成功,-1表示出差。故可以由: sigemptyset(&s);  sigprocmask(SIG_BLOCK,NULL,&s);//block

由&s传出。

未决信号可以由 int sigpending(sigset_t*set),通过set传递出来。获取未决信号。0表示成功,-1失败

六、信号在内核中的表示:

信号递达(Delivery):执行信号的处理动作。

信号未决(Pending):信号从产生到递达之间的状态。

--》进程可以选择阻塞(Block)某个信号,被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。

 

例子:

#include<sys/types.h>
#include<sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/wait.h>
#include <signal.h>

void signal_callback(int sigNum)
{
 if(sigNum==SIGRTMIN+2)
 {
  //Unblock the signal 1;
  sigset_t tmp;
  sigemptyset(&tmp);
  sigaddset(&tmp,SIGRTMIN+1);
  sigprocmask(SIG_UNBLOCK,&tmp,0);//block

 

//--》进程可以选择阻塞(Block)某个信号,被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。因为刚开始时信号1已经被阻塞,因此这个信号将在未决状态。因此当发送信号1即35时将变成未决状态,当发送信号2即36时,如上将信号1进行解阻塞,就会把刚才的信号1执行递达的动作,因此会显示执行printf("recvsignal %d\n",sigNum);


 }
 if(sigNum==SIGRTMIN+1)
 {
  printf("recv signal%d\n",sigNum);
 }
}

void printfSigSet(sigset_t *tmp)
{
 int i;
 for( i=0;i<=64;i++)
 {
  if(sigismember(tmp,i))
  {
   putchar('1');
  }
  else
  {
   putchar('0');
  }
  if (i==0)
   putchar('\n');

 }
 printf("----------------------------------\n");

}
int main()
{
 sigset_t p;
 sigset_t s;
 signal(SIGRTMIN+1,signal_callback);
 signal(SIGRTMIN+2,signal_callback);

 //block the signal 1;
 sigemptyset(&p);
 sigaddset(&p,SIGRTMIN+1);
 sigprocmask(SIG_BLOCK,&p,0);//block

 while(1)
 {
  //get which signal ispending
  sigemptyset(&s);
  sigpending(&s);
  printf("pendingsignal:\n");
  printfSigSet(&s);    


  ////get which signalis  block
  printf("blocksignal:\n");
  sigemptyset(&s);
  sigprocmask(SIG_BLOCK,0,&s);//block
  printfSigSet(&s);
  sleep(2);
 }

}

 

运行程序时显示:

pending signal:
1
0000000000000000
0000000000000000
0000000000000000
0000000000000000
----------------------------------
block signal:
1
0000000000000000
0000000000000000
0010000000000000
0000000000000000
----------------------------------

 

当终端发送 kill -35 进程号。时,

pending signal:

1
0000000000000000
0000000000000000
0010000000000000
0000000000000000
----------------------------------
block signal:
1
0000000000000000
0000000000000000
0010000000000000
0000000000000000
----------------------------------

当发送 kill -36 给进程时:

recv signal 35
pending signal:
1
0000000000000000
0000000000000000
0000000000000000
0000000000000000
----------------------------------
block signal:
1
0000000000000000
0000000000000000
0010000000000000
0000000000000000
----------------------------------