博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OK6410A 开发板 (八) 29 linux-5.11 OK6410A 主要内核线程解析
阅读量:4286 次
发布时间:2019-05-27

本文共 6892 字,大约阅读时间需要 22 分钟。

  • 简述了 一下 系统内创建的 所有内核线程
// 进程 1 2 的 父进程为 0// 其他所有内核线程(被[]包括的) 父进程都是 kthreadd进程ID 所属用户 		 状态  COMMAND进程名		进程创建文件		进程创建函数// 1号用户进程    1 root      1412 S    {
linuxrc} init //init/main.c kernel_thread // 1号用户进程 // 2号内核进程 2 root 0 SW [kthreadd] // init/main.c kernel_thread // 2号内核线程,负责 创建所有的内核线程// 内核的管家进程 3 root 0 IW [kworker/0:0-eve] //kernel/workqueue.c create_worker 4 root 0 IW< [kworker/0:0H-kb] 5 root 0 IW [kworker/u2:0-ev] 16 root 0 IW [kworker/0:1-eve] 30 root 0 IW< [kworker/0:1H-kb] 31 root 0 IW< [kworker/u3:1-xp] 48 root 0 IW [kworker/u2:7-nf] 67 root 0 IW< [kworker/u3:4-xp] // "kworker" is a placeholder process for kernel worker threads, which perform most of the actual processing for the kernel, especially in cases where there are interrupts, timers, I/O, etc. // These typically correspond to the vast majority of any allocated "system" time to running processes. // It is not something that can be safely removed from the system in any way, and is completely unrelated to nepomuk or KDE (except in that these programs may make system calls, which may require the kernel to do something). // 用于执行内核工作队列,分为绑定 CPU (名称格式为 kworker/0:0-eve)和未绑定 CPU(名称格式为 kworker/u3:4-xp)两类。 7 root 0 SW [ksoftirqd/0] // kernel/softirq.c smpboot_register_percpu_thread // ksoftirqd以与kworker几乎相同的方式处理 softirq // softirq 使用的内核线程ksoftirqd// 模块相关进程 // 内存相关进程 6 root 0 IW< [mm_percpu_wq] // mm/vmstat.c alloc_workqueue 10 root 0 SW [oom_reaper] // mm/oom_kill.c kthread_run 11 root 0 IW< [writeback] // mm/backing-dev.c alloc_workqueue 12 root 0 SW [kcompactd0] // mm/compaction.c kthread_run 19 root 0 SW [kswapd0] // mm/vmscan.c kthread_run // 用于内存回收 // 网络相关进程 20 root 0 IW< [nfsiod] // fs/nfs/inode.c alloc_workqueue 21 root 0 IW< [ipv6_addrconf] // net/ipv6/addrconf.c create_workqueue 8 root 0 IW< [netns] // net/core/net_namespace.c create_singlethread_workqueue 9 root 0 IW< [inet_frag_wq] // net/ipv4/inet_fragment.c create_workqueue // 块设备相关进程 13 root 0 IW< [kblockd] // block/blk-core.c alloc_workqueue // rpc相关 15 root 0 IW< [rpciod] // net/sunrpc/sched.c alloc_workqueue 18 root 0 IW< [xprtiod] // net/sunrpc/sched.c alloc_workqueue // 防死机看门狗内核进程 14 root 0 SW [watchdogd] // drivers/watchdog/watchdog_dev.c kthread_create_worker // mmc 相关 23 root 0 IW< [sdhci] // drivers/mmc/host/sdhci.c alloc_workqueue 24 root 0 SW [irq/88-mmc0] // drivers/mmc/host/sdhci.c request_threaded_irq // 给中断线程化使用的irq内核线程 29 root 0 IW< [mmc_complete] // drivers/mmc/core/block.c alloc_workqueue// 用户进程 53 root 4100 S /sbin/mdev -df 64 root 19388 S /usr/bin/Xorg :0.0 vt01 -s 0 -noreset -allowMouseOpe// 后期 需 重点关注 这些进程// init kthreadd // kworker ksoftirqd // mem(5个) kblockd mmc(3个) watchdogd
  • kworker线程

入口是 worker_threadkthread	create->threadfn/即worker_thread		woke_up:			...					recheck:					if (!need_more_worker(pool))				goto sleep;			if (unlikely(!may_start_working(pool)) && manage_workers(worker))				goto recheck;			do{
process_scheduled_works process_one_work worker->current_func(work); }while(keep_working(pool)); sleep: schedule(); goto woke_up;
  • ksoftirqd 线程
kthread	create->threadfn/即run_ksoftirqd		__do_softirq			struct softirq_action *h;			h = softirq_vec;			while ((softirq_bit = ffs(pending))) {
h += softirq_bit - 1; h->action(h); h++; }
  • watchdogd 线程
总结 : 1.watchdogd 线程 是个 kworker 线程2.定时器的处理函数会提交喂狗任务给 watchdogd 线程4.watchdogd 线程被调入后喂狗---- 初始化时subsys_initcall_sync(watchdog_init);watchdog_init	watchdog_dev_init		watchdog_kworker = kthread_create_worker(0, "watchdogd"); // 即 kthread -> (create->threadfn/即worker_thread)module_platform_driver(s3c2410wdt_driver)	.probe      = s3c2410wdt_probe,	s3c2410wdt_probe	watchdog_register_device		__watchdog_register_device			watchdog_dev_register				watchdog_cdev_register										// 喂狗任务					kthread_init_work(&wd_data->work, watchdog_ping_work);										// 定时器					hrtimer_init(&wd_data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);					wd_data->timer.function = watchdog_timer_expired;----运行时// 定时器时间到了,watchdog_timer_expired被调用// watchdog_timer_expired 提交喂狗任务 给 watchdog_kworkerwatchdog_timer_expired	kthread_queue_work(watchdog_kworker, &wd_data->work);// 喂狗任务 被调用 watchdog_ping_work	__watchdog_ping(wd_data->wdd);		wdd->ops->ping(wdd)/即s3c2410wdt_keepalive			writel(wdt->count, wdt->reg_base + S3C2410_WTCNT);
  • mmc 相关线程
//等涉及到 mmc 分析了再说// 设备驱动相关
  • kblockd 线程
// 等涉及 ext3 分析了再说// 文件系统相关
  • mem 相关线程
// 等涉及到内存分析了再说// 内存相关

其他

  • 创建内核线程的API是什么
A.比较高级的API : kernel_threadB.比较中级的API : kthread_createC.比较简单的API : alloc_workqueue/create_workqueue/smpboot_register_percpu_thread/request_threaded_irq使用A 的 场景 : 就 两个使用B 的 场景 : 不超过20个使用C 的 场景 : 很多,有超过200个 内核建议我们使用CC 对于 我们来说是什么一个创建线程的方法(包括3方面)	1.工作者线程的创建 					// 任务的创建完全是内核处理的,我们不需要关心	2.工作任务的提交(当然先要创建任务) 	// 任务的创建和提交是我们处理的,需要关心 // 有些是内核处理的	3.工作者线程的唤醒 					// 唤醒 是 我们处理的,需要关心 // 有些是内核处理的C 创建的线程(名为target)  会 查询 队列(名为queue)中的任务,然后没有任务(task)就睡眠如果有代码将任务(task)插入了该队列(queue),然后唤醒target,此时 target 会执行任务(task)中的处理函数对于内核,这个框架的实现有好几种	1. 工作队列	2. softirq工作队列	1.利用 alloc_workqueue/create_workqueue 完成 工作者线程的创建	2.利用 insert_work 						完成 工作任务的提交 	// queue_work 调用的深层函数	3.利用 wake_up_worker 					完成 工作者线程的唤醒 // queue_work 调用的深层函数softirq	1. 利用 smpboot_register_percpu_thread 	完成 工作者线程的创建	2. 利用 or_softirq_pending 				完成 工作任务的提交	3. 利用 wakeup_softirqd 				完成 工作者线程的唤醒

softirq机制

处理函数的调用分为两种	1. 直接处理 // 对应 __do_softirq  ,但是 __do_softirq  中也会 有 该动作(唤醒 softirqd 处理)执行的条件判断	2. 唤醒 softirqd 处理 // 对应 __do_softirqd  , 该函数位于 softirqd 中,是主体函数
原因:	处理函数的调用A :	1.__do_softirq // 一个函数,直接调用即可,该函数可以直接处理softirq,而不用唤醒 softirqd	2.__do_softirqd // 在一个线程里面,使其被调用只能先 唤醒该线程1		// linux-5.11 中没有这个函数,而是用的__do_softirq 		// TODO 处理函数的调用A的封装:	1.invoke_softirq/do_softirq	2.wakeup_softirqd处理函数的调用A的封装的封装:	1.irq_exit/netif_rx_ni/local_bn_enable	2.raise_softirq/__do_softirq 处理函数的调用A的封装的封装的封装:	1.无	2.invoke_softirq/do_softirq处理函数的调用A的封装的封装的封装的封装:	1.无	2.irq_exit/netif_rx_ni/local_bn_enable
  • 引起 __do_softirq 运行的函数
处理函数的调用A :	1.__do_softirq // 一个函数,直接调用即可处理函数的调用A的封装:	1.invoke_softirq/do_softirq处理函数的调用A的封装的封装:	1.irq_exit/netif_rx_ni/local_bn_enable
  • 引起 __do_softirqd 运行的函数
处理函数的调用A :	2.__do_softirqd // 在一个线程里面,使其被调用只能先 唤醒该线程1处理函数的调用A的封装:	2.wakeup_softirqd处理函数的调用A的封装的封装:	2.raise_softirq/__do_softirq 处理函数的调用A的封装的封装的封装:	2.invoke_softirq/do_softirq处理函数的调用A的封装的封装的封装的封装:	2.irq_exit/netif_rx_ni/local_bn_enable
  • 同时引起 两者 运行的函数
irq_exit/netif_rx_ni/local_bn_enableinvoke_softirq/do_softirq__do_softirq
  • 只引起 __do_softirq(绝对不会引起唤醒softirqd的函数) 运行的函数
  • 只引起 __do_softirqd 运行的函数
raise_softirqwakeup_softirqd__do_softirqd

转载地址:http://lcigi.baihongyu.com/

你可能感兴趣的文章
QtCreator介绍
查看>>
QT工程实例
查看>>
pkg-config
查看>>
Linux内核分析-1/反汇编(堆栈)
查看>>
Linux内核分析-2/时间片轮转多道程序
查看>>
Linux内核分析-4/5/系统调用
查看>>
c/c++常见关键字
查看>>
C++内存地址分配和内存区划分简介
查看>>
C++数值交换
查看>>
指针数组、数组指针、函数指针、指针函数
查看>>
float,double在内存中的存储方式
查看>>
int main(int argc,char* argv[])详解
查看>>
C++打印地址
查看>>
ARM处理器比较:A8/A9
查看>>
ARM处理器工作模式
查看>>
ARM处理器寄存器
查看>>
汇编语言学习
查看>>
ARM寻址方式
查看>>
uboot工作流程分析
查看>>
不錯的技術論壇
查看>>