文章链接:https://codemouse.online/archives/2020-03-23190627
发送信号
-
kill命令
指令格式: kill -signum pid
-
kill 函数
int kill(pid,signum);
pid>0 发给pid进程
pid=0 发给当前进程组的所有进程
pid=-1 发送给所有进程
pid<0 发送给|PID|所对应的组上发送给自己:int kill(getpid(),signum);
-
raise 自举函数
自举信号,会给自己发送一个信号
int raise(int sig); -
sigqueue函数
类似于kill,但是可以传送参数
int sigqueue(pid_t pid, int sig, const union sigval value);
union sigval {
int sival_int;
void *sival_ptr;
}; -
alarm 定时函数
unsigned int alarm(unsigned int seconds);
用法:
signal(SIGALRM,自定义函数);
alarm(2); -
ualarm 定时函数
useconds_t ualarm(useconds_t usecs, useconds_t interval);
useconds为单位,第一个参数为第一次产生时间,第二个参数为间隔产生
-
setitimer 定时器
int getitimer(int which, struct itimerval *curr_value);
int setitimer(int which, const struct itimerval *new_value,
struct itimerval *old_value);
Linux会给进程提供三个定时器
ITIMER_REAL:系统真实的时间来计算,发送的信号是SIGALRM。
ITIMER_VIRTUAL:该进程在用户态下花费的时间来计算,发送的信号是SIGVTALRM。
ITIMER_PROF:该进程在用户态下和内核态下所费的时间来计算,发送的信号是SIGPROFstruct itimerval { struct timeval it_interval; /* next value\*/ struct timeval it_value; /* current value */ }; struct timeval { time_t tv_sec; /* seconds \*/ suseconds_t tv_usec; /* microseconds */ };
安装和捕获信号
-
自定义捕捉函数
signal(signum,handler);
-
忽略信号
signal(signum,SIG_IGN);
-
不可捕捉信号
SIGKILL SIGSTOP 不能够被捕捉
-
sigaction对象
默认sa_flags = 0就使用单参数函数指针,设置SA_SIGINFO就使用多参数函数指针,重点只有这两个。
使用该函数使用此对象
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
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);// 用处不大,不必考究 };
sa_flags可选值:
-
SA_NOCLDSTOP
If signum is SIGCHLD, do not receive notification when child processes stop (i.e., when they receive one of SIGSTOP, SIGTSTP, SIGTTIN, or SIGTTOU) or resume (i.e., they receive SIGCONT)
(see wait(2)). This flag is meaningful only when establishing a handler for SIGCHLD. -
SA_NOCLDWAIT (since Linux 2.6)
If signum is SIGCHLD, do not transform children into zombies when they terminate. See also waitpid(2). This flag is meaningful only when establishing a handler for SIGCHLD, or when
setting that signal’s disposition to SIG_DFL.If the SA_NOCLDWAIT flag is set when establishing a handler for SIGCHLD, POSIX.1 leaves it unspecified whether a SIGCHLD signal is generated when a child process terminates. On Linux,
a SIGCHLD signal is generated in this case; on some other implementations, it is not. -
SA_NODEFER
Do not prevent the signal from being received from within its own signal handler. This flag is meaningful only when establishing a signal handler. SA_NOMASK is an obsolete, nonstan‐
dard synonym for this flag. -
SA_ONSTACK
Call the signal handler on an alternate signal stack provided by sigaltstack(2). If an alternate stack is not available, the default stack will be used. This flag is meaningful only
when establishing a signal handler. -
SA_RESETHAND
Restore the signal action to the default upon entry to the signal handler. This flag is meaningful only when establishing a signal handler. SA_ONESHOT is an obsolete, nonstandard syn‐
onym for this flag. -
SA_RESTART
Provide behavior compatible with BSD signal semantics by making certain system calls restartable across signals. This flag is meaningful only when establishing a signal handler. See
signal(7) for a discussion of system call restarting. -
SA_RESTORER
Not intended for application use. This flag is used by C libraries to indicate that the sa_restorer field contains the address of a “signal trampoline”. See sigreturn(2) for more
details. -
SA_SIGINFO (since Linux 2.2)
The signal handler takes three arguments, not one. In this case, sa_sigaction should be set instead of sa_handler. This flag is meaningful only when establishing a signal handler.
siginfo_t结构体样式:
// 多参数函数指针第二参数的结构体 siginfo_t { int si_signo; /* Signal number */ int si_errno; /* An errno value */ int si_code; /* Signal code */ int si_trapno; /* Trap number that caused hardware-generated signal (unused on most architectures) */ pid_t si_pid; /* Sending process ID */ uid_t si_uid; /* Real user ID of sending process */ int si_status; /* Exit value or signal */ clock_t si_utime; /* User time consumed */ clock_t si_stime; /* System time consumed */ sigval_t si_value; /* Signal value */ int si_int; /* POSIX.1b signal */ void *si_ptr; /* POSIX.1b signal */ int si_overrun; /* Timer overrun count; POSIX.1b timers */ int si_timerid; /* Timer ID; POSIX.1b timers */ void *si_addr; /* Memory location which caused fault */ long si_band; /* Band event (was int in glibc 2.3.2 and earlier) */ int si_fd; /* File descriptor */ short si_addr_lsb; /* Least significant bit of address (since Linux 2.6.32) */ }
-
信号集合函数说明
-
函数调用
int sigemptyset(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); // 判断是否存在集合中
int sigpending(sigset_t *set); //返回未决信号集合
int sigsuspend(const sigset_t *mask); // 阻塞等待,直到遇到该mask集合以外的信号,然后还原之前的信号屏蔽集合
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);// 设置信号屏蔽集合
-
设置信号屏蔽集合
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
how的参数:
SIG_BLOCK :将集合中的信号加入到信号掩码中(信号进来会成为未决信号,暂时不处理)
SIG_UNBLOCK:将集合中的信号从信号掩码中删除
SIG_SETMASK:设置信号的屏蔽集合(直接覆盖操作)
注意
- 信号不能做 时间长的,容易死锁的,线程不安全(malloc)的操作。
- 服务器一定要处理SIGPIPE,SIGINT,SIGCHLD这三个信号。