内核线程
来源:互联网 发布:qq群淘宝客用什么软件 编辑:程序博客网 时间:2024/05/16 16:21
linux 内核线程拥有独立堆栈和优先级运行机制,内核线程跟用户空间进程一样用结构体struct task_struct来描述,所以从运行机制看,实际上就是一个进程,并且共享父进程资源,但是没有自己独立的进程空间,而且还不能跟用户空间交互,即current->mm 为空。
使用该接口创建的线程,必须在该线程中调用daemonize()函数,这是因为只有当线程的父进程指向"Kthreadd"时,该线程才算是内核线程, 而恰好daemonize()函数主要工作便是将该线程的父进程改成“kthreadd"内核线程;默认情况下,调用deamonize()后,会阻塞所有信号,如果想操作某个信号可以调用allow_signal()函数。
而kthread_create接口,则是标准的内核线程创建接口,只须调用该接口便可创建内核线程;默认创建的线程是存于不可运行的状态,所以需要在父进程中通过调用wake_up_process()函数来启动该线程。
创建内核线程
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,
- 内核线程
- 内核线程
- 内核线程
- 内核线程
- 内核线程
- 内核线程
- 内核线程
- 内核线程
- 内核线程
- 内核线程
- 内核线程
- 内核线程
- 内核线程
- 内核线程
- 内核线程
- 内核线程
- 内核线程
- Linux内核-内核线程
- apache tomcat问题
- android文件下载大小和网络不一致(偏大)
- android RatingBar自定义图片
- 像计算机科学家一样思考python2 笔记 - 字典 Dictionary
- iOS eXosip2 osip2 编译
- 内核线程
- C/C++:函数的编译方式与调用约定以及extern “C”的使用
- cvCreateVideoWriter 录制视频的一个可用程序
- 给js添加 in_array 方法
- 电力通信资源管理系统
- 关于Eclipse中各种小标志的说明
- 我也说说Hough变换【转】
- TDD测试驱动的javascript开发(2) ---- javascript面向对象 ~~ 深入学习javascript中prototype
- MyEclipse启动tomcat增加内存配置