Linux进程间通信:信号(signal)

目录

信号说明

一 信号发送

① raise函数

② kill函数

③  alarm函数

二 信号接收

while函数:

sleep函数:

pause函数:

 三 信号处理

signal函数


信号说明

在Linux中,①信号可以简单理解为软中断,许多重要的程序都需要处理信号。信号,为 Linux 提供了一种处理异步事件的方法。比如,终端用户输入了 ctrl+c 来中断程序,会通过信号机制停止一个程序。②信号也是进程间通信的一种方式,也是如此,进程才能收到信号指令,完成操作。

kill -l命令:查询系统中的信号

dhw@dhw-virtual-machine:~$ kill -l
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX	

一 信号发送

信号发送函数:kill(),raise(),alarm()

① raise函数

作用:自己给自己发信号

int raise(int sig);

int sig:信号种类的编号

代码示例:

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

int main(void)
{
        printf("raise before\n");
        raise(9);// 9) SIGKILL, 自己中断自己的进程
        printf("raise after\n");//于是这句不打印
        return 0;
}
编译结果:
dhw@dhw-virtual-machine:~/signal$ ./a.out
raise before
已杀死

② kill函数

作用:发送杀死其它进程的信号

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

  int kill(pid_t pid, int sig);
  pid:进程号
  sig:信号的编码

代码示例:和在命令行直接输入kill相关指令是一样的效果 

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

int main(int argc,char **argv)
{
        int pid;//进程号
        int sig;//信号编号
        if(argc < 3){
                printf("kill <pid> <sig>\n");
                return -1;
        }
        pid = atoi(argv[1]);//atoi函数作用:将字符串转换成整型
        sig = atoi(argv[2]);
        kill(pid,sig);

        return 0;
}

③  alarm函数

作用:为传递信号设定一个闹钟,相当于一个定时器,当进程运行到设定好的时间时,该进程就会停止

#include <unistd.h>

unsigned int alarm(unsigned int seconds);
seconds:可以理解为设置多少秒

代码示例:

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

int main(void)
{
        int i=0;
        alarm(6); //闹钟设置6秒,时间到立刻停止运行
        while(1){
                sleep(1);
                i++;
                printf("i=%d\n",i);
        }
        return 0;
}

编译结果:
dhw@dhw-virtual-machine:~/signal$ ./a.out
i=1
i=2
i=3
i=4
i=5
闹钟

二 信号接收

while函数:

sleep函数:

pause函数:

说明:如果要让我们接收信号的进程可以接收到信号,那么这个接收信号的进程就不能停止,否则无法接收到信号。

操作:while(),sleep(),pause()

pause函数:让当前的进程暂停(进入睡眠状态),直到收到信号被信号(signal)所中断,返回值只返回-1.

​#include <unistd.h>
int pause(void);

代码示例:

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

int main()
{
        printf("pause before\n");
        pause();//休眠,进程未停止,等待接收信号
        printf("pause after\n");//于是此处不打印内容
        return 0;
}

 三 信号处理

signal函数

信号处理的三种方式:系统默认,忽略,捕获

  • 忽略信号,大多数信号可以使用这个方式来处理,但是有两种信号不能被忽略(分别是 SIGKILL和SIGSTOP)。因为他们向内核和超级用户提供了进程终止和停止的可靠方法,如果忽略了,那么这个进程就变成了没人能管理的的进程,显然是内核设计者不希望看到的场景。
  • 捕捉信号,需要告诉内核,用户希望如何处理某一种信号,说白了就是写一个信号处理函数,然后将这个函数告诉内核。当该信号产生时,由内核来调用用户自定义的函数,以此来实现某种信号的处理。
  • 系统默认动作,对于每个信号来说,系统都对应由默认的处理动作,当发生了该信号,系统会自动执行。不过,对系统来说,大部分的处理方式都比较粗暴,就是直接杀死该进程。
    具体的信号默认动作可以使用man 7 signal来查看系统的具体定义

signal函数原型看起来有点复杂,简化如下:

 #include <signal.h>

 typedef void (*sighandler_t)(int);

 sighandler_t signal(int signum, sighandler_t handler);
signal(参数1,参数2)

参数1:我们要进行处理的信号,如果是系统的信号我们在命令行中输入kill_l查看;

参数2:处理的方式(默认,忽略,捕获);

① signal(SIGINT,SIG_IGN)—— SIG_IGN:代表忽略,就是忽略SIGINT的信号;

② signal(SIGINT,SIG_DFL)—— SIG_DFL:代表执行系统默认操作,大多数信号的系统默认动作时终止该进程;

③ signal(SIGINT,myfun)—— 捕捉SIGINT这个信号,然后执行myfun函数里的代码,myfun由我们自己定义。

忽略:kill -9才可以杀死进程

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

int main()
{
        signal(SIGINT,SIG_IGN);
        while(1){
                sleep(2);
                printf("hhhhhh!\n");
        }
        return 0;
}

编译结果:
dhw@dhw-virtual-machine:~$ ./a.out
hhhhhh!
hhhhhh!
hhhhhh!
^Chhhhhh!  //使用ctrl+c中断不了
hhhhhh!
^Chhhhhh!

默认:系统默认中断

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

int main()
{
        signal(SIGINT,SIG_DFL);//系统默认 终止
        while(1){
                sleep(2);
                printf("hhhhhh!\n");
        }
        return 0;
}
编译结果:
dhw@dhw-virtual-machine:~$ ./a.out
hhhhhh!
hhhhhh!
hhhhhh!
hhhhhh!
^C        ctrl+c默认终止

捕获:既不会忽略该进程也不会终止该进程,而是捕获到该进程

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

void myfun(int sig)
{
        if(sig == SIGINT){
                printf("kkkkkk");
        }
}
int main()
{
        signal(SIGINT,myfun);
        while(1){
                sleep(2);
                printf("hhhhhh!\n");
        }
        return 0;
}
编译结果:
dhw@dhw-virtual-machine:~$ ./a.out
hhhhhh!
hhhhhh!
^Ckkkkkkhhhhhh! //既没有忽略也没有终止进程,
hhhhhh!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

D.•

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

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

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

打赏作者

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

抵扣说明:

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

余额充值