298 lines
9.8 KiB
Text
298 lines
9.8 KiB
Text
<!--
|
|
The FreeBSD Documentation Project
|
|
|
|
$FreeBSD$
|
|
-->
|
|
|
|
<chapter id="kernel-objects">
|
|
<title>Kernel Objects</title>
|
|
|
|
<para>Kernel Objects, or <firstterm>Kobj</firstterm> provides an
|
|
object-oriented C programming system for the kernel. As such the
|
|
data being operated on carries the description of how to operate
|
|
on it. This allows operations to be added and removed from an
|
|
interface at run time and without breaking binary
|
|
compatibility.</para>
|
|
|
|
<sect1 id="kernel-objects-term">
|
|
<title>Terminology</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term>Object</term>
|
|
<listitem><para>A set of data - data structure - data
|
|
allocation.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Method</term>
|
|
<listitem>
|
|
<para>An operation - function.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Class</term>
|
|
<listitem>
|
|
<para>One or more methods.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Interface</term>
|
|
<listitem>
|
|
<para>A standard set of one or more methods.</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</sect1>
|
|
|
|
<sect1 id="kernel-objects-operation">
|
|
<title>Kobj Operation</title>
|
|
|
|
<para>Kobj works by generating descriptions of methods. Each
|
|
description holds a unique id as well as a default function. The
|
|
description's address is used to uniquely identify the method
|
|
within a class' method table.</para>
|
|
|
|
<para>A class is built by creating a method table associating one
|
|
or more functions with method descriptions. Before use the class
|
|
is compiled. The compilation allocates a cache and associates it
|
|
with the class. A unique id is assigned to each method
|
|
description within the method table of the class if not already
|
|
done so by another referencing class compilation. For every
|
|
method to be used a function is generated by script to qualify
|
|
arguments and automatically reference the method description for
|
|
a lookup. The generated function looks up the method by using
|
|
the unique id associated with the method description as a hash
|
|
into the cache associated with the object's class. If the method
|
|
is not cached the generated function proceeds to use the class'
|
|
table to find the method. If the method is found then the
|
|
associated function within the class is used; otherwise, the
|
|
default function associated with the method description is
|
|
used.</para>
|
|
|
|
<para>These indirections can be visualized as the
|
|
following:</para>
|
|
|
|
<programlisting>object->cache<->class</programlisting>
|
|
|
|
</sect1>
|
|
|
|
<sect1 id="kernel-objects-using">
|
|
<title>Using Kobj</title>
|
|
|
|
<sect2>
|
|
<title>Structures</title>
|
|
|
|
<programlisting>struct kobj_method</programlisting>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Functions</title>
|
|
|
|
<programlisting>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);</programlisting>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Macros</title>
|
|
|
|
<programlisting>KOBJ_CLASS_FIELDS
|
|
KOBJ_FIELDS
|
|
DEFINE_CLASS(name, methods, size)
|
|
KOBJMETHOD(NAME, FUNC)</programlisting>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Headers</title>
|
|
|
|
<programlisting><sys/param.h>
|
|
<sys/kobj.h></programlisting>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Creating an interface template</title>
|
|
|
|
<para>The first step in using Kobj is to create an
|
|
Interface. Creating the interface involves creating a template
|
|
that the script
|
|
<filename>src/sys/kern/makeobjops.pl</filename> can use to
|
|
generate the header and code for the method declarations and
|
|
method lookup functions.</para>
|
|
|
|
<para>Within this template the following keywords are used:
|
|
<literal>#include</literal>, <literal>INTERFACE</literal>,
|
|
<literal>CODE</literal>, <literal>METHOD</literal>,
|
|
<literal>STATICMETHOD</literal>, and
|
|
<literal>DEFAULT</literal>.</para>
|
|
|
|
<para>The <literal>#include</literal> statement and what follows
|
|
it is copied verbatim to the head of the generated code
|
|
file.</para>
|
|
|
|
<para>For example:</para>
|
|
|
|
<programlisting>#include <sys/foo.h></programlisting>
|
|
|
|
<para>The <literal>INTERFACE</literal> keyword is used to define
|
|
the interface name. This name is concatenated with each method
|
|
name as [interface name]_[method name]. Its syntax is
|
|
INTERFACE [interface name];.</para>
|
|
|
|
<para>For example:</para>
|
|
|
|
<programlisting>INTERFACE foo;</programlisting>
|
|
|
|
<para>The <literal>CODE</literal> keyword copies its arguments
|
|
verbatim into the code file. Its syntax is
|
|
<literal>CODE { [whatever] };</literal></para>
|
|
|
|
<para>For example:</para>
|
|
|
|
<programlisting>CODE {
|
|
struct foo * foo_alloc_null(struct bar *)
|
|
{
|
|
return NULL;
|
|
}
|
|
};</programlisting>
|
|
|
|
<para>The <literal>METHOD</literal> keyword describes a method. Its syntax is
|
|
<literal>METHOD [return type] [method name] { [object [,
|
|
arguments]] };</literal></para>
|
|
|
|
<para>For example:</para>
|
|
|
|
<programlisting>METHOD int bar {
|
|
struct object *;
|
|
struct foo *;
|
|
struct bar;
|
|
};</programlisting>
|
|
|
|
<para>The <literal>DEFAULT</literal> keyword may follow the
|
|
<literal>METHOD</literal> keyword. It extends the
|
|
<literal>METHOD</literal> key word to include the default
|
|
function for method. The extended syntax is
|
|
<literal>METHOD [return type] [method name] {
|
|
[object; [other arguments]] }DEFAULT [default
|
|
function];</literal></para>
|
|
|
|
<para>For example:</para>
|
|
|
|
<programlisting>METHOD int bar {
|
|
struct object *;
|
|
struct foo *;
|
|
int bar;
|
|
} DEFAULT foo_hack;</programlisting>
|
|
|
|
<para>The <literal>STATICMETHOD</literal> keyword is used like
|
|
the <literal>METHOD</literal> keyword except the kobj data is not
|
|
at the head of the object structure so casting to kobj_t would
|
|
be incorrect. Instead <literal>STATICMETHOD</literal> relies on the Kobj data being
|
|
referenced as 'ops'. This is also useful for calling
|
|
methods directly out of a class's method table.</para>
|
|
|
|
<para>Other complete examples:</para>
|
|
|
|
<programlisting>src/sys/kern/bus_if.m
|
|
src/sys/kern/device_if.m</programlisting>
|
|
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Creating a Class</title>
|
|
|
|
<para>The second step in using Kobj is to create a class. A
|
|
class consists of a name, a table of methods, and the size of
|
|
objects if Kobj's object handling facilities are used. To
|
|
create the class use the macro
|
|
<function>DEFINE_CLASS()</function>. To create the method
|
|
table create an array of kobj_method_t terminated by a NULL
|
|
entry. Each non-NULL entry may be created using the macro
|
|
<function>KOBJMETHOD()</function>.</para>
|
|
|
|
<para>For example:</para>
|
|
|
|
<programlisting>DEFINE_CLASS(fooclass, foomethods, sizeof(struct foodata));
|
|
|
|
kobj_method_t foomethods[] = {
|
|
KOBJMETHOD(bar_doo, foo_doo),
|
|
KOBJMETHOD(bar_foo, foo_foo),
|
|
{ NULL, NULL}
|
|
};</programlisting>
|
|
|
|
<para>The class must be <quote>compiled</quote>. Depending on
|
|
the state of the system at the time that the class is to be
|
|
initialized a statically allocated cache, <quote>ops
|
|
table</quote> have to be used. This can be accomplished by
|
|
declaring a <structname>struct kobj_ops</structname> and using
|
|
<function>kobj_class_compile_static();</function> otherwise,
|
|
<function>kobj_class_compile()</function> should be used.</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Creating an Object</title>
|
|
|
|
<para>The third step in using Kobj involves how to define the
|
|
object. Kobj object creation routines assume that Kobj data is
|
|
at the head of an object. If this in not appropriate you will
|
|
have to allocate the object yourself and then use
|
|
<function>kobj_init()</function> on the Kobj portion of it;
|
|
otherwise, you may use <function>kobj_create()</function> to
|
|
allocate and initialize the Kobj portion of the object
|
|
automatically. <function>kobj_init()</function> may also be
|
|
used to change the class that an object uses.</para>
|
|
|
|
<para>To integrate Kobj into the object you should use the macro
|
|
KOBJ_FIELDS.</para>
|
|
|
|
<para>For example</para>
|
|
|
|
<programlisting>struct foo_data {
|
|
KOBJ_FIELDS;
|
|
foo_foo;
|
|
foo_bar;
|
|
};</programlisting>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Calling Methods</title>
|
|
|
|
<para>The last step in using Kobj is to simply use the generated
|
|
functions to use the desired method within the object's
|
|
class. This is as simple as using the interface name and the
|
|
method name with a few modifications. The interface name
|
|
should be concatenated with the method name using a '_'
|
|
between them, all in upper case.</para>
|
|
|
|
<para>For example, if the interface name was foo and the method
|
|
was bar then the call would be:</para>
|
|
|
|
<programlisting>[return value = ] FOO_BAR(object [, other parameters]);</programlisting>
|
|
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Cleaning Up</title>
|
|
|
|
<para>When an object allocated through
|
|
<function>kobj_create()</function> is no longer needed
|
|
<function>kobj_delete()</function> may be called on it, and
|
|
when a class is no longer being used
|
|
<function>kobj_class_free()</function> may be called on it.</para>
|
|
</sect2>
|
|
</sect1>
|
|
</chapter>
|
|
|
|
<!--
|
|
Local Variables:
|
|
mode: sgml
|
|
sgml-declaration: "../chapter.decl"
|
|
sgml-indent-data: t
|
|
sgml-omittag: nil
|
|
sgml-always-quote-attributes: t
|
|
sgml-parent-document: ("../book.sgml" "part" "chapter")
|
|
End:
|
|
-->
|