目录
一、信号量
1、什么是信号
信号是一种异步通信机制,一般情况下,进程什么时候会收到信号、收到什么信号是无法事先预料的(就像你家的门铃,你不知道它什么时候会响,但是门铃响的时候我们可以下楼开门(处理))
2、在linux下,有哪些信号
gec@ubuntu:/mnt/hgfs/GZ2034/09 系统编程/02/code/fifo$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL10) 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) SIGWINCH29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN
例如:
19) SIGSTOP
信号值)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()时,如果到点了,就会自动发出这个信号。 注:alarm为闹钟函数
17) SIGCHLD -> 当子进程退出时,自动发出这个信号给父进程。
2)信号也可以由用户来发送。
如果是由用户来发送,则需要学习 kill / killall 这两个命令。
4、用户如何发送信号给进程?
方法一:
1)首先查看目标进程的PID号。 -> ps -ef
PID号
gec 4630 4310 0 00:30 pts/4 00:00:00 ./a.out
2)通过kill命令发送9号信号给该进程,杀死进程。
kill -9 4630
kill -SIGKILL 4630 或者 kill -KILL 4630
方法二:
直接通过killall命令给进程名字发送信号
killall -9 a.out
killall -SIGKILL a.out 或者 killall -KILL a.out -> 只要名字为a.out,都会收到这个信号。
二、信号的函数接口
1、 如何发送信号给另外一个进程
#include <sys/types.h>
#include <signal.h> -> linux信号的专属头文件
int kill(pid_t pid, int sig);
函数作用:
向指定进程或者进程组,发送一个指定的信号
返回值
成功:0 失败:-1
2、如何捕捉信号
#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 ((__sighandler_t) -1)
注意:
1、所谓的捕捉信号 就是 获取当这个信号来之后,去执行 信号响应函数,原本的信号默认动作就不会执行了。
2、当调用signal 函数之后 ,程序不会阻塞,而是往下面代码执行,但是这个捕捉设置 是 全局有效
3、SIGKILL 、SIGSTOP 不能被捕捉,只能执行默认的动作
例子:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
typedef void (*sighandler_t)(int);
//回调函数 arg是信号的值
void signalHandler(int arg)
{
//没有收到信号,所以这个不会执行
printf("接收到信号!\n");
}
int main(void)
{
sighandler_t fun; //函数指针
//捕获信号,有对应的信号过来,执行回调函数 ,这个是非阻塞函数
fun = signal(SIGINT, signalHandler);
if(fun == SIG_ERR)
{
printf("signal failure\n");
}
while(1)
{
sleep(1);
printf("hello world\n");
}
return 0;
}
结果:
3、发送信号
#include <signal.h>
int raise(int sig);
参数:
sig: 发送的信号。
返回值:
成功:0 失败:非0
代码:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
typedef void (*sighandler_t)(int);
//回调函数 arg是信号的值
void signalHandler(int arg)
{
//没有收到信号,所以这个不会执行
printf("接收到信号!\n");
}
int main(void)
{
sighandler_t fun; //函数指针
//捕获信号,有对应的信号过来,执行回调函数 ,这个是非阻塞函数
fun = signal(SIGINT, signalHandler);
if(fun == SIG_ERR)
{
printf("signal failure\n");
}
while(1)
{
sleep(1);
printf("hello world\n");
//发送信号
raise(SIGINT);
}
return 0;
}
结果: