linux进程 信号处理相关API介绍:
1. 信号产生
int kill(pid_t pid,int sig);
int raise(int sig);
unisigned int alarm(unsigned int seconds);
kill系统调用负责向进程发送信号sig.
如果pid是正数,那么向信号sig被发送到进程pid.
如果pid等于0,那么信号sig被发送到所以和pid进程在同一个进程组的进程
如果pid等于-1,那么信号发给所有的进程表中的进程,除了最大的哪个进程号.
如果pid由于-1,和0一样,只是发送进程组是-pid.
我们用最多的是第一个情况.
int raise(int sig);
unisigned int alarm(unsigned int seconds);
kill系统调用负责向进程发送信号sig.
如果pid是正数,那么向信号sig被发送到进程pid.
如果pid等于0,那么信号sig被发送到所以和pid进程在同一个进程组的进程
如果pid等于-1,那么信号发给所有的进程表中的进程,除了最大的哪个进程号.
如果pid由于-1,和0一样,只是发送进程组是-pid.
我们用最多的是第一个情况.
raise系统调用向自己发送一个sig信号.
alarm函数和时间有点关系了,这个函数可以在seconds秒后向自己发送一个SIGALRM信号.
alarm函数和时间有点关系了,这个函数可以在seconds秒后向自己发送一个SIGALRM信号.
2. 信号操作
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set,int signo);
int sigdelset(sigset_t *set,int signo);
int sigismember(sigset_t *set,int signo);
int sigprocmask(int how,const sigset_t *set,sigset_t *oset);
sigemptyset函数初始化信号集合set,将set设置为空.sigfillset也初始化信号集合,只是将信号集合设置为所有信号的集合.sigaddset将信号signo加入到信号集合之中,sigdelset将信号从信号集合中删除.sigismember查询信号是否在信号集合之中.
sigprocmask是最为关键的一个函数.在使用之前要先设置好信号集合set.这个函数的作用是将指定的信号集合set加入到进程的信号阻塞集合之中去,如果提供了oset那么当前的进程信号阻塞集合将会保存在oset里面.参数how决定函数的操作方式.
SIG_BLOCK:增加一个信号集合到当前进程的阻塞集合之中.
SIG_UNBLOCK:从当前的阻塞集合之中删除一个信号集合.
SIG_SETMASK:将当前的信号集合设置为信号阻塞集合.
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set,int signo);
int sigdelset(sigset_t *set,int signo);
int sigismember(sigset_t *set,int signo);
int sigprocmask(int how,const sigset_t *set,sigset_t *oset);
sigemptyset函数初始化信号集合set,将set设置为空.sigfillset也初始化信号集合,只是将信号集合设置为所有信号的集合.sigaddset将信号signo加入到信号集合之中,sigdelset将信号从信号集合中删除.sigismember查询信号是否在信号集合之中.
sigprocmask是最为关键的一个函数.在使用之前要先设置好信号集合set.这个函数的作用是将指定的信号集合set加入到进程的信号阻塞集合之中去,如果提供了oset那么当前的进程信号阻塞集合将会保存在oset里面.参数how决定函数的操作方式.
SIG_BLOCK:增加一个信号集合到当前进程的阻塞集合之中.
SIG_UNBLOCK:从当前的阻塞集合之中删除一个信号集合.
SIG_SETMASK:将当前的信号集合设置为信号阻塞集合.
3.信号处理
int sigaction(int signo,const struct sigaction *act,
struct sigaction *oact);
struct sigaction {
void (*sa_handler)(int signo);
void (*sa_sigaction)(int siginfo_t *info,void *act);
sigset_t sa_mask;
int sa_flags;
void (*sa_restore)(void);
}
signo很简单就是我们要处理的信号了,可以是任何的合法的信号.有两个信号不能够使用(SIGKILL和SIGSTOP). act包含我们要对这个信号进行如何处理的信息.oact更简单了就是以前对这个函数的处理信息了,主要用来保存信息的,一般用NULL就OK了.
信号结构中 sa_handler是一个函数型指针,这个指针指向一个函数,这个函数有一个参数.这个函数就是我们要进行的信号操作的函数. sa_sigaction,sa_restore和sa_handler差不多的,只是参数不同罢了.这两个元素我们很少使用,就不管了.
sa_flags用来设置信号操作的各个情况.一般设置为0好了.sa_mask我们已经学习过了
在使用的时候我们用sa_handler指向我们的一个信号操作函数,就可以了.sa_handler有两个特殊的值:SIG_DEL和SIG_IGN.SIG_DEL是使用缺省的信号操作函数,而SIG_IGN是使用忽略该信号的操作函数.
struct sigaction *oact);
struct sigaction {
void (*sa_handler)(int signo);
void (*sa_sigaction)(int siginfo_t *info,void *act);
sigset_t sa_mask;
int sa_flags;
void (*sa_restore)(void);
}
signo很简单就是我们要处理的信号了,可以是任何的合法的信号.有两个信号不能够使用(SIGKILL和SIGSTOP). act包含我们要对这个信号进行如何处理的信息.oact更简单了就是以前对这个函数的处理信息了,主要用来保存信息的,一般用NULL就OK了.
信号结构中 sa_handler是一个函数型指针,这个指针指向一个函数,这个函数有一个参数.这个函数就是我们要进行的信号操作的函数. sa_sigaction,sa_restore和sa_handler差不多的,只是参数不同罢了.这两个元素我们很少使用,就不管了.
sa_flags用来设置信号操作的各个情况.一般设置为0好了.sa_mask我们已经学习过了
在使用的时候我们用sa_handler指向我们的一个信号操作函数,就可以了.sa_handler有两个特殊的值:SIG_DEL和SIG_IGN.SIG_DEL是使用缺省的信号操作函数,而SIG_IGN是使用忽略该信号的操作函数.
linux线程 信号处理相关API介绍
信号产生
int pthread_kill(pthread_t thread, int sig);
向指定ID的线程发送sig信号,如果线程代码内不做处理,则按照信号默认的行为影响
整个进程
成功:0
线程不存在:ESRCH
信号不合法:EINVAL
信号处理
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set,int signo);
int sigdelset(sigset_t *set,int signo);
int sigismember(sigset_t *set,int signo);
int pthread_sigmask (int how,
const sigset_t *set,
sigset_t *oset)
用作在主调线程里控制信号掩码。
How:
SIG_BLOCK: 结果集是当前集合参数集的并集
SIG_UNBLOCK: 结果集是当前集合参数集的差集
SIG_SETMASK: 结果集是由参数集指向的集
提示: 除非信号在所有的线程里都阻塞,否则总能将异步信号传输给这个进程。
int sigwait(const sigset_t *restrict set, int *restrict signop);
Returns: 0 if OK, error number on failure
sigwait的作用是:挂起进程,对于参数指向的sigset_t里的信号进行监测。如果所监视的信号被阻塞,则它把阻塞信号从挂起信号集中删除,解除对它的阻塞,然后返回。也就是它监测的进程必须是先进行阻塞处理的,它才监测到并且对信号进行解除阻塞。。挂起信号集是系统记录被阻塞的信号的数据结构。
总之:sigwait监测参数指向的sigset_t里的信号一旦有信号属于它且被阻塞,则它解除信号的阻塞,然后返回。
相关实例介绍
#include
#include
#include
#include
#include
#include
#include
void sig_handler(int signum)
{
static int j = 0;
static int k = 0;
pthread_t sig_ppid = pthread_self();
// used to show which thread the signal is handled in.
if (signum == SIGUSR1) {
printf("thread %d, receive SIGUSR1[%d] No. %d\n", sig_ppid,signum, j);
j++;
//SIGRTMIN should not be considered constants from userland,
//there is compile error when use switch case
} else if (signum == SIGRTMIN) {
printf("thread %d, receive SIGRTMIN[%d] No. %d\n", sig_ppid,signum, k);
k++;
}
}
void* worker_thread()
{
pthread_t ppid = pthread_self();
pthread_detach(ppid);
while (1) {
// printf("I'm thread %d, I'm alive\n", ppid);
sleep(10);
}
}
void* sigmgr_thread()
{
sigset_t waitset, oset;
siginfo_t info;
int rc;
pthread_t ppid = pthread_self();
pthread_detach(ppid);
sigemptyset(&waitset);
sigaddset(&waitset, SIGRTMIN);
sigaddset(&waitset, SIGUSR1);
#if 1
while (1)
{
rc = sigwaitinfo(&waitset, &info);
if (rc != -1)
{
printf("sigwaitinfo() fetch the signal - %d\n", rc);
sig_handler(info.si_signo);
}
else
{
// printf("sigwaitinfo() returned err: %d; %m\n", errno);
printf("sigwaitinfo() returned err: %d; %s\n", errno,strerror(errno));
}
}
#endif
while(1);
}
int main()
{
sigset_t bset, oset;
int i = 0;
pid_t pid = getpid();
pthread_t ppid[5],mpid;
#if 0
//block SIGUSR1
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
sigprocmask(SIG_BLOCK, &set, NULL);
#endif
#if 1
// Block SIGRTMIN and SIGUSR1 which will be handled in
//dedicated thread sigmgr_thread()
// Newly created threads will inherit the pthread mask from its creator
sigemptyset(&bset);
sigaddset(&bset, SIGRTMIN);
sigaddset(&bset, SIGUSR1);
if (pthread_sigmask(SIG_BLOCK, &bset, &oset) != 0)
printf("!! Set pthread mask failed\n");
// Create the dedicated thread sigmgr_thread() which will handle
// SIGUSR1 and SIGRTMIN synchronously
#endif
pthread_create(&mpid, NULL, sigmgr_thread, NULL);
// Create 5 worker threads, which will inherit the thread mask of
// the creator main thread
for (i = 0; i < 5; i++) {
pthread_create(&ppid, NULL, worker_thread, NULL);
}
// send out 50 SIGUSR1 and SIGRTMIN signals
for (i = 0; i < 50; i++) {
// kill(pid, SIGUSR1);
pthread_kill(mpid, SIGUSR1);
// printf("main thread, send SIGUSR1 No. %d\n", i);
// kill(pid, SIGRTMIN);
pthread_kill(mpid, SIGRTMIN);
// printf("main thread, send SIGRTMIN No. %d\n", i);
sleep(10);
}
exit (0);
}
Returns: 0 if OK, error number on failure
sigwait的作用是:挂起进程,对于参数指向的sigset_t里的信号进行监测。如果所监视的信号被阻塞,则它把阻塞信号从挂起信号集中删除,解除对它的阻塞,然后返回。也就是它监测的进程必须是先进行阻塞处理的,它才监测到并且对信号进行解除阻塞。。挂起信号集是系统记录被阻塞的信号的数据结构。
总之:sigwait监测参数指向的sigset_t里的信号一旦有信号属于它且被阻塞,则它解除信号的阻塞,然后返回。
相关实例介绍
#include
#include
#include
#include
#include
#include
#include
void sig_handler(int signum)
{
static int j = 0;
static int k = 0;
pthread_t sig_ppid = pthread_self();
// used to show which thread the signal is handled in.
if (signum == SIGUSR1) {
printf("thread %d, receive SIGUSR1[%d] No. %d\n", sig_ppid,signum, j);
j++;
//SIGRTMIN should not be considered constants from userland,
//there is compile error when use switch case
} else if (signum == SIGRTMIN) {
printf("thread %d, receive SIGRTMIN[%d] No. %d\n", sig_ppid,signum, k);
k++;
}
}
void* worker_thread()
{
pthread_t ppid = pthread_self();
pthread_detach(ppid);
while (1) {
// printf("I'm thread %d, I'm alive\n", ppid);
sleep(10);
}
}
void* sigmgr_thread()
{
sigset_t waitset, oset;
siginfo_t info;
int rc;
pthread_t ppid = pthread_self();
pthread_detach(ppid);
sigemptyset(&waitset);
sigaddset(&waitset, SIGRTMIN);
sigaddset(&waitset, SIGUSR1);
#if 1
while (1)
{
rc = sigwaitinfo(&waitset, &info);
if (rc != -1)
{
printf("sigwaitinfo() fetch the signal - %d\n", rc);
sig_handler(info.si_signo);
}
else
{
// printf("sigwaitinfo() returned err: %d; %m\n", errno);
printf("sigwaitinfo() returned err: %d; %s\n", errno,strerror(errno));
}
}
#endif
while(1);
}
int main()
{
sigset_t bset, oset;
int i = 0;
pid_t pid = getpid();
pthread_t ppid[5],mpid;
#if 0
//block SIGUSR1
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
sigprocmask(SIG_BLOCK, &set, NULL);
#endif
#if 1
// Block SIGRTMIN and SIGUSR1 which will be handled in
//dedicated thread sigmgr_thread()
// Newly created threads will inherit the pthread mask from its creator
sigemptyset(&bset);
sigaddset(&bset, SIGRTMIN);
sigaddset(&bset, SIGUSR1);
if (pthread_sigmask(SIG_BLOCK, &bset, &oset) != 0)
printf("!! Set pthread mask failed\n");
// Create the dedicated thread sigmgr_thread() which will handle
// SIGUSR1 and SIGRTMIN synchronously
#endif
pthread_create(&mpid, NULL, sigmgr_thread, NULL);
// Create 5 worker threads, which will inherit the thread mask of
// the creator main thread
for (i = 0; i < 5; i++) {
pthread_create(&ppid, NULL, worker_thread, NULL);
}
// send out 50 SIGUSR1 and SIGRTMIN signals
for (i = 0; i < 50; i++) {
// kill(pid, SIGUSR1);
pthread_kill(mpid, SIGUSR1);
// printf("main thread, send SIGUSR1 No. %d\n", i);
// kill(pid, SIGRTMIN);
pthread_kill(mpid, SIGRTMIN);
// printf("main thread, send SIGRTMIN No. %d\n", i);
sleep(10);
}
exit (0);
}