sigprocmask不会阻止不需要的信号

时间:2016-07-02 09:50:48

标签: c linux kernel signals handler

我目前正在Linux源代码树中修改perf以实现我需要的工具。

perf最初安装了一个信号处理程序(SIGUSR2的处理程序),但我想通过处理两个信号(SIGUSR1和SIGUSR2)扩展其功能

如下图所示,内核(非用户进程)连续发送两个信号。

    asmlinkage long sys_pt_signal_perf(void) //new syscall No.500
    {
            return (long)pt_signal_perf_wrapper();
    }

    int pt_signal_perf_wrapper(void)
    {
            if(signal_perf(2) != -1) { //SIGUSR2
                    /* Some dummy loop */
                    signal_perf(1); //SIGUSR1

                    printk(KERN_EMERG "Marker chunk : %d\n", j);
                    printk(KERN_EMERG "[SEMAPHORE LOCK] Marker Chunk\n");
                    pt_down_interruptible(&decode_semaphore); //perf user process unlocks this semaphore lock
                    printk(KERN_EMERG "Decoding for this syscall seems to be finished\n");

                    return 1;
            }
            else {
                    return 0;
            }
    }
    EXPORT_SYMBOL(pt_signal_perf_wrapper);

    int signal_perf(int sig_type)
    {
            int signal_to_send;
            if(sig_type == 1)
                    signal_to_send = SIGUSR1;
            else
                    signal_to_send = SIGUSR2;


            if(!perf_pid) {
                    return -1;
            }
            if(!target_pid) {
                    return -1;
            }

            struct siginfo info;
            memset(&info, 0, sizeof(struct siginfo));
            info.si_signo = signal_to_send;
            info.si_code = SI_QUEUE;
            info.si_int = SI_USER;

            struct task_struct *t = find_task_by_vpid(perf_pid);
            if(!t) {
                    printk(KERN_EMERG "No task struct for %d!\n", perf_pid);
                    return -1;
            }
            int send_sig_info_result = send_sig_info(signal_to_send, &info, t);
            if(send_sig_info_result < 0)
                    printk(KERN_EMERG "KKM : Error sending signal!!\n");
            else
                    printk(KERN_EMERG "KKM : sending signal successful!!\n");

            return (long)perf_pid;
    }

信号接收器perf作为用户进程运行。

    static sigset_t pt_sigset;

...(在主要功能中)

    signal(SIGUSR2, snapshot_sig_handler);
    signal(SIGUSR1, snapshot_sig_handler);

    /* set pt_sigset to block SIGUSR1/2 when they are being processed */
    sigemptyset(&pt_sigset);
    if(sigaddset(&pt_sigset, SIGUSR1) == -1) {
            pr_err("sigaddset for SIGUSR1 returned -1\n");
            return -1;
    }
    if(sigaddset(&pt_sigset, SIGUSR2) == -1) {
            pr_err("sigaddset for SIGUSR2 returned -1\n");
            return -1;
    }

在信号处理程序中,当收到信号(SIGUSR1或SIGUSR2)时,它会使用sigprocmask阻塞SIGUSR1和SIGUSR2信号。

    static void snapshot_sig_handler(int sig __maybe_unused)
    {
            pr_err("Blocking the two signals\n");
            if(sigprocmask(SIG_BLOCK, &pt_sigset, NULL) == -1) {
                    pr_err("sigprocmask returned with error\n");
            }

            if(sig == SIGUSR2) {
                    pr_err("SIG_HANDLER from a non-marker chunk\n");
            }
            else if(sig == SIGUSR1) {
                    pr_err("SIG_HANDLER from a marker chunk\n");
            }
            else {
                    pr_err("NOT A VALID SIGNAL!\n");
                    return;
            }

            /* Real operation which is omitted here */
    }

未显示解锁这两个信号,但肯定存在。

但是当我实际运行代码时,在某些情况下,即使两个信号都被解除阻塞,也会调用信号处理函数。 (如下所示)

Blocking the two signals
SIG_HANDLER from a non-marker chunk
Blocking the two signals
SIG_HANDLER from a marker chunk
Unblocking the two signals
Unblocking the two signals

虽然sigprocmask()没有返回错误,但似乎两个信号的阻塞似乎永远不会起作用。

这是因为信号是从更高的权限发送的吗?(kernel-&gt; user)与大多数信号事务在两个用户进程之间完成的情况不同?

非常感谢你。

0 个答案:

没有答案