将上面的代码编译成内核模块,插入到系统中,打开系统日志,查看创建的内核线程的ID(我的是3278,如下图所示),然后在另一个终端中使用kill命令给创建的内核线程发送SIGTERM命令。测试结果要通过系统日志文件(/var/log/messages)来查看,如下图所示:

  查看系统日志发现获取到的信号位图竟然是0!不可能啊,因为从上面的代码中可以看出只有在signal_pending()函数返回true的情况下(也是接收到信号时),才能输出上图中的日志信息。代码很简单,关键的函数是my_sigpending(),该函数只是对sys_sigpending()进行了简单的封装,

  因此还是要从sys_sigpending()的实现中查找原因。

  查看sys_sigpending()的源码,只是对do_sigpending()函数的简单封装,继续从do_sigpending()中找原因。do_sigpending()源码如下:

long do_sigpending(void __user *set, unsigned long sigsetsize)
{
 long error = -EINVAL;
 sigset_t pending;

 if (sigsetsize > sizeof(sigset_t))
  goto out;

 spin_lock_irq(&current->sighand->siglock);
 sigorsets(&pending, &current->pending.signal,
    &current->signal->shared_pending.signal);
 spin_unlock_irq(&current->sighand->siglock);

 /* Outside the lock because only this thread touches it.  */
 sigandsets(&pending, &current->blocked, &pending);

 error = -EFAULT;
 if (!copy_to_user(set, &pending, sigsetsize))
  error = 0;

out:
 return error;
}

  do_sigpending()首先调用sigorsets()将当前进程的信号信息(current->pending.signal和current->signal->shared_pending.signal)进行或操作(也是将两个地方的信号掩码合并起来),存储在临时变量pending中。获取当前进程的信号掩码后,在传递到上层时,还要调用sigandsets()将pending和当前进程的信号掩码进行与操作后的结果再传递到上层。

  现在的问题是要确定在调用sigandsets()之前pending的值和current->blocked的值。根据do_sigpending()来修改thread_process()函数,打印输出当前进程的信号位图和信号掩码,修改后的thread_process()函数如下所示:

static int thread_process(void *arg)
{
    sigset_t *sigset, __sigset;
  
    sigset = &__sigset;
  
    allow_signal(SIGURG);
    allow_signal(SIGTERM);
    allow_signal(SIGKILL);
    allow_signal(SIGSTOP);
    allow_signal(SIGCONT);
  
    printk(KERN_ALERT "the pid of thread_process is %d. ", current->pid);
  
    spin_lock_irq(&current->sighand->siglock);
    sigorsets(sigset, &current->pending.signal,
        &current->signal->shared_pending.signal);
    spin_unlock_irq(&current->sighand->siglock<SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">);</SPAN>
 
    printk(KERN_ALERT "Before receive signal, signal map: 0x%lX. ", sigset->sig[0]);
    printk(KERN_ALERT "Beofore receive signal, blocked map: 0x%lX. ", current->blocked.sig[0]);
  
    for ( ; !remove_mod; ) {
        /* Avoid infinite loop */
        msleep(1000);
        if (signal_pending(current)) {
            spin_lock_irq(&current->sighand->siglock);
         sigorsets(sigset, &current->pending.signal,
          &current->signal->shared_pending.signal);
         spin_unlock_irq(&current->sighand->siglock);
            printk(KERN_ALERT "Received signal, signal map: 0x%lX. ", sigset->sig[0]);
          
            printk(KERN_ALERT "Receive SIGURG signal ? %s. ",
                sigismember(sigset, SIGURG) ? "true" : "false");
            printk(KERN_ALERT "Receive SIGTERM signal ? %s. ",
                sigismember(sigset, SIGTERM) ? "true" : "false");
            printk(KERN_ALERT "Receive SIGKILL signal ? %s. ",
                sigismember(sigset, SIGKILL) ? "true" : "false");
            printk(KERN_ALERT "Receive SIGSTOP signal ? %s. ",
                sigismember(sigset, SIGSTOP) ? "true" : "false");
            /* Use halt to stop the system */
            printk(KERN_ALERT "Receive SIGCONT signal ? %s. ",
                sigismember(sigset, SIGCONT) ? "true" : "false");
            break;
        }
    }
    return 0;
}