mysleep

来源:互联网 发布:oracle数据库实时复制 编辑:程序博客网 时间:2024/06/05 02:34

一、普通版本的mysleep函数

1.main函数调用mysleep函数,后者调用sigaction注册了SIGALRM信号的处理函数handler。 
2.调用alarm(timeout)设定闹钟。 
3.调用pause等待,内核切换到别的进程运行。 
4.timeout秒之后,闹钟超时,内核发SIGALRM给这个进程。 
5.从内核态返回这个进程的用户态之前处理未决信号,发现有SIGALRM信号,其处理函数是handler。 
6.切换到用户态执行handler函数,进入handler函数时SIGALRM信号被自动屏蔽, 从handler函数返回时SIGALRM信号自动解除屏蔽。然后自动执行系统调用sigreturn再次进入 内核,再返回用户态继续执行进程的主控制流程(main函数调用的mysleep函数)。 
7.pause函数返回-1,然后调用alarm(0)取消闹钟,调用sigaction恢复SIGALRM信号以前的处理动作。

代码实现:

#include<stdio.h>#include<signal.h>#include<unistd.h>#include<stdlib.h>void handler(int signum){}int mysleep(int time){    struct sigaction act,oldact;    act.sa_handler = handler;    int sa_flags = 0;    sigset_t sa_mask;    sigemptyset(&sa_mask);    sigaction(SIGALRM, &act, &oldact);    alarm(time);    pause();    int ret = alarm(0);    sigaction(SIGALRM, &act, NULL);    return ret;}int main(){    while(1)    {        mysleep(1);        printf("I am sleeping!!\n");    }    return 0;}
运行结果:


二、规避竞态条件的mysleep函数

1.屏蔽SIGALRM信号; 
2.alarm(time); 
3.解除对SIGALRM的屏蔽; 
4.pause(); 

代码实现:

#include<stdio.h>#include<signal.h>#include<unistd.h>#include<stdlib.h>void handler(int signum){}int mysleep(int time){    struct sigaction act,oldact;    act.sa_handler = handler;    int sa_flags = 0;    sigset_t sa_mask, oldmask, suspmask;    sigaction(SIGALRM, &act, &oldact);    sigemptyset(&sa_mask);    sigaddset(&sa_mask, SIGALRM);    sigprocmask(SIG_BLOCK, &sa_mask, &oldmask);    alarm(time);    suspmask = oldmask;    sigdelset(&suspmask, SIGALRM);    sigsuspend(&suspmask);    int ret = alarm(0);    sigaction(SIGALRM, &act, NULL);    sigprocmask(SIG_SETMASK, &oldmask, NULL);    return ret;}int main(){    while(1)    {        mysleep(1);        printf("I am sleeping!!\n");    }    return 0;}
运行结果:


原创粉丝点击