The translation is temporarily closed for contributions due to maintenance, please come back later.
English Chinese (Simplified) (zh_CN)
<function>init386()</function> initializes the tunable parameters passed from bootstrap by setting the environment pointer (envp) and calling <function>init_param1()</function>. The envp pointer has been passed from loader in the <literal>bootinfo</literal> structure: <function>init386()</function>首先初始化内核的可调整参数,
这些参数由引导程序传来。先设置环境指针(environment pointer, envp)调用,
再调用<function>init_param1()</function>。
envp指针已由loader存放在结构<literal>bootinfo</literal>中:
The <literal>#include</literal> statement and what follows it is copied verbatim to the head of the generated code file. <literal>#include</literal>语句的整行内容将被一字不差的
复制到被生成的代码文件的头部。
We will now be looking at the file <filename>/usr/src/sys/kern/kern_jail.c</filename>. This is the file where the <citerefentry><refentrytitle>jail</refentrytitle><manvolnum>2</manvolnum></citerefentry> system call, appropriate sysctls, and networking functions are defined. 现在我们来看文件<filename>/usr/src/sys/kern/kern_jail.c</filename>。
在这里定义了<citerefentry><refentrytitle>jail</refentrytitle><manvolnum>2</manvolnum></citerefentry>的系统调用、相关的sysctl项,还有网络函数。
#include &lt;sys/kernel.h&gt;

void foo_null(void *unused)
{
foo_doo();
}
SYSINIT(foo, SI_SUB_FOO, SI_ORDER_FOO, foo_null, NULL);

struct foo foo_voodoo = {
FOO_VOODOO;
}

void foo_arg(void *vdata)
{
struct foo *foo = (struct foo *)vdata;
foo_data(foo);
}
SYSINIT(bar, SI_SUB_FOO, SI_ORDER_FOO, foo_arg, &amp;foo_voodoo);
#include &lt;sys/kernel.h&gt;

void foo_null(void *unused)
{
foo_doo();
}
SYSINIT(foo, SI_SUB_FOO, SI_ORDER_FOO, foo_null, NULL);

struct foo foo_voodoo = {
FOO_VOODOO;
}

void foo_arg(void *vdata)
{
struct foo *foo = (struct foo *)vdata;
foo_data(foo);
}
SYSINIT(bar, SI_SUB_FOO, SI_ORDER_FOO, foo_arg, &amp;foo_voodoo);
#include &lt;sys/kernel.h&gt;

void foo_cleanup(void *unused)
{
foo_kill();
}
SYSUNINIT(foobar, SI_SUB_FOO, SI_ORDER_FOO, foo_cleanup, NULL);

struct foo_stack foo_stack = {
FOO_STACK_VOODOO;
}

void foo_flush(void *vdata)
{
}
SYSUNINIT(barfoo, SI_SUB_FOO, SI_ORDER_FOO, foo_flush, &amp;foo_stack);
#include &lt;sys/kernel.h&gt;

void foo_cleanup(void *unused)
{
foo_kill();
}
SYSUNINIT(foobar, SI_SUB_FOO, SI_ORDER_FOO, foo_cleanup, NULL);

struct foo_stack foo_stack = {
FOO_STACK_VOODOO;
}

void foo_flush(void *vdata)
{
}
SYSUNINIT(barfoo, SI_SUB_FOO, SI_ORDER_FOO, foo_flush, &amp;foo_stack);
As the set of active policies may change at run-time, and the invocation of entry points is non-atomic, synchronization is required to prevent loading or unloading of policies while an entry point invocation is in progress, freezing the set of active policies for the duration. This is accomplished by means of a framework busy count: whenever an entry point is entered, the busy count is incremented; whenever it is exited, the busy count is decremented. While the busy count is elevated, policy list changes are not permitted, and threads attempting to modify the policy list will sleep until the list is not busy. The busy count is protected by a mutex, and a condition variable is used to wake up sleepers waiting on policy list modifications. One side effect of this synchronization model is that recursion into the MAC Framework from within a policy module is permitted, although not generally used. 在运行时,系统中活跃的策略集合可能发生变化,然而对策略入口函数的使用操作并不是原子性的,因此,当某一个入口函数正被使用时,
系统需要提供额外的同步机制来阻止对该策略模块的加载与卸载,以确保当前活跃的策略集合不会在此过程中发生改变。
通过使用"框架忙”计数器,就可以做到这一点:一旦某个入口函数被调用,计数器的值被增加1;而每当一个入口函数调用结束时,计数器的值被减少1。检查计数器的值,如果其值为正,框架将阻止对策略链表的修改操作,请求操作的线程将被迫进入睡眠,直到计数器的值重新减少到0为止。计数器本身由一个互斥锁保护,同时结合一个条件变量(用于唤醒等待对策略链表进行修改操作的睡眠线程)。采用这种同步模型的一个副作用是,在同一个策略模块内部,允许嵌套地调用框架,不过这种情况其实很少出现。
The MAC Framework maintains two lists of active policies: a static list, and a dynamic list. The lists differ only with regards to their locking semantics: an elevated reference count is not required to make use of the static list. When kernel modules containing MAC Framework policies are loaded, the policy module will use <literal>SYSINIT</literal> to invoke a registration function; when a policy module is unloaded, <literal>SYSINIT</literal> will likewise invoke a de-registration function. Registration may fail if a policy module is loaded more than once, if insufficient resources are available for the registration (for example, the policy might require labeling and insufficient labeling state might be available), or other policy prerequisites might not be met (some policies may only be loaded prior to boot). Likewise, de-registration may fail if a policy is flagged as not unloadable. 为了记录当前使用的策略模块集合,MAC 框架维护两个链表:一个静态链表和一个动态链表。
两个链表的数据结构和操作基本相同,只是动态链表还额外使用了一个"引用计数"以同步对其的访问操作。
当包含 MAC 框架策略的内核模块被加载时,该策略模块会通过 <literal>SYSINIT</literal> 调用一个注册函数;
相对应的,每当一个策略模块被卸载,<literal>SYSINIT</literal> 也会调用一个注销函数。只有当遇到下列情况之一时,注册过程才会失败: 一个策略模块被加载多次,或者系统资源不足不能满足注册过程的需要(例如,策略模块需要对内核对象添加标记而可用资源不足),或者其他的策略加载前提条件不满足(有些策略要求只能在系统引导之前加载)。类似的,如果一个策略被标记为不可卸载的,对其调用注销过程将会失败。
<function>mac_get_fd()</function> may be used to retrieve the label of an object (file, socket, pipe, ...) referenced by a file descriptor. <function>mac_get_fd()</function> 用于查询由文件描述符所引用的对象( 文件、
套接字、 管道文件等等) 的安全标记。
<function>mac_set_fd()</function> may be used to request a change in the label of an object (file, socket, pipe, ...) referenced by a file descriptor. <function>mac_set_fd()</function> 用于请求改变由文件描述符所引用的对象(
文件、套接字、 管道文件等等) 的安全标记。
Destroy the label on an IP fragment queue. In this entry point, a policy module should free any internal storage associated with <parameter>label</parameter> so that it may be destroyed. 销毁与一个 IP 分片队列相关联的标记。在该入口函数中,策略应当释放所有在内部分配的与 <parameter>label</parameter>
相关联的存储空间,以便销毁该标记。
Determine whether the policy will want to perform a transition event as a result of the execution of the passed vnode by the passed subject credential. Return <returnvalue>1</returnvalue> if a transition is required, <returnvalue>0</returnvalue> if not. Even if a policy returns <returnvalue>0</returnvalue>, it should behave correctly in the presence of an unexpected invocation of <function>mpo_execve_transition</function>, as that call may happen as a result of another policy requesting a transition. 由策略决定,当参数主体信任状执行参数 vnode 时,是否需要进行一个标记转换操作。如果需要,返回<returnvalue>1</returnvalue>;
否则,返回<returnvalue>0</returnvalue>。即使一个策略返回<returnvalue>0</returnvalue>,它也必须为自己不期望的对<function>mpo_execve_transition</function>的调用作好准备,因为只要有其他任何一个策略要求转换,就将执行此函数。
APIs for Policy-Agnostic Label Management .ps.1;,使用这些策略无关的接口查询网络结构、文件和进程的标记信息。
这些 API 也被用于支持 MAC 管理工具
uint16_t
board_read(struct ni_softc *sc, uint16_t address)
{
return bus_space_read_2(sc-&gt;bar1_bt, sc-&gt;bar1_bh, address);
}
uint16_t
board_read(struct ni_softc *sc, uint16_t address)
{
return bus_space_read_2(sc-&gt;bar1_bt, sc-&gt;bar1_bh, address);
}
void
board_write(struct ni_softc *sc, uint16_t address, uint16_t value)
{
bus_space_write_2(sc-&gt;bar1_bt, sc-&gt;bar1_bh, address, value);
}
void
board_write(struct ni_softc *sc, uint16_t address, uint16_t value)
{
bus_space_write_2(sc-&gt;bar1_bt, sc-&gt;bar1_bh, address, value);
}
uint16_t
board_read(struct ni_softc *sc, uint16_t address)
{
return (bus_read(sc-&gt;bar1res, address));
}
uint16_t
board_read(struct ni_softc *sc, uint16_t address)
{
return (bus_read(sc-&gt;bar1res, address));
}
/* Get the IRQ resource */

sc-&gt;irqid = 0x0;
sc-&gt;irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &amp;(sc-&gt;irqid),
0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
if (sc-&gt;irqres == NULL) {
printf("IRQ allocation failed!\n");
error = ENXIO;
goto fail3;
}

/* Now we should set up the interrupt handler */

error = bus_setup_intr(dev, sc-&gt;irqres, INTR_TYPE_MISC,
my_handler, sc, &amp;(sc-&gt;handler));
if (error) {
printf("Couldn't set up irq\n");
goto fail4;
}
/* Get the IRQ resource */

sc-&gt;irqid = 0x0;
sc-&gt;irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &amp;(sc-&gt;irqid),
0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
if (sc-&gt;irqres == NULL) {
printf("IRQ allocation failed!\n");
error = ENXIO;
goto fail3;
}

/* Now we should set up the interrupt handler */

error = bus_setup_intr(dev, sc-&gt;irqres, INTR_TYPE_MISC,
my_handler, sc, &amp;(sc-&gt;handler));
if (error) {
printf("Couldn't set up irq\n");
goto fail4;
}
#include &lt;vm/vm.h&gt;
#include &lt;vm/pmap.h&gt;

#define vtophys(virtual_address) (...)
#include &lt;vm/vm.h&gt;
#include &lt;vm/pmap.h&gt;

#define vtophys(virtual_address) (...)
#if defined(__alpha__)
#define vtobus(va) alpha_XXX_dmamap((vm_offset_t)va)
#else
#define vtobus(va) vtophys(va)
#endif
#if defined(__alpha__)
#define vtobus(va) alpha_XXX_dmamap((vm_offset_t)va)
#else
#define vtobus(va) vtophys(va)
#endif