Linux 信号 模拟实现sleep

来源:互联网 发布:c语言学习文档 编辑:程序博客网 时间:2024/05/18 19:39

1、产生信号

产生信号的3种方式:

1、调用系统函数:kill(); raise(); abort(();

2、软件异常行为;

3、组合键:Ctrl+c Ctrl+d Ctrl+\等;

处理信号的3种方式:

1、忽略。

2、默认(很多情况下是终止)。

3、自定义(信号捕捉)。

信号在内核中的表示:

1、递达:执行信号的处理动作称为信号递达(Delivery)。

2、未决:信号从产生到递达之间的状态,称为信号未决(Pending)。

3、阻塞:进程可以选择阻塞(Block )某个信号。被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞才执行递达的动作。

注意:阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后 可选的一种处理动作。

信号集操作函数

#include <signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);

#include<stdio.h>#include<signal.h>#include<unistd.h>void show_pending(sigset_t *set){int i = 1;for(;i<31;i++){if(sigismember(set,i)){printf("1");}else{printf("0");}}printf("\n");}int main(){sigset_t block,oblock,pending;sigemptyset(&block);sigemptyset(&oblock);sigemptyset(&pending);sigaddset(&block,2);sigprocmask(SIG_SETMASK,&block,&oblock);while(1){sigpending(&pending);sleep(1);show_pending(&pending);}return 0;}




模拟实现Sleep

1、该程序有bug(无保护机制)

#include<stdio.h>#include<signal.h>#include<unistd.h>int count = 0;void handler(int sig){}int mysleep(int second){struct sigaction act,oact;act.sa_handler = handler;sigemptyset(&act.sa_mask);act.sa_flags = 0;sigaction(SIGALRM,&act,&oact);alarm(second);pause();int time = alarm(0);sigaction(SIGALRM,&oact,NULL);return time;}int main(){while(1){printf("hello I am sleping\n");mysleep(3);}return 0;}


模拟实现Sleep

2、该程序无Bug(有保护机制)

#include<stdio.h>#include<signal.h>#include<unistd.h>int count = 0;void handler(int sig){}int mysleep(int second){struct sigaction act,oact;sigset_t nmask,onmask,unmask;//信号捕捉动作设置act.sa_handler = handler;sigemptyset(&act.sa_mask);act.sa_flags = 0;sigaction(SIGALRM,&act,&oact);//信号屏蔽设置sigemptyset(&nmask);sigaddset(&nmask,SIGALRM);sigprocmask(SIG_BLOCK,&nmask,&onmask);alarm(second);//设置闹钟//解除信号屏蔽unmask = onmask;sigdelset(&unmask,SIGALRM);sigsuspend(&unmask);int time = alarm(0);sigaction(SIGALRM,&oact,NULL);return time;}int main(){while(1){printf("hello I am sleping\n");mysleep(3);}return 0;}




注:

1. 调用sigprocmask(SIG_BLOCK, &nmask, &omask);时屏蔽SIGALRM。

2. 调用sigsuspend(&unpmask);时解除对SIGALRM的屏蔽,然后挂起等待待。

3. SIGALRM递达后suspend返回,自动恢复原来的屏蔽字,也就是再次屏蔽SIGALRM。

4. 调用sigprocmask(SIG_SETMASK, &oldmask, NULL);时再次解除对SIGALRM的屏蔽。



0 0