⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kernel-hacking.tmpl

📁 linux 内核源代码
💻 TMPL
📖 第 1 页 / 共 3 页
字号:
   <filename class="headerfile">include/asm/atomic.h</filename>; this   contains a signed integer (at least 32 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.  </para>  <para>   The second class of atomic operations is atomic bit operations on an   <type>unsigned long</type>, defined in   <filename class="headerfile">include/linux/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 atomically setting flags.  </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> </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: dynamically    loaded modules will be able to use the symbol as normal.   </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_LICENSE()</function> that specifies a GPL    compatible license.  It implies that the function is considered    an internal implementation issue, and not really an interface.   </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 used to be three sets of linked-list routines in the kernel    headers, but this one is the winner.  If you don't have some    particular pressing need for a single list, it's a good choice.   </para>   <para>    In particular, <function>list_for_each_entry</function> is useful.   </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 kernel.   </para>   <para>    Using <function>ERR_PTR()</function>    <filename class="headerfile">include/linux/err.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>   <para>    Linus and the other developers sometimes change function or    structure names in development kernels; this is not done just to    keep everyone on their toes: it reflects a fundamental change    (eg. can no longer be called with interrupts on, or does extra    checks, or doesn't do checks which were caught before).  Usually    this is accompanied by a fairly complete note to the linux-kernel    mailing list; search the archive.  Simply doing a global replace    on the file usually makes things <emphasis>worse</emphasis>.   </para>  </sect1>  <sect1 id="conventions-initialising">   <title>Initializing structure members</title>   <para>    The preferred method of initializing structures is to use    designated initialisers, as defined by ISO C99, eg:   </para>   <programlisting>static struct block_device_operations opt_fops = {        .open               = opt_open,        .release            = opt_release,        .ioctl              = opt_ioctl,        .check_media_change = opt_media_change,};   </programlisting>   <para>    This makes it easy to grep for, and makes it clear which    structure fields are set.  You should do this because it looks    cool.   </para>  </sect1>  <sect1 id="conventions-gnu-extns">   <title>GNU Extensions</title>   <para>    GNU Extensions are explicitly allowed in the Linux kernel.    Note that some of the more complex ones are not very well    supported, due to lack of general use, but the following are    considered standard (see the GCC info page section "C    Extensions" for more details - Yes, really the info page, the    man page is only a short summary of the stuff in info).   </para>   <itemizedlist>    <listitem>     <para>      Inline functions     </para>    </listitem>    <listitem>     <para>      Statement expressions (ie. the ({ and }) constructs).     </para>    </listitem>    <listitem>     <para>      Declaring attributes of a function / variable / type      (__attribute__)     </para>    </listitem>    <listitem>     <para>      typeof     </para>    </listitem>    <listitem>     <para>      Zero length arrays     </para>    </listitem>    <listitem>     <para>      Macro varargs     </para>    </listitem>    <listitem>     <para>      Arithmetic on void pointers     </para>    </listitem>    <listitem>     <para>      Non-Constant initializers     </para>    </listitem>    <listitem>     <para>      Assembler Instructions (not outside arch/ and include/asm/)     </para>    </listitem>    <listitem>     <para>      Function names as strings (__FUNCTION__).     </para>    </listitem>    <listitem>     <para>      __builtin_constant_p()     </para>    </listitem>   </itemizedlist>   <para>    Be wary when using long long in the kernel, the code gcc generates for    it is horrible and worse: division and multiplication does not work    on i386 because the GCC runtime functions for it are missing from    the kernel environment.   </para>    <!-- FIXME: add a note about ANSI aliasing cleanness -->  </sect1>  <sect1 id="conventions-cplusplus">   <title>C++</title>      <para>    Using C++ in the kernel is usually a bad idea, because the    kernel does not provide the necessary runtime environment    and the include files are not tested for it.  It is still    possible, but not recommended.  If you really want to do    this, forget about exceptions at least.   </para>  </sect1>  <sect1 id="conventions-ifdef">   <title>&num;if</title>      <para>    It is generally considered cleaner to use macros in header files    (or at the top of .c files) to abstract away functions rather than    using `#if' pre-processor statements throughout the source code.   </para>  </sect1> </chapter> <chapter id="submitting">  <title>Putting Your Stuff in the Kernel</title>  <para>   In order to get your stuff into shape for official inclusion, or   even to make a neat patch, there's administrative work to be   done:  </para>  <itemizedlist>   <listitem>    <para>     Figure out whose pond you've been pissing in.  Look at the top of     the source files, inside the <filename>MAINTAINERS</filename>     file, and last of all in the <filename>CREDITS</filename> file.     You should coordinate with this person to make sure you're not     duplicating effort, or trying something that's already been     rejected.    </para>    <para>     Make sure you put your name and EMail address at the top of     any files you create or mangle significantly.  This is the     first place people will look when they find a bug, or when     <emphasis>they</emphasis> want to make a change.    </para>   </listitem>   <listitem>    <para>     Usually you want a configuration option for your kernel hack.     Edit <filename>Kconfig</filename> in the appropriate directory.     The Config language is simple to use by cut and paste, and there's     complete documentation in     <filename>Documentation/kbuild/kconfig-language.txt</filename>.    </para>    <para>     You may well want to make your CONFIG option only visible if     <symbol>CONFIG_EXPERIMENTAL</symbol> is enabled: this serves as a     warning to users.  There many other fancy things you can do: see     the various <filename>Kconfig</filename> files for ideas.    </para>    <para>     In your description of the option, make sure you address both the     expert user and the user who knows nothing about your feature.  Mention     incompatibilities and issues here.  <emphasis> Definitely     </emphasis> end your description with <quote> if in doubt, say N     </quote> (or, occasionally, `Y'); this is for people who have no     idea what you are talking about.    </para>   </listitem>   <listitem>    <para>     Edit the <filename>Makefile</filename>: the CONFIG variables are     exported here so you can usually just add a "obj-$(CONFIG_xxx) +=     xxx.o" line.  The syntax is documented in     <filename>Documentation/kbuild/makefiles.txt</filename>.    </para>   </listitem>   <listitem>    <para>     Put yourself in <filename>CREDITS</filename> if you've done     something noteworthy, usually beyond a single file (your name     should be at the top of the source files anyway).     <filename>MAINTAINERS</filename> means you want to be consulted     when changes are made to a subsystem, and hear about bugs; it     implies a more-than-passing commitment to some part of the code.    </para>   </listitem>      <listitem>    <para>     Finally, don't forget to read <filename>Documentation/SubmittingPatches</filename>     and possibly <filename>Documentation/SubmittingDrivers</filename>.    </para>   </listitem>  </itemizedlist> </chapter> <chapter id="cantrips">  <title>Kernel Cantrips</title>  <para>   Some favorites from browsing the source.  Feel free to add to this   list.  </para>  <para>   <filename>include/asm-x86/delay_32.h:</filename>  </para>  <programlisting>#define ndelay(n) (__builtin_constant_p(n) ? \        ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \        __ndelay(n))  </programlisting>  <para>   <filename>include/linux/fs.h</filename>:  </para>  <programlisting>/* * Kernel pointers have redundant information, so we can use a * scheme where we can return either an error code or a dentry * pointer with the same return value. * * This should be a per-architecture thing, to allow different * error and pointer decisions. */ #define ERR_PTR(err)    ((void *)((long)(err))) #define PTR_ERR(ptr)    ((long)(ptr)) #define IS_ERR(ptr)     ((unsigned long)(ptr) > (unsigned long)(-1000))</programlisting>  <para>   <filename>include/asm-x86/uaccess_32.h:</filename>  </para>  <programlisting>#define copy_to_user(to,from,n)                         \        (__builtin_constant_p(n) ?                      \         __constant_copy_to_user((to),(from),(n)) :     \         __generic_copy_to_user((to),(from),(n)))  </programlisting>  <para>   <filename>arch/sparc/kernel/head.S:</filename>  </para>  <programlisting>/* * Sun people can't spell worth damn. "compatability" indeed. * At least we *know* we can't spell, and use a spell-checker. *//* Uh, actually Linus it is I who cannot spell. Too much murky * Sparc assembly will do this to ya. */C_LABEL(cputypvar):        .asciz "compatability"/* Tested on SS-5, SS-10. Probably someone at Sun applied a spell-checker. */        .align 4C_LABEL(cputypvar_sun4m):        .asciz "compatible"  </programlisting>  <para>   <filename>arch/sparc/lib/checksum.S:</filename>  </para>  <programlisting>        /* Sun, you just can't beat me, you just can't.  Stop trying,         * give up.  I'm serious, I am going to kick the living shit         * out of you, game over, lights out.         */  </programlisting> </chapter> <chapter id="credits">  <title>Thanks</title>  <para>   Thanks to Andi Kleen for the idea, answering my questions, fixing   my mistakes, filling content, etc.  Philipp Rumpf for more spelling   and clarity fixes, and some excellent non-obvious points.  Werner   Almesberger for giving me a great summary of   <function>disable_irq()</function>, and Jes Sorensen and Andrea   Arcangeli added caveats. Michael Elizabeth Chastain for checking   and adding to the Configure section. <!-- Rusty insisted on this   bit; I didn't do it! --> Telsa Gwynne for teaching me DocBook.   </para> </chapter></book>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -