内核线程

来源:互联网 发布:qq群淘宝客用什么软件 编辑:程序博客网 时间:2024/05/16 16:21
linux 内核线程拥有独立堆栈和优先级运行机制,内核线程跟用户空间进程一样用结构体struct task_struct来描述,所以从运行机制看,实际上就是一个进程,并且共享父进程资源,但是没有自己独立的进程空间,而且还不能跟用户空间交互,即current->mm 为空。

创建内核线程

o 利用kernel_thread() 创建
使用该接口创建的线程,必须在该线程中调用daemonize()函数,这是因为只有当线程的父进程指向"Kthreadd"时,该线程才算是内核线程, 而恰好daemonize()函数主要工作便是将该线程的父进程改成“kthreadd"内核线程;默认情况下,调用deamonize()后,会阻塞所有信号,如果想操作某个信号可以调用allow_signal()函数。
int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);void daemonize(const char * name,...);
o 利用kthread_create() 创建
而kthread_create接口,则是标准的内核线程创建接口,只须调用该接口便可创建内核线程;默认创建的线程是存于不可运行的状态,所以需要在父进程中通过调用wake_up_process()函数来启动该线程。
struct task_struct *kthread_create(int (*threadfn)(void *data),void *data,                                  const char namefmt[], ...);int wake_up_process(struct task_struct *p); // 唤醒线程开始运行struct task_struct *kthread_run(int (*threadfn)(void *data),void *data,                                const char namefmt[], ...); // 封装上述两个函数

以watchdog喂狗内核线程为例

static int __init start_watchdog_daemon(void){int ret = 0;struct task_struct *watchdog_task;/* Register watchdog feed man */pr_info("%s: Start watchdog feed thread\n", __func__);watchdog_task = kthread_run(watchdog_thread, NULL, "s3c_wdt/daemon"); // 利用kthread_run创建内核 线程并且开始运行if (IS_ERR(watchdog_task)) {pr_err("%s: Failed to create watchdog_thread\n", __func__);ret = -EFAULT;}return ret;}static int watchdog_thread(void *data) // threadfn{unsigned int keepalive_cycle = tmr_margin / 2;pr_info("%s: Enter into watchdog_thread\n", __func__);while (1) {msleep_interruptible(keepalive_cycle * 1000); // 让出cpu, 延时keppalive_cycle * 1000 时间pr_debug("%s: feed the watchdog\n", __func__);s3c2410wdt_keepalive(&s3c2410_wdd); // 喂狗}return 0;}

内核机制分析

kthread_run(threadfn, data, namefmt, ...)-> kthread_create(threadfn, data, namefmt, arg...)-> kthread_create_on_node(threadfn, data, -1, namefmt, ##arg)-> struct kthread_create_info create; // 添加线程创建结构体   create.threadfn = threadfn;   create.data = data;   create.node = node;   init_completion(&create.done);   list_add_tail(&create.list, &kthread_create_list); // 加入kthread_create_list, threadd 会   wake_up_process(kthreadd_task); // wakeup init/main.c rese_init() 里创建的kthreadd内核线程   wait_for_completion(&create.done); // 线程创建同步控制-> wake_up_process() // 唤醒线程开始执行init/main.c rest_init()-> pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES); // 创建内核线程kthreaddd-> kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns); // 被 wake_up_process(kthreadd_task); 唤醒执行kthreaddkthreadd()-> struct task_struct *tsk = current; // 继承父进程,并且设置新环境   /* Setup a clean context for our children to inherit. */   set_task_comm(tsk, "kthreadd");   ignore_signals(tsk);   set_cpus_allowed_ptr(tsk, cpu_all_mask);   set_mems_allowed(node_states[N_HIGH_MEMORY]);   current->flags |= PF_NOFREEZE-> set_current_state(TASK_INTERRUPTIBLE);if (list_empty(&kthread_create_list)) // 为空,让出cpuschedule();__set_current_state(TASK_RUNNING); // 设置running状态-> for (;;) // for 循环遍历 kthread_create_list, 创建线程create_kthread(create); // 创建线程create_kthread(create)-> pid = kernel_thread(kthread, create, CLONE_FS | CLONE_FILES | SIGCHLD);-> return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); // 创建内核线程-> complete(&create->done); // 完成kthread_run() 中的同步控制, 至此线程创建完毕kernel_thread(kthread, create, CLONE_FS | CLONE_FILES | SIGCHLD);-> return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); // 创建内核线程void daemonize(const char *name, ...)-> reparent_to_kthreadd(); // 指定父进程为kthreadd,



原创粉丝点击