进程间通信之信号signal

信号是进程间通信机制中唯一的异步通信机制。也就是说进程是不知道什么时候会收到其他进程发来的信号而进行相应的处理。提到信号,不能不提到的就是中断。信号全称为软信号中断,或软中断。进程到在收到信号后会有相应的反应:

  • 1.捕获信号。类似于中断处理函数,进程在收到指定信号后,会调用之前注册的信号处理函数。例如signal(3, sigroutine)就是说进程先绑定下信号值为3的信号处理函数,当进程收到信号值为3的信号后,中断正在运行的代码而执行一次函数sigroutine。
  • 2.忽略信号。就是收到指定信号后什么都不做。类似于signal(3, SIG_IGN)。
  • 3.默认操作。如果没有指定信号处理函数,收到信号后按照默认的函数执行动作,类似于signal(3, SIG_DFL)。
    下面以一段代码为例演示信号的使用方法:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
int g_step = 0;
void sig(int num)
{
    /* Actually I can do anything according to num */
    printf("Signal num=%d catched! ", num);
    printf("You can kill me with \"kill -9 %d\"\n", getpid());
    g_step = 0;
    return;
}
int main()
{
    int signum;
    for(signum = 1; signum <= 64; signum++)
    {
        if(signal(signum, sig) == SIG_ERR)
        {
            printf("cannot set handler for signal %d: %s\n", signum, strerror(errno));
        }
        else
        {
            printf("set handler for signal %d OK.\n", signum);
        }
    }
    printf("My pid:%d. I have started to count:\n", getpid());
    while(1)
    {
        printf("%d.", g_step++);
        fflush(stdout);
        sleep(1);
    }
    return 0;
}

程序开始运行后先给所有的信号值绑定下同一个信号处理函数sig,注意,实际上信号值为9(SIGKILL)和信号值为19(SIGSTOP)的信号是不能重新绑定信号处理函数的,否则恶意进程就不用担心被根用户的kill命令杀死,而可以肆意破坏了。
在使用signal设置信号处理函数时,如果出错会返回SIG_ERR,在上述代码中我们会打印出具体错误的原因。
然后进程就开始数秒。异步地,如果进程收到某个信号,就会中断数秒的工作,执行一次信号处理函数sig。我们在信号处理函数中将全局变量g_step重置为0,让进程从中断返回后从头开始数秒,以此演示信号处理函数和主函数的变量传递。
另外还要说明的是信号处理函数其实可以根据实际捕获的信号值进行不同的操作,这里我只是将信号值打印出来而已。
下面来看下实际运行效果:

set handler for signal 1 OK.
set handler for signal 2 OK.
set handler for signal 3 OK.
set handler for signal 4 OK.
set handler for signal 5 OK.
set handler for signal 6 OK.
set handler for signal 7 OK.
set handler for signal 8 OK.
cannot set handler for signal 9: Invalid argument
set handler for signal 10 OK.
set handler for signal 11 OK.
set handler for signal 12 OK.
set handler for signal 13 OK.
set handler for signal 14 OK.
set handler for signal 15 OK.
set handler for signal 16 OK.
set handler for signal 17 OK.
set handler for signal 18 OK.
cannot set handler for signal 19: Invalid argument
set handler for signal 20 OK.
set handler for signal 21 OK.
set handler for signal 22 OK.
set handler for signal 23 OK.
set handler for signal 24 OK.
set handler for signal 25 OK.
set handler for signal 26 OK.
set handler for signal 27 OK.
set handler for signal 28 OK.
set handler for signal 29 OK.
set handler for signal 30 OK.
set handler for signal 31 OK.
cannot set handler for signal 32: Invalid argument
cannot set handler for signal 33: Invalid argument
set handler for signal 34 OK.
set handler for signal 35 OK.
set handler for signal 36 OK.
set handler for signal 37 OK.
set handler for signal 38 OK.
set handler for signal 39 OK.
set handler for signal 40 OK.
set handler for signal 41 OK.
set handler for signal 42 OK.
set handler for signal 43 OK.
set handler for signal 44 OK.
set handler for signal 45 OK.
set handler for signal 46 OK.
set handler for signal 47 OK.
set handler for signal 48 OK.
set handler for signal 49 OK.
set handler for signal 50 OK.
set handler for signal 51 OK.
set handler for signal 52 OK.
set handler for signal 53 OK.
set handler for signal 54 OK.
set handler for signal 55 OK.
set handler for signal 56 OK.
set handler for signal 57 OK.
set handler for signal 58 OK.
set handler for signal 59 OK.
set handler for signal 60 OK.
set handler for signal 61 OK.
set handler for signal 62 OK.
set handler for signal 63 OK.
set handler for signal 64 OK.
My pid:4428. I have started to count:
0.1.2.3.4.^CSignal num=2 catched! You can kill me with "kill -9 4428"
0.1.2.3.^\Signal num=3 catched! You can kill me with "kill -9 4428"
0.1.2.3.4.5.6.7.8.^ZSignal num=20 catched! You can kill me with "kill -9 4428"
0.1.2.3.4.5.6.7.8.9.Signal num=60 catched! You can kill me with "kill -9 4428"
0.1.2.3.4.5.6.7.8.9.10.11.Killed

可以看到9号,19号,32号,33号信号果然是不能重新指定信号处理函数的,原因是signal不接受这几个参数(参数错误)。
进程打印出自己的进程号后开始数秒。
第一行数字4后我按下了Ctrl加C组合键,进程收到了信号2(SIGINT)。
第二行数字3后我按下了Ctrl加\组合键,进程收到了信号3(SIGQUIT)。
第三行数字8后我按下了Ctrl加Z组合键,进程收到了信号20(SIGTSTP)。
第四行时,从其他终端运行命令“kill -60 4428”即向4428号进程发送60号信号。这个进程在数到9时,响应了这个信号中断,并执行了信号处理函数,然后回到主函数中继续数数。
最后一行时,从其他终端运行命令“kill -9 4428”即向4428号进程发送SIGKILL信号,然后这个进程就被kill掉了。
其实也可以通过kill -2 4428向4428号进程发送SIGINT信号。

最后列举下有关信号的若干函数名:
设置信号处理函数的2个函数:信号安装函数

  • signal
  • sigaction

信号发送函数.

  • kill:给指定pid发送指定信号
  • raise:给自己发送指定信号
  • alarm:给自己SIGALRM信号
  • settimer:给自己发送有关timer的3种信号

信号集操作函数.

  • sigemptyset
  • sigfillset
  • sigaddset
  • sigdelset
  • sigismember
  • sigprocmask
  • sigpending

还有几个关于信号的特殊函数:

  • sigsuspend:屏蔽指定信号集并暂停
  • sigpause:暂停,等待任意信号
  • pause:暂停,等待任意信号
  • sleep:暂停,直到进程被信号唤醒或者到达睡眠时间
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yilonglucky

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值