Linux中的signal是一种异步处通信机制,信号类型分为可靠信号和非可靠信号两种。所谓非可靠信号是linux继承unix的编号从1至31号信号,是用作特殊用处;可靠信号即linux中新添加的编号从34至64的信号,此类信号可以用户自定义使用。
由于linux的signal机制也经过了一系列的改造,因此我们就拿现在的signal机制来分析一下signal的使用。
一、信号的发送
信号的产生方式有多种,可能是用户程序使用相关函数进行发送,也可能是用户通过外部输入通知内核来产生信号等等。我们就那用户程序来说明一下用户空间信号的发送。
1)进程中:
int kill(pid_t pid, int sig);
int raise(int sig);
kill函数来给对应的进程发送信号。其中pid参数有三种类型:
pid 大于0时,就是给PID为pid的进程发送sig信号。
Pid 等于0时, 就是给和当前进程在同一进程组的所有进程发送sig信号。
Pid 等于-1时,会给所有有权限发送的进程发送sig信号,除了init进程。
父进程杀死子进程的示例代码:
Pid = fork();
If (pid == 0)
{
Printf(“in the child process\n”);
While (1);
}
else if (pid > 0)
{
Printf(“in the parent process\n”);
Kill(getpid(), SIGKILL);
Wait(NULL);
}
return 0;
raise函数就是进程给自己发送信号。
比如: raise(SIGKILL);就是进程的自杀信号。
2)线程的信号发送
int pthread_kill(pthread_t thread, int sig);
参数pthread_t就是指定要发送的线程标识符,sig就是要送的信号。
如果给线程发送的信号的默认处理方式是终止进程,那么也会导致进程直接退出。
比如:
pthread_t thread1, thread2;
void handler1(void *arg);
void handler2(void*arg);
Int main(int argc, const char*argv[])
{
pthread_create(&thread1, NULL, handler1, NULL);
pthread_create(&thread2, NULL, handler2, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
}
void handler1(void *arg)
{
While (1);
}
void handler2(void *arg)
{
pthread_kill(thread1, SIGKILL);
pthread_exit(0);
}
线程2一旦发送SIGKILL信号,那么会导致整个进程也立刻退出。
二、信号的捕捉处理
常用的信号捕捉处理函数有两个。
1)signal函数
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
参数 signum就是signal函数要捕捉的信号,参数handler就是对捕捉信号的处理函数。
示例代码:让程序在执行过程中不受crtl + C的影响
void handler(int signo)
{
printf(“SIGINT is ignore\n”);
}
Int main()
{
….
signal(SIGINT, handler);
….
}
2) sigaction函数
int sigaction (int signum, const struct sigaction *act, struct sigaction *oldact);
参数signum: 要捕捉的信号
act : 对信号处理的结构体
oldact: 用来保存旧的信号处理方式的结构体
struct 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);
};
igaction函数的功能要比signal函数要强大,但是使用也比较复杂。
示例代码:
void handler(int signo)
{
printf(“SIGINT is ignore\n”);
}
Int main()
{
struct sigaction new, old;
new.sa_handler = handler;
sigemptyset(&new.sa_mask);
new.sa_flags = 0;
sigaction(SIGINT, NULL, &old);
if (old.sa_handler != SIG_IGN)
{
sigaction(SIGINT, &new, NULL);
}
…….
}