linux mysleep实现

一、模拟sleep函数
利用pause和alarm以及信号相关接口来模拟sleep函数
1.利用sigaction改变alarm发出的信号的递达方式
2.设置闹钟
3.pause
4.闹钟响了,发送信号
5.pause出错返回
二、代码实现
1.未考虑竞态

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void handler(void* avg)
{
                    //自定义处理动作:什么也不做!
}
int my_sleep(int timeout)
{
    sigset_t set;
    sigemptyset(&set);
    struct sigaction act ,oact;//创建两种信号处理方式
    act.sa_handler = handler;//捕捉信号(自定义函数)
    act.sa_mask = set;//信号屏蔽字(是否对某一信号阻塞)
    act.sa_flags = 0;
    sigaction(SIGALRM,&act,&oact);//将SIGALRM信号的处理方式改为自定义函数
    alarm(timeout);//设置闹钟
    pause();//挂起进程,直到有信号递达
    int ret = alarm(0);//关闭闹钟
    sigaction(SIGALRM,&oact,NULL);//恢复系统默认对SIGALRM信号的处理方式
    return ret;
}


int main()
{
    while(1){
    printf("I am sleeping \n");
    my_sleep(2);

    }
    return 0;
}

上面的代码中如果刚把闹钟设置了之后,进程就被系统切出去,执行更高优先级的进程,而且这个进程执行的时间很长。但此时闹钟响了,发送SIGALRM给进程,该信号处于未决状态,这时系统切回来了,并递达了这个信号。那么下面的pause将不会再收到alarm的信号。
所以,要考虑这种情况。即竞态条件。
2.竞态版本

#include<stdio.h>
#include<unistd.h>
#include<signal.h>
void handler(int signo)
{
}
int mysleep(int time)
{
    sigset_t set,oset,susmask;
    sigemptyset(&set);
    sigaddset(&set,SIGALRM);
    sigprocmask(SIG_BLOCK,&set,&oset);
    struct sigaction act;
    struct sigaction oact;
    act.sa_handler = handler;
    act.sa_mask = set;
    act.sa_flags = 0;   
    sigaction(SIGALRM,&act,&oact);
    alarm(time);
    susmask = oset;
    sigdelset(&susmask,SIGALRM);
    sigsuspend(&susmask);
    int _time = alarm(0);
    sigaction(SIGALRM,&oact,NULL);
    sigprocmask(SIG_BLOCK,&oset,NULL);
    return _time;
}

int main()
{
    while(1){
    printf("I am sleeping \n");
    my_sleep(2);

    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值