kill()函数和raise()函数
kill函数将一个信号发送给一个进程或一个进程组,raise函数则允许一个进程向自身发送。
int kill(pid_t pid,int signo);
int raise(int signo);
参数pid的值 信号的接受进程
pid>0 进程ID为pid的进程
pid=0 同一个进程组的进程
pid<0 进程组ID为-pid的所有进程
pid=-1 除发送进程自身外,所有进程ID都大于1的进程
kill()函数的signo为欲发送的信号值。调用成功返回0,否则返回-1.同时设置errno变量:如果失败的原因是给定的信号无效,errno将被设置为WINVAL;如果是权限不足,errno将被设置为SPERM;如果指定的进程不存在,errno将被设置为ESRCH.
Linux用typedef将该函数原型定义为sighandler_t,其他的Unix系统直接使用函数指针;为了可移植性,不要直接使用sighandler_t
这一类型。
signal也可以指示内核对当前的进程忽略指定的信号或者重新设定为该信号的默认值:
SIG_DEL: 将signo所表示的信号处理设置为默认操作。
SIG_IGN: 忽略signo表示的信号。
例子:
- #include
- #include
-
- static void sig_usr(int);
-
- int main(void){
- if(signal(SIGUSR1,sig_usr) == SIG_ERR){
- perror("signal SIGUSR1");
- return 1;
- }
-
- if(signal(SIGUSR2,sig_usr) == SIG_ERR){
- perror("signal SIGUSR2");
- return 2;
- }
-
- for(;;) pause();
- }
-
- static void sig_usr(int signo){
- if(signo == SIGUSR1)
- printf("receive SIGUSR1\n");
- else if(signo == SIGUSR2)
- printf("receive SIGUSR2\n");
- }
#include
#include static void sig_usr(int);/* one handler for both signals */ int main(void){ if(signal(SIGUSR1,sig_usr) == SIG_ERR){ perror("signal SIGUSR1"); return 1; } if(signal(SIGUSR2,sig_usr) == SIG_ERR){ perror("signal SIGUSR2"); return 2; } for(;;) pause(); } static void sig_usr(int signo){ if(signo == SIGUSR1) printf("receive SIGUSR1\n"); else if(signo == SIGUSR2) printf("receive SIGUSR2\n"); }
当一个程序被执行,它的所有信号的状态都是默认的或者被忽略的。一般,所有的信号都被设置为默认的action,
除非父进程忽略它们。更具体,在exec执行之后,会把原先捕捉的信号设置为默认,其他的不变,因为
被捕获信号的action处理函数可能在新的程序中不在有效。
alarm()函数和pause()函数
alarm函数是专门为SIGALRM信号而设,在指定时间seconds秒后,将向进程本身发送SIGALRM信号。由于每个进程只能有一个闹钟,进程调用alarm函数后任何以前的alarm函数调用都无效。如果参数seconds为0,那么进程内将不在包含任何闹钟。pause函数是用于将调用的进程挂起直至捕捉到信号为止,常用来判断信号是否已到达。
unsigned int alarm(unsigned int seconds)
int pause(void)
int sigemptyset(sigset_t *set):初始化由set指定的信号集,信号集里的所有信号被清空。
int sigfillset(sigset_t *set):调用该函数后set指向的信号集将包含linux支持的64种信号
int sigaddset(sigset_t *set,int signum):在set指向的信号集中加入signum信号
int sigdelset(sigset_t *set,int signum):在set指向的信号集中删去signum信号
int sigismember(const sigset_t *set,int signum):判定信号signum是否在set指向的信号集中。
它们在成功时都返回0,失败都返回-1.并设置errno。
int sigprocmask(int how,const sigset_t *newset,sigset_t *oldset):
how:SIG_BLOCK:在进程当前阻塞信号集中添加set指向信号集中的信号
SIG_UNBLOCK:如果进程阻塞信号集中包含set指向信号集中的信号,则接触堆该信号的阻塞
SIG_SETMASK:更新进程阻塞信号集为set指向的信号集
intsigpending(sigset_t *set);
sigpending函数获得当前已递送到进程,却被阻塞的所有信号。
#include
#include
#include
static void sig_quit(int signo)
{
printf("caught SIGQUIT\n");
if(signal(SIGQUIT,SIG_DFL)==SIG_ERR)
perror("can't reset SIGQUIT");
}
static void sig_int(int signo)
{
printf("caught SIGINT\n");
if(signal(SIGINT,SIG_DFL)==SIG_ERR)
perror("can't reset SIGINT");
}
int main()
{
sigset_t newmask,oldmask,pendmask;
if(signal(SIGQUIT,sig_quit)==SIG_ERR)
perror("can't catch SIGQUIT");
if(signal(SIGINT,sig_int)==SIG_ERR)
perror("can't catch SIGINT");
sigemptyset(&newmask);
sigaddset(&newmask,SIGINT);
sigaddset(&newmask,SIGQUIT);
if(sigprocmask(SIG_BLOCK,&newmask,&oldmask)<0)
perror("SIG_BLOCK error");
sleep(5);
if(sigpending(&pendmask)<0)
perror("sigpending error");
if(sigismember(&pendmask,SIGQUIT))
printf("SIGQUIT pending\n");
if(sigismember(&pendmask,SIGINT))
printf("SIGINT pending\n");
if(sigprocmask(SIG_SETMASK,&oldmask,NULL)<0)
perror("SIG_SETMASK error");
fprintf(stderr,"SIGNAL unblocked\n");
sleep(5);
exit(0);
}
阅读(892) | 评论(0) | 转发(1) |