zoukankan      html  css  js  c++  java
  • ARM Linux对signal的处理过程

    // 本文部分内容来自网络

    // 基于内核版本3.4

    一.整体流程

    Linux 用户进程不能处理信号,操作系统也不会为了处理一个信号而把当前正在运行的进程挂起,而是选择在内核态切换回用户态的时候(一般都是中断或者系统调用返回)处理信号。

    所以处理信号的整个过程是这样的:进程由于 系统调用或者中断 进入内核,完成相应任务返回用户空间的前夕,检查信号队列,如果有信号,则根据信号向量表找到信号处理函数,设置好“堆栈”后,跳到用户态执行信号处理函数。信号处理函数执行完毕后,返回内核态,设置“堆栈”,再返回到用户态继续执行程序。

    具体步骤:

          1、用户为某信号注册一个信号处理函数sighandler

          2、当前正在执行主程序,这时候因为中断、异常或系统调用进入内核态。

          3、在处理完异常要返回用户态的主程序之前,检查到有信号未处理,并发现该信号需要按照用户自定义的函数来处理。

          4、内核决定返回用户态执行sighandler函数,而不是恢复main函数的上下文继续执行!(sighandlermain函数使用的是不同的堆栈空间,它们之间不存在调用和被调用的关系,是两个独立的控制流程)

          5、sighandler函数返回后,执行特殊的系统调用sigreturn从用户态回到内核态

          6、检查是否还有其它信号需要递达,如果没有 则返回用户态并恢复主程序的上下文信息继续执行。

     

    二.代码分析

    ARM Linux中,内核态返回用户态通常接口是ret_fast_syscall(系统调用)和ret_to_user(中断),所以signal的处理流程:ret_to_user()/ret_fast_syscall–>work_pending()–>do_notify_resume()–>do_signal

     

     ret_fast_syscall为例分析具体实现,代码位于 archarmkernelentry-common.S

    ret_fast_syscall:
     UNWIND(.fnstart    )
     UNWIND(.cantunwind    )
        disable_irq                @ disable interrupts
        ldr    r1, [tsk, #TI_FLAGS]
        tst    r1, #_TIF_WORK_MASK
        bne    fast_work_pending
    #if defined(CONFIG_IRQSOFF_TRACER)
        asm_trace_hardirqs_on
    #endif
    
        /* perform architecture specific actions before user return */
        arch_ret_to_user r1, lr
    
        restore_user_regs fast = 1, offset = S_OFF
     UNWIND(.fnend        )

     

    ldr r1, [tsk, #TI_FLAGS]:

     TI_FLAGS表示thread_info结构体中的flags变量,相关宏定义位于archarmkernelAsm-offsets.c

      DEFINE(TI_FLAGS,        offsetof(struct thread_info, flags));
      DEFINE(TI_PREEMPT,        offsetof(struct thread_info, preempt_count));
      DEFINE(TI_ADDR_LIMIT,        offsetof(struct thread_info, addr_limit));
      DEFINE(TI_TASK,        offsetof(struct thread_info, task));
      DEFINE(TI_EXEC_DOMAIN,    offsetof(struct thread_info, exec_domain));
      DEFINE(TI_CPU,        offsetof(struct thread_info, cpu));
      DEFINE(TI_CPU_DOMAIN,        offsetof(struct thread_info, cpu_domain));
      DEFINE(TI_CPU_SAVE,        offsetof(struct thread_info, cpu_context));
      DEFINE(TI_USED_CP,        offsetof(struct thread_info, used_cp));
      DEFINE(TI_TP_VALUE,        offsetof(struct thread_info, tp_value));
      DEFINE(TI_FPSTATE,        offsetof(struct thread_info, fpstate));
      DEFINE(TI_VFPSTATE,        offsetof(struct thread_info, vfpstate));

    flags变量表示了该线程基本状态,例如是否有信号pending,是否需要调度等,其可能的值定义位于/arch/arm/include/asm/thread_info.h

    /*
     * thread information flags:
     *  TIF_SYSCALL_TRACE    - syscall trace active
     *  TIF_SYSCAL_AUDIT    - syscall auditing active
     *  TIF_SIGPENDING    - signal pending
     *  TIF_NEED_RESCHED    - rescheduling necessary
     *  TIF_NOTIFY_RESUME    - callback before returning to user
     *  TIF_USEDFPU        - FPU was used by this task this quantum (SMP)
     *  TIF_POLLING_NRFLAG    - true if poll_idle() is polling TIF_NEED_RESCHED
     */
    #define TIF_SIGPENDING        0
    #define TIF_NEED_RESCHED    1
    #define TIF_NOTIFY_RESUME    2    /* callback before returning to user */
    #define TIF_SYSCALL_TRACE    8
    #define TIF_SYSCALL_AUDIT    9
    #define TIF_POLLING_NRFLAG    16
    #define TIF_USING_IWMMXT    17
    #define TIF_MEMDIE        18    /* is terminating due to OOM killer */
    #define TIF_RESTORE_SIGMASK    20
    #define TIF_SECCOMP        21
    #define TIF_SWITCH_MM        22    /* deferred switch_mm */
    
    #define _TIF_SIGPENDING        (1 << TIF_SIGPENDING)
    #define _TIF_NEED_RESCHED    (1 << TIF_NEED_RESCHED)
    #define _TIF_NOTIFY_RESUME    (1 << TIF_NOTIFY_RESUME)
    #define _TIF_SYSCALL_TRACE    (1 << TIF_SYSCALL_TRACE)
    #define _TIF_SYSCALL_AUDIT    (1 << TIF_SYSCALL_AUDIT)
    #define _TIF_POLLING_NRFLAG    (1 << TIF_POLLING_NRFLAG)
    #define _TIF_USING_IWMMXT    (1 << TIF_USING_IWMMXT)
    #define _TIF_RESTORE_SIGMASK    (1 << TIF_RESTORE_SIGMASK)
    #define _TIF_SECCOMP        (1 << TIF_SECCOMP)
    
    /* Checks for any syscall work in entry-common.S */
    #define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT)

    例如flags=1,表示_TIF_SIGPENDING即有信号pending;flags=2,表示__TIF_NEED_RESCHED即线程需要调度;

    tst r1, #_TIF_WORK_MASK

    bne fast_work_pending

    _TIF_WORK_MASK的值定于同样位于/arch/arm/include/asm/thread_info.h,值为0xff;这两条指令比较了flags值是否为0,如果不为0,则跳转到fast_work_pending函数。

    fast_work_pending根据flags的具体值,跳转到work_resched/do_notify_resume等具体接口继续处理:

    fast_work_pending:
        str    r0, [sp, #S_R0+S_OFF]!        @ returned r0
    work_pending:
        tst    r1, #_TIF_NEED_RESCHED
        bne    work_resched
        tst    r1, #_TIF_SIGPENDING|_TIF_NOTIFY_RESUME
        beq    no_work_pending
        mov    r0, sp                @ 'regs'
        mov    r2, why                @ 'syscall'
        tst    r1, #_TIF_SIGPENDING        @ delivering a signal?
        movne    why, #0                @ prevent further restarts
        bl    do_notify_resume
        b    ret_slow_syscall        @ Check work again

    // to be continued......

  • 相关阅读:
    在Ubuntu上安装Mono
    CSS 外边距(margin)重叠及防止方法
    如何通过 iframe 共享 jQuery $.data?
    给ajax表单提交数据前面加上实体名称
    发布web应用程序是出现unsafe code
    ASP.NET MVC 基于页面的权限管理
    jquery旋转图片
    artTemplate子模板include
    JS调试必备的5个debug技巧_javascript技巧
    jQuery中position()与offset()区别
  • 原文地址:https://www.cnblogs.com/DF11G/p/9012498.html
Copyright © 2011-2022 走看看