?? kernel-hacking.tmpl
字號(hào):
<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 the gcc Labeled Elements extension, 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> Labeled elements </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>#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>Config.in</filename> in the appropriate directory (but under <filename>arch/</filename> it's called <filename>config.in</filename>). The Config Language used is not bash, even though it looks like bash; the safe way is to use only the constructs that you already see in <filename>Config.in</filename> files (see <filename>Documentation/kbuild/config-language.txt</filename>). It's good to run "make xconfig" at least once to test (because it's the only one with a static parser). </para> <para> Variables which can be Y or N use <type>bool</type> followed by a tagline and the config define name (which must start with CONFIG_). The <type>tristate</type> function is the same, but allows the answer M (which defines <symbol>CONFIG_foo_MODULE</symbol> in your source, instead of <symbol>CONFIG_FOO</symbol>) if <symbol>CONFIG_MODULES</symbol> is enabled. </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>Config.in</filename> files for ideas. </para> </listitem> <listitem> <para> Edit the <filename>Makefile</filename>: the CONFIG variables are exported here so you can conditionalize compilation with `ifeq'. If your file exports symbols then add the names to <varname>export-objs</varname> so that genksyms will find them. <caution> <para> There is a restriction on the kernel build system that objects which export symbols must have globally unique names. If your object does not have a globally unique name then the standard fix is to move the <function>EXPORT_SYMBOL()</function> statements to their own object with a unique name. This is why several systems have separate exporting objects, usually suffixed with ksyms. </para> </caution> </para> </listitem> <listitem> <para> Document your option in Documentation/Configure.help. 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> 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/linux/brlock.h:</filename> </para> <programlisting>extern inline void br_read_lock (enum brlock_indices idx){ /* * This causes a link-time bug message if an * invalid index is used: */ if (idx >= __BR_END) __br_lock_usage_bug(); read_lock(&__brlock_array[smp_processor_id()][idx]);} </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-i386/uaccess.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>
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -