mysleep与竞态条件下的mysleep

来源:互联网 发布:感动一个人 知乎 编辑:程序博客网 时间:2024/05/16 05:05

1.编写代码实现sleep功能
利用pause()和alarm()函数来实现
<1> 用alarm()设置闹钟

#include<unistd.h>unsigned int alarm(unsigned seconds);

alarm函数可以设置一个闹钟,及让内核在seconds秒之后发送一个SIGALRM信号该信号的默认处理动作是终止该进程;
<2> 用pause()等待,内核切换到其他进程运行

#include<unistd.h>int pause(void)

pause函数使调⽤进程挂起直到有信号递达。如果信号的处理动作是终⽌进程,则进程终⽌,pause函数没有机会返回;如果信号的处理动作是忽略,则进程继续处于挂起状态,pause不返回;如果信号的处理动作是捕捉,则调⽤了信号处理函数之后pause返回-1,errno设置为EINTR, 所以pause只有出错的返回值。

//mysleep代码#include<stdio.h>#include<unistd.h>#include<signal.h>void sig_alrm(){}unsigned int mysleep(unsigned int nsecs){     struct sigaction new,old;     unsigned int unslept = 0;                                                                            new.sa_handler=sig_alrm;     sigemptyset(&new.sa_mask);     new.sa_flags=0;     sigaction(SIGALRM,&new,&old);//注册信号处理函数     alarm(nsecs);//设置闹钟     pause();     unslept=alarm(0);//清空闹钟     sigaction(SIGALRM,&old,NULL);//恢复默认信号处理函数     return unslept; }  int main() {    while(1)     {         mysleep(1);        printf("5 second passed\n");     }     return 0;}                                                                                               

<3> sigaction函数

#include <signal.h>int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);

sigaction函数可以读取和修改与指定信号相关联的处理动作。调⽤成功则返回0,出错则返回- 1。 signo是指定信号的编号。若act指针⾮空,则根据act修改该信号的处理动作。若oact指针⾮ 空,则通过oact传出该信号原来的处理动作。
sigaction结构体:

 struct sigaction {               void   (*sa_handler)(int);               void   (*sa_sigaction)(int, siginfo_t *, void *);               sigset_t sa_mask;               int      sa_flags;               void     (*sa_restorer)(void);           };

2.竞态条件下mysleep

#include<stdio.h>#include<unistd.h>#include<signal.h>void sig_alrm(){}unsigned int mysleep(unsigned int nsecs){     struct sigaction new,old;     sigset_t newmask,oldmask,suspmask;     unsigned int unslept = 0;     new.sa_handler=sig_alrm;     sigemptyset(&new.sa_mask);     new.sa_flags=0;     sigaction(SIGALRM,&new,&old);     sigemptyset(&newmask);     sigaddset(&newmask,SIGALRM);     sigprocmask(SIG_BLOCK,&newmask,&oldmask);     alarm(nsecs);     suspmask=oldmask;     sigdelset(&suspmask,SIGALRM);     sigsuspend(&suspmask);     unslept=alarm(0);     sigaction(SIGALRM,&old,NULL);    sigprocmask(SIG_SETMASK,&oldmask,NULL);     return unslept; } int main() {     while(1)     {         mysleep(1);         printf("5 second passed\n");     }     return 0; }