FreeBSD 系统结构手册
上一页 | 第3章 　内核对象 | 下一页

# 3.3 使用Kobj

## 3.3.1 结构

    struct kobj_method

## 3.3.2 函数

    void kobj_class_compile(kobj_class_t cls);
    void kobj_class_compile_static(kobj_class_t cls, kobj_ops_t ops);
    void kobj_class_free(kobj_class_t cls);
    kobj_t kobj_create(kobj_class_t cls, struct malloc_type *mtype, int mflags);
    void kobj_init(kobj_t obj, kobj_class_t cls);
    void kobj_delete(kobj_t obj, struct malloc_type *mtype);

## 3.3.3 宏

    KOBJ_CLASS_FIELDS
    KOBJ_FIELDS
    DEFINE_CLASS(name, methods, size)
    KOBJMETHOD(NAME, FUNC)

## 3.3.4 头文件

    <sys/param.h>
    <sys/kobj.h>

## 3.3.5 建立一个接口的模板

使用Kobj的第一步是建立一个接口。建立接口包括建立模板的工作。 建立模板可用脚本`src/sys/kern/makeobjops.pl`完成， 它会产生申明方法的头文件和代码，脚本还会生成方法查找函数。

在这个模板中如下关键词会被使用: `#include`, `INTERFACE`, `CODE`, `METHOD`, `STATICMETHOD`, 和 `DEFAULT`.

`#include`语句的整行内容将被一字不差的 复制到被生成的代码文件的头部。

例如:

    #include <sys/foo.h>

关键词`INTERFACE`用来定义接口名。 这个名字将与每个方法名接合在一起，形成 [interface name]_[method name]。 语法是：INTERFACE [接口名];

例如:

    INTERFACE foo;

关键词`CODE`会将它的参数一字不差的复制到代码文件中。 语法是`CODE { [任何代码] };`

例如:

    CODE {
        struct foo * foo_alloc_null(struct bar *)
        {
            return NULL;
    }
    };

关键词`METHOD`用来描述一个方法。语法是: `METHOD [返回值类型] [方法名] { [对象 [, 参数若干]] };`

例如:

    METHOD int bar {
        struct object *;
        struct foo *;
        struct bar;
    };

关键词`DEFAULT`跟在关键词`METHOD`之后， 是对关键词`METHOD`的补充。它给这个方法补充上缺省函数。语法是： `METHOD [返回值类型] [方法名] { [对象; [其它参数]] }DEFAULT [缺省函数];`

例如:

    METHOD int bar {
        struct object *;
        struct foo *;
        int bar;
    } DEFAULT foo_hack;

关键词`STATICMETHOD`类似关键词`METHOD`。 对于每个Kobj对象，一般其头部都有一些Kobj专有的数据。 `METHOD`定义的方法就假设这些专有数据位于对象头部； 假如对象头部没有这些专有数据，这些方法对这个对象的访问就可能出错。 而`STATICMETHOD`定义的对象可以不受这个限制： 这样描述出的方法，其操作的数据不由这个类的某个对象实例给出， 而是全都由调用这个方法时的操作数(译者注:即参数)给出。 这也对于在某个类的方法表之外调用这个方法有用。

> 译者注: 这一段的语言与原文相比调整很大。 静态方法是不依赖于对象实例的方法。 参看C++类中的“静态函数”的概念。

其它完整的例子:

    src/sys/kern/bus_if.m
    src/sys/kern/device_if.m

## 3.3.6 建立一个类

使用Kobj的第二步是建立一个类。一个类的组有名字、方法表； 假如使用了Kobj的“对象管理工具”(Object Handling Facilities)， 类中还包含对象的大小。建立类时使用宏`DEFINE_CLASS()`。 建立方法表时，须建立一个kobj_method_t数组，用NULL项结尾。 每个非NULL项可用宏`KOBJMETHOD()`建立。

例如:

    DEFINE_CLASS(fooclass, foomethods, sizeof(struct foodata));

    kobj_method_t foomethods[] = {
        KOBJMETHOD(bar_doo, foo_doo),
        KOBJMETHOD(bar_foo, foo_foo),
        { NULL, NULL}
    };

类须被“编译”。根据该类被初始化时系统的状态， 将要用到一个静态分配的缓存和“操作数表”(ops table， 译者注：即“参数表”)。这些操作可通过声明一个结构体 `struct kobj_ops`并使用 `kobj_class_compile_static()`， 或是只使用`kobj_class_compile()`来完成。

## 3.3.7 建立一个对象

使用Kobj的第三步是定义对象。Kobj对象建立程序假定Kobj 专有数据在一个对象的头部。如果不是如此，应当先自行分配对象， 再使用`kobj_init()`初始化对象中的Kobj专有数据； 其实可以使用`kobj_create()`分配对象， 并自动初始化对象中的Kobj专有内容。`kobj_init()` 也可以用来改变一个对象所使用的类。

将Kobj的数据集成到对象中要使用宏KOBJ_FIELDS。

例如

    struct foo_data {
        KOBJ_FIELDS;
        foo_foo;
        foo_bar;
    };

## 3.3.8 调用方法

使用Kobj的最后一部就是通过生成的函数调用对象类中的方法。 调用时，接口名与方法名用'_'接合，而且全部使用大写字母。

例如，接口名为foo，方法为bar，调用就是:

    [返回值 = ] FOO_BAR(对象 [, 其它参数]);

## 3.3.9 善后处理

当一个用`kobj_create()`不再需要被使用时， 可对这个对象调用`kobj_delete()`。 当一个类不再需要被使用时， 可对这个类调用`kobj_class_free()`。

上一页 | 起始页 | 下一页
Kobj的工作流程 | 上一级 | Jail子系统

本文档和其它文档可从这里下载：ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

如果对于FreeBSD有问题，请先阅读文档，如不能解决再联系<questions@FreeBSD.org>.
关于本文档的问题请发信联系 <doc@FreeBSD.org>.