内核线程分析报告

刚刚开机之后,使用ps 查看系统内的内核线程,主要情况如下:   

共发现有232 个内核线程存在,它们分别是:

   (1 )kthreadd :这种内核线程只有一个,它的作用是管理调度其它的内核线程。它在内核初始化的时候被创建,会循环运行一个叫做kthreadd 的函数,该函数的作用是运行kthread_create_list 全局链表中维护的kthread 。可以调用kthread_create 创建一个kthread,它会被加入到kthread_create_list 链表中,同时kthread_create 会weak up kthreadd_task。kthreadd 在执行kthread 会调用老的接口——kernel_thread 运行一个名叫“kthread” 的内核线程去运行创建 的kthread ,被执行过的kthread 会从kthread_create_list 链表中删除,并且kthreadd 会不断调用scheduler 让出CPU 。这个线程不能关闭。

   (2 )migration :这种内核线程共有32 个,从migration/0 到migration/31 ,每个处理器核对应一个migration 内核线程,主要作用是作为相应CPU 核的迁移进程,用来执行进程迁移操作,内核中的函数是migration_thread() 。属于2.6 内核的负载平衡系统,该进程在系统启动时自动加载(每个 cpu 一个),并将自己设为 SCHED_FIFO 的实时进程,然后检查runqueue::migration_queue 中是否有请求等待处理,如果没有,就在 TASK_INTERRUPTIBLE 中休眠,直至被唤醒后再次检查。migration_queue 仅在set_cpu_allowed() 中添加,当进程(比如通过 APM 关闭某 CPU 时)调用set_cpu_allowed() 改变当前可用 cpu ,从而使某进程不适于继续在当前 cpu 上运行时,就会构造一个迁移请求数据结构 migration_req_t ,将其植入进程所在cpu 就绪队列的migration_queue 中,然后唤醒该就绪队列的迁移 daemon (记录在runqueue::migration_thread 属性中),将该进程迁移到合适的cpu 上去在 目前的实现中,目的 cpu 的选择和负载无关,而是"any_online_cpu(req->task->cpus_allowed)" ,也就是按 CPU编号顺序的第一个 allowed 的CPU 。所以,和 load_balance() 与调度器、负载平衡策略密切相关不同,migration_thread() 应该说仅仅是一个 CPU 绑定以及 CPU 电源管理等功能的一个接口。这个线程是调度系统的重要组成部分,也不能被关闭。

      (3 )watchdog :这种内核线程共有32 个,从watchdog/0 到watchdog/31, 每个处理器核对应一个watchdog 内核线程,watchdog 用于监视系统的运行,在系统出现故障时自动重新启动系统,包括一个内核 watchdog module 和一个用户空间的 watchdog 程序。在Linux 内核下, watchdog 的基本工作原理是:当watchdog 启动后( 即/dev/watchdog 设备被打开后) ,如果在某一设定的时间间隔(1 分钟)内/dev/watchdog 没有被执行写操作, 硬件watchdog 电路或软件定时器就会重新启动系统,每次写操作会导致重新设定定时器。/dev/watchdog 是一个主设备号为10, 从设备号130 的字符设备节点。 Linux 内核不仅为各种不同类型的watchdog 硬件电路提供了驱动,还提供了一个基于定时器的纯软件watchdog 驱动。如果不需要这种故障处理机制,或者有相应的替代方案,可以在menuconfig 的

   Device Drivers --->

      Watchdog Timer Support

处取消watchdog 功能。

   (4 )events :这种内核线程共有32 个,从events/0 到events/31, 每个处理器核对应一个events 内核线程。用来处理内核事件很多软硬件事件( 比如断电,文件变更) 被转换为events ,并分发给对相应事件感兴趣的线程进行响应。用来处理内核事件的重要线程,不能被去掉

   (5 )khelper :这种内核线程只有一个,主要作用是指定用户空间的程序路径和环境变量,最终运行指定的user space 的程序,属于关键线程,不能关闭

   (6 )kblockd :这种内核线程共有32 个,从kblockd/0 到kblockd/31, 每个处理器核对应一个 kblockd 内核线程。用于管理系统的块设备,它会周期地激活系统内的块设备驱动。如果拥有块设备,那么这些线程就不能被去掉,要是想去掉,需要在.config 中直接将CONFIG_BLOCK 设成n,同时在menuconfig 中取消

    Device Drivers   --->

           Block devices

   (7 )kseriod :这种内核线程只有一个,主要作用是管理Serio 总线上的设备的各种事件,Serio 是一种虚拟总线,是Serial I/O 的输写,表示串行的输入输出设备。对应内核中的serio_thread 函数, 流程大致是这样的:调用serio_get_event() 从链表中取出struct serio_event 元素,然后对这个元素的事件类型做不同的时候,处理完了之后,调用serio_remove_duplicate_events() 在链表中删除相同请求的event 。例如:如果要注册新的serio 设备,它产生的事件类型是SERIO_REGISTER_PORT ,然后流程会转入serio_add_port()。使用Serio 总线的主要是标准AT 键盘、PS/2 鼠标、串口鼠标、Sun 键盘,以及一些游戏手柄,不过由于I2C 依赖于Serio ,所以不关闭I2C 就无法关闭Serio ,menuconfig 中Serial I/O 的开关位于

Device Driver   --->

      Input device support

       Hardware I/O ports

           Serial I/O support

   (8 )pdflush :这种内核线程共有两个,线程名都是pdflush ,主要作用是回写内存中的脏页,回收脏页占据的空间。由于页高速缓存的缓存作用,写操作实际上会被延迟。当页高速缓存中的数据比后台存储的数据更新时,那么该数据就被称做脏数据。在内存中累积起来的脏页最终必须被写回。在以下两种情况发生时,脏页被写回:

1. 当空闲内存低于一个特定的阈值时,内核必须将脏页写回磁盘,以便释放内存。

2. 当脏页在内存中驻留时间超过一个特定的阈值时,内核必须将超时的脏页写回磁盘,以确保脏页不会无限期地驻留在内存中。

对于第一个目标,pdflush 线程在系统中的空闲内存低于一个特定的阈值时,将脏页刷新回磁盘。该后台回写例 程的目的在于在可用物理 内存过低时,释放脏页以重新获得内存。特定的内存阈值可以通过dirty_background_ratio sysctl 系统调用设置。当空闲内存比阈值:dirty_ background_ratio 还低时,内核便会调用函数wakeup_bdflush() 唤醒一个pdflush 线程,随后pdflush 线程进一步 调用函数background_writeout() 开始将脏页写回磁盘。函数background_ writeout() 需要一个长整型参数,该参数指定试图写回的页面数目。函数background_writeout()会连续地写出数据,直到满足以下两个条件:

1. 已经有指定的最小数目的页被写出到磁盘。

2. 空闲内存数已经回升,超过了阈值dirty_background_ratio 。

上述条件确保了pdflush 操作可以减轻系统中内存不足的压力。回写操作不会在达到这两个条件前停止,除非pdflush 写回了所有的脏页,没有剩下的脏页可再被写回了。

对于第二个目标,pdflush 后台例程会被周期性唤醒(和空闲内存是否过低无关), 将那些在内存中驻留时间过长的脏页写出,确保内存中不会有长期存在的脏页。如果系统发生崩溃,由于内存处于混乱之中,所以那些在内存中还没来得及写回磁盘 的脏页就会丢失,所以周期性同步页高速缓存和磁盘非常重要。在系统启动时,内核初始化一个定时器,让它周期地唤醒pdflush 线程,随后使其运行函数 wb_kupdate() 。该函数将把所有驻留时间超过百分之dirty_expire_centisecs秒的脏页写回。然后定时器将再次被初始化为百 分之dirty_expire_ centisecs 秒后唤醒pdflush线程。总而言之,pdflush 线程周期地被唤醒并且把超过特定期限的脏页写回磁盘。

系统管理员可以在/proc/sys/vm 中设置回写相关的参数,也可以通过sysctl 系统调用设置它们

        属于核心的内存管理线程,这个线程也不能被关闭

(9 )kswapd0 :这种内核线程只有一个,主要作用是用来回收内存。在kswapd 中,有2 个阀值, pages_hige 和pages_low 。当空闲内存页的数量低于pages_low 的时候,kswapd 进程就会扫描内存并且每次释放出32 个 free pages ,直到free page 的数量到达pages_high 。具体回收内存有如下原则:

      1. 如果页未经更改就将该页放入空闲队列;

      2. 如果页已经更改并且是可备份回文件系统的,就理解将内存页的内容写回磁盘;

      3. 如果页已经更改但是没有任何磁盘上的备份,就将其写入swap 分区。

        同样,属于核心的内存管理线程,这个线程也不能被关闭  

(10 )aio :这种内核线程共有32 个,从 aio/0 到aio/31, 每个处理器核对应一个 aio 内核线程, 代替用户进程管理I/O ,用以支持用户态的AIO (异步I/O ),不应该被关闭。

  (11 )unionfs_siod : 这种内核线程共有32 个,但是名称都是 unionfs_siod/ ,每个处理器核对应一个 unionfs_siod 内核线程

   (12 )nfsiod :这种内核线程只有一个,主要作用是为nfs 提供高效的缓冲机制, 从而改善nfs 文件系统的性能,如果不需nfs ,可以取消这一线程,取消这一线程的方法为menuconfig中取消

     File systems  --->

          Network File Systems

   (13 )rpciod :这种内核线程共有32 个,从 rpciod/0 到rpciod/31, 每个处理器核对应一个 rpciod 内核线程, 主要作用是作为远过程调用服务的守护进程,用于从客户端启动I/O 服务,通常启动NFS 服务时要用到它,想要关闭它,需要在.config 中把CONFIG_SUNRPC ,CONFIG_SUNRPC_GSS , CONFIG_SUNRPC_XPRT_RDMA 的值设成n

   (14 )kpsmoused :这种内核线程只有一个,主要作用是支持ps/2 接口的鼠标驱动。如要没有鼠标,可以取消,取消方法是menuconfig 中取消

Device Drivers   --->

      Input device support

       Mice

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值