unix_c--信号学习

什么是信号?

信号—-signal也, 当进程收到信号后,会根据不同的信号给出不同的回应。
当信号传输给了程序,程序会先作出判断,响应它,或在忽略它。
响应:如果进程没有设置响应的handler函数,则会使用默认的
忽略:忽略信号,信号并不会消失,依然会始终在那,当忽略信号的机制消失时,依然会传给进程

signal

用来注册指定信号的行为。

1
2
3
4
#include <signal.h>

typedef void ( *sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

说明:
注册行为就是修改当进程接受到信号之后所作出的默认响应。
以ctrl+c 也就是SIGINT来说,当进程收到这个信号,默认是直接终止程序,
但是可以更改,所以可以发现,有的程序即使按ctrl+c也不能直接退出。
当然,更多的时候不能退出是由于系统来不及响应ctrl+c造成的。
sighandler是函数指针,这个函数的返回值也是返回函数指针值

kill

给指定pid的进程发送信号

1
2
3
#include <signal.h>

int kill(pid_t pid, int sig);

说明:
pid > 0 时 给指定的进程发送信号
pid == 0 时,给当前进程组的所有进程发送信号
pid == -1时,给所有pid > 1的进程发送信号
pid < 0 时,给所有属于pid绝对值进程组的进程发送信号

###alarm
指定时间用来发 SIGALRM 信号给自己

1
2
3
#include <signal.h>

unsigned int alarm(unsigned int seconds);

sigprocmask

设置信号的屏蔽字,指定屏蔽那些信号

1
2
3
#include <signal.h>

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

说明:
sigset_t 是一个结构体,有64位,每一位用来表示一个信号屏蔽状态
不能简单的用一个long来表示,因为32和64位long的大小是不一样的
对于sigset_t有特定的函数来修改它的值

1
2
3
4
5
6
7
8
9
10
11
#include <siganl.h>

int sigempty(sigset_t *set);

int sigfillset(sigset_t *set);

int sigaddset(sigset_t *set, int signum);

int sigdelset(sigset_t *set, int signum);

int sigismember(const sigset_t *set, int signum);

sigempty 把set结构体里面所有的屏蔽状态取消
sigfillset 把set结构体里面的所有信号都设置屏蔽
sigaddset 把set结构体里对应的signum信号设置屏蔽
sigdelset 把set结构体里对应的signum信号取消屏蔽
sigismember 判断set结构体里对应的signum信号是否为屏蔽状态

sigpending

用来查看哪些信号发送过来并且被屏蔽了。

1
2
3
#include <signal.h>

int sigpending(sigset_t *set);

当使用sigprocmask屏蔽掉某些信号之后,当信号发送过来,被屏蔽时,
使用sigpending就能找出哪些信号目前被屏蔽了
同时于sigismember函数配合使用就能一一查看哪些信号被屏蔽了

sigsuspend

临时改变屏蔽字,始程序处于挂起状态

1
2
3
#include <signal.h>

int sigsuspend(const sigset_t *mask);

用法主要有两种:
1 当设置了信号的屏蔽字之后,信号并不会消失,进程只是暂时不会理会这个
信号,当屏蔽字取消之后,信号就会直接发送给进程,所以呢,常常用一个
pause函数来接受这个信号。但是当屏蔽字取消之后,可能pause函数还没来的
及执行,信号就已经发送过来,这样系统就会处理这个信号,当处理完这个信号
之后,再执行pasue函数,进程就可能陷入无限的挂起当中。。。。
所以需要sigsupend函数来把还原屏蔽字和pause来封装成一个原子操作

sigaction

和signal一样,用来改变处理信号的默认方式。

1
2
3
4
#include <signal.h>

int sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact)
;

说明:
signum用来指定进程号
act用来指定新的动作,oldact用来来保存原来的动作
struct sigaction 的结构体如下

1
2
3
4
5
6
7
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};

sa_handler和sa_sigaction 都是用来指定信号的处理方式
只有使用了SA_SIGINFO标志的时候才使用sa_sigaction这个来处理信号

sigqueue

类似kill用来给指定pid的进程发送信号,但是可以发送更多信息

1
2
3
#include <signal.h>

int sigqueue(pid_t pid, int sig, const union sigval value);
Contents
  1. 1. 什么是信号?
  2. 2. signal
  3. 3. kill
  4. 4. sigprocmask
  5. 5. sigpending
  6. 6. sigsuspend
  7. 7. sigaction
  8. 8. sigqueue
,