linux相关函数,linux学习-信号相关函数

未决:在信号产生和递送之间的时间间隔内,我们称信号是未决的。

阻塞信号递送:如果为进程产生了一个阻塞信号,而且对该信号的动作是默认动作或捕捉该信号,则为该进程将此信号保持为未决的,直到进程对此信号解除阻塞,或者对此信号的动作更改为忽略。

信号屏蔽字:每个进程都有一个信号屏蔽字,它规定了当前要阻塞递送到该进程的信号集。

信号集:可以表示多个信号的数据类型,定义数据类型为sigset_t

#includeint sigemptyset(sigset_t *set); //初始化信号集为空

int sigfillset(sigset_t *set); //初始化信号集包括所有信号

int sigaddset(sigset_t *set,int signo); // 将信号signo加入到set信号集

int sigdelset(sigset_t *set,int signo); //将信号signo从信号集中删除

1.函数kill和raise

#includeint kill(pid_t pid,int signo);

int raise(int signo);

返回值: 成功返回0,失败返回-1

kill的pid参数

pid>0 将该信号发送进程ID为pid的进程

pid==0 将信号发送给与发送进程同一进程组的所有进程,但不包 括系统进程集,既内核进程和init。

pid<0 将该进程发送给其他进程组ID为pid绝对值的所有进程,不包括系统进程集

pid==-1将该信号发送给进程有权限向它们发送信号的所有进程,不包括系统进程集

如上所述,进程发送信号是要权限的,超级用户可以发送给所有的进程。非超级的,发送者的实际用户ID或者有效用户ID必须等于接收者的实际用户ID或者有效用户ID。

2.函数alarm和pause

alarm函数可以设置一个闹钟时间,超时产生SIGALRM信号。如忽略或者不捕捉该信号,系统默认动作是终止调用alarm函数的进程。

#includeunsigned int alarm(unsigned int seconds);

返回值:0,或者是以前设置的闹钟时间的剩余时间

每个进程只能有一个闹钟时间。如果在调用alarm之前已经为该进程注册的闹钟时间还未超时,则该闹钟的剩余时间作为本次alarm函数调用的值返回。以前注册的闹钟时间则被新值代替。如果本次调用的seconds值是0,则取消以前的闹钟,其剩余值,作为alarm函数的返回值。

pause函数调用进程挂起,直到捕捉到一个信号

#includeint paush(void);

返回值:-1;errno设置为EINTR

给出一个用alarm和pause实现sleep的实例

#include#include#include#includestatic jmp_buf env_alrm;

static void myalrm(int signo) //信号处理函数

{

longjmp(env_alrm,1); //局部跳转

}

int mysleep(int sec)

{

int minsec,ret,tmp=0;

if(signal(SIGALRM,myalrm)==SIG_EER)

return sec;

minsec=alrm(0); //得到上一次未超时定时器所剩的时间

ret=sec>minsec?(sec-minsec):0;

if(setjmp(env_alrm)==0) //局部跳转

{

if(minsec) //考虑之前设置了定时器

alarm(minsecsec){ //若前面登记的定时器比睡眠时间长,退出后需要复位之前定时器剩下的时间

alarm(minsec-sec);

}

if(tmp)

ret+=tmp;

return ret;

}

int main()

{

int othersec;

alarm(6);

othersec=mysleep(3);

printf("return %d\n",othersec);

return 0;

}

3.函数sigprocmask

调用函数sigprocmask可以检测和更改当前阻塞而不能递送给进程的信号集。

#includeint sigprocmask(int how,const sigset_t *restrict set,sigset_t *restrict oset);

返回值:成功返回0,失败返回-1;

若oset为非空指针,进程当前的信号屏蔽子通过oset返回。

若set为非空指针,参数how指示进行何种操作。若为空,则不改变当前信号屏蔽字,how参数也无用。

how

说明

SIG_BLOCK

新set中的信号加到信号屏蔽字中

SIG_UNBLOCK

将set中信号从当前信号屏蔽子中取出

SIG_SETMASK

该进程新的信号屏蔽是set指向的值

4.函数sigismember

函数sigismember用来测试参数signum 代表的信号是否已加入至参数set信号集里。

int sigismember(const sigset_t *set,int signum)

返回值:有该信号,返回1,无则返回0;出错返回-1

5.函数sigpending

sigpending函数返回在送往进程的时候被阻塞挂起的信号集合。这个信号集合通过参数set返回。

#includeint sigpengding(sigset_t *set);

返回值:成功返回0,出错返回-1

下面这个例程,用到了上面几个函数

static void sig_quit(int signo)

{

printf("caught sigquit\n");

}

int main()

{

sigset_t newmak,oldmask,pendmsk;

if(signal(SIGQUIT,sig_quit)==SIG_ERR)

printf("can not catch quit\n");

sigemptyset(&newmask); //信号集清空函数

sigaddmask(&newmask,SIGQUIT); //将信号添加到信号集中

if(sigprocmask(SIG_BLOCK,&newmask,&oldmask)<0) //将信号SIGQUIT添加到信号屏蔽字中

printf("err\n");

sleep(5);

if(sigpending(&pendmask)<0) //检测当前进程中阻塞的信号,通过pendmask返回

printf("sigpending err\n");

if(sigismember(&pendmask,SIGQUIT)) //检测SIGQUIT是否在pendmask信号集中

printf("sigquit pending\n");

if(sigprocmask(SIG_SETMASK,&oldmask,NULL)<0) //将SIGQUIT信号取消屏蔽

printf("err\n");

sleep(5);

exit(0);

}

6.函数sigaction

sigaction函数的功能是检查或者修改与指定信号相关联的动作。此函数取代了早期使用的signal函数。

#includeint sigaction(int signo,conststruct sigaction*restrict act,

struct sigaction*restrict oact);

返回值:成功返回0,失败返回-1

给信号signo设置新的信号处理函数act, 同时保留该信号原有的信号处理函数oldact。

此函数用到了一个数据结构

struct sigaction{

void (*sa_handler)(int);

sigset_t sa_mask;

int sa_flag;

void (*sa_sigaction)(int,siginfo_t*,void*);

};

sa_handler字段:包含一个信号捕捉函数的地址。

sa_mask字段:说明了一个信号集,在调用该信号捕捉函数之前,这一信号集要加进进程的信号屏蔽字中。仅当从信号捕捉函数返回时再将进程的信号屏蔽字复位为原先值。

sa_flags字段:指定对信号进行处理的 各个选项。有张表格,我就不列了,自己百度吧。简单说明下面程序用到的两个标志

SA_NODEFER: 当信号处理函数正在进行时,不堵塞对于信号处理函数自身信号功能。

SA_RESETHAND:当用户注册的信号处理函数被执行过一次后,该信号的处理函数被设为系统默认的处理函数。

sa_sigaction字段:是一个替代的信号处理程序,当sa_flags 为SA_SIGINFO时,使用该信号处理程序。sa_sigaction和sa_handler,应用只能一次调用其中一个。

static void sig_quit(int signo)

{

printf("catch quit\n");

}

int main()

{

struct sigaction act,oldact;

act.sa_handler = sig_quit;

act.sa_flags = SA_NODEFER | SA_RESETHAND;

sigaction(SIGINT,&act,&oldact);

sleep(5);

printf("hello \n");

return 0;

}

7.函数sigsuspend

sigsuspend函数和pause函数一样,可以使进程挂起(进入睡眠状态),直至有信号发生。

sigsuspend函数的参数是一个信号集,这个信号集是用来屏蔽信号的,信号集中存放了要屏蔽的信号。

如果该信号集为空的话,sigsuspend就不屏蔽任何信号,任何信号都可以使进程从挂起状态唤醒,这就与pause函数一样了。

#includeint sigsuspend(const sigset_t *sigmask);

返回值:-1,并将errno设置为EINTR

可以用于保护代码临界区,使其不被特定的信号中断

#include#include#include#include#include#include#include#include#include#include#include#include#includestatic void sig_init(int);

int main()

{

sigset_t newmask,oldmask,waitmask;

printf("hello");

if(signal(SIGINT,sig_init)==SIG_ERR)

perror("signal");

sigemptyset(&waitmask);

sigaddset(&waitmask,SIGUSR1);

sigemptyset(&newmask);

sigaddset(&newmask,SIGINT);

if(sigprocmask(SIG_BLOCK,&newmask,&oldmask)<0) //将SIGINT加入到信号屏蔽字中,以oldmask返回

perror("sigprocmask");

printf("ok");

if(sigsuspend(&waitmask)!=-1) //将sigusr1屏蔽

perror("sigsuspend");

if(sigprocmask(SIG_SETMASK,&oldmask,NULL)<0) //将阻塞信号SIGINT恢复

perror("sigprocmask");

exit(0);

}

static void sig_init(int signo)

{

printf("how are you\n");

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值