linux 内核线程

linux内核可以看做是一个服务进程(管理软硬件资源,响应用户进程的种种合理以及不合理的请求)。内核需要多个执行流并行,为了防止可能的阻塞,多线程化是必要的。内核线程就是内核的分身,一个分身可以处理一件特定的事情。Linux内核使用内核线程来将内核分成几个功能模块,像kswapd、kflushd等等,这在处理异步事件如异步IO时特别有用,像我们在内核中可以通过创建一个线程来查询按键状态。内核线程的使用是廉价的,唯一使用的资源就是内核栈和上下文切换时保存寄存器的空间。支持多线程的内核叫多线程内核(Multi-Threads kernel)。内核线程的调度由内核负责,一个内核线程处于阻塞状态时不影响其他的内核线程,因为其实调度的基本单位。

查看linux内核线程文件kthread.h可以发现内核线程有以下几个函数

1、创建内核线程

struct task_struct *kthread_create(int (*threadfn)(void *data),
  void *data,
  const char namefmt[], ...);

注意:通过kthread_create创建的内核线程不会立即运行,还需要调用wake_up_process唤醒线程,即是kthread_run函数

2、创建内核线程并运行

/**
 * kthread_run - create and wake a thread.
 * @threadfn: the function to run until signal_pending(current).
 * @data: data ptr for @threadfn.
 * @namefmt: printf-style name for the thread.
 *
 * Description: Convenient wrapper for kthread_create() followed by
 * wake_up_process().  Returns the kthread or ERR_PTR(-ENOMEM).
 */
#define kthread_run(threadfn, data, namefmt, ...)			   \
({									   \
	struct task_struct *__k						   \
		= kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \
	if (!IS_ERR(__k))						   \
		wake_up_process(__k);					   \
	__k;								   \
})
创建并运行线程(kthread_run)是在kthread_create的基础上加了wake_up_process实现的

3、将内核线程绑定到某个CPU

/**
 * kthread_bind - bind a just-created kthread to a cpu.
 * @k: thread created by kthread_create().
 * @cpu: cpu (might not be online, must be possible) for @k to run on.
 *
 * Description: This function is equivalent to set_cpus_allowed(),
 * except that @cpu doesn't need to be online, and the thread must be
 * stopped (i.e., just returned from kthread_create()).
 */
void kthread_bind(struct task_struct *k, unsigned int cpu)
{
	BUG_ON(k->state != TASK_INTERRUPTIBLE);
	/* Must have done schedule() in kthread() before we set_task_cpu */
	wait_task_inactive(k);
	set_task_cpu(k, cpu);
	k->cpus_allowed = cpumask_of_cpu(cpu);
}

4、停止内核线程

/**
 * kthread_stop - stop a thread created by kthread_create().
 * @k: thread created by kthread_create().
 *
 * Sets kthread_should_stop() for @k to return true, wakes it, and
 * waits for it to exit.  Your threadfn() must not call do_exit()
 * itself if you use this function!  This can also be called after
 * kthread_create() instead of calling wake_up_process(): the thread
 * will exit without calling threadfn().
 *
 * Returns the result of threadfn(), or %-EINTR if wake_up_process()
 * was never called.
 */
int kthread_stop(struct task_struct *k)
{
	int ret;

	mutex_lock(&kthread_stop_lock);

	/* It could exit after stop_info.k set, but before wake_up_process. */
	get_task_struct(k);

	/* Must init completion *before* thread sees kthread_stop_info.k */
	init_completion(&kthread_stop_info.done);
	smp_wmb();

	/* Now set kthread_should_stop() to true, and wake it up. */
	kthread_stop_info.k = k;
	wake_up_process(k);
	put_task_struct(k);

	/* Once it dies, reset stop ptr, gather result and we're done. */
	wait_for_completion(&kthread_stop_info.done);
	kthread_stop_info.k = NULL;
	ret = kthread_stop_info.err;
	mutex_unlock(&kthread_stop_lock);

	return ret;
}

5、内核线程是否停止

/**
 * kthread_should_stop - should this kthread return now?
 *
 * When someone calls kthread_stop() on your kthread, it will be woken
 * and this will return true.  You should then return, and your return
 * value will be passed through to kthread_stop().
 */
int kthread_should_stop(void)
{
	return (kthread_stop_info.k == current);
}

6、内核线程测试例子

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


static struct task_struct *MyThread = NULL;

static int MyPrintk(void *data)
{
	char *mydata = kmalloc(strlen(data)+1, GFP_KERNEL);
	memset(mydata, '\0', strlen(data)+1);
	strncpy(mydata, data, strlen(data));
	
	while (!kthread_should_stop()) {
		printk("%s\n", mydata);
		msleep(1000);
	}
	kfree(mydata);
	return 0;
}

static int __init init_thread(void)
{
	MyThread = kthread_run(MyPrintk, "hello world", "mythread");
	return 0; 
}

static void __exit exit_thread1(void)
{
	if (MyThread) {
		printk("stop MyThread\n");
		kthread_stop(MyThread);
	}
}

module_init(init_thread);
module_exit(exit_thread1);


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值