电脑技术学习

FreeBSD的Loader和内核初始化

dn001

  hz = HZ;

  TUNABLE_INT_FETCH("kern.hz", &hz);

  TUNABLE__FETCH用来获取环境变量的值:/usr/src/sys/sys/kernel.h

  #define TUNABLE_INT_FETCH(path, var)  getenv_int((path), (var))

  Sysctlkern.hz是系统时钟频率。同时,这些sysctl项被init_param1()设定:

kern.maxswzone, kern.maxbcache, kern.maxtsiz, kern.dfldsiz, kern.dflssiz,
kern.maxssiz, kern.sgrowsiz。然后init386() 准备全局描述符表(Global Descriptors Table, GDT)。

  在x86上每个任务都运行在自己的虚拟地址空间里,这个空间由"段址:偏移量"的数对指定。

  举个例子,当前将要由处理器执行的指令在 CS:EIP,那么这条指令的线性虚拟地址就是“代码段虚拟段地址CS + EIP。为了简便,段起始于虚拟地址0,终止于界限4G字节。所以,在这个例子中,指令的线性虚拟地址正是EIP的值。段寄存器,如CS、DS等是选择符,即全局描述符表中的索引(更精确的说,索引并非选择符的全部,而是选择符中的INDEX部分)。译者注: 对于80386,选择符有16位,INDEX部分是其中的高13位。

  FreeBSD的全局描述符表为每个CPU保存着15个选择符:sys/i386/i386/Machdep.c:

union descriptor gdt[NGDT * MAXCPU];  /* 全局描述符表 */
sys/i386/include/segments.h:
/*
* 全局描述符表(GDT)中的入口
*/
#define GNULL_SEL  0  /* 空描述符 */
#define GCODE_SEL  1  /* 内核代码描述符 */
#define GDATA_SEL  2  /* 内核数据描述符 */
#define GPRIV_SEL  3  /* 对称多处理(SMP)每处理器专有数据 */
#define GPROC0_SEL 4  /* Task state process slot zero and up, 任务状态进程 */
#define GLDT_SEL  5  /* 每个进程的局部描述符表 */
#define GUSERLDT_SEL  6  /* 用户自定义的局部描述符表 */
#define GTGATE_SEL 7  /* 进程任务切换关口 */
#define GBIOSLOWMEM_SEL 8  /* BIOS低端内存访问(必须是这第8个入口) */
#define GPANIC_SEL 9  /* 会导致全系统异常中止工作的任务状态 */
#define GBIOSCODE32_SEL 10 /* BIOS接口(32位代码) */
#define GBIOSCODE16_SEL 11 /* BIOS接口(16位代码) */
#define GBIOSDATA_SEL  12 /* BIOS接口(数据) */
#define GBIOSUTIL_SEL  13 /* BIOS接口(工具) */
#define GBIOSARGS_SEL  14 /* BIOS接口(自变量,参数) */

标签: