美文网首页程序员
内核线程同步之signal

内核线程同步之signal

作者: 网路元素 | 来源:发表于2019-10-20 15:35 被阅读0次

对于内核线程,尤其是在同一模块里有多个时,我们想终止其中一个,而又不想卸载模块,此时signal就帮上我们一个大忙了,在设计时让线程接收信号并处理,想停止时发信号给它,而在内核里需要用到如下信号相关函数: 

1.signal_pending 

在Linux内核源码include/linux/sched.h文件里,有如下函数定义:

static inline int signal_pending(struct task_struct *p)
{
        return unlikely(test_tsk_thread_flag(p,TIF_SIGPENDING));
}

该函数用于判断指定线程有没有接收到信号,即信号有没有被阻塞。上面的参数我们一般是判断当前线程,故而会用到include/asm-generic/current.h里的current宏,定义如下:

#define current get_current()

2.allow_signal 

在Linux内核源码kernel/exit.c有该函数的实现,而在include/linux/sched.h文件里有如下声明:

extern int allow_signal(int);

其参数是SIGKILL等宏,在include/uapi/asm-generic/signal.h文件中有相应的宏定义。 内核线程允许接收信号后,还需要确保该线程是可打断的,需要用到如下宏: 

1.set_current_state 

在include/linux/sched.h文件中有如下宏定义:

#define set_current_state(state_value) \
        set_mb(current->state, (state_value))

2.TASK_INTERRUPTIBLE 

在同一头文件中如下宏定义:

#define TASK_INTERRUPTIBLE 1

上面两个宏结合使用用于配置当前线程的状态是可被中断的。接下来上代码吧:

#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/delay.h>

static struct task_struct * slam_thread = NULL;
static int is_signal_exited = 0;

static int slam_func(void *data)
{
        printk("<xinu>%s()!\n", __func__);
        allow_signal(SIGKILL);
        mdelay(1000);

        while(!signal_pending(current) && !kthread_should_stop())
        {
                printk("<xinu>jiffies(%lu)\n", jiffies);
                set_current_state(TASK_INTERRUPTIBLE);
                schedule_timeout(msecs_to_jiffies(5000));
        }

        printk("<xinu>leave slam_func!\n");
        is_signal_exited = 1;

        return 0;
}

static __init int kthread_signal_example_init(void)
{
        slam_thread = kthread_run(slam_func, NULL, "slam");
        printk("<xinu>kthread_signal_example_init()!\n");

        return 0;
}

static __exit void kthread_signal_example_exit(void)
{
        if(!is_signal_exited && !IS_ERR(slam_thread))
        {
                kthread_stop(slam_thread);
        }

        printk("<xinu>%s()!\n", __FUNCTION__);
}

module_init(kthread_signal_example_init);
module_exit(kthread_signal_example_exit);

相应的Makefile文件内容如下:

obj-m += kthread_signal_example.o

CUR_PATH:=$(shell pwd)
LINUX_KERNEL_PATH:=/home/xinu/linux-3.13.6

all:
        make -C $(LINUX_KERNEL_PATH) M=$(CUR_PATH) modules

clean:
        make -C $(LINUX_KERNEL_PATH) M=$(CUR_PATH) clean

对应的源码文件目录树如下:

 /home/xinu/xinu/linux_kernel_driver_l1/kthread_signal_example/
├── kthread_signal_example.c
└── Makefile 

当我们编译加载模块后,使用ps aux命令可以看到有如下一行信息: 

root 11390 0.0 0.0 0 0 ? S 17:46 0:00 [slam] 

其中11390就是该线程的PID,此时我们通过使用kill -SIGKILL 11390发信号终止线程rmmod卸载模块的方式对比dmesg的输出情况,就可以知道信号在什么时候使用,避免每执行一条命令都看下dmesg信息。 

参考网址: 

http://www.cnblogs.com/zhuyp1015/archive/2012/06/13/2548494.html
http://lwn.net/Articles/53563/
http://reneeciou.blogspot.com/2013/08/linux-kernel-threads.html

相关文章

  • 内核线程同步之signal

    对于内核线程,尤其是在同一模块里有多个时,我们想终止其中一个,而又不想卸载模块,此时signal就帮上我们一个大忙...

  • 内核线程同步之completion

    Completion,完成量,用于多线程间同步,即线程A要往下执行需要等待线程B执行到指定代码后才继续执行,这时就...

  • Windows内核模式下的线程同步

    Windwos下内核模式/用户模式实现线程同步的比较 在用户模式下进行线程同步的最大好处就是非常快。利用内核对象进...

  • 同步异步,阻塞和非阻塞概念说明

    同步和异步:就是用户线程与内核的交互方式:同步是指用户线程发起IO请求后需要等待或者轮询内核IO操作完成后才能继续...

  • 深入理解异步I/O+epoll+协程

    前言 同步和异步的概念描述的是用户线程与内核的交互方式:同步是指用户线程发起IO请求后需要等待或者轮询内核IO操作...

  • 内核线程同步之wait_queue

    在《内核线程同步之completion》一文中说到completion完成量也是基于wait_queue等待队列机...

  • 网络 I/O 模型的演进

    一、同步和异步 同步和异步描述的是用户线程与内核的交互方式: 同步是指用户线程发起 I/O 请求后需要等待或者轮询...

  • 五种 I/O 模型简述

    相关概念 同步和异步 描述的是用户线程与内核的交互方式: 同步是指用户线程发起 I/O 请求后需要等待(阻塞)或者...

  • 浏览器JS运行机制(线程)

    浏览器常驻线程 浏览器的内核是多线程的,它们在内核制控下相互配合以保持同步,一个浏览器至少实现三个常驻线程:jav...

  • Linux之IO模型机制

    同步和异步 同步和异步是用户线程与内核交互的方式,关注的是消息通知机制,是如何通知调用者. 同步: synchro...

网友评论

    本文标题:内核线程同步之signal

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