系统编程03-信号SIGNAL(kill、signal、pause、raise、sigemptyset、sigfillset、sigaddset、sigdelset、sigismember)

这篇博客详细介绍了Linux系统中的信号机制,包括信号的定义、种类、来源以及用户如何发送信号。讨论了信号的处理方式,如忽略、默认动作、捕捉和阻塞,并通过实例展示了如何使用kill、signal、pause等函数进行进程间通信。此外,还涉及到了信号集的概念和处理函数,以及如何利用信号控制开发板上的音乐播放状态。
摘要由CSDN通过智能技术生成

目录

一、进程之间的通信 -- 信号

1.什么是信号

2.在linux下,有哪些信号

3.在linux下,这些信号究竟是由谁来发出?

4.用户如何发送信号给进程?

二、关于信号的函数接口

1.如何发送信号给另外一个进程?  -> kill()  -> man 2 kill

2.如何捕捉信号?  -> signal()  -> man 2 signal

3.挂起进程,直到收到一个信号为止。

4.自己给自己发送信号。  -> raise()

三、在开发板上播放音乐,使用信号控制音乐的状态

1.控制对象

2.如何在开发板上播放音乐?

3、例子

四、信号的处理(除了SIGKILL,SIGSTOP)

1.忽略(将信号丢弃)

2.缺省(默认动作)

3.捕捉(去执行指定的函数)

4.阻塞(信号挂起)

五、linux系统信号集

1.什么是信号集?

2.信号阻塞与信号忽略有什么区别?

六、信号集处理函数

1.信号集如何定义?

2.例题1: 写一个程序,先清空信号集,再把SIGUSR1加入到集合中,判断信号是不是在集合中。

七、如何设置信号集为阻塞状态?  -> sigprocmask()  -> man 2 sigprocmask

作业1

作业2 


一、进程之间的通信 -- 信号

1.什么是信号

信号是一种异步通信机制,一般情况下,进程什么时候会收到信号、收到什么信号是无法事先预料的(就像你家的门铃,你不知道它什么时候会响,但是门铃响的时候我们可以下楼开门(处理))

2.在linux下,有哪些信号

gec@ubuntu:/mnt/hgfs/GZ22229/09系统编程/03/1-code$ 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    
例如:
19) SIGSTOP   //signal  信号
信号值)SIG+信号名字

其实信号的名字与信号值是等价的,它们是宏定义来的,被定义在一个头文件:
/usr/include/asm-generic/signal.h

#define SIGHUP 1
#define SIGINT 2
#define SIGQUIT 3
#define SIGILL 4

3.在linux下,这些信号究竟是由谁来发出?

1)由系统来发出。
14) SIGALRM  -> 当在程序中调用alarm()时,如果到点了,就会自动发出这个信号。
17) SIGCHLD  -> 当子进程退出时,自动发出这个信号给父进程。SIGCHLD = signal child

2)信号也可以由用户来发送。
如果是由用户来发送,则需要学习 kill / killall 这两个命令。

4.用户如何发送信号给进程?

方法一:
1)首先查看目标进程的PID号。  -> ps -ef(或者使用getpid打印自己的进程id号)
   PID号 
gec        4630   4310  0 00:30 pts/4    00:00:00 ./a.out
2)通过kill命令发送9号信号给该进程,杀死进程。(kill -9 杀死进程这个指令很常用)
kill -9 4630
kill -SIGKILL 4630  或者 kill -KILL 4630
说明:kill是给pid值发送信号

方法二:
直接通过killall命令给进程名字发送信号
killall -9 a.out
killall -SIGKILL a.out  或者 killall  -KILL a.out   -> 只要名字为a.out,都会收到这个信号。
说明:killall是给进程名发送信号

练习1:
写一个进程fork之后,父进程一直执行,子进程也一直执行,分别用kill和killall干掉他们。

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

int main(int argc,char **argv)
{
	pid_t id = fork();
	if(id == -1)
	{
		perror("fork fail");
		return -1;
	}
	else if(id > 0)
	{
		while(1)
		{
			//\n的重要性 刷新缓冲区
			printf("[%d]我走上路\n",getpid());
			sleep(1);
		}
	}
	else if(id == 0)
	{
		while(1)
		{	
			printf("[%d]我走中路\n",getpid());
			sleep(1);		
		}	
	}
	
	return 0;
}

二、关于信号的函数接口

1.如何发送信号给另外一个进程?  -> kill()  -> man 2 kill

#include <sys/types.h>
#include <signal.h>    -> linux信号的专属头文件
int kill(pid_t pid, int sig);
函数作用:
    向指定进程或者进程组,发送一个指定的信号
参数:
    pid:进程号
    sig:信号值

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

int main(int argc, char*argv[]) // ./a.out 3445
{
    //获取你要发送的信号的进程的ID号
    int id = atoi(argv[1]);
    //发送信号
    kill(id,SIGINT);
    
    return 0;
}

2.如何捕捉信号?  -> signal()  -> man 2 signal

#include <signal.h>
typedef void (*sighandler_t)(int); //函数指针
sighandler_t signal(int signum, sighandler_t handler);
函数作用:
    捕捉一个指定的信号,即预先为某信号的到来做好准备
参数:
    signum     需要捕捉的信号
    handler    
        SIG_IGN    忽略该信号
        SIG_DFL    执行该信号的默认动作
void (*p)(int)    执行由 p 指向的信号响应函数

返回值:
    成功返回   最近一次调用该函数时第二个参数的值
    失败返回   SIG_ERR (#define SIG_ERR    -1)
注意:
>1.所谓的捕捉信号就是获取当这个信号来之后,去执行信号响应函数,原本的信号默认动作就不会执行了。
>2.当调用signal函数之后 ,程序不会阻塞,而是往下面代码执行,但是这个捕捉设置是全局有效
>3.SIGKILL 、SIGSTOP 不能被捕捉,只能执行默认的动作

例子:
#include<stdio.h>
#include <sys/types.h>
#include <signal.h>

//信号响应函数 ,也就是说signal捕捉到指定的信号之后,去执行这个函数
void signalHandle(int arg)
{
    printf("arg:%d\n",arg);
    printf("signalHandle 听说你想杀死我\n");
}

int main(int argc, char*argv[]) // ./a.out 3445
{
    //捕捉信号SIGINT,去执行信号响应函数
    signal(SIGINT,signalHandle); 

    while(1);

    return 0;
}

说明:函数名本身就是指针

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值