kthread usage

本文介绍了Linux内核中线程的创建与管理方法,包括使用kthread_create及kthread_run函数创建线程,以及如何利用kthread_stop安全地终止线程。文中还详细展示了线程函数的具体实现方式。

1 使用kthread_create创建线程:
struct task_struct *kthread_create(int (*threadfn)(void *data),

void *data,
const char *namefmt, ...);
这个函数可以像printk一样传入某种格式的线程名
线程创建后,不会马上运行,而是需要将kthread_create() 返回的task_struct指针传给wake_up_process(),然后通过此函数运行线程。
2. 当然,还有一个创建并启动线程的函数:kthread_run
struct task_struct *kthread_run(int (*threadfn)(void *data),
void *data,
const char *namefmt, ...);
3. 线程一旦启动起来后,会一直运行,除非该线程主动调用do_exit函数,或者其他的进程调用kthread_stop函数,结束线程的运行。
int kthread_stop(struct task_struct *thread);
kthread_stop() 通过发送信号给线程。
如果线程函数正在处理一个非常重要的任务,它不会被中断的。当然如果线程函数永远不返回并且不检查信号,它将永远都不会停止。
参考:Kernel threads made easy

--

#include <linux/kthread.h> static struct task_struct * _task; static struct task_struct * _task2; static struct task_struct * _task3; static int thread_func(void *data) { int j,k; int timeout; wait_queue_head_t timeout_wq; static int i = 0; i++; j = 0; k = i; printk("thread_func %d started/n", i); init_waitqueue_head(&timeout_wq); while(!kthread_should_stop()) { interruptible_sleep_on_timeout(&timeout_wq, HZ); printk("[%d]sleeping..%d/n", k, j++); } return 0; } void my_start_thread(void) { //_task = kthread_create(thread_func, NULL, "thread_func2"); //wake_up_process(_task); _task = kthread_run(thread_func, NULL, "thread_func2"); _task2 = kthread_run(thread_func, NULL, "thread_func2"); _task3 = kthread_run(thread_func, NULL, "thread_func2"); if (!IS_ERR(_task)) { printk("kthread_create done/n"); } else { printk("kthread_create error/n"); } } void my_end_thread(void) { int ret = 0; ret = kthread_stop(_task); printk("end thread. ret = %d/n" , ret); ret = kthread_stop(_task2); printk("end thread. ret = %d/n" , ret); ret = kthread_stop(_task3); printk("end thread. ret = %d/n" , ret); }

在执行kthread_stop的时候,目标线程必须没有退出,否则会Oops。原因很容易理解,当目标线程退出的时候,其对应的task结构也变得无效,kthread_stop引用该无效task结构就会出错。

为了避免这种情况,需要确保线程没有退出,其方法如代码中所示:

thread_func()

{

// do your work here

// wait to exit

while(!thread_could_stop())

{

wait();

}

}

exit_code()

{

kthread_stop(_task); //发信号给task,通知其可以退出了

}

这种退出机制很温和,一切尽在thread_func()的掌控之中,线程在退出时可以从容地释放资源,而不是莫名其妙地被人“暗杀”。

#include <linux/module.h> #include <linux/kernel.h> #include <linux/time.h> #include <linux/jiffies.h> #include <linux/kernel_stat.h> static struct timer_list cpu_monitor_timer; static u64 prev_user, prev_nice, prev_system, prev_idle; static u64 prev_iowait, prev_irq, prev_softirq, prev_steal; void cpu_timer_callback(struct timer_list *t) { int cpu_usage = 0; struct kernel_cpustat *kstat = &kcpustat_cpu(0); u64 cur_user = kstat->cpustat[CPUTIME_USER]; u64 cur_nice = kstat->cpustat[CPUTIME_NICE]; u64 cur_system = kstat->cpustat[CPUTIME_SYSTEM]; u64 cur_idle = kstat->cpustat[CPUTIME_IDLE]; u64 cur_iowait = kstat->cpustat[CPUTIME_IOWAIT]; u64 cur_irq = kstat->cpustat[CPUTIME_IRQ]; u64 cur_softirq = kstat->cpustat[CPUTIME_SOFTIRQ]; u64 cur_steal = kstat->cpustat[CPUTIME_STEAL]; u64 prev_total = prev_user + prev_nice + prev_system + prev_idle + prev_iowait + prev_irq + prev_softirq + prev_steal; u64 cur_total = cur_user + cur_nice + cur_system + cur_idle + cur_iowait + cur_irq + cur_softirq + cur_steal; u64 prev_busy = prev_total - prev_idle; u64 cur_busy = cur_total - cur_idle; s64 diff_total = cur_total - prev_total; s64 diff_busy = cur_busy - prev_busy; if (diff_total > 0) { cpu_usage = div64_u64(diff_busy * 100, diff_total); cpu_usage = min(cpu_usage, 100); cpu_usage = max(cpu_usage, 0); printk(KERN_INFO "CPU usage: %d%%\n", cpu_usage); } prev_user = cur_user; prev_nice = cur_nice; prev_system = cur_system; prev_idle = cur_idle; prev_iowait = cur_iowait; prev_irq = cur_irq; prev_softirq = cur_softirq; prev_steal = cur_steal; mod_timer(&cpu_monitor_timer, jiffies + HZ); } static int __init cpu_monitor_init(void) { printk(KERN_INFO "cpu monitor init\n"); struct kernel_cpustat *kstat = &kcpustat_cpu(0); prev_user = kstat->cpustat[CPUTIME_USER]; prev_nice = kstat->cpustat[CPUTIME_NICE]; prev_system = kstat->cpustat[CPUTIME_SYSTEM]; prev_idle = kstat->cpustat[CPUTIME_IDLE]; prev_iowait = kstat->cpustat[CPUTIME_IOWAIT]; prev_irq = kstat->cpustat[CPUTIME_IRQ]; prev_softirq = kstat->cpustat[CPUTIME_SOFTIRQ]; prev_steal = kstat->cpustat[CPUTIME_STEAL]; setup_timer(&cpu_monitor_timer, cpu_timer_callback, 0); mod_timer(&cpu_monitor_timer, jiffies + HZ); return 0; } static void __exit cpu_monitor_exit(void) { printk(KERN_INFO "cpu monitor exit\n"); del_timer(&cpu_monitor_timer); } module_init(cpu_monitor_init); module_exit(cpu_monitor_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Cly"); MODULE_DESCRIPTION("CPU usage monitor"); 希望占用率>90发送信号
最新发布
09-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值