内核线程中获取接收到的信号
作者:网络转载 发布时间:[ 2013/2/1 10:17:45 ] 推荐标签:
将上面的代码编译成内核模块,插入到系统中,打开系统日志,查看创建的内核线程的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(¤t->sighand->siglock);
sigorsets(&pending, ¤t->pending.signal,
¤t->signal->shared_pending.signal);
spin_unlock_irq(¤t->sighand->siglock);
/* Outside the lock because only this thread touches it. */
sigandsets(&pending, ¤t->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(¤t->sighand->siglock);
sigorsets(sigset, ¤t->pending.signal,
¤t->signal->shared_pending.signal);
spin_unlock_irq(¤t->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(¤t->sighand->siglock);
sigorsets(sigset, ¤t->pending.signal,
¤t->signal->shared_pending.signal);
spin_unlock_irq(¤t->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;
}
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11