linux 创建内核线程
Linux内核可以看作一个服务进程(管理软硬件资源,响应用户进程的种种合理以及不合理的请求)。内核需要多个执行流并行,为了防止可能的阻塞,支持多线程是必要的。内核线程就是内核的分身,一个分身可以处理一件特定事情。内核线程的调度由内核负责,一个内核线程处于阻塞状态时不影响其他的内核线程,因为其是调度的基本单位。这与用户线程是不一样的。因为内核线程只运行在内核态,因此,它只能使用大于PAGE_OFFSET(3G)的地址空间。内核线程和普通的进程间的区别在于内核线程没有独立的地址空间,mm指针被设置为NULL;它只在 内核空间运行,从来不切换到用户空间去;并且和普通进程一样,可以被调度,也可以被抢占。
内核线程(thread)或叫守护进程(daemon),在操作系统中占据相当大的比例,当Linux操作系统启动以后,你可以用”ps -ef”命令查看系统中的进程,这时会发现很多以”d”结尾的进程名,确切说名称显示里面加 "[]"的,这些进程就是内核线程。
创建内核线程最基本的两个接口函数是:
kthread_run(threadfn, data, namefmt, ...)
和
kernel_thread(int(* fn)(void *),void * arg,unsigned long flags)
这里我们主要介绍kthread_run,后面会专门分析这两个函数的异同。
kthread_run 事实上是一个宏定义:
/*** 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()两部分组成,这样的好处是用kthread_run()创建的线程可以直接运行。外界调用kthread_run创建运行线程。kthread_run是个宏定义,首先调用kthread_create()创建线程,如果创建成功,再调用wake_up_process()唤醒新创建的线程。kthread_create()根据参数向kthread_create_list中发送一个请求,并唤醒kthreadd,之后会调用wait_for_completion(&create.done)等待线程创建完成。新创建的线程开始运行后,入口在kthread(),kthread()调用complete(&create->done)唤醒阻塞的模块进程,并使用schedule()调度出去。kthread_create()被唤醒后,设置新线程的名称,并返回到kthread_run中。kthread_run调用wake_up_process()重新唤醒新创建线程,此时新线程才开始运行kthread_run参数中的入口函数。
在介绍完如何创建线程之后,下面来介绍另外两个基本的函数:
int kthread_stop(struct task_struct *k);
int kthread_should_stop(void);
kthread_stop()负责结束创建的线程,参数是创建时返回的task_struct指针。kthread设置标志should_stop,并等待线程主动结束,返回线程的返回值。在调用 kthread_stop()结束线程之前一定要检查该线程是否还在运行(通过 kthread_run 返回的 task_stuct 是否有效),否则会造成灾难性的后果。kthread_run的返回值tsk。不能用tsk是否为NULL进行检查,而要用IS_ERR()宏定义检查,这是因为返回的是错误码,大致从0xfffff000~0xffffffff。
kthread_should_stop()返回should_stop标志(参见 struct kthread )。它用于创建的线程检查结束标志,并决定是否退出。
kthread() (注:原型为:static int kthread(void *_create) )的实现在kernel/kthread.c中,头文件是include/linux/kthread.h。内核中一直运行一个线程kthreadd,它运行kthread.c中的kthreadd函数。在kthreadd()中,不断检查一个kthread_create_list链表。kthread_create_list中的每个节点都是一个创建内核线程的请求,kthreadd()发现链表不为空,就将其第一个节点退出链表,并调用create_kthread()创建相应的线程。create_kthread()则进一步调用更深层的kernel_thread()创建线程,入口函数设在kthread()中。
外界调用kthread_stop()删除线程。kthread_stop首先设置结束标志should_stop,然后调用wake_for_completion(&kthread->exited)上,这个其实是新线程task_struct上的vfork_done,会在线程结束调用do_exit()时设置。
附:
struct kthread {int should_stop;struct completion exited;};int kthreadd(void *unused) {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 | PF_FREEZER_NOSIG;for (;;) {set_current_state(TASK_INTERRUPTIBLE);if (list_empty(&kthread_create_list))schedule();__set_current_state(TASK_RUNNING);spin_lock(&kthread_create_lock);while (!list_empty(&kthread_create_list)) {struct kthread_create_info *create;create = list_entry(kthread_create_list.next,struct kthread_create_info, list);list_del_init(&create->list);spin_unlock(&kthread_create_lock);create_kthread(create);spin_lock(&kthread_create_lock);}spin_unlock(&kthread_create_lock);}return 0; }/*** 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. This can also be called after kthread_create()* instead of calling wake_up_process(): the thread will exit without* calling threadfn().** If threadfn() may call do_exit() itself, the caller must ensure* task_struct can't go away.** Returns the result of threadfn(), or %-EINTR if wake_up_process()* was never called.*/int kthread_stop(struct task_struct *k) {struct kthread *kthread;int ret;trace_sched_kthread_stop(k);get_task_struct(k);kthread = to_kthread(k);barrier(); /* it might have exited */if (k->vfork_done != NULL) {kthread->should_stop = 1;wake_up_process(k);wait_for_completion(&kthread->exited);}ret = k->exit_code;put_task_struct(k);trace_sched_kthread_stop_ret(ret);return ret;}
linux 创建内核线程相关推荐
- kthread_run创建内核线程的原理
kthread_run是一个宏,用来创建一个进程,并且将其唤醒,其定义在头文件include/linux/kthread.h中. #define kthread_run(threadfn, data, ...
- linux 获取内核线程数,如何从命令行获取Linux中的CPU /内核数量?
前言: 基于/proc/cpuinfo的答案的问题是,它们parsing了供人类使用的信息,因此缺乏为机器分析devise的稳定格式 :输出格式可能因平台和运行时间条件而有所不同; 在Linux上使用 ...
- linux内核线程创建销毁机制
这个话题乍一听貌似比较大,其实线程创建本身就是一件很平常的事情. 下面将要介绍的是,新版linux中创建内核线程的机制做了一些变化(其实本质没变,最终还是调用do_fork()来实现),和控制线程的时 ...
- 【Linux 内核】进程管理 ( 内核线程概念 | 内核线程、普通进程、用户线程 | 内核线程与普通进程区别 | 内核线程主要用途 | 内核线程创建函数 kernel_thread 源码 )
文章目录 一.内核线程概念 二.内核线程.普通进程.用户线程 三.内核线程.普通进程区别 四.内核线程主要用途 五.内核线程创建函数 kernel_thread 源码 一.内核线程概念 直接 由 Li ...
- Linux内核线程kernel thread详解--Linux进程的管理与调度(十)【转】
转自:https://blog.csdn.net/gatieme/article/details/51589205 版权声明:本文为博主原创文章 && 转载请著名出处 @ http:/ ...
- Linux内核线程kernel thread详解--Linux进程的管理与调度
内核线程 为什么需要内核线程 Linux内核可以看作一个服务进程(管理软硬件资源,响应用户进程的种种合理以及不合理的请求). 内核需要多个执行流并行,为了防止可能的阻塞,支持多线程是必要的. 内核线程 ...
- linux kernel基本构成的内容有下列哪些项_Linux内核线程kernel thread详解
内核线程 为什么需要内核线程 Linux内核可以看作一个服务进程(管理软硬件资源,响应用户进程的种种合理以及不合理的请求). 内核需要多个执行流并行,为了防止可能的阻塞,支持多线程是必要的. 内核线程 ...
- 深入理解Linux内核之内核线程(上)
1.开场白 环境: 处理器架构:arm64 内核源码:linux-5.11 ubuntu版本:20.04.1 代码阅读工具:vim+ctags+cscope 在linux系统中, 我们接触最多的莫过于 ...
- linux内核编程_内核线程kthread_run
linux内核编程_内核线程kthread_run 1. 简述: 2. 使用示例: 3. 详述: 1. 简述: 头文件: include/linux/kthread.h 数据类型: struct ta ...
最新文章
- mysql的基本介绍简书_mysql 简介
- python之迭代器,生成器
- hdu-5781 ATM Mechine(dp+概率期望)
- java之Synchronized(锁住对象和锁住代码)
- Hibernate4.3基础知识2
- 实话!为什么2019年,我劝你别再闷头学Python!
- Python的矩阵分块
- Oracle查看表空间使用率及爆满解决方案
- kali 运行wifite时遇到的问题及解决办法
- 2022氯化工艺考试题库及答案
- Local Storage、Session Storage、Cookies
- Linux vim分屏,如何切换窗口
- FPGA之旅设计99例之第二十一例----VGA串口SDRAM显示图片
- STC8H单片机I2C协议驱动OLED 的困惑
- deny后加to do还是doing_区别的to do和doing用法的小技巧
- 【215】第K个大的数,K相关题目-分治、堆应用
- apicloud (第五篇 bmap百度地图一键回到当前位置)
- 计算机中丢失ENWeb,vbaen32.olb
- 一起设计一个Android倒计时组件
- GNSS 差分定位技术
热门文章
- 怎样让datalist的记录条滚动呢?_马自达阿特兹,这款车怎样?
- android win8风格布局,Android仿Win8界面开发
- thymeleaf if判断_Thymeleaf入门——入门与基本概述
- c语言程序错误提示一个找不到,C语言编辑程序出现错误提示.doc
- python矩阵中的冒号:
- layui 日期格式不正确(date、datetime)区别
- WampServer + phpcms 开发中,浏览器 localhost 出现 Cannot to connect to mySQL server 的原因分析和解决办法?
- java游戏西门大官人_valueOf()方法的使用
- PHP导航猫导航系统源码
- 简单FTP服务器(ccd) v1.0