免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 9347 | 回复: 8

[FreeBSD] freebsd9.2-内核子系统初始化-SYSINIT框架 [复制链接]

论坛徽章:
0
发表于 2014-06-20 15:32 |显示全部楼层
本帖最后由 71v5 于 2014-06-25 21:00 编辑

个人觉的freebsd内核子系统的初始化过程比linux更清晰,这主要归功于SYSINIT框架。SYSINIT的基本原理就是构造一个数据结构,将该数据结构的地址放到
一个统一的数据节中,这样当内核初始化时,就会处理该数据节中的数据。有两种时刻需要使用SYSINIT:系统启动或内核模块加载时, 系统析构或
内核模块卸载时。

SYSINIT的标准形式如下:
  1. SYSINIT(uniquifier, subsystem, order, func, ident)
复制代码
SYSINIT宏建立了一种让系统能够够按顺序启动的两级结构,参数subsystem这第一级,每个子系统都有一个特殊的数字常量,这个数字常量确定了在第一级
里的启动顺序;第二级参数数据哦order,如果第一级相同,那么order确定了在第一级相同时的加载顺序。

uniquifier:标识符
subsystem:第一级参数
order:第二级参数
func:初始化函数
ident:初始化函数的参数

[subsystem]:
subsystem可以取值如下,这也提供了一种学习bsd内核的方法,如果按照这个顺序把相应的初始化函数分析完,那么freebsd内核你已经掌握的差不多了:
  1.     70        /*
  2.     71         * Enumerated types for known system startup interfaces.
  3.     72         *
  4.     73         * Startup occurs in ascending numeric order; the list entries are
  5.     74         * sorted prior to attempting startup to guarantee order.  Items
  6.     75         * of the same level are arbitrated for order based on the 'order'
  7.     76         * element.
  8.     77         *
  9.     78         * These numbers are arbitrary and are chosen ONLY for ordering; the
  10.     79         * enumeration values are explicit rather than implicit to provide
  11.     80         * for binary compatibility with inserted elements.
  12.     81         *
  13.     82         * The SI_SUB_RUN_SCHEDULER value must have the highest lexical value.
  14.     83         *
  15.     84         * The SI_SUB_SWAP values represent a value used by
  16.     85         * the BSD 4.4Lite but not by FreeBSD; it is maintained in dependent
  17.     86         * order to support porting.
  18.     87         */
  19.     88        enum sysinit_sub_id {
  20.     89                SI_SUB_DUMMY                = 0x0000000,        /* not executed; for linker*/
  21.     90                SI_SUB_DONE                = 0x0000001,        /* processed*/
  22.     91                SI_SUB_TUNABLES                = 0x0700000,        /* establish tunable values */
  23.     92                SI_SUB_COPYRIGHT        = 0x0800001,        /* first use of console*/
  24.     93                SI_SUB_SETTINGS                = 0x0880000,        /* check and recheck settings */
  25.     94                SI_SUB_MTX_POOL_STATIC        = 0x0900000,        /* static mutex pool */
  26.     95                SI_SUB_LOCKMGR                = 0x0980000,        /* lockmgr locks */
  27.     96                SI_SUB_VM                = 0x1000000,        /* virtual memory system init*/
  28.     97                SI_SUB_KMEM                = 0x1800000,        /* kernel memory*/
  29.     98                SI_SUB_KVM_RSRC                = 0x1A00000,        /* kvm operational limits*/
  30.     99                SI_SUB_WITNESS                = 0x1A80000,        /* witness initialization */
  31.    100                SI_SUB_MTX_POOL_DYNAMIC        = 0x1AC0000,        /* dynamic mutex pool */
  32.    101                SI_SUB_LOCK                = 0x1B00000,        /* various locks */
  33.    102                SI_SUB_EVENTHANDLER        = 0x1C00000,        /* eventhandler init */
  34.    103                SI_SUB_VNET_PRELINK        = 0x1E00000,        /* vnet init before modules */
  35.    104                SI_SUB_KLD                = 0x2000000,        /* KLD and module setup */
  36.    105                SI_SUB_CPU                = 0x2100000,        /* CPU resource(s)*/
  37.    106                SI_SUB_RACCT                = 0x2110000,        /* resource accounting */
  38.    107                SI_SUB_RANDOM                = 0x2120000,        /* random number generator */
  39.    108                SI_SUB_KDTRACE                = 0x2140000,        /* Kernel dtrace hooks */
  40.    109                SI_SUB_MAC                = 0x2180000,        /* TrustedBSD MAC subsystem */
  41.    110                SI_SUB_MAC_POLICY        = 0x21C0000,        /* TrustedBSD MAC policies */
  42.    111                SI_SUB_MAC_LATE                = 0x21D0000,        /* TrustedBSD MAC subsystem */
  43.    112                SI_SUB_VNET                = 0x21E0000,        /* vnet 0 */
  44.    113                SI_SUB_INTRINSIC        = 0x2200000,        /* proc 0*/
  45.    114                SI_SUB_VM_CONF                = 0x2300000,        /* config VM, set limits */
  46.    115                SI_SUB_DDB_SERVICES        = 0x2380000,        /* capture, scripting, etc.*/
  47.    116                SI_SUB_RUN_QUEUE        = 0x2400000,        /* set up run queue */
  48.    117                SI_SUB_KTRACE                = 0x2480000,        /* ktrace */
  49.    118                SI_SUB_OPENSOLARIS        = 0x2490000,        /* OpenSolaris compatibility */
  50.    119                SI_SUB_CYCLIC                = 0x24A0000,        /* Cyclic timers */
  51.    120                SI_SUB_AUDIT                = 0x24C0000,        /* audit */
  52.    121                SI_SUB_CREATE_INIT        = 0x2500000,        /* create init process 创建1号进程 */
  53.    122                SI_SUB_SCHED_IDLE        = 0x2600000,        /* required idle procs 创建每cpu上的idle线程 */
  54.    123                SI_SUB_MBUF                = 0x2700000,        /* mbuf subsystem */
  55.    124                SI_SUB_INTR                = 0x2800000,        /* interrupt threads */
  56.    125                SI_SUB_SOFTINTR                = 0x2800001,        /* start soft interrupt thread */
  57.    126                SI_SUB_ACL                = 0x2900000,        /* start for filesystem ACLs */
  58.    127                SI_SUB_DEVFS                = 0x2F00000,        /* devfs ready for devices */
  59.    128                SI_SUB_INIT_IF                = 0x3000000,        /* prep for net interfaces */
  60.    129                SI_SUB_NETGRAPH                = 0x3010000,        /* Let Netgraph initialize */
  61.    130                SI_SUB_DTRACE                = 0x3020000,        /* DTrace subsystem */
  62.    131                SI_SUB_DTRACE_PROVIDER        = 0x3048000,        /* DTrace providers */
  63.    132                SI_SUB_DTRACE_ANON        = 0x308C000,        /* DTrace anon enabling */
  64.    133                SI_SUB_DRIVERS                = 0x3100000,        /* Let Drivers initialize */
  65.    134                SI_SUB_CONFIGURE        = 0x3800000,        /* Configure devices */
  66.    135                SI_SUB_VFS                = 0x4000000,        /* virtual filesystem*/
  67.    136                SI_SUB_CLOCKS                = 0x4800000,        /* real time and stat clocks*/
  68.    137                SI_SUB_CLIST                = 0x5800000,        /* clists*/
  69.    138                SI_SUB_SYSV_SHM                = 0x6400000,        /* System V shared memory*/
  70.    139                SI_SUB_SYSV_SEM                = 0x6800000,        /* System V semaphores*/
  71.    140                SI_SUB_SYSV_MSG                = 0x6C00000,        /* System V message queues*/
  72.    141                SI_SUB_P1003_1B                = 0x6E00000,        /* P1003.1B realtime */
  73.    142                SI_SUB_PSEUDO                = 0x7000000,        /* pseudo devices */
  74.    143                SI_SUB_EXEC                = 0x7400000,        /* execve() handlers */
  75.    144                SI_SUB_PROTO_BEGIN        = 0x8000000,        /* VNET initialization */
  76.    145                SI_SUB_PROTO_IF                = 0x8400000,        /* interfaces*/
  77.    146                SI_SUB_PROTO_DOMAININIT        = 0x8600000,        /* domain registration system */
  78.    147                SI_SUB_PROTO_DOMAIN        = 0x8800000,        /* domains (address families?)*/
  79.    148                SI_SUB_PROTO_IFATTACHDOMAIN        = 0x8800001,        /* domain dependent data init*/
  80.    149                SI_SUB_PROTO_END        = 0x8ffffff,        /* VNET helper functions */
  81.    150                SI_SUB_KPROF                = 0x9000000,        /* kernel profiling*/
  82.    151                SI_SUB_KICK_SCHEDULER        = 0xa000000,        /* start the timeout events*/
  83.    152                SI_SUB_INT_CONFIG_HOOKS        = 0xa800000,        /* Interrupts enabled config */
  84.    153                SI_SUB_ROOT_CONF        = 0xb000000,        /* Find root devices */
  85.    154                SI_SUB_DUMP_CONF        = 0xb200000,        /* Find dump devices */
  86.    155                SI_SUB_RAID                = 0xb380000,        /* Configure GEOM classes */
  87.    156                SI_SUB_SWAP                = 0xc000000,        /* swap */
  88.    157                SI_SUB_INTRINSIC_POST        = 0xd000000,        /* proc 0 cleanup*/
  89.    158                SI_SUB_SYSCALLS                = 0xd800000,        /* register system calls */
  90.    159                SI_SUB_VNET_DONE        = 0xdc00000,        /* vnet registration complete */
  91.    160                SI_SUB_KTHREAD_INIT        = 0xe000000,        /* init process*/
  92.    161                SI_SUB_KTHREAD_PAGE        = 0xe400000,        /* pageout daemon*/
  93.    162                SI_SUB_KTHREAD_VM        = 0xe800000,        /* vm daemon*/
  94.    163                SI_SUB_KTHREAD_BUF        = 0xea00000,        /* buffer daemon*/
  95.    164                SI_SUB_KTHREAD_UPDATE        = 0xec00000,        /* update daemon*/
  96.    165                SI_SUB_KTHREAD_IDLE        = 0xee00000,        /* idle procs*/
  97.    166                SI_SUB_SMP                = 0xf000000,        /* start the APs 负责**暂停激活的AP*/
  98.    167                SI_SUB_RACCTD                = 0xf100000,        /* start raccd*/
  99.    168                SI_SUB_RUN_SCHEDULER        = 0xfffffff        /* scheduler*/
  100.    169        };
复制代码
[order]-order参数可以取值如下:
  1.    172        /*
  2.    173         * Some enumerated orders; "ANY" sorts last.
  3.    174         */
  4.    175        enum sysinit_elem_order {
  5.    176                SI_ORDER_FIRST                = 0x0000000,        /* first*/
  6.    177                SI_ORDER_SECOND                = 0x0000001,        /* second*/
  7.    178                SI_ORDER_THIRD                = 0x0000002,        /* third*/
  8.    179                SI_ORDER_FOURTH                = 0x0000003,        /* fourth*/
  9.    180                SI_ORDER_MIDDLE                = 0x1000000,        /* somewhere in the middle */
  10.    181                SI_ORDER_ANY                = 0xfffffff        /* last*/
  11.    182        };
复制代码
下面以虚拟内存系统的初始化为例,说明一下SYSINIT宏的工作过程。
在源代码文件"release/9.2.0/sys/vm/vm_init.c"中,使用了下面的SYSINIT宏声明:
  1. SI_SUB_VM                = 0x1000000,        /* virtual memory system init*/
  2. SYSINIT(vm_mem, SI_SUB_VM, SI_ORDER_FIRST, vm_mem_init, NULL);
复制代码
下面逐步展开宏SYSINIT:
宏SYSINIT定义如下所示:
  1.    239        #define        SYSINIT(uniquifier, subsystem, order, func, ident)        \
  2.    240                C_SYSINIT(uniquifier, subsystem, order,                        \
  3.    241                (sysinit_cfunc_t)(sysinit_nfunc_t)func, (void *)(ident))
复制代码
[1]--展开宏SYSINIT:
  1. C_SYSINIT(vm_mem, SI_SUB_VM, SI_ORDER_FIRST,vm_mem_init, NULL)
复制代码
[2]--展开宏C_SYSINIT:
宏C_SYSINIT定义如下所示:
  1.    230        #define        C_SYSINIT(uniquifier, subsystem, order, func, ident)        \
  2.    231                static struct sysinit uniquifier ## _sys_init = {        \
  3.    232                        subsystem,                                        \
  4.    233                        order,                                                \
  5.    234                        func,                                                \
  6.    235                        (ident)                                                \
  7.    236                };                                                        \
  8.    237                DATA_SET(sysinit_set,uniquifier ## _sys_init)
复制代码
展开宏C_SYSINIT如下所示:
  1.    231                static struct sysinit vm_mem_sys_init = {       
  2.    232                        SI_SUB_VM,        /* subsystem成员 */                               
  3.    233                        SI_ORDER_FIRST,        /* order成员 */                                       
  4.    234                        vm_mem_init,        /* func成员 */                                       
  5.    235                        NULL                /* udata成员 */                               
  6.    236                };                                                       
  7.    237                DATA_SET(sysinit_set,vm_mem_sys_init)
复制代码
[3]--展开宏DATA_SET:
宏DATA_SET定义如下所示:
  1. #define DATA_SET(set, sym)        __MAKE_SET(set, sym)
复制代码
展开宏DATA_SET如下所示:
  1.    231                static struct sysinit vm_mem_sys_init = {       
  2.    232                        SI_SUB_VM,        /* subsystem成员 */                               
  3.    233                        SI_ORDER_FIRST,        /* order成员 */                                       
  4.    234                        vm_mem_init,        /* func成员 */                                       
  5.    235                        NULL                /* udata成员 */                               
  6.    236                };
  7.    237                __MAKE_SET(sysinit_set,vm_mem_sys_init)
复制代码
[4]--展开宏__MAKE_SET:
宏__MAKE_SET定义如下所示:
  1.     47        #define __MAKE_SET(set, sym)                                                \
  2.     48                __GLOBL(__CONCAT(__start_set_,set));                                \
  3.     49                __GLOBL(__CONCAT(__stop_set_,set));                                \
  4.     50                static void const * const __set_##set##_sym_##sym                 \
  5.     51                __section("set_" #set) __used = &sym
复制代码
展开宏__MAKE_SET如下所示:
  1.    231                static struct sysinit vm_mem_sys_init = {       
  2.    232                        SI_SUB_VM,        /* subsystem成员 */                               
  3.    233                        SI_ORDER_FIRST,        /* order成员 */                                       
  4.    234                        vm_mem_init,        /* func成员 */                                       
  5.    235                        NULL                /* udata成员 */                               
  6.    236                };                                       
  7.     48                __GLOBL(__CONCAT(__start_set_,sysinit_set));                               
  8.     49                __GLOBL(__CONCAT(__stop_set_,sysinit_set));                               
  9.     50                static void const * const __set_sysinit_set_sym_vm_mem_sys_init __section("set_" sysinit_set) __used = &vm_mem_sys_init
复制代码
从宏SYSINIT的展开过程来看,宏SYSINIT用其参数构造一个类型为struct sysinit的数据对象,并将这个数据对象的地址保存到set_sysinit_set节中,mi_startup函数会遍历
该节,依次调用初始化函数对系统进行初始化。
  1.    118        /*
  2.    119         * The sysinit table itself.  Items are checked off as the are run.
  3.    120         * If we want to register new sysinit types, add them to newsysinit.

  4.            set_sysinit_set节的起始和结束地址由链接器确定,同时链接器构造了两个全局符号来标识该数据
  5.            节的起始和结束地址:
  6.            __start_set_sysinit_set:set_sysinit_set节的起始地址
  7.            __stop_set_sysinit_set:  set_sysinit_set节的结束地址

  8.            宏SET_DECLARE展开后如下所示:
  9.            extern struct sysinit *__start_set_sysinit_set;
  10.            extern struct sysinit *__stop_set_sysinit_set;

  11.            因为__start_set_sysinit_set和__stop_set_sysinit_set变量是由链接器自动生成的,所以内核
  12.            想要使用这两个变量的话就得使用SET_DECLARE(sysinit_set, struct sysinit),表明
  13.            这两个变量是在别处定义的。这里有点疑惑,__start_set_sysinit_set和__stop_set_sysinit_set
  14.            应该是struct sysinit **类型,但是宏SET_DECLARE(sysinit_set, struct sysinit)展开后的类型
  15.            却是struct sysinit *?

  16.            sysinit:set_sysinit_set节的起始地址
  17.            sysinit_end: set_sysinit_set节的结束地址

  18.            如果执行了SI_SUB_KLD子系统的初始化函数后,set_sysinit_set节可能会改变,此时
  19.            newsysinit:更新后set_sysinit_set节的起始地址
  20.            newsysinit_end:更新后set_sysinit_set节的结束地址
  21.    121         */
  22.    122        SET_DECLARE(sysinit_set, struct sysinit);
  23.    123        struct sysinit **sysinit, **sysinit_end;
  24.    124        struct sysinit **newsysinit, **newsysinit_end;

  25.    185        /*
  26.    186         * A system initialization call instance
  27.    187         *
  28.    188         * At the moment there is one instance of sysinit.  We probably do not
  29.    189         * want two which is why this code is if'd out, but we definitely want
  30.    190         * to discern SYSINIT's which take non-constant data pointers and
  31.    191         * SYSINIT's which take constant data pointers,
  32.    192         *
  33.    193         * The C_* macros take functions expecting const void * arguments
  34.    194         * while the non-C_* macros take functions expecting just void * arguments.
  35.    195         *
  36.    196         * With -Wcast-qual on, the compiler issues warnings:
  37.    197         *        - if we pass non-const data or functions taking non-const data
  38.    198         *          to a C_* macro.
  39.    199         *
  40.    200         *        - if we pass const data to the normal macros
  41.    201         *
  42.    202         * However, no warning is issued if we pass a function taking const data
  43.    203         * through a normal non-const macro.  This is ok because the function is
  44.    204         * saying it won't modify the data so we don't care whether the data is
  45.    205         * modifiable or not.
  46.    206         */
  47.    207       
  48.    208        typedef void (*sysinit_nfunc_t)(void *);
  49.    209        typedef void (*sysinit_cfunc_t)(const void *);
  50.    210       
  51.    211        struct sysinit {
  52.    212                enum sysinit_sub_id        subsystem;        /* subsystem identifier SYSINIT宏的第二个参数 */
  53.    213                enum sysinit_elem_order        order;                /* init order within subsystem SYSINIT宏的第三个参数 */
  54.    214                sysinit_cfunc_t func;                        /* function 初始化函数 */
  55.    215                const void        *udata;                        /* multiplexer/argument 初始化函数的参数 */
  56.    216        };
复制代码

论坛徽章:
0
发表于 2014-06-23 16:41 |显示全部楼层
回复 1# 71v5

针对你的疑惑聊一下。不知你是如何得出“__start_set_sysinit_set和__stop_set_sysinit_set应该是struct sysinit **类型”的结论的?以10.0的代码为例,你可以看一下init_main.c文件第214行对sysinit的赋值和linker_set.h文件第75行对SET_BEGIN的定义,应该就清楚了。

事实上,SYSINIT宏同时定义了一对struct sysinit结构体实例和指向这个实例的指针(参见DATA_SET宏的定义),假设实例的名字为xxx,则指针名字为__set_sysinit_set_sym_xxx。通过指定变量在ELF文件中的布局,将所有指针连续放在一起,每项占8个字节(64位系统上);所有的实例则放在另外一片区域,每项占24个字节(两个枚举加两个指针,64位系统上)。因此,在内核刚加载时,这部分数据结构可以视作两个已经建好链接关系的指针数组和实例数组,__start_set_sysinit_set和__stop_set_sysinit_set就是用来标识指针数组的起止位置的。在mi_startup()中对各初始化实体进行冒泡排序时,只需要对指针数组进行冒泡排序。

   

论坛徽章:
0
发表于 2014-06-23 18:35 |显示全部楼层
回复 2# 雨丝风片


哈哈,谢谢前辈指点,有时间向你多多请教!   

论坛徽章:
0
发表于 2014-06-23 19:30 |显示全部楼层
回复 3# 71v5

你的大作我还没来的及看完,大家一起学习!


   

论坛徽章:
0
发表于 2014-06-23 20:21 |显示全部楼层
回复 4# 雨丝风片

谈不上什么大作,就是平时自己捡到的一点知识,毕竟bsd方面的书籍很少,唯一的两本就是4.4bsd操作系统设计与实现和freebsd操作系统设计与实现,不过这两本书都是大概提了相关的内容,具体还得看源代码,相信这个学习过程比看什么书都来的痛快,也是
看书所获取不到的。

有错误的地方麻烦指点一下。


   

论坛徽章:
2
亥猪
日期:2014-03-19 16:36:35午马
日期:2014-11-23 23:48:46
发表于 2014-06-30 00:24 |显示全部楼层
@雨丝风片
好久没见你上坛子啦,什么时候出来喝茶?

论坛徽章:
0
发表于 2014-06-30 08:32 |显示全部楼层
回复 6# gvim

你这是半夜三更边看球边灌水的节奏啊,空了约一下,:)
   

论坛徽章:
0
发表于 2014-09-11 16:48 |显示全部楼层
好东西!!!!

论坛徽章:
4
双子座
日期:2014-05-25 00:04:52摩羯座
日期:2014-05-25 23:22:39未羊
日期:2014-06-16 09:10:30水瓶座
日期:2014-11-24 09:12:49
发表于 2015-04-30 21:53 |显示全部楼层
非常不错,支持一个
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP