sleep function error ("Advanced Programming in the UNIX Environment" Third Edition No.374)

信号处理与睡眠函数实现
本文介绍了一个通过信号处理实现自定义sleep函数的C程序示例。该程序使用SIGALRM信号来达到延时的效果,并展示了如何通过sigsuspend和nanosleep函数精确控制进程的阻塞时间。

测试证明代码:

#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include "apue.h"

static void sig_alrm(int signo)
{
    /* nothing to do, just returning wakes up sigsuspend */
}

static void sig_usr1(int signo)
{

}

//static void sig_alrm_test(int signo)
//{
//    err_msg("left an alrm");
//}

unsigned int sleep(unsigned int seconds)
{
    struct sigaction newact, oldact;
    sigset_t newmask, oldmask, suspmask;
    unsigned int unslept;

    timespec ts;            // ++
    ts.tv_sec = 25;         // ++
    ts.tv_nsec = 0;         // ++

    /* set our handler, save previous information */
    newact.sa_handler = sig_alrm;
    sigemptyset(&newact.sa_mask);
    newact.sa_flags = 0;
    sigaction(SIGALRM, &newact, &oldact);

    /* block SIGALRM and save current signal mask */
    sigemptyset(&newmask);
    sigaddset(&newmask, SIGALRM);
    sigprocmask(SIG_BLOCK, &newmask, &oldmask);

    alarm(seconds);
    suspmask = oldmask;

    /* make sure SIGALRM isn't block */
    sigdelset(&suspmask, SIGALRM);

    /* wait for any signal to be caught */
    sigsuspend(&suspmask);

    nanosleep(&ts, NULL);                   // ++

    /* some signal has been caught, SIGALRM is now blocked */
    unslept = alarm(0);

    /* reset previous action */
    sigaction(SIGALRM, &oldact, NULL);

    /* reset signal mask, which unblocks SIGALRM */
    sigprocmask(SIG_SETMASK, &oldmask, NULL);
    return unslept;
}

int main(int argc, char *argv[])
{
    struct sigaction useract;
    struct sigaction alrmact;

    useract.sa_handler = sig_usr1;
    sigemptyset(&useract.sa_mask);
    useract.sa_flags = 0;
    if (sigaction(SIGUSR1, &useract, NULL) < 0)
        err_sys("SIG SUR1 error");

//    alrmact.sa_handler = sig_alrm_test;
//    sigemptyset(&alrmact.sa_mask);
//    alrmact.sa_flags = 0;
//    if (sigaction(SIGALRM, &alrmact, NULL) < 0)
//        err_sys("SIG ALRM error");

    sleep(20);

    return 0;
}

操作说明,这里我给出我和作者交流时的说明,所以用的是英文,不过我英文水平有限,希望谅解:

I should give you my manipulation. You should send a SIGUSR1 to the process in less than 20 seconds. So that when alarm(0) tries to cancel the alarm, it was not expired. You see, I didn't send the process SIGALARM, but the SIGALARM handler was fired.

下面是运行时候的结果(为了让作者可以看清楚,使用的是英文):

下面是作者的回复(中间有一些曲折,给出最后的部分回复内容):

Yes, there is a very small window where if the sigsuspend() is interrupted by a different signal and the SIGALRM is posted before calling alarm(0) to cancel it, that the process will be terminated if the default disposition of SIGALRM is in effect.  You have artificially widened that window by adding the call to nanosleep().

转载于:https://www.cnblogs.com/albizzia/p/8512272.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值