美文网首页
信号函数编写研究

信号函数编写研究

作者: 五菱老司机 | 来源:发表于2017-12-06 09:56 被阅读11次

    APUE读书笔记

    ToDoList

    • [ ] sleep初级实现 2017年12月6日 10:41:30
    • [ ] sleep进阶实现
    • [ ] sleep高阶实现
    • [ ] sleep内核具体实现

    第十章

    项目 时间 文档版本 作者 备注
    读书笔记 2017/12/06 初稿 shiyanhk@gmail.com 添加第十章内容

    [TOC]


    1 编写目的

    之前对singnal信号理解一知半解,就这篇文章想通过我的描述来把signal这一章节,深入浅出的讲解出来.

    不妨我们就从apue书中具体用例展开我们需要的描述,虽然片面,后续仍会有修改和添加,

    2 sleep函数基于信号实现,循序渐进的几个用例

    2.1.1 sleep初级实现

    2.1.2 代码

    static void sig_alrm(int signo){
        /* nothing to do, just return to wake up the pause */
    }
    
    unsigned int sleep1(unsigned int nsecs){
        if (signal(SIGALRM, sig_alrm) == SIG_ERR)
            return(nsecs);
        alarm(nsecs);       /* start the timer */
        pause();            /* next caught signal wakes us up */
        return(alarm(0));   /* turn off timer, return unslept time */
    }
    
    
    2.1.2问题
    • 1.如果调用者已设置了闹钟,则它被sleep1函数中的第一次alarm调用擦去
    • 2.该程序中修改了对SIGALRM的配置。
    • 3.在调用 alarm和pause之间有一个竞态条件。

    2.1.3解决办法

    • 1.利用alarm返回值确定上次信号状态
    • 2.利用signal返回值确定signal函数原始回调操作
    • 3.利用setjmp和longjmp修改

    2.1.4 详细分析

    问题 1
    利用alarm返回值记录 剩余时钟

    可用下列方法更正这一点:检查第一次调用alarm的返回值,如其小于本次调用 alarm的参数值,则只应等到该前次设置的闹钟时间超时。如果前次设置闹钟时间的超时时刻后于本次设置值,则在sleep1函数返回之前,再次设置闹钟时间,使其在预定时间再发生超时。

    问题1代码实现

    
    

    问题 2
    该程序中修改了对SIGALRM的配置。

    在一个繁忙的系统中,可能 a l a r m在调用 p a u s e之前超时,并调用了信号处理程序。如果发生了这种情况,则在调用 p a u s e后,如果没有 捕捉到其他信号,则调用者将永远被挂起.

    没有对原信号处理程序做保存 修改信号掩码 对未决信号 做特殊处理=
    可用下列方法更正这一点:检查第一次调用 alarm的返回值,如其小于本次调用 alarm的参数值,则只应等到该前次设置的闹钟时间超时。如果前次设置闹钟时间的超时时刻后于本次设置值,则在sleep1函数返回之前,再次设置闹钟时间,使其在预定时间再发生超时。

    问题 2代码实现

    
    
    

    问题 3
    **在调用 alarm和pause之间有一个竞态条件。 **

    在一个繁忙的系统中,可能 a l a r m在调用 p a u s e之前超时,并调用了信号处理程序。如果发生了这种情况,则在调用 p a u s e后,如果没有 捕捉到其他信号,则调用者将永远被挂起

    ** 利用setjmp和longjmp函数切换上下文**
    SVR2中的sleep实现使用了setjmp和longjmp (见7 . 1 0节)以避免问题( 3 )中所说明的竞态条件。
    此函数的一个简化版本,称为 s l e e p 2,示于程序 1 0 - 5中(为了缩短实例长度,程序中没有处理
    上面所说的问题( 1 )和( 2 )

    问题 3代码实现

    这部分比较复杂,我们放到下一章节单独来讲
    

    10.8

    sleep进阶实现

    代码

    static jmp_buf  env_alrm;
    
    static void
    sig_alrm(int signo)
    {
        printf("时钟信号来了,我进入了信号回调函数 sig_alrm\n");
        printf("我尝试了longjmp(env_alrm, 1);再次跳转到主调函数 \n");
        longjmp(env_alrm, 1);// 通常第二个参数都默认写成1
        printf("跳出了 sig_alrm\n");//此行代码无效
    }
    
    
    
    
    // 避免了pause函数和alarm韩寒苏竞争
    unsigned int
    sleep2(unsigned int nsecs)
    {
        if (signal(SIGALRM, sig_alrm) == SIG_ERR)  
            return(nsecs);
        if (setjmp(env_alrm) == 0) { // 设置一个longjmp的标签  返回值为0表示成功完成了设置
           // 我设置了一个 
            printf("我成功的设置了 setjmp(env_alrm) \n");
            printf("我设置了一个 %d 秒的闹钟信号\n",nsecs);
            alarm(nsecs);       /* start the timer */   // 来个闹钟实时  如果时钟信号来了  那么代码跳到25行重新来过 避免了alarm先调用 后面pause没法结束
            printf("成功定时向本进程发送一个时钟信号\n");
            printf("在此pause等待时钟信号.......\n\n\n");
            pause();            /* next caught signal wakes us up */
        }
        return(alarm(0));       /* turn off timer, return unslept time */
    }
    
    
    
    st=>start: Start 
    io=>inputoutput: verification 
    op=>operation: Your Operation 
    cond=>condition: Yes or No? 
    e=>end
    
    st->io->op->cond 
    cond(yes)->e 
    cond(no)->io 
    

    相关文章

      网友评论

          本文标题:信号函数编写研究

          本文链接:https://www.haomeiwen.com/subject/jskkixtx.html