linux信号机制基础

通过本文你会了解到:
1. 信号机制简介
2. 信号处理函数( signal/sigaction/kill)

信号机制简介
信号机制就是进程间相互传递消息的机制,又称做软中断信号。就像电话一样,你不能确定什么时候有人打电话,随时随地发生。linux系统中处理信号有一下几种方式:

  • Term - 终止进程
  • Ign - 忽略该信号
  • Core - 终止该进程并保存内存信息
  • Stop - 停止进程
  • Cont - 恢复已停止的进程

除了上述的5种处理,用户还可以自定义处理函数。

信号处理函数
那么在linux中应用什么函数来实现对信号进行处理呢,接下来我们一起来学习几个常用函数:

signal函数 – 为信号设置处理方法 – 早期linux版本使用,知道怎么用就可以了,在编程时还是不要用这么老的函数了。

#include <signal.h>

typedef void (*sighandler_t)(int);
sighandler_t signalint signum, sighandler_t handler);

signum - 信号值
handler - 可以为自定义的信号处理函数,也可以是SIG_IGN(忽略该信号)和SIG_DEL(信号默认处理)。

下面以大家最熟悉的ctrl-c(终止进程)为例,根据handler取值不同给出实例(终于可以上代码了,窃喜):

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void signal_handler(int signo)
{
    switch(signo) {
        case SIGINT:
            printf("handle SIGINT by user\n");
            break;
        default:
            break;
    }

}

int main(int argc, char **argv)
{
    printf("ctr-c will be handled by user, enter to continue..\n");
    signal(SIGINT, signal_handler);
    getchar();

    printf("ctr-c will be ignore, enter to continue..\n");
    signal(SIGINT, SIG_IGN);
    getchar();

    printf("ctr-c will handle by default, enter to continue..\n");
    signal(SIGINT, SIG_DFL);
    getchar();

    printf("thanks, bye!\n");

    return 0;
}

运行测试:

$ ./signal
ctr-c will be handled by user, enter to continue..
^Chandle SIGINT by user // 信号被自定义函数获取
^Chandle SIGINT by user // 信号被自定义函数获取

ctr-c will be ignore, enter to continue..
^C^C // 信号被忽略
ctr-c will handle by default, enter to continue..
^C // 默认操作,终止进程

sigaction函数 - 为信号设置处理方法

#include <signal.h>

int sigaction(int signum, const struct sigaction *act,
                     struct sigaction *oldact);

signum - 信号值
act - sigaction结构体,指定当前信号的处理信息
oldact - sigaction结构体,返回信号之前的处理信息
要了解后两个参数的作用必须要了解sigaction结构体的构成:

struct sigaction {
    void     (*sa_handler)(int);
    void     (*sa_sigaction)(int, siginfo_t *, void *);
    sigset_t   sa_mask;
    int        sa_flags;
    void     (*sa_restorer)(void);
};

sa_handler - 与signal函数中的处理函数作用相同,可以为用户自定义的处理函数,也可以为SIG_IGNSIG_DFL
sa_sigaction - 信号的另一个处理函数,当sa_flags含有SA_SIGINFO时,应用此处理函数。此函数可以提供信号的更过信息。
sa_mask - 指定在信号处理函数运行期间需要屏蔽的信号。屏蔽的信号会被阻塞直到处理函数结束。
sa_flags - 指定信号的处理行为,可以为0SA_NOCLDSTOP/A_NOCLDSTOP等,具体参考man 7 signal
sa_restorer - 暂为使用,保留。

sigaction的使用也时比较复杂的,后续会结合具体实例做分析,先给一个简单的例子,完成与signal实例同样的功能:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void signal_handler(int signo)
{
    switch(signo) {
        case SIGINT:
            printf("handle SIGINT by user\n");
            break;
        default:
            break;
    }

}

int main(int argc, char **argv)
{
    struct sigaction act;

    printf("ctr-c will be handled by user, enter to continue..\n");
    act.sa_flags = 0;
    act.sa_handler = signal_handler;
    sigaction(SIGINT, &act, NULL);
    getchar();

    printf("ctr-c will be ignore, enter to continue..\n");
    act.sa_flags = 0;
    act.sa_handler = SIG_IGN;
    sigaction(SIGINT, &act, NULL);
    getchar();

    printf("ctr-c will handle by default, enter to continue..\n");
    act.sa_flags = 0;
    act.sa_handler = SIG_DFL;
    signal(SIGINT, SIG_DFL);
    getchar();

    printf("thanks, bye!\n");

    return 0;
}

运行测试:

$ ./sigaction 
ctr-c will be handled by user, enter to continue..
^Chandle SIGINT by user // 信号被自定义函数获取,此处与signal行为不同,getchar函数被中断
ctr-c will be ignore, enter to continue..
^C^C^C // 信号被忽略
ctr-c will handle by default, enter to continue..
^C // 默认处理,终端程序

信号发送函数

#include <sys/types.h>
#include <signal.h>

int kill(pid_t pid, int sig);

pid:可能选择有以下四种
1. pid大于零时,将信号发送给进程ID为pid的进程。
2. pid等于零时,信号将送往所有与调用kill()的那个进程属同一个使用组的进程。
3. pid等于-1时,信号将送往所有调用进程有权给其发送信号的进程,除了进程1(init)。
4. pid小于-1时,信号将送往以-pid为组标识的进程。

sig:信号值,若为0则不发送任何信号。

kill函数的使用实例:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void signal_handler(int signo)
{
    switch(signo) {
        case SIGUSR1:
            printf("get signal -- SIGUSR1\n");
            break;
        default:
            break;
    }

}

int main(int argc, char **argv)
{
    pid_t pid;
    struct sigaction act;

    act.sa_flags = 0;
    act.sa_handler = signal_handler;
    sigaction(SIGUSR1, &act, NULL);

    pid = getpid();

    printf("send SIGUSR1 to curent process\n");
    kill(pid, SIGUSR1);

    getchar();

    printf("thanks, bye!\n");

    return 0;
}

运行测试:

$ ./kill 
send SIGUSR1 to curent process
get signal -- SIGUSR1

thanks, bye!

本文代码实例github地址:
https://github.com/zsirkg/myWorks/tree/master/signal

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值