信号量处理有关的函数和数据结构

xiaoxiao2021-02-28  25

1 kill和raise函数

#include<signal.h> int kill(pid_t pid,int signo);//pid>0 将信号发送给进程ID==PID的进程 //pid==0 讲信号发送给其进程组ID等于发送进程的进程组ID的进程组

kill函数将信号量发送给进程或者进程组,raise函数允许进程向自身发送信号,我们常在终端下杀死一个进程使用kill -9 [pid],这实际上是调用了kill函数给[pid]发送了一个SIGKILL信号量,并且这个信号量不能捕捉,不能忽略,也就是[pid]这个进程收到这个信号就必须得死,如果权限足够的情况下。

2 alrm和pause函数

unsigned int alrm(unsigned int seconds); int pause(void);

alrm函数设定一个时间值,比如alarm(5),五秒之后将会产生SIGALRM信号,如果不捕捉这个信号,当前进程将会终止。

int main() { signal(SIGALRM,fun);//注册了捕捉函数后,闹钟时间到进入处理函数,如果注释掉这句,闹钟时间到会终止当前进程 alarm(5); while(1); } void fun(int signo) { cout<<"收到了alarm信号"<<endl; }

pause函数使调用进程挂起,直到捕捉到一个信号,只有执行了一个信号处理程序并从其返回时,pause才返回,这种情况下pause返回-1;

int main() { signal(SIGALRM,fun_sigint); cout<<"pause在等待信号处理程序"<<endl; alarm(5); pause();//进程会阻塞在这里,直到fun函数返回 cout<<"pause函数返回了"<<endl; while(1); } void fun(int signo) { cout<<"收到了alarm信号"<<endl; }

3 信号集

这是一个数据结构,这个数据结构中保存了很多信号

sigset_t set; int sigemptyset(sigset_t *set);//清空当前信号集合 int sigaddset(sigset_t *set,int signo);//将信号量signo添加到信号集中 int sigismember(const sigset_t *set,int signo);//信号signo在信号集返回1,否则返回0

4 sigprocmask函数

int sigprocmask(int how,const sigset_t *set,sigset_t *oset); //set是一个信号集,根据前边的how决定如何处理这个集中的信号(屏蔽set中的信号,解除屏蔽),oset返回一个集合,这个集合记录了当前进程屏蔽了哪些信号,关于how: //SIG_BLOCK :屏蔽set信号集中所有的信号 //SIG_UNBLOCK :该进程新的屏蔽字是当前的屏蔽字和set指向的信号的交集 //SIG_SETMASK :该进程新的信号屏蔽字是set指向的值 int main() { sigset_t set; sigemptyset(&set);//清空set sigaddset(&set,SIGINT);//将ctrl+c添加到set中 sigprocmask(SIG_BLOCK,&set,NULL);//屏蔽此信号集中的信号 while(1); }

运行以上代码,在终端ctrl+c,当前进程就不会退出了。杀掉此进程的方法是:kill -9 [pid]; 或者:

int main() { kill(10314,9);//10314是要杀死的进程的pid. }

5 sigpending函数

int sigpending(sigset_t *set);//返回当前进程被阻塞不能传递的信号集,通过set(传指针)返回,成功函数返回0,出错返回-1.

6 sigaction函数

我们先来看看sigaction这个结构体:

struct sigation { void (*sa_handler)();//信号处理函数 sigset_set sa_mask;//屏蔽字 int sa_flags; } //sigation函数 int sigaction(int sigo,const struct sigaction *act,struct sigaction *oact);

这个我们可以理解为高级版的signal函数,可以修改其屏蔽字,处理函数。

int main() { struct sigaction action; action.sa_handler=fun_sigint;//设置信号处理函数 action.sa_flags=0; sigemptyset(&action.sa_mask);//清空屏蔽字 sigaddset(&action.sa_mask,SIGINT);//添加SIGINT到屏蔽字中 sigprocmask(SIG_BLOCK,&action.sa_mask,NULL);//屏蔽屏蔽集中的信号 sigaction(SIGQUIT,&action,NULL);//捕捉SIGQUIT信号 while(1); } void fun_sigint(int signo) { cout<<"SIGQUIT"<<endl; }

7 sigsetjmp和siglongjmp函数

类似与setjmp和longjmp,遇到longjmp直接跳转回到setjmp处,适用于函数间的跳转,只不过这里是从信号处理函数中直接跳转到上一个函数中设置sigsetjmp处。例如:

void func1() { signal(SIGINT,sigfunc); //1 sigsetjmp(buf,savemask);<<<------------------ //2 | } | int sigfunc(int sigo) | { | ...//信号处理函数 | siglongjmp(buf,val);---------------------->>> //这后边的代码都不会执行了 }

8sigsuspend函数

int sigsuspend(const sigset_t *sigmask); //屏蔽sigmask中的信号量,并且阻塞,直到从任何一个信号处理函数返回 int main() { sigset_t set; signal(SIGQUIT,fun_sigint); sigemptyset(&set); sigaddset(&set,SIGINT); sigsuspend(&set);//阻塞,并且屏蔽掉SIGINT信号 while(1); } void fun_sigint(int signo) { cout<<"进入了处理函数"<<endl; }
转载请注明原文地址: https://www.6miu.com/read-1700221.html

最新回复(0)