Unix 下信号相关知识(Signal, kill)

1. 文章参考APUE第10章

kill在*nux族中主要代表两类,一是在函数内部调用的kill函数,用于给其他进程发送signal。
函数原型 int kill(pid_t pid, int sig);)

二是在Shell执行的kill命令,用于给后台进程发送信号。(参考这里

至于9是什么,在*unix中,signal是一组整数。
参考这个头文件

例如:

#define SIGKILL		 9
#define SIGUSR1		10
#define SIGUSR2		12
#define SIGSTOP		19

上面代码展示的几个值是比较关键的。我们继续来谈。

聊完了kill, 就有必要知道程序是怎么处理信号的,因为是特别篇所以我懒得讲到中断什么的。。这里就讲一下怎么用signal覆盖或者无视中断。

程序调用signal()函数来自定义对信号的处理,他的原型是: void (*signal(int signo, void (*func)(int)))(int);

这个原型比较复杂,推荐把他看懂。 (看不懂参考这里

简单介绍一下。 首先我们看到 signal, 他的左边是(),右边是*, 说明他是一个返回*号的函数,参数是()里面的东西。

然后跳出 signal所在的括号看,void ()(int) 眼熟么,就像void (*p) (int) ,这是一个指向函数的指针,函数的参数是int。如此以来,signal返回的是一个指向函数的指针

说明signal返回的是一个函数指针,然后在看signal(这里),是 int signo, void(*func)(int) 眼熟么,第一个参数是int, 第二个参数是函数指针。

当然这是自我折腾的函数声明,其实人民也会这样定义它。

typedef void Signalfunc(int);

Signalfunc * signal(int, Signalfunc *);

好了,这回还看不懂。。。就去多读书孩子。。

说了那么多,signal可以做几件事情,我们关心的有:

1. 屏蔽对一些信号的响应,传入 Signalfunc = SIG_IGN

一般来说,SIG_IGN 的定义是: #define SIG_IGN (void (*)()) 1,我暂时没有找到他在头文件里的定义,有兴趣可以找找。

2. 修改对一些信号的响应,自己定义一个Signalfunc函数,传到signal接口里就行了。

要注意的事情是,参数 SIGKILL 和 SIGSTOP 不能覆盖或者屏蔽。

最后贴一段代码,测试signal函数

#include 
#include 

static void sig_usr(int);

int main()
{
    if (signal(SIGUSR1, sig_usr) == SIG_ERR)
        printf("can't catch SIGUSR1\n");
    if (signal(SIGUSR2, sig_usr) == SIG_ERR)
        printf("can't catch SIGUSR2\n");

    for (;;)
        sleep(1);
}

static void sig_usr(int signo)
{
    if (signo == SIGUSR1)
        printf("recevied SIGUSR1\n");
    else 
        if (signo = SIGUSR2)
            printf("recevied SIGUSR2\n");
        else
            printf("recevied signal %d\n", signo);
}

下班了,准备出趟门,对了SIGUSR1和SIGUSR2是系统默认给用户自定义的。

测试这个函数的方法是:
mattchen@ooxx:~/code/signal$ ./a.out &
[1] 15781
mattchen@ooxx:~/code/signal$ kill -USR1 15781
recevied SIGUSR1
mattchen@ooxx:~/code/signal$ kill -USR2 15781
recevied SIGUSR2
mattchen@ooxx:~/code/signal$ kill -9 15781

此条目发表在C, C++, Linux, 系统, 编程分类目录,贴了, , 标签。将固定链接加入收藏夹。

发表评论

邮箱地址不会被公开。 必填项已用*标注