美文网首页
day14 signal

day14 signal

作者: 柯基是只dog | 来源:发表于2018-12-12 18:01 被阅读0次

信号是一种在进程间异步相应的方式,进程可以通过系统调用设置不同信号的相应回调,每次调度之前内核都会检查进程的信号,如果有置位的信号,则会唤醒该进程,下面两个是设置信号的调用

// signal()系统调用。类似于sigaction()。为指定的信号安装新的信号句柄(信号处理程序)。
// 信号句柄可以是用户指定的函数,也可以是SIG_DFL(默认句柄)或SIG_IGN(忽略)。
// 参数signum --指定的信号;handler -- 指定的句柄;restorer –原程序当前执行的地址位置。
// 函数返回原信号句柄。
int sys_signal (int signum, long handler, long restorer)
{
    struct sigaction tmp;

    if (signum < 1 || signum > 32 || signum == SIGKILL) // 信号值要在(1-32)范围内,
        return -1;          // 并且不得是SIGKILL。
    tmp.sa_handler = (void (*)(int)) handler;   // 指定的信号处理句柄。
    tmp.sa_mask = 0;        // 执行时的信号屏蔽码。
    tmp.sa_flags = SA_ONESHOT | SA_NOMASK;  // 该句柄只使用1 次后就恢复到默认值,
// 并允许信号在自己的处理句柄中收到。
    tmp.sa_restorer = (void (*)(void)) restorer;    // 保存返回地址。
    handler = (long) current->sigaction[signum - 1].sa_handler;
    current->sigaction[signum - 1] = tmp;
    return handler;
}

// sigaction()系统调用。改变进程在收到一个信号时的操作。signum 是除了SIGKILL 以外的任何
// 信号。[如果新操作(action)不为空]则新操作被安装。如果oldaction 指针不为空,则原操作
// 被保留到oldaction。成功则返回0,否则为-1。
int sys_sigaction (int signum, const struct sigaction *action,
                    struct sigaction *oldaction)
{
    struct sigaction tmp;

// 信号值要在(1-32)范围内,并且信号SIGKILL 的处理句柄不能被改变。
    if (signum < 1 || signum > 32 || signum == SIGKILL)
        return -1;
// 在信号的sigaction 结构中设置新的操作(动作)。
    tmp = current->sigaction[signum - 1];
    get_new ((char *) action, (char *) (signum - 1 + current->sigaction));
// 如果oldaction 指针不为空的话,则将原操作指针保存到oldaction 所指的位置。
    if (oldaction)
        save_old ((char *) &tmp, (char *) oldaction);
// 如果允许信号在自己的信号句柄中收到,则令屏蔽码为0,否则设置屏蔽本信号。
    if (current->sigaction[signum - 1].sa_flags & SA_NOMASK)
        current->sigaction[signum - 1].sa_mask = 0;
    else
        current->sigaction[signum - 1].sa_mask |= (1 << (signum - 1));
    return 0;
}

然后信号处理函数有点意思,因为是在内核态本来是要返回到用户态并从中断点重新开始运行的。但内核如果检测到需要处理信号的时候,就会把eip改成信号处理入口地址,然后通过修改用户态的栈,把中断返回出的eip和段等必要的寄存器压入,这样当从内核恢复到用户态的时候首先执行的是信号处理函数,信号处理函数返回的时候,会从堆栈中弹出原来的地址,但这个时候已经被内核修改成了当初中断打断的地方,于是就继续从中断点开始执行了

void do_signal (long signr, long eax, long ebx, long ecx, long edx,
            long fs, long es, long ds,
            long eip, long cs, long eflags, unsigned long *esp, long ss)
{
    unsigned long sa_handler;
    long old_eip = eip;
    struct sigaction *sa = current->sigaction + signr - 1;  //current->sigaction[signu-1]。
    int longs;
    unsigned long *tmp_esp;

    sa_handler = (unsigned long) sa->sa_handler;
// 如果信号句柄为SIG_IGN(忽略),则返回;如果句柄为SIG_DFL(默认处理),则如果信号是
// SIGCHLD 则返回,否则终止进程的执行
    if (sa_handler == 1)
        return;
    if (!sa_handler)
    {
        if (signr == SIGCHLD)
            return;
        else
// 这里应该是do_exit(1<<signr))。
            do_exit (1 << (signr - 1)); // [?? 为什么以信号位图为参数?不为什么!??]
    }
// 如果该信号句柄只需使用一次,则将该句柄置空(该信号句柄已经保存在sa_handler 指针中)。
    if (sa->sa_flags & SA_ONESHOT)
        sa->sa_handler = NULL;
// 下面这段代码将信号处理句柄插入到用户堆栈中,同时也将sa_restorer,signr,进程屏蔽码(如果
// SA_NOMASK 没置位),eax,ecx,edx 作为参数以及原调用系统调用的程序返回指针及标志寄存器值
// 压入堆栈。因此在本次系统调用中断(0x80)返回用户程序时会首先执行用户的信号句柄程序,然后
// 再继续执行用户程序。
// 将用户调用系统调用的代码指针eip 指向该信号处理句柄。
    *(&eip) = sa_handler;
// 如果允许信号自己的处理句柄收到信号自己,则也需要将进程的阻塞码压入堆栈。
    longs = (sa->sa_flags & SA_NOMASK) ? 7 : 8;
// 将原调用程序的用户的堆栈指针向下扩展7(或8)个长字(用来存放调用信号句柄的参数等),
// 并检查内存使用情况(例如如果内存超界则分配新页等)。
    *(&esp) -= longs;
    verify_area (esp, longs * 4);
// 在用户堆栈中从下到上存放sa_restorer, 信号signr, 屏蔽码blocked(如果SA_NOMASK 置位),
// eax, ecx, edx, eflags 和用户程序原代码指针。
    tmp_esp = esp;
    put_fs_long ((long) sa->sa_restorer, tmp_esp++);
    put_fs_long (signr, tmp_esp++);
    if (!(sa->sa_flags & SA_NOMASK))
        put_fs_long (current->blocked, tmp_esp++);
    put_fs_long (eax, tmp_esp++);
    put_fs_long (ecx, tmp_esp++);
    put_fs_long (edx, tmp_esp++);
    put_fs_long (eflags, tmp_esp++);
    put_fs_long (old_eip, tmp_esp++);
    current->blocked |= sa->sa_mask;    // 进程阻塞码(屏蔽码)添上sa_mask 中的码位。
}

相关文章

  • day14 signal

    信号是一种在进程间异步相应的方式,进程可以通过系统调用设置不同信号的相应回调,每次调度之前内核都会检查进程的信号,...

  • swift 抓取奔溃日志

    `signal(SIGABRT) { (signal:Int32)in `

  • EOS 通信机制

    boost signal机制: boost的signal/slots用来实现event事件机制,一个signal可...

  • MVVM终结者(三)

    signal的Operations signal的Operations或者称它是signal的运算与操作,对sig...

  • 2020-10-11

    # comprehensive exam -- signal 这是关于comprehensive signal 的...

  • [python]signal

    signal包的核心是使用signal.signal()函数来预设(register)信号处理函数,singnal...

  • AQS源码解析(9)Condition.signal

    signal和signalAll大同小异,本节我们来看下signal函数,signal核心调用的是doSignal...

  • Signal Media

    Signal Media by sennchi Signal Media Media Monitoring T...

  • note_17.2_shell、信号

    signal trap -lsignal listkill -lsignal listman 7 signal t...

  • SignalR从。。。到。。。

    Signal搭建一个聊天室。 Signal框架学习 1.引入NuGut包ASPNET.net.Signal.Hub...

网友评论

      本文标题:day14 signal

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