?? kernel-hacking.tmpl
字號:
</para> </sect1> <sect1 id="routines-init"> <title><type>__init</type>/<type>__exit</type>/<type>__initdata</type> <filename class=headerfile>include/linux/init.h</filename></title> <para> After boot, the kernel frees up a special section; functions marked with <type>__init</type> and data structures marked with <type>__initdata</type> are dropped after boot is complete (within modules this directive is currently ignored). <type>__exit</type> is used to declare a function which is only required on exit: the function will be dropped if this file is not compiled as a module. See the header file for use. Note that it makes no sense for a function marked with <type>__init</type> to be exported to modules with <function>EXPORT_SYMBOL()</function> - this will break. </para> <para> Static data structures marked as <type>__initdata</type> must be initialised (as opposed to ordinary static data which is zeroed BSS) and cannot be <type>const</type>. </para> </sect1> <sect1 id="routines-init-again"> <title><function>__initcall()</function>/<function>module_init()</function> <filename class=headerfile>include/linux/init.h</filename></title> <para> Many parts of the kernel are well served as a module (dynamically-loadable parts of the kernel). Using the <function>module_init()</function> and <function>module_exit()</function> macros it is easy to write code without #ifdefs which can operate both as a module or built into the kernel. </para> <para> The <function>module_init()</function> macro defines which function is to be called at module insertion time (if the file is compiled as a module), or at boot time: if the file is not compiled as a module the <function>module_init()</function> macro becomes equivalent to <function>__initcall()</function>, which through linker magic ensures that the function is called on boot. </para> <para> The function can return a negative error number to cause module loading to fail (unfortunately, this has no effect if the module is compiled into the kernel). For modules, this is called in user context, with interrupts enabled, and the kernel lock held, so it can sleep. </para> </sect1> <sect1 id="routines-moduleexit"> <title> <function>module_exit()</function> <filename class=headerfile>include/linux/init.h</filename> </title> <para> This macro defines the function to be called at module removal time (or never, in the case of the file compiled into the kernel). It will only be called if the module usage count has reached zero. This function can also sleep, but cannot fail: everything must be cleaned up by the time it returns. </para> </sect1> <sect1 id="routines-module-use-counters"> <title> <function>MOD_INC_USE_COUNT</function>/<function>MOD_DEC_USE_COUNT</function> <filename class=headerfile>include/linux/module.h</filename></title> <para> These manipulate the module usage count, to protect against removal (a module also can't be removed if another module uses one of its exported symbols: see below). Every reference to the module from user context should be reflected by this counter (e.g. for every data structure or socket) before the function sleeps. To quote Tim Waugh: </para> <programlisting>/* THIS IS BAD */foo_open (...){ stuff.. if (fail) return -EBUSY; sleep.. (might get unloaded here) stuff.. MOD_INC_USE_COUNT; return 0;}/* THIS IS GOOD /foo_open (...){ MOD_INC_USE_COUNT; stuff.. if (fail) { MOD_DEC_USE_COUNT; return -EBUSY; } sleep.. (safe now) stuff.. return 0;} </programlisting> <para> You can often avoid having to deal with these problems by using the <structfield>owner</structfield> field of the <structname>file_operations</structname> structure. Set this field as the macro <symbol>THIS_MODULE</symbol>. </para> <para> For more complicated module unload locking requirements, you can set the <structfield>can_unload</structfield> function pointer to your own routine, which should return <returnvalue>0</returnvalue> if the module is unloadable, or <returnvalue>-EBUSY</returnvalue> otherwise. </para> </sect1> </chapter> <chapter id="queues"> <title>Wait Queues <filename class=headerfile>include/linux/wait.h</filename> </title> <para> <emphasis>[SLEEPS]</emphasis> </para> <para> A wait queue is used to wait for someone to wake you up when a certain condition is true. They must be used carefully to ensure there is no race condition. You declare a <type>wait_queue_head_t</type>, and then processes which want to wait for that condition declare a <type>wait_queue_t</type> referring to themselves, and place that in the queue. </para> <sect1 id="queue-declaring"> <title>Declaring</title> <para> You declare a <type>wait_queue_head_t</type> using the <function>DECLARE_WAIT_QUEUE_HEAD()</function> macro, or using the <function>init_waitqueue_head()</function> routine in your initialization code. </para> </sect1> <sect1 id="queue-waitqueue"> <title>Queuing</title> <para> Placing yourself in the waitqueue is fairly complex, because you must put yourself in the queue before checking the condition. There is a macro to do this: <function>wait_event_interruptible()</function> <filename class=headerfile>include/linux/sched.h</filename> The first argument is the wait queue head, and the second is an expression which is evaluated; the macro returns <returnvalue>0</returnvalue> when this expression is true, or <returnvalue>-ERESTARTSYS</returnvalue> if a signal is received. The <function>wait_event()</function> version ignores signals. </para> <para> Do not use the <function>sleep_on()</function> function family - it is very easy to accidentally introduce races; almost certainly one of the <function>wait_event()</function> family will do, or a loop around <function>schedule_timeout()</function>. If you choose to loop around <function>schedule_timeout()</function> remember you must set the task state (with <function>set_current_state()</function>) on each iteration to avoid busy-looping. </para> </sect1> <sect1 id="queue-waking"> <title>Waking Up Queued Tasks</title> <para> Call <function>wake_up()</function> <filename class=headerfile>include/linux/sched.h</filename>;, which will wake up every process in the queue. The exception is if one has <constant>TASK_EXCLUSIVE</constant> set, in which case the remainder of the queue will not be woken. </para> </sect1> </chapter> <chapter id="atomic-ops"> <title>Atomic Operations</title> <para> Certain operations are guaranteed atomic on all platforms. The first class of operations work on <type>atomic_t</type> <filename class=headerfile>include/asm/atomic.h</filename>; this contains a signed integer (at least 24 bits long), and you must use these functions to manipulate or read atomic_t variables. <function>atomic_read()</function> and <function>atomic_set()</function> get and set the counter, <function>atomic_add()</function>, <function>atomic_sub()</function>, <function>atomic_inc()</function>, <function>atomic_dec()</function>, and <function>atomic_dec_and_test()</function> (returns <returnvalue>true</returnvalue> if it was decremented to zero). </para> <para> Yes. It returns <returnvalue>true</returnvalue> (i.e. != 0) if the atomic variable is zero. </para> <para> Note that these functions are slower than normal arithmetic, and so should not be used unnecessarily. On some platforms they are much slower, like 32-bit Sparc where they use a spinlock. </para> <para> The second class of atomic operations is atomic bit operations on a <type>long</type>, defined in <filename class=headerfile>include/asm/bitops.h</filename>. These operations generally take a pointer to the bit pattern, and a bit number: 0 is the least significant bit. <function>set_bit()</function>, <function>clear_bit()</function> and <function>change_bit()</function> set, clear, and flip the given bit. <function>test_and_set_bit()</function>, <function>test_and_clear_bit()</function> and <function>test_and_change_bit()</function> do the same thing, except return true if the bit was previously set; these are particularly useful for very simple locking. </para> <para> It is possible to call these operations with bit indices greater than BITS_PER_LONG. The resulting behavior is strange on big-endian platforms though so it is a good idea not to do this. </para> <para> Note that the order of bits depends on the architecture, and in particular, the bitfield passed to these operations must be at least as large as a <type>long</type>. </para> </chapter> <chapter id="symbols"> <title>Symbols</title> <para> Within the kernel proper, the normal linking rules apply (ie. unless a symbol is declared to be file scope with the <type>static</type> keyword, it can be used anywhere in the kernel). However, for modules, a special exported symbol table is kept which limits the entry points to the kernel proper. Modules can also export symbols. </para> <sect1 id="sym-exportsymbols"> <title><function>EXPORT_SYMBOL()</function> <filename class=headerfile>include/linux/module.h</filename></title> <para> This is the classic method of exporting a symbol, and it works for both modules and non-modules. In the kernel all these declarations are often bundled into a single file to help genksyms (which searches source files for these declarations). See the comment on genksyms and Makefiles below. </para> </sect1> <sect1 id="sym-exportnosymbols"> <title><symbol>EXPORT_NO_SYMBOLS</symbol> <filename class=headerfile>include/linux/module.h</filename></title> <para> If a module exports no symbols then you can specify <programlisting>EXPORT_NO_SYMBOLS; </programlisting> anywhere in the module. In kernel 2.4 and earlier, if a module contains neither <function>EXPORT_SYMBOL()</function> nor <symbol>EXPORT_NO_SYMBOLS</symbol> then the module defaults to exporting all non-static global symbols. In kernel 2.5 onwards you must explicitly specify whether a module exports symbols or not. </para> </sect1> <sect1 id="sym-exportsymbols-gpl"> <title><function>EXPORT_SYMBOL_GPL()</function> <filename class=headerfile>include/linux/module.h</filename></title> <para> Similar to <function>EXPORT_SYMBOL()</function> except that the symbols exported by <function>EXPORT_SYMBOL_GPL()</function> can only be seen by modules with a <function>MODULE_LICENCE()</function> that specifies a GPL compatible license. </para> </sect1> </chapter> <chapter id="conventions"> <title>Routines and Conventions</title> <sect1 id="conventions-doublelinkedlist"> <title>Double-linked lists <filename class=headerfile>include/linux/list.h</filename></title> <para> There are three sets of linked-list routines in the kernel headers, but this one seems to be winning out (and Linus has used it). If you don't have some particular pressing need for a single list, it's a good choice. In fact, I don't care whether it's a good choice or not, just use it so we can get rid of the others. </para> </sect1> <sect1 id="convention-returns"> <title>Return Conventions</title> <para> For code called in user context, it's very common to defy C convention, and return <returnvalue>0</returnvalue> for success, and a negative error number (eg. <returnvalue>-EFAULT</returnvalue>) for failure. This can be unintuitive at first, but it's fairly widespread in the networking code, for example. </para> <para> The filesystem code uses <function>ERR_PTR()</function> <filename class=headerfile>include/linux/fs.h</filename>; to encode a negative error number into a pointer, and <function>IS_ERR()</function> and <function>PTR_ERR()</function> to get it back out again: avoids a separate pointer parameter for the error number. Icky, but in a good way. </para> </sect1> <sect1 id="conventions-borkedcompile"> <title>Breaking Compilation</title>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -