FreeBSD内核可以被看做是一种服务器,它向用户进程提供服务。进程通过系统调用访问这些服务。其中有些服务,比如进程调度和内存管理,采用内核态执行的进程,或者内核里定期执行的例程这样的形式来实现。

内核进程和用户进程

内核进程只在内核中发挥作用,执行内核镜像的代码,以内核特权模式执行。内核还为每台设备启动一个内核进程,负责处理该设备的中断。

常见内核进程
idle	在系统没有其它要执行的任务时运行
swapper	在有系统资源的时候,把进程从辅助存储器调入主存
pagedaemon	把系进程的部分地址空间写入辅助存储器,以支持虚拟内存系统的调页机制
g_event	在发现新设备以及当设备消失时清除设备的过程中,负责处理配置任务
g_up	处理从设备驱动来的要被送往进程的数据
g_down	处理从进程来的要被送往设备驱动的数据

在创建好内核进程之后,内核就创建第一个用户态进程init,作为以后所有进程的父进程。Init进程负责许多管理性的任务,比如为机器上的每个终端派生一个getty进程、接收孤儿进程的退出状态,以及在系统从多用户转为单用户模式运行时,负责依次执行关闭操作。

内核态和用户态切换

进入内核的人口可以根据发起进入内核的事件或者操作分为以下几类:

  • 硬件中断:如I/O设备请求。与当前执行进程的上下文无关。
  • 硬件陷阱:如非法算数操作。与当前执行的进程有关系。
  • 软件陷阱:如进程的重新调度或网络处理。在进程准备从内核退出时,设置标志。

在进程通过陷阱或中断进入内核时:

1.CPU切换到内核模式,拥有内核栈指针,可以执行特权指令。
2.CPU硬件将程序计数器、处理器状态等推入进程的内核栈中
3.CPU执行汇编程序,将硬件没有保存的所有状态信息推入内核栈中,比如通用寄存器和用户态栈指针。

在内核完成处理之后,就会恢复用户进程的状态,把控制权还给用户进程:

1.CPU执行汇编程序,将之前保存的通用寄存器和用户栈指针恢复回来。
2. 	CPU硬件恢复程序计数器和处理器状态,切换到用户态权限,拥有用户态栈指针。

运行时的内核结构

内核可以在逻辑上划分为上半部下半部
上半部向进程提供服务,对系统调用和陷阱做出响应,可以当做是所有进程共享的库函数。
下半部由负责硬件中断的例程组成。下半部与上半部是异步的,也就是说,对于下半部内核来说,没有当前执行进程的上下文。
当freebsd在上半部运行时,它不会被其它用户进程抢占,但是当它需要等待某个事件或共享资源时,会主动放弃CPU。
上半部会被下半部打断,当接收到一个中断时,会执行负责处理该设备的内核进程,这个内核进程要比上半部的内核进程优先级高。
内核的上下半部也会进行协作,比如上半部启动一个I/O操作,随即放弃CPU进入睡眠状态,等待下半部发回I/O执行完毕的通知。上下半部可以通过工作队列通信。

参考《freebsd操作系统设计与实现》