aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2016-06-14 16:42:10 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2016-06-14 16:42:10 -0400
commitdb5dfef7121752ec9053160e0a7804815d4608c3 (patch)
tree6cdd00f9fcbaceadcf7e173ff671abbcf4f95711
parent0d841ac0ec213f70ab59d65129e80f229846fadf (diff)
parent8569de68e79e94cce6709831edd94accb6942ade (diff)
Merge tag 'sphinx-4.8' of git://git.lwn.net/linux into topic/drm-misc
Stable tag for sphinx work Pull current state of the sphinx rework from Jonathan into drm-misc so that we can start converting gpu.tmpl. Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
-rw-r--r--Documentation/.gitignore1
-rw-r--r--Documentation/DocBook/Makefile7
-rw-r--r--Documentation/Makefile.sphinx63
-rw-r--r--Documentation/conf.py414
-rw-r--r--Documentation/dmaengine/provider.txt2
-rw-r--r--Documentation/index.rst23
-rw-r--r--Documentation/kernel-parameters.txt5
-rw-r--r--Documentation/mic/mpssd/mpssd.c4
-rw-r--r--Documentation/security/self-protection.txt28
-rw-r--r--Documentation/sphinx/convert_template.sed18
-rw-r--r--Documentation/sphinx/kernel-doc.py127
-rw-r--r--Documentation/sphinx/post_convert.sed23
-rwxr-xr-xDocumentation/sphinx/tmplcvt19
-rw-r--r--Documentation/sync_file.txt6
-rw-r--r--Documentation/zh_CN/CodingStyle581
-rw-r--r--Makefile5
-rwxr-xr-xscripts/kernel-doc393
17 files changed, 1326 insertions, 393 deletions
diff --git a/Documentation/.gitignore b/Documentation/.gitignore
new file mode 100644
index 000000000000..53752db253e3
--- /dev/null
+++ b/Documentation/.gitignore
@@ -0,0 +1 @@
output
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index d70f9b68174e..e0c7e1e0590b 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -33,10 +33,6 @@ PDF_METHOD = $(prefer-db2x)
33PS_METHOD = $(prefer-db2x) 33PS_METHOD = $(prefer-db2x)
34 34
35 35
36###
37# The targets that may be used.
38PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs cleandocs
39
40targets += $(DOCBOOKS) 36targets += $(DOCBOOKS)
41BOOKS := $(addprefix $(obj)/,$(DOCBOOKS)) 37BOOKS := $(addprefix $(obj)/,$(DOCBOOKS))
42xmldocs: $(BOOKS) 38xmldocs: $(BOOKS)
@@ -63,6 +59,9 @@ installmandocs: mandocs
63 sort -k 2 -k 1 | uniq -f 1 | sed -e 's: :/:' | \ 59 sort -k 2 -k 1 | uniq -f 1 | sed -e 's: :/:' | \
64 xargs install -m 644 -t /usr/local/man/man9/ 60 xargs install -m 644 -t /usr/local/man/man9/
65 61
62# no-op for the DocBook toolchain
63epubdocs:
64
66### 65###
67#External programs used 66#External programs used
68KERNELDOCXMLREF = $(srctree)/scripts/kernel-doc-xml-ref 67KERNELDOCXMLREF = $(srctree)/scripts/kernel-doc-xml-ref
diff --git a/Documentation/Makefile.sphinx b/Documentation/Makefile.sphinx
new file mode 100644
index 000000000000..addf32309bc3
--- /dev/null
+++ b/Documentation/Makefile.sphinx
@@ -0,0 +1,63 @@
1# -*- makefile -*-
2# Makefile for Sphinx documentation
3#
4
5# You can set these variables from the command line.
6SPHINXBUILD = sphinx-build
7SPHINXOPTS =
8PAPER =
9BUILDDIR = $(obj)/output
10
11# User-friendly check for sphinx-build
12HAVE_SPHINX := $(shell if which $(SPHINXBUILD) >/dev/null 2>&1; then echo 1; else echo 0; fi)
13
14ifeq ($(HAVE_SPHINX),0)
15
16.DEFAULT:
17 $(warning The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed and in PATH, or set the SPHINXBUILD make variable to point to the full path of the '$(SPHINXBUILD)' executable.)
18 @echo " SKIP Sphinx $@ target."
19
20else # HAVE_SPHINX
21
22# User-friendly check for rst2pdf
23HAVE_RST2PDF := $(shell if python -c "import rst2pdf" >/dev/null 2>&1; then echo 1; else echo 0; fi)
24
25# Internal variables.
26PAPEROPT_a4 = -D latex_paper_size=a4
27PAPEROPT_letter = -D latex_paper_size=letter
28KERNELDOC = $(srctree)/scripts/kernel-doc
29KERNELDOC_CONF = -D kerneldoc_srctree=$(srctree) -D kerneldoc_bin=$(KERNELDOC)
30ALLSPHINXOPTS = -D version=$(KERNELVERSION) -D release=$(KERNELRELEASE) -d $(BUILDDIR)/.doctrees $(KERNELDOC_CONF) $(PAPEROPT_$(PAPER)) -c $(srctree)/$(src) $(SPHINXOPTS) $(srctree)/$(src)
31# the i18n builder cannot share the environment and doctrees with the others
32I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
33
34quiet_cmd_sphinx = SPHINX $@
35 cmd_sphinx = $(SPHINXBUILD) -b $2 $(ALLSPHINXOPTS) $(BUILDDIR)/$2
36
37htmldocs:
38 $(call cmd,sphinx,html)
39
40pdfdocs:
41ifeq ($(HAVE_RST2PDF),0)
42 $(warning The Python 'rst2pdf' module was not found. Make sure you have the module installed to produce PDF output.)
43 @echo " SKIP Sphinx $@ target."
44else # HAVE_RST2PDF
45 $(call cmd,sphinx,pdf)
46endif # HAVE_RST2PDF
47
48epubdocs:
49 $(call cmd,sphinx,epub)
50
51xmldocs:
52 $(call cmd,sphinx,xml)
53
54# no-ops for the Sphinx toolchain
55sgmldocs:
56psdocs:
57mandocs:
58installmandocs:
59
60cleandocs:
61 $(Q)rm -rf $(BUILDDIR)
62
63endif # HAVE_SPHINX
diff --git a/Documentation/conf.py b/Documentation/conf.py
new file mode 100644
index 000000000000..6cc41a0555a3
--- /dev/null
+++ b/Documentation/conf.py
@@ -0,0 +1,414 @@
1# -*- coding: utf-8 -*-
2#
3# The Linux Kernel documentation build configuration file, created by
4# sphinx-quickstart on Fri Feb 12 13:51:46 2016.
5#
6# This file is execfile()d with the current directory set to its
7# containing dir.
8#
9# Note that not all possible configuration values are present in this
10# autogenerated file.
11#
12# All configuration values have a default; values that are commented out
13# serve to show the default.
14
15import sys
16import os
17
18# If extensions (or modules to document with autodoc) are in another directory,
19# add these directories to sys.path here. If the directory is relative to the
20# documentation root, use os.path.abspath to make it absolute, like shown here.
21sys.path.insert(0, os.path.abspath('sphinx'))
22
23# -- General configuration ------------------------------------------------
24
25# If your documentation needs a minimal Sphinx version, state it here.
26#needs_sphinx = '1.0'
27
28# Add any Sphinx extension module names here, as strings. They can be
29# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
30# ones.
31extensions = ['kernel-doc']
32
33# Gracefully handle missing rst2pdf.
34try:
35 import rst2pdf
36 extensions += ['rst2pdf.pdfbuilder']
37except ImportError:
38 pass
39
40# Add any paths that contain templates here, relative to this directory.
41templates_path = ['_templates']
42
43# The suffix(es) of source filenames.
44# You can specify multiple suffix as a list of string:
45# source_suffix = ['.rst', '.md']
46source_suffix = '.rst'
47
48# The encoding of source files.
49#source_encoding = 'utf-8-sig'
50
51# The master toctree document.
52master_doc = 'index'
53
54# General information about the project.
55project = 'The Linux Kernel'
56copyright = '2016, The kernel development community'
57author = 'The kernel development community'
58
59# The version info for the project you're documenting, acts as replacement for
60# |version| and |release|, also used in various other places throughout the
61# built documents.
62#
63# In a normal build, version and release are are set to KERNELVERSION and
64# KERNELRELEASE, respectively, from the Makefile via Sphinx command line
65# arguments.
66#
67# The following code tries to extract the information by reading the Makefile,
68# when Sphinx is run directly (e.g. by Read the Docs).
69try:
70 makefile_version = None
71 makefile_patchlevel = None
72 for line in open('../Makefile'):
73 key, val = [x.strip() for x in line.split('=', 2)]
74 if key == 'VERSION':
75 makefile_version = val
76 elif key == 'PATCHLEVEL':
77 makefile_patchlevel = val
78 if makefile_version and makefile_patchlevel:
79 break
80except:
81 pass
82finally:
83 if makefile_version and makefile_patchlevel:
84 version = release = makefile_version + '.' + makefile_patchlevel
85 else:
86 sys.stderr.write('Warning: Could not extract kernel version\n')
87 version = release = "unknown version"
88
89# The language for content autogenerated by Sphinx. Refer to documentation
90# for a list of supported languages.
91#
92# This is also used if you do content translation via gettext catalogs.
93# Usually you set "language" from the command line for these cases.
94language = None
95
96# There are two options for replacing |today|: either, you set today to some
97# non-false value, then it is used:
98#today = ''
99# Else, today_fmt is used as the format for a strftime call.
100#today_fmt = '%B %d, %Y'
101
102# List of patterns, relative to source directory, that match files and
103# directories to ignore when looking for source files.
104exclude_patterns = ['output']
105
106# The reST default role (used for this markup: `text`) to use for all
107# documents.
108#default_role = None
109
110# If true, '()' will be appended to :func: etc. cross-reference text.
111#add_function_parentheses = True
112
113# If true, the current module name will be prepended to all description
114# unit titles (such as .. function::).
115#add_module_names = True
116
117# If true, sectionauthor and moduleauthor directives will be shown in the
118# output. They are ignored by default.
119#show_authors = False
120
121# The name of the Pygments (syntax highlighting) style to use.
122pygments_style = 'sphinx'
123
124# A list of ignored prefixes for module index sorting.
125#modindex_common_prefix = []
126
127# If true, keep warnings as "system message" paragraphs in the built documents.
128#keep_warnings = False
129
130# If true, `todo` and `todoList` produce output, else they produce nothing.
131todo_include_todos = False
132
133primary_domain = 'C'
134highlight_language = 'C'
135
136# -- Options for HTML output ----------------------------------------------
137
138# The theme to use for HTML and HTML Help pages. See the documentation for
139# a list of builtin themes.
140
141# The Read the Docs theme is available from
142# - https://github.com/snide/sphinx_rtd_theme
143# - https://pypi.python.org/pypi/sphinx_rtd_theme
144# - python-sphinx-rtd-theme package (on Debian)
145try:
146 import sphinx_rtd_theme
147 html_theme = 'sphinx_rtd_theme'
148 html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
149except ImportError:
150 sys.stderr.write('Warning: The Sphinx \'sphinx_rtd_theme\' HTML theme was not found. Make sure you have the theme installed to produce pretty HTML output. Falling back to the default theme.\n')
151
152# Theme options are theme-specific and customize the look and feel of a theme
153# further. For a list of options available for each theme, see the
154# documentation.
155#html_theme_options = {}
156
157# Add any paths that contain custom themes here, relative to this directory.
158#html_theme_path = []
159
160# The name for this set of Sphinx documents. If None, it defaults to
161# "<project> v<release> documentation".
162#html_title = None
163
164# A shorter title for the navigation bar. Default is the same as html_title.
165#html_short_title = None
166
167# The name of an image file (relative to this directory) to place at the top
168# of the sidebar.
169#html_logo = None
170
171# The name of an image file (within the static path) to use as favicon of the
172# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
173# pixels large.
174#html_favicon = None
175
176# Add any paths that contain custom static files (such as style sheets) here,
177# relative to this directory. They are copied after the builtin static files,
178# so a file named "default.css" will overwrite the builtin "default.css".
179#html_static_path = ['_static']
180
181# Add any extra paths that contain custom files (such as robots.txt or
182# .htaccess) here, relative to this directory. These files are copied
183# directly to the root of the documentation.
184#html_extra_path = []
185
186# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
187# using the given strftime format.
188#html_last_updated_fmt = '%b %d, %Y'
189
190# If true, SmartyPants will be used to convert quotes and dashes to
191# typographically correct entities.
192#html_use_smartypants = True
193
194# Custom sidebar templates, maps document names to template names.
195#html_sidebars = {}
196
197# Additional templates that should be rendered to pages, maps page names to
198# template names.
199#html_additional_pages = {}
200
201# If false, no module index is generated.
202#html_domain_indices = True
203
204# If false, no index is generated.
205#html_use_index = True
206
207# If true, the index is split into individual pages for each letter.
208#html_split_index = False
209
210# If true, links to the reST sources are added to the pages.
211#html_show_sourcelink = True
212
213# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
214#html_show_sphinx = True
215
216# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
217#html_show_copyright = True
218
219# If true, an OpenSearch description file will be output, and all pages will
220# contain a <link> tag referring to it. The value of this option must be the
221# base URL from which the finished HTML is served.
222#html_use_opensearch = ''
223
224# This is the file name suffix for HTML files (e.g. ".xhtml").
225#html_file_suffix = None
226
227# Language to be used for generating the HTML full-text search index.
228# Sphinx supports the following languages:
229# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja'
230# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr'
231#html_search_language = 'en'
232
233# A dictionary with options for the search language support, empty by default.
234# Now only 'ja' uses this config value
235#html_search_options = {'type': 'default'}
236
237# The name of a javascript file (relative to the configuration directory) that
238# implements a search results scorer. If empty, the default will be used.
239#html_search_scorer = 'scorer.js'
240
241# Output file base name for HTML help builder.
242htmlhelp_basename = 'TheLinuxKerneldoc'
243
244# -- Options for LaTeX output ---------------------------------------------
245
246latex_elements = {
247# The paper size ('letterpaper' or 'a4paper').
248#'papersize': 'letterpaper',
249
250# The font size ('10pt', '11pt' or '12pt').
251#'pointsize': '10pt',
252
253# Additional stuff for the LaTeX preamble.
254#'preamble': '',
255
256# Latex figure (float) alignment
257#'figure_align': 'htbp',
258}
259
260# Grouping the document tree into LaTeX files. List of tuples
261# (source start file, target name, title,
262# author, documentclass [howto, manual, or own class]).
263latex_documents = [
264 (master_doc, 'TheLinuxKernel.tex', 'The Linux Kernel Documentation',
265 'The kernel development community', 'manual'),
266]
267
268# The name of an image file (relative to this directory) to place at the top of
269# the title page.
270#latex_logo = None
271
272# For "manual" documents, if this is true, then toplevel headings are parts,
273# not chapters.
274#latex_use_parts = False
275
276# If true, show page references after internal links.
277#latex_show_pagerefs = False
278
279# If true, show URL addresses after external links.
280#latex_show_urls = False
281
282# Documents to append as an appendix to all manuals.
283#latex_appendices = []
284
285# If false, no module index is generated.
286#latex_domain_indices = True
287
288
289# -- Options for manual page output ---------------------------------------
290
291# One entry per manual page. List of tuples
292# (source start file, name, description, authors, manual section).
293man_pages = [
294 (master_doc, 'thelinuxkernel', 'The Linux Kernel Documentation',
295 [author], 1)
296]
297
298# If true, show URL addresses after external links.
299#man_show_urls = False
300
301
302# -- Options for Texinfo output -------------------------------------------
303
304# Grouping the document tree into Texinfo files. List of tuples
305# (source start file, target name, title, author,
306# dir menu entry, description, category)
307texinfo_documents = [
308 (master_doc, 'TheLinuxKernel', 'The Linux Kernel Documentation',
309 author, 'TheLinuxKernel', 'One line description of project.',
310 'Miscellaneous'),
311]
312
313# Documents to append as an appendix to all manuals.
314#texinfo_appendices = []
315
316# If false, no module index is generated.
317#texinfo_domain_indices = True
318
319# How to display URL addresses: 'footnote', 'no', or 'inline'.
320#texinfo_show_urls = 'footnote'
321
322# If true, do not generate a @detailmenu in the "Top" node's menu.
323#texinfo_no_detailmenu = False
324
325
326# -- Options for Epub output ----------------------------------------------
327
328# Bibliographic Dublin Core info.
329epub_title = project
330epub_author = author
331epub_publisher = author
332epub_copyright = copyright
333
334# The basename for the epub file. It defaults to the project name.
335#epub_basename = project
336
337# The HTML theme for the epub output. Since the default themes are not
338# optimized for small screen space, using the same theme for HTML and epub
339# output is usually not wise. This defaults to 'epub', a theme designed to save
340# visual space.
341#epub_theme = 'epub'
342
343# The language of the text. It defaults to the language option
344# or 'en' if the language is not set.
345#epub_language = ''
346
347# The scheme of the identifier. Typical schemes are ISBN or URL.
348#epub_scheme = ''
349
350# The unique identifier of the text. This can be a ISBN number
351# or the project homepage.
352#epub_identifier = ''
353
354# A unique identification for the text.
355#epub_uid = ''
356
357# A tuple containing the cover image and cover page html template filenames.
358#epub_cover = ()
359
360# A sequence of (type, uri, title) tuples for the guide element of content.opf.
361#epub_guide = ()
362
363# HTML files that should be inserted before the pages created by sphinx.
364# The format is a list of tuples containing the path and title.
365#epub_pre_files = []
366
367# HTML files that should be inserted after the pages created by sphinx.
368# The format is a list of tuples containing the path and title.
369#epub_post_files = []
370
371# A list of files that should not be packed into the epub file.
372epub_exclude_files = ['search.html']
373
374# The depth of the table of contents in toc.ncx.
375#epub_tocdepth = 3
376
377# Allow duplicate toc entries.
378#epub_tocdup = True
379
380# Choose between 'default' and 'includehidden'.
381#epub_tocscope = 'default'
382
383# Fix unsupported image types using the Pillow.
384#epub_fix_images = False
385
386# Scale large images.
387#epub_max_image_width = 0
388
389# How to display URL addresses: 'footnote', 'no', or 'inline'.
390#epub_show_urls = 'inline'
391
392# If false, no index is generated.
393#epub_use_index = True
394
395#=======
396# rst2pdf
397#
398# Grouping the document tree into PDF files. List of tuples
399# (source start file, target name, title, author, options).
400#
401# See the Sphinx chapter of http://ralsina.me/static/manual.pdf
402#
403# FIXME: Do not add the index file here; the result will be too big. Adding
404# multiple PDF files here actually tries to get the cross-referencing right
405# *between* PDF files.
406pdf_documents = [
407 ('index', u'Kernel', u'Kernel', u'J. Random Bozo'),
408]
409
410# kernel-doc extension configuration for running Sphinx directly (e.g. by Read
411# the Docs). In a normal build, these are supplied from the Makefile via command
412# line arguments.
413kerneldoc_bin = '../scripts/kernel-doc'
414kerneldoc_srctree = '..'
diff --git a/Documentation/dmaengine/provider.txt b/Documentation/dmaengine/provider.txt
index 122b7f4876bb..91ce82d5f0c4 100644
--- a/Documentation/dmaengine/provider.txt
+++ b/Documentation/dmaengine/provider.txt
@@ -323,7 +323,7 @@ supported.
323 * device_resume 323 * device_resume
324 - Resumes a transfer on the channel 324 - Resumes a transfer on the channel
325 - This command should operate synchronously on the channel, 325 - This command should operate synchronously on the channel,
326 pausing right away the work of the given channel 326 resuming right away the work of the given channel
327 327
328 * device_terminate_all 328 * device_terminate_all
329 - Aborts all the pending and ongoing transfers on the channel 329 - Aborts all the pending and ongoing transfers on the channel
diff --git a/Documentation/index.rst b/Documentation/index.rst
new file mode 100644
index 000000000000..71a276f34c7f
--- /dev/null
+++ b/Documentation/index.rst
@@ -0,0 +1,23 @@
1.. The Linux Kernel documentation master file, created by
2 sphinx-quickstart on Fri Feb 12 13:51:46 2016.
3 You can adapt this file completely to your liking, but it should at least
4 contain the root `toctree` directive.
5
6Welcome to The Linux Kernel's documentation!
7============================================
8
9Nothing for you to see here *yet*. Please move along.
10
11Contents:
12
13.. toctree::
14 :maxdepth: 2
15
16
17Indices and tables
18==================
19
20* :ref:`genindex`
21* :ref:`modindex`
22* :ref:`search`
23
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 82b42c958d1c..a2a662d4da83 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -3992,8 +3992,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
3992 3992
3993 trace_event=[event-list] 3993 trace_event=[event-list]
3994 [FTRACE] Set and start specified trace events in order 3994 [FTRACE] Set and start specified trace events in order
3995 to facilitate early boot debugging. 3995 to facilitate early boot debugging. The event-list is a
3996 See also Documentation/trace/events.txt 3996 comma separated list of trace events to enable. See
3997 also Documentation/trace/events.txt
3997 3998
3998 trace_options=[option-list] 3999 trace_options=[option-list]
3999 [FTRACE] Enable or disable tracer options at boot. 4000 [FTRACE] Enable or disable tracer options at boot.
diff --git a/Documentation/mic/mpssd/mpssd.c b/Documentation/mic/mpssd/mpssd.c
index 30fb842a976d..49db1def1721 100644
--- a/Documentation/mic/mpssd/mpssd.c
+++ b/Documentation/mic/mpssd/mpssd.c
@@ -1538,9 +1538,9 @@ set_cmdline(struct mic_info *mic)
1538 1538
1539 len = snprintf(buffer, PATH_MAX, 1539 len = snprintf(buffer, PATH_MAX,
1540 "clocksource=tsc highres=off nohz=off "); 1540 "clocksource=tsc highres=off nohz=off ");
1541 len += snprintf(buffer + len, PATH_MAX, 1541 len += snprintf(buffer + len, PATH_MAX - len,
1542 "cpufreq_on;corec6_off;pc3_off;pc6_off "); 1542 "cpufreq_on;corec6_off;pc3_off;pc6_off ");
1543 len += snprintf(buffer + len, PATH_MAX, 1543 len += snprintf(buffer + len, PATH_MAX - len,
1544 "ifcfg=static;address,172.31.%d.1;netmask,255.255.255.0", 1544 "ifcfg=static;address,172.31.%d.1;netmask,255.255.255.0",
1545 mic->id + 1); 1545 mic->id + 1);
1546 1546
diff --git a/Documentation/security/self-protection.txt b/Documentation/security/self-protection.txt
index babd6378ec05..3010576c9fca 100644
--- a/Documentation/security/self-protection.txt
+++ b/Documentation/security/self-protection.txt
@@ -183,8 +183,9 @@ provide meaningful defenses.
183### Canaries, blinding, and other secrets 183### Canaries, blinding, and other secrets
184 184
185It should be noted that things like the stack canary discussed earlier 185It should be noted that things like the stack canary discussed earlier
186are technically statistical defenses, since they rely on a (leakable) 186are technically statistical defenses, since they rely on a secret value,
187secret value. 187and such values may become discoverable through an information exposure
188flaw.
188 189
189Blinding literal values for things like JITs, where the executable 190Blinding literal values for things like JITs, where the executable
190contents may be partially under the control of userspace, need a similar 191contents may be partially under the control of userspace, need a similar
@@ -199,8 +200,8 @@ working?) in order to maximize their success.
199Since the location of kernel memory is almost always instrumental in 200Since the location of kernel memory is almost always instrumental in
200mounting a successful attack, making the location non-deterministic 201mounting a successful attack, making the location non-deterministic
201raises the difficulty of an exploit. (Note that this in turn makes 202raises the difficulty of an exploit. (Note that this in turn makes
202the value of leaks higher, since they may be used to discover desired 203the value of information exposures higher, since they may be used to
203memory locations.) 204discover desired memory locations.)
204 205
205#### Text and module base 206#### Text and module base
206 207
@@ -222,14 +223,21 @@ become more difficult to locate.
222Much of the kernel's dynamic memory (e.g. kmalloc, vmalloc, etc) ends up 223Much of the kernel's dynamic memory (e.g. kmalloc, vmalloc, etc) ends up
223being relatively deterministic in layout due to the order of early-boot 224being relatively deterministic in layout due to the order of early-boot
224initializations. If the base address of these areas is not the same 225initializations. If the base address of these areas is not the same
225between boots, targeting them is frustrated, requiring a leak specific 226between boots, targeting them is frustrated, requiring an information
226to the region. 227exposure specific to the region.
228
229#### Structure layout
230
231By performing a per-build randomization of the layout of sensitive
232structures, attacks must either be tuned to known kernel builds or expose
233enough kernel memory to determine structure layouts before manipulating
234them.
227 235
228 236
229## Preventing Leaks 237## Preventing Information Exposures
230 238
231Since the locations of sensitive structures are the primary target for 239Since the locations of sensitive structures are the primary target for
232attacks, it is important to defend against leaks of both kernel memory 240attacks, it is important to defend against exposure of both kernel memory
233addresses and kernel memory contents (since they may contain kernel 241addresses and kernel memory contents (since they may contain kernel
234addresses or other sensitive things like canary values). 242addresses or other sensitive things like canary values).
235 243
@@ -250,8 +258,8 @@ sure structure holes are cleared.
250When releasing memory, it is best to poison the contents (clear stack on 258When releasing memory, it is best to poison the contents (clear stack on
251syscall return, wipe heap memory on a free), to avoid reuse attacks that 259syscall return, wipe heap memory on a free), to avoid reuse attacks that
252rely on the old contents of memory. This frustrates many uninitialized 260rely on the old contents of memory. This frustrates many uninitialized
253variable attacks, stack info leaks, heap info leaks, and use-after-free 261variable attacks, stack content exposures, heap content exposures, and
254attacks. 262use-after-free attacks.
255 263
256### Destination tracking 264### Destination tracking
257 265
diff --git a/Documentation/sphinx/convert_template.sed b/Documentation/sphinx/convert_template.sed
new file mode 100644
index 000000000000..c1503fcca4ec
--- /dev/null
+++ b/Documentation/sphinx/convert_template.sed
@@ -0,0 +1,18 @@
1#
2# Pandoc doesn't grok <function> or <structname>, so convert them
3# ahead of time.
4#
5# Use the following escapes to pass through pandoc:
6# $bq = "`"
7# $lt = "<"
8# $gt = ">"
9#
10s%<function>\([^<(]\+\)()</function>%:c:func:$bq\1()$bq%g
11s%<function>\([^<(]\+\)</function>%:c:func:$bq\1()$bq%g
12s%<structname>struct *\([^<]\+\)</structname>%:c:type:$bqstruct \1 $lt\1$gt$bq%g
13s%struct <structname>\([^<]\+\)</structname>%:c:type:$bqstruct \1 $lt\1$gt$bq%g
14s%<structname>\([^<]\+\)</structname>%:c:type:$bqstruct \1 $lt\1$gt$bq%g
15#
16# Wrap docproc directives in para and code blocks.
17#
18s%^\(!.*\)$%<para><code>DOCPROC: \1</code></para>%
diff --git a/Documentation/sphinx/kernel-doc.py b/Documentation/sphinx/kernel-doc.py
new file mode 100644
index 000000000000..4adfb0e91ecc
--- /dev/null
+++ b/Documentation/sphinx/kernel-doc.py
@@ -0,0 +1,127 @@
1# coding=utf-8
2#
3# Copyright © 2016 Intel Corporation
4#
5# Permission is hereby granted, free of charge, to any person obtaining a
6# copy of this software and associated documentation files (the "Software"),
7# to deal in the Software without restriction, including without limitation
8# the rights to use, copy, modify, merge, publish, distribute, sublicense,
9# and/or sell copies of the Software, and to permit persons to whom the
10# Software is furnished to do so, subject to the following conditions:
11#
12# The above copyright notice and this permission notice (including the next
13# paragraph) shall be included in all copies or substantial portions of the
14# Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22# IN THE SOFTWARE.
23#
24# Authors:
25# Jani Nikula <jani.nikula@intel.com>
26#
27# Please make sure this works on both python2 and python3.
28#
29
30import os
31import subprocess
32import sys
33import re
34
35from docutils import nodes, statemachine
36from docutils.statemachine import ViewList
37from docutils.parsers.rst import directives
38from sphinx.util.compat import Directive
39
40class KernelDocDirective(Directive):
41 """Extract kernel-doc comments from the specified file"""
42 required_argument = 1
43 optional_arguments = 4
44 option_spec = {
45 'doc': directives.unchanged_required,
46 'functions': directives.unchanged_required,
47 'export': directives.flag,
48 'internal': directives.flag,
49 }
50 has_content = False
51
52 def run(self):
53 env = self.state.document.settings.env
54 cmd = [env.config.kerneldoc_bin, '-rst', '-enable-lineno']
55
56 filename = env.config.kerneldoc_srctree + '/' + self.arguments[0]
57
58 # Tell sphinx of the dependency
59 env.note_dependency(os.path.abspath(filename))
60
61 tab_width = self.options.get('tab-width', self.state.document.settings.tab_width)
62 source = filename
63
64 # FIXME: make this nicer and more robust against errors
65 if 'export' in self.options:
66 cmd += ['-export']
67 elif 'internal' in self.options:
68 cmd += ['-internal']
69 elif 'doc' in self.options:
70 cmd += ['-function', str(self.options.get('doc'))]
71 elif 'functions' in self.options:
72 for f in str(self.options.get('functions')).split(' '):
73 cmd += ['-function', f]
74
75 cmd += [filename]
76
77 try:
78 env.app.verbose('calling kernel-doc \'%s\'' % (" ".join(cmd)))
79
80 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
81 out, err = p.communicate()
82
83 # python2 needs conversion to unicode.
84 # python3 with universal_newlines=True returns strings.
85 if sys.version_info.major < 3:
86 out, err = unicode(out, 'utf-8'), unicode(err, 'utf-8')
87
88 if p.returncode != 0:
89 sys.stderr.write(err)
90
91 env.app.warn('kernel-doc \'%s\' failed with return code %d' % (" ".join(cmd), p.returncode))
92 return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]
93 elif env.config.kerneldoc_verbosity > 0:
94 sys.stderr.write(err)
95
96 lines = statemachine.string2lines(out, tab_width, convert_whitespace=True)
97 result = ViewList()
98
99 lineoffset = 0;
100 line_regex = re.compile("^#define LINENO ([0-9]+)$")
101 for line in lines:
102 match = line_regex.search(line)
103 if match:
104 # sphinx counts lines from 0
105 lineoffset = int(match.group(1)) - 1
106 # we must eat our comments since the upset the markup
107 else:
108 result.append(line, source, lineoffset)
109 lineoffset += 1
110
111 node = nodes.section()
112 node.document = self.state.document
113 self.state.nested_parse(result, self.content_offset, node)
114
115 return node.children
116
117 except Exception as e:
118 env.app.warn('kernel-doc \'%s\' processing failed with: %s' %
119 (" ".join(cmd), str(e)))
120 return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]
121
122def setup(app):
123 app.add_config_value('kerneldoc_bin', None, 'env')
124 app.add_config_value('kerneldoc_srctree', None, 'env')
125 app.add_config_value('kerneldoc_verbosity', 1, 'env')
126
127 app.add_directive('kernel-doc', KernelDocDirective)
diff --git a/Documentation/sphinx/post_convert.sed b/Documentation/sphinx/post_convert.sed
new file mode 100644
index 000000000000..392770bac53b
--- /dev/null
+++ b/Documentation/sphinx/post_convert.sed
@@ -0,0 +1,23 @@
1#
2# Unescape.
3#
4s/$bq/`/g
5s/$lt/</g
6s/$gt/>/g
7#
8# pandoc thinks that both "_" needs to be escaped. Remove the extra
9# backslashes.
10#
11s/\\_/_/g
12#
13# Unwrap docproc directives.
14#
15s/^``DOCPROC: !E\(.*\)``$/.. kernel-doc:: \1\n :export:/
16s/^``DOCPROC: !I\(.*\)``$/.. kernel-doc:: \1\n :internal:/
17s/^``DOCPROC: !F\([^ ]*\) \(.*\)``$/.. kernel-doc:: \1\n :functions: \2/
18s/^``DOCPROC: !P\([^ ]*\) \(.*\)``$/.. kernel-doc:: \1\n :doc: \2/
19s/^``DOCPROC: \(!.*\)``$/.. WARNING: DOCPROC directive not supported: \1/
20#
21# Trim trailing whitespace.
22#
23s/[[:space:]]*$//
diff --git a/Documentation/sphinx/tmplcvt b/Documentation/sphinx/tmplcvt
new file mode 100755
index 000000000000..909a73065e0a
--- /dev/null
+++ b/Documentation/sphinx/tmplcvt
@@ -0,0 +1,19 @@
1#!/bin/bash
2#
3# Convert a template file into something like RST
4#
5# fix <function>
6# feed to pandoc
7# fix \_
8# title line?
9#
10
11in=$1
12rst=$2
13tmp=$rst.tmp
14
15cp $in $tmp
16sed --in-place -f convert_template.sed $tmp
17pandoc -s -S -f docbook -t rst -o $rst $tmp
18sed --in-place -f post_convert.sed $rst
19rm $tmp
diff --git a/Documentation/sync_file.txt b/Documentation/sync_file.txt
index eaf8297dbca2..e8e2ebafe5fa 100644
--- a/Documentation/sync_file.txt
+++ b/Documentation/sync_file.txt
@@ -6,8 +6,8 @@
6 6
7This document serves as a guide for device drivers writers on what the 7This document serves as a guide for device drivers writers on what the
8sync_file API is, and how drivers can support it. Sync file is the carrier of 8sync_file API is, and how drivers can support it. Sync file is the carrier of
9the fences(struct fence) that needs to synchronized between drivers or across 9the fences(struct fence) that are needed to synchronize between drivers or
10process boundaries. 10across process boundaries.
11 11
12The sync_file API is meant to be used to send and receive fence information 12The sync_file API is meant to be used to send and receive fence information
13to/from userspace. It enables userspace to do explicit fencing, where instead 13to/from userspace. It enables userspace to do explicit fencing, where instead
@@ -32,7 +32,7 @@ in-fences and out-fences
32Sync files can go either to or from userspace. When a sync_file is sent from 32Sync files can go either to or from userspace. When a sync_file is sent from
33the driver to userspace we call the fences it contains 'out-fences'. They are 33the driver to userspace we call the fences it contains 'out-fences'. They are
34related to a buffer that the driver is processing or is going to process, so 34related to a buffer that the driver is processing or is going to process, so
35the driver an create out-fence to be able to notify, through fence_signal(), 35the driver creates an out-fence to be able to notify, through fence_signal(),
36when it has finished using (or processing) that buffer. Out-fences are fences 36when it has finished using (or processing) that buffer. Out-fences are fences
37that the driver creates. 37that the driver creates.
38 38
diff --git a/Documentation/zh_CN/CodingStyle b/Documentation/zh_CN/CodingStyle
index 654afd72eb24..bbb9d6ae05ca 100644
--- a/Documentation/zh_CN/CodingStyle
+++ b/Documentation/zh_CN/CodingStyle
@@ -24,34 +24,33 @@ Documentation/CodingStyle的中文翻译
24 24
25 Linux内核代ç é£Žæ ¼ 25 Linux内核代ç é£Žæ ¼
26 26
27这是一个简短的文档,æè¿°äº†linux内核的首选代ç é£Žæ ¼ã€‚代ç é£Žæ ¼æ˜¯å› äººè€Œå¼‚的,而且我 27这是一个简短的文档,æè¿°äº† linux 内核的首选代ç é£Žæ ¼ã€‚代ç é£Žæ ¼æ˜¯å› äººè€Œå¼‚的,而且我
28䏿„¿æ„把我的观点强加给任何人,ä¸è¿‡è¿™é‡Œæ‰€è®²è¿°çš„æ˜¯æˆ‘å¿…é¡»è¦ç»´æŠ¤çš„ä»£ç æ‰€éµå®ˆçš„风格, 28䏿„¿æ„æŠŠè‡ªå·±çš„è§‚ç‚¹å¼ºåŠ ç»™ä»»ä½•äººï¼Œä½†è¿™å°±åƒæˆ‘去åšä»»ä½•事情都必须éµå¾ªçš„原则那样,我也
29并且我也希望ç»å¤§å¤šæ•°å…¶ä»–代ç ä¹Ÿèƒ½éµå®ˆè¿™ä¸ªé£Žæ ¼ã€‚è¯·åœ¨å†™ä»£ç æ—¶è‡³å°‘考虑一下本文所述的 29希望在ç»å¤§å¤šæ•°äº‹ä¸Šä¿æŒè¿™ç§çš„æ€åº¦ã€‚è¯·ï¼ˆåœ¨å†™ä»£ç æ—¶ï¼‰è‡³å°‘考虑一下这里的代ç é£Žæ ¼ã€‚
30风格。
31 30
32首先,我建议你打å°ä¸€ä»½GNU代ç è§„范,然åŽä¸è¦è¯»å®ƒã€‚烧了它,这是一个具有é‡å¤§è±¡å¾æ€§ 31首先,我建议你打å°ä¸€ä»½ GNU 代ç è§„范,然åŽä¸è¦è¯»ã€‚烧了它,这是一个具有é‡å¤§è±¡å¾æ€§æ„义
33æ„义的动作。 32的动作。
34 33
35ä¸ç®¡æ€Žæ ·ï¼ŒçŽ°åœ¨æˆ‘ä»¬å¼€å§‹ï¼š 34ä¸ç®¡æ€Žæ ·ï¼ŒçŽ°åœ¨æˆ‘ä»¬å¼€å§‹ï¼š
36 35
37 36
38 第一章:缩进 37 第一章:缩进
39 38
40制表符是8个字符,所以缩进也是8个字符。有些异端è¿åŠ¨è¯•å›¾å°†ç¼©è¿›å˜ä¸º4(乃至2)个字符 39制表符是 8 个字符,所以缩进也是 8 个字符。有些异端è¿åŠ¨è¯•å›¾å°†ç¼©è¿›å˜ä¸º 4(甚至 2ï¼ï¼
41深,这几乎相当于å°è¯•将圆周率的值定义为3。 40个字符深,这几乎相当于å°è¯•将圆周率的值定义为 3。
42 41
43ç†ç”±ï¼šç¼©è¿›çš„全部æ„义就在于清楚的定义一个控制å—起止于何处。尤其是当你盯ç€ä½ çš„å±å¹• 42ç†ç”±ï¼šç¼©è¿›çš„全部æ„义就在于清楚的定义一个控制å—起止于何处。尤其是当你盯ç€ä½ çš„å±å¹•
44连续看了20å°æ—¶ä¹‹åŽï¼Œä½ å°†ä¼šå‘现大一点的缩进会使你更容易分辨缩进。 43连续看了 20 å°æ—¶ä¹‹åŽï¼Œä½ å°†ä¼šå‘现大一点的缩进会使你更容易分辨缩进。
45 44
46现在,有些人会抱怨8个字符的缩进会使代ç å‘å³è¾¹ç§»åŠ¨çš„å¤ªè¿œï¼Œåœ¨80个字符的终端å±å¹•上 45现在,有些人会抱怨 8 个字符的缩进会使代ç å‘å³è¾¹ç§»åŠ¨çš„å¤ªè¿œï¼Œåœ¨ 80 个字符的终端å±å¹•上
47就很难读这样的代ç ã€‚这个问题的答案是,如果你需è¦3级以上的缩进,ä¸ç®¡ç”¨ä½•ç§æ–¹å¼ä½  46就很难读这样的代ç ã€‚è¿™ä¸ªé—®é¢˜çš„ç­”æ¡ˆæ˜¯ï¼Œå¦‚æžœä½ éœ€è¦ 3 级以上的缩进,ä¸ç®¡ç”¨ä½•ç§æ–¹å¼ä½ 
48的代ç å·²ç»æœ‰é—®é¢˜äº†ï¼Œåº”该修正你的程åºã€‚ 47的代ç å·²ç»æœ‰é—®é¢˜äº†ï¼Œåº”该修正你的程åºã€‚
49 48
50简而言之,8个字符的缩进å¯ä»¥è®©ä»£ç æ›´å®¹æ˜“阅读,还有一个好处是当你的函数嵌套太深的 49简而言之,8 个字符的缩进å¯ä»¥è®©ä»£ç æ›´å®¹æ˜“阅读,还有一个好处是当你的函数嵌套太深的
51时候å¯ä»¥ç»™ä½ è­¦å‘Šã€‚留心这个警告。 50时候å¯ä»¥ç»™ä½ è­¦å‘Šã€‚留心这个警告。
52 51
53在switch语å¥ä¸­æ¶ˆé™¤å¤šçº§ç¼©è¿›çš„é¦–é€‰çš„æ–¹å¼æ˜¯è®©â€œswitchâ€å’Œä»Žå±žäºŽå®ƒçš„“caseâ€æ ‡ç­¾å¯¹é½äºŽåŒ 52在 switch 语å¥ä¸­æ¶ˆé™¤å¤šçº§ç¼©è¿›çš„é¦–é€‰çš„æ–¹å¼æ˜¯è®© “switch†和从属于它的 “case†标签
54一列,而ä¸è¦â€œä¸¤æ¬¡ç¼©è¿›â€â€œcaseâ€æ ‡ç­¾ã€‚比如: 53对é½äºŽåŒä¸€åˆ—,而ä¸è¦ “两次缩进†“case†标签。比如:
55 54
56 switch (suffix) { 55 switch (suffix) {
57 case 'G': 56 case 'G':
@@ -70,7 +69,6 @@ Documentation/CodingStyle的中文翻译
70 break; 69 break;
71 } 70 }
72 71
73
74ä¸è¦æŠŠå¤šä¸ªè¯­å¥æ”¾åœ¨ä¸€è¡Œé‡Œï¼Œé™¤éžä½ æœ‰ä»€ä¹ˆä¸œè¥¿è¦éšè—: 72ä¸è¦æŠŠå¤šä¸ªè¯­å¥æ”¾åœ¨ä¸€è¡Œé‡Œï¼Œé™¤éžä½ æœ‰ä»€ä¹ˆä¸œè¥¿è¦éšè—:
75 73
76 if (condition) do_this; 74 if (condition) do_this;
@@ -79,7 +77,7 @@ Documentation/CodingStyle的中文翻译
79也ä¸è¦åœ¨ä¸€è¡Œé‡Œæ”¾å¤šä¸ªèµ‹å€¼è¯­å¥ã€‚内核代ç é£Žæ ¼è¶…级简å•。就是é¿å…å¯èƒ½å¯¼è‡´åˆ«äººè¯¯è¯»çš„表 77也ä¸è¦åœ¨ä¸€è¡Œé‡Œæ”¾å¤šä¸ªèµ‹å€¼è¯­å¥ã€‚内核代ç é£Žæ ¼è¶…级简å•。就是é¿å…å¯èƒ½å¯¼è‡´åˆ«äººè¯¯è¯»çš„表
80è¾¾å¼ã€‚ 78è¾¾å¼ã€‚
81 79
82é™¤äº†æ³¨é‡Šã€æ–‡æ¡£å’ŒKconfig之外,ä¸è¦ä½¿ç”¨ç©ºæ ¼æ¥ç¼©è¿›ï¼Œå‰é¢çš„例孿˜¯ä¾‹å¤–,是有æ„为之。 80é™¤äº†æ³¨é‡Šã€æ–‡æ¡£å’Œ Kconfig 之外,ä¸è¦ä½¿ç”¨ç©ºæ ¼æ¥ç¼©è¿›ï¼Œå‰é¢çš„例孿˜¯ä¾‹å¤–,是有æ„为之。
83 81
84选用一个好的编辑器,ä¸è¦åœ¨è¡Œå°¾ç•™ç©ºæ ¼ã€‚ 82选用一个好的编辑器,ä¸è¦åœ¨è¡Œå°¾ç•™ç©ºæ ¼ã€‚
85 83
@@ -88,27 +86,18 @@ Documentation/CodingStyle的中文翻译
88 86
89代ç é£Žæ ¼çš„æ„ä¹‰å°±åœ¨äºŽä½¿ç”¨å¹³å¸¸ä½¿ç”¨çš„å·¥å…·æ¥ç»´æŒä»£ç çš„å¯è¯»æ€§å’Œå¯ç»´æŠ¤æ€§ã€‚ 87代ç é£Žæ ¼çš„æ„ä¹‰å°±åœ¨äºŽä½¿ç”¨å¹³å¸¸ä½¿ç”¨çš„å·¥å…·æ¥ç»´æŒä»£ç çš„å¯è¯»æ€§å’Œå¯ç»´æŠ¤æ€§ã€‚
90 88
91æ¯ä¸€è¡Œçš„长度的é™åˆ¶æ˜¯80列,我们强烈建议您éµå®ˆè¿™ä¸ªæƒ¯ä¾‹ã€‚ 89æ¯ä¸€è¡Œçš„长度的é™åˆ¶æ˜¯ 80 列,我们强烈建议您éµå®ˆè¿™ä¸ªæƒ¯ä¾‹ã€‚
92 90
93长于80列的语å¥è¦æ‰“æ•£æˆæœ‰æ„义的片段。æ¯ä¸ªç‰‡æ®µè¦æ˜Žæ˜¾çŸ­äºŽåŽŸæ¥çš„语å¥ï¼Œè€Œä¸”放置的ä½ç½® 91长于 80 列的语å¥è¦æ‰“æ•£æˆæœ‰æ„义的片段。除éžè¶…过 80 列能显著增加å¯è¯»æ€§ï¼Œå¹¶ä¸”ä¸ä¼šéšè—
94也明显的é å³ã€‚åŒæ ·çš„è§„åˆ™ä¹Ÿé€‚ç”¨äºŽæœ‰å¾ˆé•¿å‚æ•°åˆ—è¡¨çš„å‡½æ•°å¤´ã€‚é•¿å­—ç¬¦ä¸²ä¹Ÿè¦æ‰“æ•£æˆè¾ƒçŸ­çš„ 92ä¿¡æ¯ã€‚å­ç‰‡æ®µè¦æ˜Žæ˜¾çŸ­äºŽæ¯ç‰‡æ®µï¼Œå¹¶æ˜Žæ˜¾é å³ã€‚è¿™åŒæ ·é€‚用于有ç€å¾ˆé•¿å‚数列表的函数头。
95字符串。唯一的例外是超过80列å¯ä»¥å¤§å¹…度æé«˜å¯è¯»æ€§å¹¶ä¸”ä¸ä¼šéšè—ä¿¡æ¯çš„æƒ…况。 93然而,ç»å¯¹ä¸è¦æ‰“散对用户å¯è§çš„字符串,例如 printk ä¿¡æ¯ï¼Œå› ä¸ºè¿™å°†å¯¼è‡´æ— æ³• grep 这些
96 94ä¿¡æ¯ã€‚
97void fun(int a, int b, int c)
98{
99 if (condition)
100 printk(KERN_WARNING "Warning this is a long printk with "
101 "3 parameters a: %u b: %u "
102 "c: %u \n", a, b, c);
103 else
104 next_statement;
105}
106 95
107 第三章:大括å·å’Œç©ºæ ¼çš„æ”¾ç½® 96 第三章:大括å·å’Œç©ºæ ¼çš„æ”¾ç½®
108 97
109C语言风格中å¦å¤–一个常è§é—®é¢˜æ˜¯å¤§æ‹¬å·çš„æ”¾ç½®ã€‚和缩进大å°ä¸åŒï¼Œé€‰æ‹©æˆ–弃用æŸç§æ”¾ç½®ç­– 98C语言风格中å¦å¤–一个常è§é—®é¢˜æ˜¯å¤§æ‹¬å·çš„æ”¾ç½®ã€‚和缩进大å°ä¸åŒï¼Œé€‰æ‹©æˆ–弃用æŸç§æ”¾ç½®ç­–
110略并没有多少技术上的原因,ä¸è¿‡é¦–选的方å¼ï¼Œå°±åƒKernighanå’ŒRitchie展示给我们的,是 99略并没有多少技术上的原因,ä¸è¿‡é¦–选的方å¼ï¼Œå°±åƒ Kernighan å’Œ Ritchie 展示给我们的,
111æŠŠèµ·å§‹å¤§æ‹¬å·æ”¾åœ¨è¡Œå°¾ï¼Œè€ŒæŠŠç»“æŸå¤§æ‹¬å·æ”¾åœ¨è¡Œé¦–,所以: 100æ˜¯æŠŠèµ·å§‹å¤§æ‹¬å·æ”¾åœ¨è¡Œå°¾ï¼Œè€ŒæŠŠç»“æŸå¤§æ‹¬å·æ”¾åœ¨è¡Œé¦–,所以:
112 101
113 if (x is true) { 102 if (x is true) {
114 we do y 103 we do y
@@ -134,12 +123,12 @@ C语言风格中å¦å¤–一个常è§é—®é¢˜æ˜¯å¤§æ‹¬å·çš„æ”¾ç½®ã€‚和缩进大å°ä
134 body of function 123 body of function
135 } 124 }
136 125
137全世界的异端å¯èƒ½ä¼šæŠ±æ€¨è¿™ä¸ªä¸ä¸€è‡´æ€§æ˜¯â€¦â€¦å‘ƒâ€¦â€¦ä¸ä¸€è‡´çš„,ä¸è¿‡æ‰€æœ‰æ€ç»´å¥å…¨çš„人都知é“( 126全世界的异端å¯èƒ½ä¼šæŠ±æ€¨è¿™ä¸ªä¸ä¸€è‡´æ€§æ˜¯â€¦â€¦å‘ƒâ€¦â€¦ä¸ä¸€è‡´çš„,ä¸è¿‡æ‰€æœ‰æ€ç»´å¥å…¨çš„人都知é“
138a)K&R是_正确的_,并且(b)K&R是正确的。此外,ä¸ç®¡æ€Žæ ·å‡½æ•°éƒ½æ˜¯ç‰¹æ®Šçš„(在C语言中 127(a) K&R 是 _正确的_,并且 (b) K&R 是正确的。此外,ä¸ç®¡æ€Žæ ·å‡½æ•°éƒ½æ˜¯ç‰¹æ®Šçš„(C
139,函数是ä¸èƒ½åµŒå¥—的)。 128函数是ä¸èƒ½åµŒå¥—的)。
140 129
141注æ„结æŸå¤§æ‹¬å·ç‹¬è‡ªå æ®ä¸€è¡Œï¼Œé™¤éžå®ƒåŽé¢è·Ÿç€åŒä¸€ä¸ªè¯­å¥çš„剩余部分,也就是do语å¥ä¸­çš„ 130注æ„结æŸå¤§æ‹¬å·ç‹¬è‡ªå æ®ä¸€è¡Œï¼Œé™¤éžå®ƒåŽé¢è·Ÿç€åŒä¸€ä¸ªè¯­å¥çš„剩余部分,也就是 do 语å¥ä¸­çš„
142“whileâ€æˆ–者if语å¥ä¸­çš„“elseâ€ï¼Œåƒè¿™æ ·ï¼š 131“while†或者 if 语å¥ä¸­çš„ “elseâ€ï¼Œåƒè¿™æ ·ï¼š
143 132
144 do { 133 do {
145 body of do-loop 134 body of do-loop
@@ -158,41 +147,50 @@ a)K&R是_正确的_,并且(b)K&R是正确的。此外,ä¸ç®¡æ€Žæ ·å‡½æ
158ç†ç”±ï¼šK&R。 147ç†ç”±ï¼šK&R。
159 148
160也请注æ„è¿™ç§å¤§æ‹¬å·çš„æ”¾ç½®æ–¹å¼ä¹Ÿèƒ½ä½¿ç©ºï¼ˆæˆ–者差ä¸å¤šç©ºçš„ï¼‰è¡Œçš„æ•°é‡æœ€å°åŒ–ï¼ŒåŒæ—¶ä¸å¤±å¯ 149也请注æ„è¿™ç§å¤§æ‹¬å·çš„æ”¾ç½®æ–¹å¼ä¹Ÿèƒ½ä½¿ç©ºï¼ˆæˆ–者差ä¸å¤šç©ºçš„ï¼‰è¡Œçš„æ•°é‡æœ€å°åŒ–ï¼ŒåŒæ—¶ä¸å¤±å¯
161读性。因此,由于你的å±å¹•上的新行是ä¸å¯å†ç”Ÿèµ„æºï¼ˆæƒ³æƒ³25行的终端å±å¹•),你将会有更 150读性。因此,由于你的å±å¹•上的新行是ä¸å¯å†ç”Ÿèµ„æºï¼ˆæƒ³æƒ³ 25 行的终端å±å¹•),你将会有更
162å¤šçš„ç©ºè¡Œæ¥æ”¾ç½®æ³¨é‡Šã€‚ 151å¤šçš„ç©ºè¡Œæ¥æ”¾ç½®æ³¨é‡Šã€‚
163 152
164å½“åªæœ‰ä¸€ä¸ªå•独的语å¥çš„æ—¶å€™ï¼Œä¸ç”¨åŠ ä¸å¿…è¦çš„大括å·ã€‚ 153å½“åªæœ‰ä¸€ä¸ªå•独的语å¥çš„æ—¶å€™ï¼Œä¸ç”¨åŠ ä¸å¿…è¦çš„大括å·ã€‚
165 154
166if (condition) 155 if (condition)
167 action(); 156 action();
157
158和
159
160 if (condition)
161 do_this();
162 else
163 do_that();
168 164
169这点ä¸é€‚用于本身为æŸä¸ªæ¡ä»¶è¯­å¥çš„一个分支的å•独语å¥ã€‚这时需è¦åœ¨ä¸¤ä¸ªåˆ†æ”¯é‡Œéƒ½ä½¿ç”¨å¤§ 165这并ä¸é€‚ç”¨äºŽåªæœ‰ä¸€ä¸ªæ¡ä»¶åˆ†æ”¯æ˜¯å•语å¥çš„æƒ…况;这时所有分支都è¦ä½¿ç”¨å¤§æ‹¬å·ï¼š
170括å·ã€‚
171 166
172if (condition) { 167 if (condition) {
173 do_this(); 168 do_this();
174 do_that(); 169 do_that();
175} else { 170 } else {
176 otherwise(); 171 otherwise();
177} 172 }
178 173
179 3.1:空格 174 3.1:空格
180 175
181Linux内核的空格使用方å¼ï¼ˆä¸»è¦ï¼‰å–å†³äºŽå®ƒæ˜¯ç”¨äºŽå‡½æ•°è¿˜æ˜¯å…³é”®å­—ã€‚ï¼ˆå¤§å¤šæ•°ï¼‰å…³é”®å­—åŽ 176Linux 内核的空格使用方å¼ï¼ˆä¸»è¦ï¼‰å–决于它是用于函数还是关键字。(大多数)关键字åŽ
182è¦åŠ ä¸€ä¸ªç©ºæ ¼ã€‚å€¼å¾—æ³¨æ„的例外是sizeofã€typeofã€alignofå’Œ__attribute__,这些关键字 177è¦åŠ ä¸€ä¸ªç©ºæ ¼ã€‚å€¼å¾—æ³¨æ„的例外是 sizeofã€typeofã€alignof å’Œ __attribute__,这些
183æŸäº›ç¨‹åº¦ä¸Šçœ‹èµ·æ¥æ›´åƒå‡½æ•°ï¼ˆå®ƒä»¬åœ¨Linux里也常常伴éšå°æ‹¬å·è€Œä½¿ç”¨ï¼Œå°½ç®¡åœ¨C语言里这样 178关键字æŸäº›ç¨‹åº¦ä¸Šçœ‹èµ·æ¥æ›´åƒå‡½æ•°ï¼ˆå®ƒä»¬åœ¨ Linux 里也常常伴éšå°æ‹¬å·è€Œä½¿ç”¨ï¼Œå°½ç®¡åœ¨ C 里
184çš„å°æ‹¬å·ä¸æ˜¯å¿…需的,就åƒâ€œstruct fileinfo infoâ€å£°æ˜Žè¿‡åŽçš„“sizeof infoâ€ï¼‰ã€‚ 179è¿™æ ·çš„å°æ‹¬å·ä¸æ˜¯å¿…éœ€çš„ï¼Œå°±åƒ â€œstruct fileinfo info†声明过åŽçš„ “sizeof infoâ€ï¼‰ã€‚
185 180
186æ‰€ä»¥åœ¨è¿™äº›å…³é”®å­—ä¹‹åŽæ”¾ä¸€ä¸ªç©ºæ ¼ï¼š 181æ‰€ä»¥åœ¨è¿™äº›å…³é”®å­—ä¹‹åŽæ”¾ä¸€ä¸ªç©ºæ ¼ï¼š
182
187 if, switch, case, for, do, while 183 if, switch, case, for, do, while
188但是ä¸è¦åœ¨sizeofã€typeofã€alignof或者__attribute__è¿™äº›å…³é”®å­—ä¹‹åŽæ”¾ç©ºæ ¼ã€‚例如, 184
185但是ä¸è¦åœ¨ sizeofã€typeofã€alignof 或者 __attribute__ è¿™äº›å…³é”®å­—ä¹‹åŽæ”¾ç©ºæ ¼ã€‚例如,
186
189 s = sizeof(struct file); 187 s = sizeof(struct file);
190 188
191ä¸è¦åœ¨å°æ‹¬å·é‡Œçš„表达å¼ä¸¤ä¾§åŠ ç©ºæ ¼ã€‚è¿™æ˜¯ä¸€ä¸ªå例: 189ä¸è¦åœ¨å°æ‹¬å·é‡Œçš„表达å¼ä¸¤ä¾§åŠ ç©ºæ ¼ã€‚è¿™æ˜¯ä¸€ä¸ªå例:
192 190
193 s = sizeof( struct file ); 191 s = sizeof( struct file );
194 192
195当声明指针类型或者返回指针类型的函数时,“*â€çš„é¦–é€‰ä½¿ç”¨æ–¹å¼æ˜¯ä½¿ä¹‹é è¿‘å˜é‡å或者函 193当声明指针类型或者返回指针类型的函数时,“*â€ çš„é¦–é€‰ä½¿ç”¨æ–¹å¼æ˜¯ä½¿ä¹‹é è¿‘å˜é‡å或者函
196æ•°åï¼Œè€Œä¸æ˜¯é è¿‘类型å。例å­ï¼š 194æ•°åï¼Œè€Œä¸æ˜¯é è¿‘类型å。例å­ï¼š
197 195
198 char *linux_banner; 196 char *linux_banner;
@@ -204,15 +202,18 @@ Linux内核的空格使用方å¼ï¼ˆä¸»è¦ï¼‰å–决于它是用于函数还是关
204 = + - < > * / % | & ^ <= >= == != ? : 202 = + - < > * / % | & ^ <= >= == != ? :
205 203
206但是一元æ“作符åŽä¸è¦åŠ ç©ºæ ¼ï¼š 204但是一元æ“作符åŽä¸è¦åŠ ç©ºæ ¼ï¼š
205
207 & * + - ~ ! sizeof typeof alignof __attribute__ defined 206 & * + - ~ ! sizeof typeof alignof __attribute__ defined
208 207
209åŽç¼€è‡ªåŠ å’Œè‡ªå‡ä¸€å…ƒæ“作符å‰ä¸åŠ ç©ºæ ¼ï¼š 208åŽç¼€è‡ªåŠ å’Œè‡ªå‡ä¸€å…ƒæ“作符å‰ä¸åŠ ç©ºæ ¼ï¼š
209
210 ++ -- 210 ++ --
211 211
212å‰ç¼€è‡ªåŠ å’Œè‡ªå‡ä¸€å…ƒæ“作符åŽä¸åŠ ç©ºæ ¼ï¼š 212å‰ç¼€è‡ªåŠ å’Œè‡ªå‡ä¸€å…ƒæ“作符åŽä¸åŠ ç©ºæ ¼ï¼š
213
213 ++ -- 214 ++ --
214 215
215“.â€å’Œâ€œ->â€ç»“构体æˆå‘˜æ“作符å‰åŽä¸åŠ ç©ºæ ¼ã€‚ 216‘.â€å’Œ “->†结构体æˆå‘˜æ“作符å‰åŽä¸åŠ ç©ºæ ¼ã€‚
216 217
217ä¸è¦åœ¨è¡Œå°¾ç•™ç©ºç™½ã€‚有些å¯ä»¥è‡ªåŠ¨ç¼©è¿›çš„ç¼–è¾‘å™¨ä¼šåœ¨æ–°è¡Œçš„è¡Œé¦–åŠ å…¥é€‚é‡çš„空白,然åŽä½  218ä¸è¦åœ¨è¡Œå°¾ç•™ç©ºç™½ã€‚有些å¯ä»¥è‡ªåŠ¨ç¼©è¿›çš„ç¼–è¾‘å™¨ä¼šåœ¨æ–°è¡Œçš„è¡Œé¦–åŠ å…¥é€‚é‡çš„空白,然åŽä½ 
218å°±å¯ä»¥ç›´æŽ¥åœ¨é‚£ä¸€è¡Œè¾“入代ç ã€‚ä¸è¿‡å‡å¦‚ä½ æœ€åŽæ²¡æœ‰åœ¨é‚£ä¸€è¡Œè¾“入代ç ï¼Œæœ‰äº›ç¼–è¾‘å™¨å°±ä¸ 219å°±å¯ä»¥ç›´æŽ¥åœ¨é‚£ä¸€è¡Œè¾“入代ç ã€‚ä¸è¿‡å‡å¦‚ä½ æœ€åŽæ²¡æœ‰åœ¨é‚£ä¸€è¡Œè¾“入代ç ï¼Œæœ‰äº›ç¼–辑器就ä¸
@@ -225,23 +226,23 @@ Linux内核的空格使用方å¼ï¼ˆä¸»è¦ï¼‰å–决于它是用于函数还是关
225 226
226 第四章:命å 227 第四章:命å
227 228
228C是一个简朴的语言,你的命å也应该这样。和Modula-2å’ŒPascal程åºå‘˜ä¸åŒï¼ŒC程åºå‘˜ä¸ä½¿ 229C是一个简朴的语言,你的命å也应该这样。和 Modula-2 å’Œ Pascal 程åºå‘˜ä¸åŒï¼ŒC 程åºå‘˜
229用类似ThisVariableIsATemporaryCounter这样åŽä¸½çš„å字。C程åºå‘˜ä¼šç§°é‚£ä¸ªå˜é‡ä¸ºâ€œtmp†230ä¸ä½¿ç”¨ç±»ä¼¼ ThisVariableIsATemporaryCounter 这样åŽä¸½çš„å字。C 程åºå‘˜ä¼šç§°é‚£ä¸ªå˜é‡
230,这样写起æ¥ä¼šæ›´å®¹æ˜“,而且至少ä¸ä¼šä»¤å…¶éš¾äºŽç†è§£ã€‚ 231为 “tmpâ€ï¼Œè¿™æ ·å†™èµ·æ¥ä¼šæ›´å®¹æ˜“,而且至少ä¸ä¼šä»¤å…¶éš¾äºŽç†è§£ã€‚
231 232
232ä¸è¿‡ï¼Œè™½ç„¶æ··ç”¨å¤§å°å†™çš„åå­—æ˜¯ä¸æå€¡ä½¿ç”¨çš„ï¼Œä½†æ˜¯å…¨å±€å˜é‡è¿˜æ˜¯éœ€è¦ä¸€ä¸ªå…·æè¿°æ€§çš„åå­— 233ä¸è¿‡ï¼Œè™½ç„¶æ··ç”¨å¤§å°å†™çš„åå­—æ˜¯ä¸æå€¡ä½¿ç”¨çš„ï¼Œä½†æ˜¯å…¨å±€å˜é‡è¿˜æ˜¯éœ€è¦ä¸€ä¸ªå…·æè¿°æ€§çš„åå­—
233。称一个全局函数为“fooâ€æ˜¯ä¸€ä¸ªéš¾ä»¥é¥¶æ•的错误。 234。称一个全局函数为 “foo†是一个难以饶æ•的错误。
234 235
235全局å˜é‡ï¼ˆåªæœ‰å½“你真正需è¦å®ƒä»¬çš„æ—¶å€™å†ç”¨å®ƒï¼‰éœ€è¦æœ‰ä¸€ä¸ªå…·æè¿°æ€§çš„å字,就åƒå…¨å±€å‡½ 236全局å˜é‡ï¼ˆåªæœ‰å½“你真正需è¦å®ƒä»¬çš„æ—¶å€™å†ç”¨å®ƒï¼‰éœ€è¦æœ‰ä¸€ä¸ªå…·æè¿°æ€§çš„å字,就åƒå…¨å±€å‡½
236数。如果你有一个å¯ä»¥è®¡ç®—活动用户数é‡çš„函数,你应该å«å®ƒâ€œcount_active_users()â€æˆ–者 237数。如果你有一个å¯ä»¥è®¡ç®—活动用户数é‡çš„函数,你应该å«å®ƒ “count_active_users()â€
237类似的å字,你ä¸åº”该å«å®ƒâ€œcntuser()â€ã€‚ 238或者类似的å字,你ä¸åº”该å«å®ƒ “cntuser()â€ã€‚
238 239
239在函数å中包å«å‡½æ•°ç±»åž‹ï¼ˆæ‰€è°“çš„åŒˆç‰™åˆ©å‘½åæ³•)是脑å­å‡ºäº†é—®é¢˜â€”—编译器知é“那些类型而 240在函数å中包å«å‡½æ•°ç±»åž‹ï¼ˆæ‰€è°“çš„åŒˆç‰™åˆ©å‘½åæ³•)是脑å­å‡ºäº†é—®é¢˜â€”—编译器知é“那些类型而
240且能够检查那些类型,这样åšåªèƒ½æŠŠç¨‹åºå‘˜å¼„糊涂了。难怪微软总是制造出有问题的程åºã€‚ 241且能够检查那些类型,这样åšåªèƒ½æŠŠç¨‹åºå‘˜å¼„糊涂了。难怪微软总是制造出有问题的程åºã€‚
241 242
242本地å˜é‡å应该简短,而且能够表达相关的å«ä¹‰ã€‚å¦‚æžœä½ æœ‰ä¸€äº›éšæœºçš„æ•´æ•°åž‹çš„循环计数器 243本地å˜é‡å应该简短,而且能够表达相关的å«ä¹‰ã€‚å¦‚æžœä½ æœ‰ä¸€äº›éšæœºçš„æ•´æ•°åž‹çš„循环计数器
243,它应该被称为“iâ€ã€‚å«å®ƒâ€œloop_counterâ€å¹¶æ— ç›Šå¤„,如果它没有被误解的å¯èƒ½çš„è¯ã€‚类似 244,它应该被称为 “iâ€ã€‚å«å®ƒ “loop_counter†并无益处,如果它没有被误解的å¯èƒ½çš„è¯ã€‚
244的,“tmpâ€å¯ä»¥ç”¨æ¥ç§°å‘¼ä»»æ„类型的临时å˜é‡ã€‚ 245类似的,“tmp†å¯ä»¥ç”¨æ¥ç§°å‘¼ä»»æ„类型的临时å˜é‡ã€‚
245 246
246如果你怕混淆了你的本地å˜é‡å,你就é‡åˆ°å¦ä¸€ä¸ªé—®é¢˜äº†ï¼Œå«åšå‡½æ•°å¢žé•¿è·å°”蒙失衡综åˆç—‡ 247如果你怕混淆了你的本地å˜é‡å,你就é‡åˆ°å¦ä¸€ä¸ªé—®é¢˜äº†ï¼Œå«åšå‡½æ•°å¢žé•¿è·å°”蒙失衡综åˆç—‡
247。请看第六章(函数)。 248。请看第六章(函数)。
@@ -249,9 +250,9 @@ C是一个简朴的语言,你的命å也应该这样。和Modula-2å’ŒPascalç¨
249 250
250 第五章:Typedef 251 第五章:Typedef
251 252
252ä¸è¦ä½¿ç”¨ç±»ä¼¼â€œvps_tâ€ä¹‹ç±»çš„东西。 253ä¸è¦ä½¿ç”¨ç±»ä¼¼ “vps_t†之类的东西。
253 254
254对结构体和指针使用typedef是一个错误。当你在代ç é‡Œçœ‹åˆ°ï¼š 255对结构体和指针使用 typedef 是一个错误。当你在代ç é‡Œçœ‹åˆ°ï¼š
255 256
256 vps_t a; 257 vps_t a;
257 258
@@ -261,91 +262,91 @@ C是一个简朴的语言,你的命å也应该这样。和Modula-2å’ŒPascalç¨
261 262
262 struct virtual_container *a; 263 struct virtual_container *a;
263 264
264你就知é““aâ€æ˜¯ä»€ä¹ˆäº†ã€‚ 265ä½ å°±çŸ¥é“ â€œa†是什么了。
265 266
266很多人认为typedef“能æé«˜å¯è¯»æ€§â€ã€‚å®žé™…ä¸æ˜¯è¿™æ ·çš„。它们åªåœ¨ä¸‹åˆ—情况下有用: 267很多人认为 typedef “能æé«˜å¯è¯»æ€§â€ã€‚å®žé™…ä¸æ˜¯è¿™æ ·çš„。它们åªåœ¨ä¸‹åˆ—情况下有用:
267 268
268 (a) 完全ä¸é€æ˜Žçš„å¯¹è±¡ï¼ˆè¿™ç§æƒ…况下è¦ä¸»åŠ¨ä½¿ç”¨typedefæ¥éšè—这个对象实际上是什么)。 269 (a) 完全ä¸é€æ˜Žçš„å¯¹è±¡ï¼ˆè¿™ç§æƒ…况下è¦ä¸»åŠ¨ä½¿ç”¨ typedef æ¥éšè—这个对象实际上是什么)。
269 270
270 例如:“pte_tâ€ç­‰ä¸é€æ˜Žå¯¹è±¡ï¼Œä½ åªèƒ½ç”¨åˆé€‚的访问函数æ¥è®¿é—®å®ƒä»¬ã€‚ 271 例如:“pte_t†等ä¸é€æ˜Žå¯¹è±¡ï¼Œä½ åªèƒ½ç”¨åˆé€‚的访问函数æ¥è®¿é—®å®ƒä»¬ã€‚
271 272
272 注æ„ï¼ä¸é€æ˜Žæ€§å’Œâ€œè®¿é—®å‡½æ•°â€æœ¬èº«æ˜¯ä¸å¥½çš„。我们使用pte_t等类型的原因在于真的是 273 注æ„ï¼ä¸é€æ˜Žæ€§å’Œâ€œè®¿é—®å‡½æ•°â€æœ¬èº«æ˜¯ä¸å¥½çš„。我们使用 pte_t 等类型的原因在于真的是
273 完全没有任何共用的å¯è®¿é—®ä¿¡æ¯ã€‚ 274 完全没有任何共用的å¯è®¿é—®ä¿¡æ¯ã€‚
274 275
275 (b) 清楚的整数类型,如此,这层抽象就å¯ä»¥å¸®åŠ©æ¶ˆé™¤åˆ°åº•æ˜¯â€œintâ€è¿˜æ˜¯â€œlongâ€çš„æ··æ·†ã€‚ 276 (b) 清楚的整数类型,如此,这层抽象就å¯ä»¥å¸®åŠ©æ¶ˆé™¤åˆ°åº•æ˜¯ “int†还是 “long†的混淆。
276 277
277 u8/u16/u32是完全没有问题的typedef,ä¸è¿‡å®ƒä»¬æ›´ç¬¦åˆç±»åˆ«(d)è€Œä¸æ˜¯è¿™é‡Œã€‚ 278 u8/u16/u32 是完全没有问题的 typedef,ä¸è¿‡å®ƒä»¬æ›´ç¬¦åˆç±»åˆ« (d) è€Œä¸æ˜¯è¿™é‡Œã€‚
278 279
279 冿¬¡æ³¨æ„ï¼è¦è¿™æ ·åšï¼Œå¿…须事出有因。如果æŸä¸ªå˜é‡æ˜¯â€œunsigned longâ€œï¼Œé‚£ä¹ˆæ²¡æœ‰å¿…è¦ 280 冿¬¡æ³¨æ„ï¼è¦è¿™æ ·åšï¼Œå¿…须事出有因。如果æŸä¸ªå˜é‡æ˜¯ “unsigned long“,那么没有必è¦
280 281
281 typedef unsigned long myflags_t; 282 typedef unsigned long myflags_t;
282 283
283 ä¸è¿‡å¦‚果有一个明确的原因,比如它在æŸç§æƒ…况下å¯èƒ½ä¼šæ˜¯ä¸€ä¸ªâ€œunsigned intâ€è€Œåœ¨ 284 ä¸è¿‡å¦‚果有一个明确的原因,比如它在æŸç§æƒ…况下å¯èƒ½ä¼šæ˜¯ä¸€ä¸ª “unsigned int†而在
284 其他情况下å¯èƒ½ä¸ºâ€œunsigned longâ€ï¼Œé‚£ä¹ˆå°±ä¸è¦çŠ¹è±«ï¼Œè¯·åŠ¡å¿…ä½¿ç”¨typedef。 285 其他情况下å¯èƒ½ä¸º “unsigned longâ€ï¼Œé‚£ä¹ˆå°±ä¸è¦çŠ¹è±«ï¼Œè¯·åŠ¡å¿…ä½¿ç”¨ typedef。
285 286
286 (c) 当你使用sparse按字é¢çš„创建一个新类型æ¥åšç±»åž‹æ£€æŸ¥çš„æ—¶å€™ã€‚ 287 (c) 当你使用sparse按字é¢çš„创建一个新类型æ¥åšç±»åž‹æ£€æŸ¥çš„æ—¶å€™ã€‚
287 288
288 (d) 和标准C99类型相åŒçš„类型,在æŸäº›ä¾‹å¤–的情况下。 289 (d) 和标准C99类型相åŒçš„类型,在æŸäº›ä¾‹å¤–的情况下。
289 290
290 虽然让眼ç›å’Œè„‘ç­‹æ¥é€‚应新的标准类型比如“uint32_tâ€ä¸éœ€è¦èŠ±å¾ˆå¤šæ—¶é—´ï¼Œå¯æ˜¯æœ‰äº› 291 虽然让眼ç›å’Œè„‘ç­‹æ¥é€‚应新的标准类型比如 “uint32_t†ä¸éœ€è¦èŠ±å¾ˆå¤šæ—¶é—´ï¼Œå¯æ˜¯æœ‰äº›
291 人ä»ç„¶æ‹’ç»ä½¿ç”¨å®ƒä»¬ã€‚ 292 人ä»ç„¶æ‹’ç»ä½¿ç”¨å®ƒä»¬ã€‚
292 293
293 因此,Linux特有的等åŒäºŽæ ‡å‡†ç±»åž‹çš„“u8/u16/u32/u64â€ç±»åž‹å’Œå®ƒä»¬çš„æœ‰ç¬¦å·ç±»åž‹æ˜¯è¢« 294 因此,Linux 特有的等åŒäºŽæ ‡å‡†ç±»åž‹çš„ “u8/u16/u32/u64†类型和它们的有符å·ç±»åž‹æ˜¯è¢«
294 å…许的——尽管在你自己的新代ç ä¸­ï¼Œå®ƒä»¬ä¸æ˜¯å¼ºåˆ¶è¦æ±‚è¦ä½¿ç”¨çš„。 295 å…许的——尽管在你自己的新代ç ä¸­ï¼Œå®ƒä»¬ä¸æ˜¯å¼ºåˆ¶è¦æ±‚è¦ä½¿ç”¨çš„。
295 296
296 当编辑已ç»ä½¿ç”¨äº†æŸä¸ªç±»åž‹é›†çš„å·²æœ‰ä»£ç æ—¶ï¼Œä½ åº”该éµå¾ªé‚£äº›ä»£ç ä¸­å·²ç»åšå‡ºçš„选择。 297 当编辑已ç»ä½¿ç”¨äº†æŸä¸ªç±»åž‹é›†çš„å·²æœ‰ä»£ç æ—¶ï¼Œä½ åº”该éµå¾ªé‚£äº›ä»£ç ä¸­å·²ç»åšå‡ºçš„选择。
297 298
298 (e) å¯ä»¥åœ¨ç”¨æˆ·ç©ºé—´å®‰å…¨ä½¿ç”¨çš„类型。 299 (e) å¯ä»¥åœ¨ç”¨æˆ·ç©ºé—´å®‰å…¨ä½¿ç”¨çš„类型。
299 300
300 在æŸäº›ç”¨æˆ·ç©ºé—´å¯è§çš„结构体里,我们ä¸èƒ½è¦æ±‚C99类型而且ä¸èƒ½ç”¨ä¸Šé¢æåˆ°çš„“u32†301 在æŸäº›ç”¨æˆ·ç©ºé—´å¯è§çš„结构体里,我们ä¸èƒ½è¦æ±‚C99类型而且ä¸èƒ½ç”¨ä¸Šé¢æåˆ°çš„ “u32â€
301 类型。因此,我们在与用户空间共享的所有结构体中使用__u32和类似的类型。 302 类型。因此,我们在与用户空间共享的所有结构体中使用 __u32 和类似的类型。
302 303
303å¯èƒ½è¿˜æœ‰å…¶ä»–的情况,ä¸è¿‡åŸºæœ¬çš„规则是永远ä¸è¦ä½¿ç”¨typedef,除éžä½ å¯ä»¥æ˜Žç¡®çš„应用上 304å¯èƒ½è¿˜æœ‰å…¶ä»–的情况,ä¸è¿‡åŸºæœ¬çš„规则是永远ä¸è¦ä½¿ç”¨ typedef,除éžä½ å¯ä»¥æ˜Žç¡®çš„应用上
304è¿°æŸä¸ªè§„则中的一个。 305è¿°æŸä¸ªè§„则中的一个。
305 306
306总的æ¥è¯´ï¼Œå¦‚果一个指针或者一个结构体里的元素å¯ä»¥åˆç†çš„è¢«ç›´æŽ¥è®¿é—®åˆ°ï¼Œé‚£ä¹ˆå®ƒä»¬å°±ä¸ 307总的æ¥è¯´ï¼Œå¦‚果一个指针或者一个结构体里的元素å¯ä»¥åˆç†çš„被直接访问到,那么它们就ä¸
307应该是一个typedef。 308应该是一个 typedef。
308 309
309 310
310 第六章:函数 311 第六章:函数
311 312
312函数应该简短而漂亮,并且åªå®Œæˆä¸€ä»¶äº‹æƒ…。函数应该å¯ä»¥ä¸€å±æˆ–è€…ä¸¤å±æ˜¾ç¤ºå®Œï¼ˆæˆ‘们都知 313函数应该简短而漂亮,并且åªå®Œæˆä¸€ä»¶äº‹æƒ…。函数应该å¯ä»¥ä¸€å±æˆ–è€…ä¸¤å±æ˜¾ç¤ºå®Œï¼ˆæˆ‘们都知
313é“ISO/ANSIå±å¹•大尿˜¯80x24),åªåšä¸€ä»¶äº‹æƒ…,而且把它åšå¥½ã€‚ 314é“ ISO/ANSI å±å¹•大尿˜¯ 80x24),åªåšä¸€ä»¶äº‹æƒ…,而且把它åšå¥½ã€‚
314 315
315ä¸€ä¸ªå‡½æ•°çš„æœ€å¤§é•¿åº¦æ˜¯å’Œè¯¥å‡½æ•°çš„å¤æ‚度和缩进级数æˆå比的。所以,如果你有一个ç†è®ºä¸Š 316ä¸€ä¸ªå‡½æ•°çš„æœ€å¤§é•¿åº¦æ˜¯å’Œè¯¥å‡½æ•°çš„å¤æ‚度和缩进级数æˆå比的。所以,如果你有一个ç†è®ºä¸Š
316很简å•çš„åªæœ‰ä¸€ä¸ªå¾ˆé•¿ï¼ˆä½†æ˜¯ç®€å•)的case语å¥çš„函数,而且你需è¦åœ¨æ¯ä¸ªcase里åšå¾ˆå¤šå¾ˆ 317很简å•çš„åªæœ‰ä¸€ä¸ªå¾ˆé•¿ï¼ˆä½†æ˜¯ç®€å•)的 case 语å¥çš„函数,而且你需è¦åœ¨æ¯ä¸ª case 里åš
317å°çš„事情,这样的函数尽管很长,但也是å¯ä»¥çš„。 318很多很å°çš„事情,这样的函数尽管很长,但也是å¯ä»¥çš„。
318 319
319ä¸è¿‡ï¼Œå¦‚æžœä½ æœ‰ä¸€ä¸ªå¤æ‚çš„å‡½æ•°ï¼Œè€Œä¸”ä½ æ€€ç–‘ä¸€ä¸ªå¤©åˆ†ä¸æ˜¯å¾ˆé«˜çš„高中一年级学生å¯èƒ½ç”šè‡³ 320ä¸è¿‡ï¼Œå¦‚æžœä½ æœ‰ä¸€ä¸ªå¤æ‚çš„å‡½æ•°ï¼Œè€Œä¸”ä½ æ€€ç–‘ä¸€ä¸ªå¤©åˆ†ä¸æ˜¯å¾ˆé«˜çš„高中一年级学生å¯èƒ½ç”šè‡³
320æžä¸æ¸…楚这个函数的目的,你应该严格的éµå®ˆå‰é¢æåˆ°çš„长度é™åˆ¶ã€‚使用辅助函数,并为之 321æžä¸æ¸…楚这个函数的目的,你应该严格的éµå®ˆå‰é¢æåˆ°çš„长度é™åˆ¶ã€‚使用辅助函数,并为之
321å–个具æè¿°æ€§çš„å字(如果你觉得它们的性能很é‡è¦çš„è¯ï¼Œå¯ä»¥è®©ç¼–译器内è”它们,这样的 322å–个具æè¿°æ€§çš„å字(如果你觉得它们的性能很é‡è¦çš„è¯ï¼Œå¯ä»¥è®©ç¼–译器内è”它们,这样的
322æ•ˆæžœå¾€å¾€ä¼šæ¯”ä½ å†™ä¸€ä¸ªå¤æ‚函数的效果è¦å¥½ã€‚) 323æ•ˆæžœå¾€å¾€ä¼šæ¯”ä½ å†™ä¸€ä¸ªå¤æ‚函数的效果è¦å¥½ã€‚)
323 324
324函数的å¦å¤–ä¸€ä¸ªè¡¡é‡æ ‡å‡†æ˜¯æœ¬åœ°å˜é‡çš„æ•°é‡ã€‚此数é‡ä¸åº”超过5ï¼10个,å¦åˆ™ä½ çš„函数就有 325函数的å¦å¤–ä¸€ä¸ªè¡¡é‡æ ‡å‡†æ˜¯æœ¬åœ°å˜é‡çš„æ•°é‡ã€‚此数é‡ä¸åº”超过 5ï¼10 个,å¦åˆ™ä½ çš„函数就有
325é—®é¢˜äº†ã€‚é‡æ–°è€ƒè™‘ä¸€ä¸‹ä½ çš„å‡½æ•°ï¼ŒæŠŠå®ƒåˆ†æ‹†æˆæ›´å°çš„函数。人的大脑一般å¯ä»¥è½»æ¾çš„åŒæ—¶è·Ÿ 326é—®é¢˜äº†ã€‚é‡æ–°è€ƒè™‘ä¸€ä¸‹ä½ çš„å‡½æ•°ï¼ŒæŠŠå®ƒåˆ†æ‹†æˆæ›´å°çš„函数。人的大脑一般å¯ä»¥è½»æ¾çš„åŒæ—¶è·Ÿ
326踪7个ä¸åŒçš„事物,如果å†å¢žå¤šçš„è¯ï¼Œå°±ä¼šç³Šæ¶‚了。å³ä¾¿ä½ èªé¢–过人,你也å¯èƒ½ä¼šè®°ä¸æ¸…ä½ 2 327踪 7 个ä¸åŒçš„事物,如果å†å¢žå¤šçš„è¯ï¼Œå°±ä¼šç³Šæ¶‚了。å³ä¾¿ä½ èªé¢–过人,你也å¯èƒ½ä¼šè®°ä¸æ¸…ä½ 
327个星期å‰åšè¿‡çš„事情。 3282 个星期å‰åšè¿‡çš„事情。
328 329
329åœ¨æºæ–‡ä»¶é‡Œï¼Œä½¿ç”¨ç©ºè¡Œéš”å¼€ä¸åŒçš„函数。如果该函数需è¦è¢«å¯¼å‡ºï¼Œå®ƒçš„EXPORT*å®åº”该紧贴 330åœ¨æºæ–‡ä»¶é‡Œï¼Œä½¿ç”¨ç©ºè¡Œéš”å¼€ä¸åŒçš„函数。如果该函数需è¦è¢«å¯¼å‡ºï¼Œå®ƒçš„ EXPORT* å®åº”该紧贴
330在它的结æŸå¤§æ‹¬å·ä¹‹ä¸‹ã€‚比如: 331在它的结æŸå¤§æ‹¬å·ä¹‹ä¸‹ã€‚比如:
331 332
332int system_is_up(void) 333 int system_is_up(void)
333{ 334 {
334 return system_state == SYSTEM_RUNNING; 335 return system_state == SYSTEM_RUNNING;
335} 336 }
336EXPORT_SYMBOL(system_is_up); 337 EXPORT_SYMBOL(system_is_up);
337 338
338在函数原型中,包å«å‡½æ•°å和它们的数æ®ç±»åž‹ã€‚虽然Cè¯­è¨€é‡Œæ²¡æœ‰è¿™æ ·çš„è¦æ±‚,在Linux里这 339在函数原型中,包å«å‡½æ•°å和它们的数æ®ç±»åž‹ã€‚虽然Cè¯­è¨€é‡Œæ²¡æœ‰è¿™æ ·çš„è¦æ±‚,在 Linux 里这
339是æå€¡çš„åšæ³•,因为这样å¯ä»¥å¾ˆç®€å•的给读者æä¾›æ›´å¤šçš„æœ‰ä»·å€¼çš„ä¿¡æ¯ã€‚ 340是æå€¡çš„åšæ³•,因为这样å¯ä»¥å¾ˆç®€å•的给读者æä¾›æ›´å¤šçš„æœ‰ä»·å€¼çš„ä¿¡æ¯ã€‚
340 341
341 342
342 第七章:集中的函数退出途径 343 第七章:集中的函数退出途径
343 344
344虽然被æŸäº›äººå£°ç§°å·²ç»è¿‡æ—¶ï¼Œä½†æ˜¯goto语å¥çš„等价物还是ç»å¸¸è¢«ç¼–è¯‘å™¨æ‰€ä½¿ç”¨ï¼Œå…·ä½“å½¢å¼æ˜¯ 345虽然被æŸäº›äººå£°ç§°å·²ç»è¿‡æ—¶ï¼Œä½†æ˜¯ goto 语å¥çš„等价物还是ç»å¸¸è¢«ç¼–è¯‘å™¨æ‰€ä½¿ç”¨ï¼Œå…·ä½“å½¢å¼æ˜¯
345æ— æ¡ä»¶è·³è½¬æŒ‡ä»¤ã€‚ 346æ— æ¡ä»¶è·³è½¬æŒ‡ä»¤ã€‚
346 347
347当一个函数从多个ä½ç½®é€€å‡ºå¹¶ä¸”需è¦åšä¸€äº›é€šç”¨çš„æ¸…ç†å·¥ä½œçš„æ—¶å€™ï¼Œgotoçš„å¥½å¤„å°±æ˜¾çŽ°å‡ºæ¥ 348当一个函数从多个ä½ç½®é€€å‡ºï¼Œå¹¶ä¸”需è¦åšä¸€äº›ç±»ä¼¼æ¸…ç†çš„å¸¸è§æ“作时,goto 语å¥å°±å¾ˆæ–¹ä¾¿äº†ã€‚
348了。 349如果并ä¸éœ€è¦æ¸…çæ“ä½œï¼Œé‚£ä¹ˆç›´æŽ¥ return å³å¯ã€‚
349 350
350ç†ç”±æ˜¯ï¼š 351ç†ç”±æ˜¯ï¼š
351 352
@@ -354,26 +355,37 @@ EXPORT_SYMBOL(system_is_up);
354- å¯ä»¥é¿å…由于修改时忘记更新æŸä¸ªå•独的退出点而导致的错误 355- å¯ä»¥é¿å…由于修改时忘记更新æŸä¸ªå•独的退出点而导致的错误
355- å‡è½»äº†ç¼–译器的工作,无需删除冗余代ç ;) 356- å‡è½»äº†ç¼–译器的工作,无需删除冗余代ç ;)
356 357
357int fun(int a) 358 int fun(int a)
358{ 359 {
359 int result = 0; 360 int result = 0;
360 char *buffer = kmalloc(SIZE); 361 char *buffer;
361 362
362 if (buffer == NULL) 363 buffer = kmalloc(SIZE, GFP_KERNEL);
363 return -ENOMEM; 364 if (!buffer)
364 365 return -ENOMEM;
365 if (condition1) { 366
366 while (loop1) { 367 if (condition1) {
367 ... 368 while (loop1) {
369 ...
370 }
371 result = 1;
372 goto out_buffer;
368 } 373 }
369 result = 1; 374 ...
370 goto out; 375 out_buffer:
376 kfree(buffer);
377 return result;
371 } 378 }
372 ... 379
373out: 380ä¸€ä¸ªéœ€è¦æ³¨æ„的常è§é”™è¯¯æ˜¯â€œä¸€ä¸ª err 错误â€ï¼Œå°±åƒè¿™æ ·ï¼š
374 kfree(buffer); 381
375 return result; 382 err:
376} 383 kfree(foo->bar);
384 kfree(foo);
385 return ret;
386
387这段代ç çš„错误是,在æŸäº›é€€å‡ºè·¯å¾„上 “foo†是 NULL。通常情况下,通过把它分离æˆä¸¤ä¸ª
388错误标签 “err_bar:†和 “err_foo:†æ¥ä¿®å¤è¿™ä¸ªé”™è¯¯ã€‚
377 389
378 第八章:注释 390 第八章:注释
379 391
@@ -386,10 +398,10 @@ out:
386加太多。你应该åšçš„,是把注释放在函数的头部,告诉人们它åšäº†ä»€ä¹ˆï¼Œä¹Ÿå¯ä»¥åŠ ä¸Šå®ƒåšè¿™ 398加太多。你应该åšçš„,是把注释放在函数的头部,告诉人们它åšäº†ä»€ä¹ˆï¼Œä¹Ÿå¯ä»¥åŠ ä¸Šå®ƒåšè¿™
387些事情的原因。 399些事情的原因。
388 400
389当注释内核API函数时,请使用kernel-docæ ¼å¼ã€‚请看 401当注释内核API函数时,请使用 kernel-doc æ ¼å¼ã€‚请看
390Documentation/kernel-doc-nano-HOWTO.txtå’Œscripts/kernel-doc以获得详细信æ¯ã€‚ 402Documentation/kernel-doc-nano-HOWTO.txtå’Œscripts/kernel-doc 以获得详细信æ¯ã€‚
391 403
392Linux的注释风格是C89“/* ... */â€é£Žæ ¼ã€‚ä¸è¦ä½¿ç”¨C99风格“// ...â€æ³¨é‡Šã€‚ 404Linux的注释风格是 C89 “/* ... */†风格。ä¸è¦ä½¿ç”¨ C99 风格 “// ...†注释。
393 405
394长(多行)的首选注释风格是: 406长(多行)的首选注释风格是:
395 407
@@ -402,6 +414,15 @@ Linux的注释风格是C89“/* ... */â€é£Žæ ¼ã€‚ä¸è¦ä½¿ç”¨C99风格“// ...
402 * with beginning and ending almost-blank lines. 414 * with beginning and ending almost-blank lines.
403 */ 415 */
404 416
417对于在 net/ å’Œ drivers/net/ 的文件,首选的长(多行)注释风格有些ä¸åŒã€‚
418
419 /* The preferred comment style for files in net/ and drivers/net
420 * looks like this.
421 *
422 * It is nearly the same as the generally preferred comment style,
423 * but there is no initial almost-blank line.
424 */
425
405注释数æ®ä¹Ÿæ˜¯å¾ˆé‡è¦çš„,ä¸ç®¡æ˜¯åŸºæœ¬ç±»åž‹è¿˜æ˜¯è¡ç”Ÿç±»åž‹ã€‚为了方便实现这一点,æ¯ä¸€è¡Œåº”åª 426注释数æ®ä¹Ÿæ˜¯å¾ˆé‡è¦çš„,ä¸ç®¡æ˜¯åŸºæœ¬ç±»åž‹è¿˜æ˜¯è¡ç”Ÿç±»åž‹ã€‚为了方便实现这一点,æ¯ä¸€è¡Œåº”åª
406声明一个数æ®ï¼ˆä¸è¦ä½¿ç”¨é€—å·æ¥ä¸€æ¬¡å£°æ˜Žå¤šä¸ªæ•°æ®ï¼‰ã€‚这样你就有空间æ¥ä¸ºæ¯ä¸ªæ•°æ®å†™ä¸€æ®µ 427声明一个数æ®ï¼ˆä¸è¦ä½¿ç”¨é€—å·æ¥ä¸€æ¬¡å£°æ˜Žå¤šä¸ªæ•°æ®ï¼‰ã€‚这样你就有空间æ¥ä¸ºæ¯ä¸ªæ•°æ®å†™ä¸€æ®µ
407å°æ³¨é‡Šæ¥è§£é‡Šå®ƒä»¬çš„用途了。 428å°æ³¨é‡Šæ¥è§£é‡Šå®ƒä»¬çš„用途了。
@@ -409,49 +430,63 @@ Linux的注释风格是C89“/* ... */â€é£Žæ ¼ã€‚ä¸è¦ä½¿ç”¨C99风格“// ...
409 430
410 第ä¹ç« ï¼šä½ å·²ç»æŠŠäº‹æƒ…弄糟了 431 第ä¹ç« ï¼šä½ å·²ç»æŠŠäº‹æƒ…弄糟了
411 432
412这没什么,我们都是这样。å¯èƒ½ä½ çš„使用了很长时间Unix的朋å‹å·²ç»å‘Šè¯‰ä½ â€œGNU emacsâ€èƒ½ 433这没什么,我们都是这样。å¯èƒ½ä½ çš„使用了很长时间 Unix 的朋å‹å·²ç»å‘Šè¯‰ä½  “GNU emacs†能
413自动帮你格å¼åŒ–Cæºä»£ç ï¼Œè€Œä¸”你也注æ„到了,确实是这样,ä¸è¿‡å®ƒæ‰€ä½¿ç”¨çš„默认值和我们 434自动帮你格å¼åŒ– C æºä»£ç ï¼Œè€Œä¸”你也注æ„到了,确实是这样,ä¸è¿‡å®ƒæ‰€ä½¿ç”¨çš„默认值和我们
414想è¦çš„ç›¸åŽ»ç”šè¿œï¼ˆå®žé™…ä¸Šï¼Œç”šè‡³æ¯”éšæœºæ‰“的还è¦å·®â€”—无数个猴å­åœ¨GNU emacsé‡Œæ‰“å­—æ°¸è¿œä¸ 435想è¦çš„ç›¸åŽ»ç”šè¿œï¼ˆå®žé™…ä¸Šï¼Œç”šè‡³æ¯”éšæœºæ‰“的还è¦å·®â€”—无数个猴å­åœ¨ GNU emacs 里打字永远ä¸
415会创造出一个好程åºï¼‰ï¼ˆè¯‘注:请å‚考Infinite Monkey Theorem) 436会创造出一个好程åºï¼‰ï¼ˆè¯‘注:请å‚考 Infinite Monkey Theorem)
416 437
417所以你è¦ä¹ˆæ”¾å¼ƒGNU emacs,è¦ä¹ˆæ”¹å˜å®ƒè®©å®ƒä½¿ç”¨æ›´åˆç†çš„设定。è¦é‡‡ç”¨åŽä¸€ä¸ªæ–¹æ¡ˆï¼Œä½ å¯ 438所以你è¦ä¹ˆæ”¾å¼ƒ GNU emacs,è¦ä¹ˆæ”¹å˜å®ƒè®©å®ƒä½¿ç”¨æ›´åˆç†çš„设定。è¦é‡‡ç”¨åŽä¸€ä¸ªæ–¹æ¡ˆï¼Œä½ å¯
418以把下é¢è¿™æ®µç²˜è´´åˆ°ä½ çš„.emacs文件里。 439以把下é¢è¿™æ®µç²˜è´´åˆ°ä½ çš„ .emacs 文件里。
419 440
420(defun linux-c-mode () 441(defun c-lineup-arglist-tabs-only (ignored)
421 "C mode with adjusted defaults for use with the Linux kernel." 442 "Line up argument lists by tabs, not spaces"
422 (interactive) 443 (let* ((anchor (c-langelem-pos c-syntactic-element))
423 (c-mode) 444 (column (c-langelem-2nd-pos c-syntactic-element))
424 (c-set-style "K&R") 445 (offset (- (1+ column) anchor))
425 (setq tab-width 8) 446 (steps (floor offset c-basic-offset)))
426 (setq indent-tabs-mode t) 447 (* (max steps 1)
427 (setq c-basic-offset 8)) 448 c-basic-offset)))
428 449
429这样就定义了M-x linux-c-mode命令。当你hack一个模å—的时候,如果你把字符串 450(add-hook 'c-mode-common-hook
430-*- linux-c -*-放在头两行的æŸä¸ªä½ç½®ï¼Œè¿™ä¸ªæ¨¡å¼å°†ä¼šè¢«è‡ªåŠ¨è°ƒç”¨ã€‚å¦‚æžœä½ å¸Œæœ›åœ¨ä½ ä¿®æ”¹ 451 (lambda ()
431/usr/src/linux里的文件时魔术般自动打开linux-c-modeçš„è¯ï¼Œä½ ä¹Ÿå¯èƒ½éœ€è¦æ·»åŠ  452 ;; Add kernel style
432 453 (c-add-style
433(setq auto-mode-alist (cons '("/usr/src/linux.*/.*\\.[ch]$" . linux-c-mode) 454 "linux-tabs-only"
434 auto-mode-alist)) 455 '("linux" (c-offsets-alist
435 456 (arglist-cont-nonempty
436到你的.emacs文件里。 457 c-lineup-gcc-asm-reg
437 458 c-lineup-arglist-tabs-only))))))
438ä¸è¿‡å°±ç®—ä½ å°è¯•让emacs正确的格å¼åŒ–代ç å¤±è´¥äº†ï¼Œä¹Ÿå¹¶ä¸æ„味ç€ä½ å¤±åŽ»äº†ä¸€åˆ‡ï¼šè¿˜å¯ä»¥ç”¨â€œ 459
439indentâ€ã€‚ 460(add-hook 'c-mode-hook
440 461 (lambda ()
441ä¸è¿‡ï¼ŒGNU indent也有和GNU emacs一样有问题的设定,所以你需è¦ç»™å®ƒä¸€äº›å‘½ä»¤é€‰é¡¹ã€‚ä¸ 462 (let ((filename (buffer-file-name)))
442过,这还ä¸ç®—太糟糕,因为就算是GNU indent的作者也认åŒK&Rçš„æƒå¨æ€§ï¼ˆGNUçš„äººå¹¶ä¸æ˜¯å 463 ;; Enable kernel mode for the appropriate files
443äººï¼Œä»–ä»¬åªæ˜¯åœ¨è¿™ä¸ªé—®é¢˜ä¸Šè¢«ä¸¥é‡çš„误导了),所以你åªè¦ç»™indent指定选项“-kr -i8†464 (when (and filename
444(代表“K&R,8个字符缩进â€ï¼‰ï¼Œæˆ–者使用“scripts/Lindentâ€ï¼Œè¿™æ ·å°±å¯ä»¥ä»¥æœ€æ—¶é«¦çš„æ–¹å¼ 465 (string-match (expand-file-name "~/src/linux-trees")
466 filename))
467 (setq indent-tabs-mode t)
468 (setq show-trailing-whitespace t)
469 (c-set-style "linux-tabs-only")))))
470
471这会让 emacs 在 ~/src/linux-trees 目录下的 C æºæ–‡ä»¶èŽ·å¾—æ›´å¥½çš„å†…æ ¸ä»£ç é£Žæ ¼ã€‚
472
473ä¸è¿‡å°±ç®—ä½ å°è¯•让 emacs 正确的格å¼åŒ–代ç å¤±è´¥äº†ï¼Œä¹Ÿå¹¶ä¸æ„味ç€ä½ å¤±åŽ»äº†ä¸€åˆ‡ï¼šè¿˜å¯ä»¥ç”¨
474“indentâ€ã€‚
475
476ä¸è¿‡ï¼ŒGNU indent 也有和 GNU emacs 一样有问题的设定,所以你需è¦ç»™å®ƒä¸€äº›å‘½ä»¤é€‰é¡¹ã€‚ä¸
477过,这还ä¸ç®—太糟糕,因为就算是 GNU indent çš„ä½œè€…ä¹Ÿè®¤åŒ K&R çš„æƒå¨æ€§ï¼ˆGNU çš„äººå¹¶ä¸æ˜¯
478åäººï¼Œä»–ä»¬åªæ˜¯åœ¨è¿™ä¸ªé—®é¢˜ä¸Šè¢«ä¸¥é‡çš„误导了),所以你åªè¦ç»™ indent 指定选项 “-kr -i8â€
479(代表 “K&R,8 个字符缩进â€ï¼‰ï¼Œæˆ–者使用 “scripts/Lindentâ€ï¼Œè¿™æ ·å°±å¯ä»¥ä»¥æœ€æ—¶é«¦çš„æ–¹å¼
445缩进æºä»£ç ã€‚ 480缩进æºä»£ç ã€‚
446 481
447“indentâ€æœ‰å¾ˆå¤šé€‰é¡¹ï¼Œç‰¹åˆ«æ˜¯é‡æ–°æ ¼å¼åŒ–注释的时候,你å¯èƒ½éœ€è¦çœ‹ä¸€ä¸‹å®ƒçš„æ‰‹å†Œé¡µã€‚ä¸è¿‡ 482“indentâ€ æœ‰å¾ˆå¤šé€‰é¡¹ï¼Œç‰¹åˆ«æ˜¯é‡æ–°æ ¼å¼åŒ–注释的时候,你å¯èƒ½éœ€è¦çœ‹ä¸€ä¸‹å®ƒçš„æ‰‹å†Œé¡µã€‚ä¸è¿‡
448è®°ä½ï¼šâ€œindentâ€ä¸èƒ½ä¿®æ­£å的编程习惯。 483è®°ä½ï¼šâ€œindent†ä¸èƒ½ä¿®æ­£å的编程习惯。
449 484
450 485
451 第å章:Kconfigé…置文件 486 第å章:Kconfig é…置文件
452 487
453对于é布æºç æ ‘的所有Kconfig*é…置文件æ¥è¯´ï¼Œå®ƒä»¬ç¼©è¿›æ–¹å¼ä¸ŽC代ç ç›¸æ¯”有所ä¸åŒã€‚紧挨 488对于é布æºç æ ‘的所有 Kconfig* é…置文件æ¥è¯´ï¼Œå®ƒä»¬ç¼©è¿›æ–¹å¼ä¸Ž C 代ç ç›¸æ¯”有所ä¸åŒã€‚紧挨
454在“configâ€å®šä¹‰ä¸‹é¢çš„行缩进一个制表符,帮助信æ¯åˆ™å†å¤šç¼©è¿›2个空格。比如: 489在 “config†定义下é¢çš„行缩进一个制表符,帮助信æ¯åˆ™å†å¤šç¼©è¿› 2 个空格。比如:
455 490
456config AUDIT 491config AUDIT
457 bool "Auditing support" 492 bool "Auditing support"
@@ -470,7 +505,7 @@ config ADFS_FS_RW
470 depends on ADFS_FS 505 depends on ADFS_FS
471 ... 506 ...
472 507
473è¦æŸ¥çœ‹é…置文件的完整文档,请看Documentation/kbuild/kconfig-language.txt。 508è¦æŸ¥çœ‹é…置文件的完整文档,请看 Documentation/kbuild/kconfig-language.txt。
474 509
475 510
476 第å一章:数æ®ç»“æž„ 511 第å一章:数æ®ç»“æž„
@@ -489,11 +524,11 @@ config ADFS_FS_RW
489很多数æ®ç»“构实际上有2级引用计数,它们通常有ä¸åŒâ€œç±»â€çš„用户。å­ç±»è®¡æ•°å™¨ç»Ÿè®¡å­ç±»ç”¨ 524很多数æ®ç»“构实际上有2级引用计数,它们通常有ä¸åŒâ€œç±»â€çš„用户。å­ç±»è®¡æ•°å™¨ç»Ÿè®¡å­ç±»ç”¨
490户的数é‡ï¼Œæ¯å½“å­ç±»è®¡æ•°å™¨å‡è‡³é›¶æ—¶ï¼Œå…¨å±€è®¡æ•°å™¨å‡ä¸€ã€‚ 525户的数é‡ï¼Œæ¯å½“å­ç±»è®¡æ•°å™¨å‡è‡³é›¶æ—¶ï¼Œå…¨å±€è®¡æ•°å™¨å‡ä¸€ã€‚
491 526
492è¿™ç§â€œå¤šçº§å¼•用计数â€çš„例å­å¯ä»¥åœ¨å†…存管ç†ï¼ˆâ€œstruct mm_structâ€ï¼šmm_userså’Œmm_count) 527è¿™ç§â€œå¤šçº§å¼•用计数â€çš„例å­å¯ä»¥åœ¨å†…存管ç†ï¼ˆâ€œstruct mm_structâ€ï¼šmm_users å’Œ mm_count)
493和文件系统(“struct super_blockâ€ï¼šs_countå’Œs_active)中找到。 528和文件系统(“struct super_blockâ€ï¼šs_countå’Œs_active)中找到。
494 529
495è®°ä½ï¼šå¦‚æžœå¦ä¸€ä¸ªæ‰§è¡Œçº¿ç´¢å¯ä»¥æ‰¾åˆ°ä½ çš„æ•°æ®ç»“构,但是这个数æ®ç»“构没有引用计数器,这 530è®°ä½ï¼šå¦‚æžœå¦ä¸€ä¸ªæ‰§è¡Œçº¿ç´¢å¯ä»¥æ‰¾åˆ°ä½ çš„æ•°æ®ç»“构,但是这个数æ®ç»“构没有引用计数器,这
496里几乎肯定是一个bug。 531里几乎肯定是一个 bug。
497 532
498 533
499 第å二章:å®ï¼Œæžšä¸¾å’ŒRTL 534 第å二章:å®ï¼Œæžšä¸¾å’ŒRTL
@@ -508,102 +543,128 @@ config ADFS_FS_RW
508 543
509一般的,如果能写æˆå†…è”函数就ä¸è¦å†™æˆåƒå‡½æ•°çš„å®ã€‚ 544一般的,如果能写æˆå†…è”函数就ä¸è¦å†™æˆåƒå‡½æ•°çš„å®ã€‚
510 545
511嫿œ‰å¤šä¸ªè¯­å¥çš„å®åº”该被包å«åœ¨ä¸€ä¸ªdo-while代ç å—里: 546嫿œ‰å¤šä¸ªè¯­å¥çš„å®åº”该被包å«åœ¨ä¸€ä¸ª do-while 代ç å—里:
512 547
513#define macrofun(a, b, c) \ 548 #define macrofun(a, b, c) \
514 do { \ 549 do { \
515 if (a == 5) \ 550 if (a == 5) \
516 do_this(b, c); \ 551 do_this(b, c); \
517 } while (0) 552 } while (0)
518 553
519使用å®çš„æ—¶å€™åº”é¿å…的事情: 554使用å®çš„æ—¶å€™åº”é¿å…的事情:
520 555
5211) å½±å“æŽ§åˆ¶æµç¨‹çš„å®ï¼š 5561) å½±å“æŽ§åˆ¶æµç¨‹çš„å®ï¼š
522 557
523#define FOO(x) \ 558 #define FOO(x) \
524 do { \ 559 do { \
525 if (blah(x) < 0) \ 560 if (blah(x) < 0) \
526 return -EBUGGERED; \ 561 return -EBUGGERED; \
527 } while(0) 562 } while (0)
528 563
529éžå¸¸ä¸å¥½ã€‚它看起æ¥åƒä¸€ä¸ªå‡½æ•°ï¼Œä¸è¿‡å´èƒ½å¯¼è‡´â€œè°ƒç”¨â€å®ƒçš„函数退出;ä¸è¦æ‰“乱读者大脑里 564éžå¸¸ä¸å¥½ã€‚它看起æ¥åƒä¸€ä¸ªå‡½æ•°ï¼Œä¸è¿‡å´èƒ½å¯¼è‡´â€œè°ƒç”¨â€å®ƒçš„函数退出;ä¸è¦æ‰“乱读者大脑里
530的语法分æžå™¨ã€‚ 565的语法分æžå™¨ã€‚
531 566
5322) ä¾èµ–于一个固定å字的本地å˜é‡çš„å®ï¼š 5672) ä¾èµ–于一个固定å字的本地å˜é‡çš„å®ï¼š
533 568
534#define FOO(val) bar(index, val) 569 #define FOO(val) bar(index, val)
535 570
536å¯èƒ½çœ‹èµ·æ¥åƒæ˜¯ä¸ªä¸é”™çš„东西,ä¸è¿‡å®ƒéžå¸¸å®¹æ˜“把读代ç çš„人æžç³Šæ¶‚ï¼Œè€Œä¸”å®¹æ˜“å¯¼è‡´çœ‹èµ·æ¥ 571å¯èƒ½çœ‹èµ·æ¥åƒæ˜¯ä¸ªä¸é”™çš„东西,ä¸è¿‡å®ƒéžå¸¸å®¹æ˜“把读代ç çš„人æžç³Šæ¶‚,而且容易导致看起æ¥
537ä¸ç›¸å…³çš„æ”¹åЍ另æ¥é”™è¯¯ã€‚ 572ä¸ç›¸å…³çš„æ”¹åЍ另æ¥é”™è¯¯ã€‚
538 573
5393) ä½œä¸ºå·¦å€¼çš„å¸¦å‚æ•°çš„å®ï¼š FOO(x) = y;如果有人把FOOå˜æˆä¸€ä¸ªå†…è”函数的è¯ï¼Œè¿™ç§ç”¨ 5743) ä½œä¸ºå·¦å€¼çš„å¸¦å‚æ•°çš„å®ï¼š FOO(x) = y;如果有人把 FOO å˜æˆä¸€ä¸ªå†…è”函数的è¯ï¼Œè¿™ç§ç”¨
540法就会出错了。 575法就会出错了。
541 576
5424) 忘记了优先级:使用表达å¼å®šä¹‰å¸¸é‡çš„å®å¿…须将表达å¼ç½®äºŽä¸€å¯¹å°æ‹¬å·ä¹‹å†…ã€‚å¸¦å‚æ•°çš„ 5774) 忘记了优先级:使用表达å¼å®šä¹‰å¸¸é‡çš„å®å¿…须将表达å¼ç½®äºŽä¸€å¯¹å°æ‹¬å·ä¹‹å†…ã€‚å¸¦å‚æ•°çš„
543å®ä¹Ÿè¦æ³¨æ„此类问题。 578å®ä¹Ÿè¦æ³¨æ„此类问题。
544 579
545#define CONSTANT 0x4000 580 #define CONSTANT 0x4000
546#define CONSTEXP (CONSTANT | 3) 581 #define CONSTEXP (CONSTANT | 3)
582
5835) 在å®é‡Œå®šä¹‰ç±»ä¼¼å‡½æ•°çš„æœ¬åœ°å˜é‡æ—¶å‘½å冲çªï¼š
547 584
548cpp手册对å®çš„讲解很详细。Gcc internals手册也详细讲解了RTL(译注:register 585 #define FOO(x) \
586 ({ \
587 typeof(x) ret; \
588 ret = calc_ret(x); \
589 (ret); \
590 })
591
592ret 是本地å˜é‡çš„通用åå­— - __foo_ret æ›´ä¸å®¹æ˜“与一个已存在的å˜é‡å†²çªã€‚
593
594cpp 手册对å®çš„讲解很详细。gcc internals 手册也详细讲解了 RTL(译注:register
549transfer language),内核里的汇编语言ç»å¸¸ç”¨åˆ°å®ƒã€‚ 595transfer language),内核里的汇编语言ç»å¸¸ç”¨åˆ°å®ƒã€‚
550 596
551 597
552 第å三章:打å°å†…æ ¸æ¶ˆæ¯ 598 第å三章:打å°å†…核消æ¯
553 599
554内核开å‘者应该是å—过良好教育的。请一定注æ„内核信æ¯çš„æ‹¼å†™ï¼Œä»¥ç»™äººä»¥å¥½çš„å°è±¡ã€‚ä¸è¦ 600内核开å‘者应该是å—过良好教育的。请一定注æ„内核信æ¯çš„æ‹¼å†™ï¼Œä»¥ç»™äººä»¥å¥½çš„å°è±¡ã€‚ä¸è¦
555用ä¸è§„范的å•è¯æ¯”如“dontâ€ï¼Œè€Œè¦ç”¨â€œdo notâ€æˆ–者“don'tâ€ã€‚ä¿è¯è¿™äº›ä¿¡æ¯ç®€å•ã€æ˜Žäº†ã€æ—  601用ä¸è§„范的å•è¯æ¯”如 “dontâ€ï¼Œè€Œè¦ç”¨ “do notâ€æˆ–者 “don'tâ€ã€‚ä¿è¯è¿™äº›ä¿¡æ¯ç®€å•ã€æ˜Žäº†ã€
556歧义。 602无歧义。
557 603
558内核信æ¯ä¸å¿…以å¥å·ï¼ˆè¯‘注:英文å¥å·ï¼Œå³ç‚¹ï¼‰ç»“æŸã€‚ 604内核信æ¯ä¸å¿…以å¥å·ï¼ˆè¯‘注:英文å¥å·ï¼Œå³ç‚¹ï¼‰ç»“æŸã€‚
559 605
560åœ¨å°æ‹¬å·é‡Œæ‰“å°æ•°å­—(%d)没有任何价值,应该é¿å…这样åšã€‚ 606åœ¨å°æ‹¬å·é‡Œæ‰“å°æ•°å­— (%d) 没有任何价值,应该é¿å…这样åšã€‚
561 607
562<linux/device.h>里有一些驱动模型诊断å®ï¼Œä½ åº”该使用它们,以确ä¿ä¿¡æ¯å¯¹åº”于正确的 608<linux/device.h> 里有一些驱动模型诊断å®ï¼Œä½ åº”该使用它们,以确ä¿ä¿¡æ¯å¯¹åº”于正确的
563设备和驱动,并且被标记了正确的消æ¯çº§åˆ«ã€‚è¿™äº›å®æœ‰ï¼šdev_err(), dev_warn(), 609设备和驱动,并且被标记了正确的消æ¯çº§åˆ«ã€‚è¿™äº›å®æœ‰ï¼šdev_err(),dev_warn(),
564dev_info()等等。对于那些ä¸å’ŒæŸä¸ªç‰¹å®šè®¾å¤‡ç›¸å…³è¿žçš„ä¿¡æ¯ï¼Œ<linux/kernel.h>定义了 610dev_info() 等等。对于那些ä¸å’ŒæŸä¸ªç‰¹å®šè®¾å¤‡ç›¸å…³è¿žçš„ä¿¡æ¯ï¼Œ<linux/printk.h> 定义了
565pr_debug()和pr_info()。 611pr_notice(),pr_info(),pr_warn(),pr_err() 和其他。
566 612
567写出好的调试信æ¯å¯ä»¥æ˜¯ä¸€ä¸ªå¾ˆå¤§çš„æŒ‘战;当你写出æ¥ä¹‹åŽï¼Œè¿™äº›ä¿¡æ¯åœ¨è¿œç¨‹é™¤é”™çš„æ—¶å€™ 613写出好的调试信æ¯å¯ä»¥æ˜¯ä¸€ä¸ªå¾ˆå¤§çš„æŒ‘战;一旦你写出åŽï¼Œè¿™äº›ä¿¡æ¯åœ¨è¿œç¨‹é™¤é”™æ—¶èƒ½æä¾›æžå¤§
568就会æˆä¸ºæžå¤§çš„帮助。当DEBUGç¬¦å·æ²¡æœ‰è¢«å®šä¹‰çš„æ—¶å€™ï¼Œè¿™äº›ä¿¡æ¯ä¸åº”该被编译进内核里 614的帮助。然而打å°è°ƒè¯•ä¿¡æ¯çš„å¤„ç†æ–¹å¼åŒæ‰“å°éžè°ƒè¯•ä¿¡æ¯ä¸åŒã€‚å…¶ä»– pr_XXX() 函数能无æ¡ä»¶åœ°
569(也就是说,默认地,它们ä¸åº”该被包å«åœ¨å†…)。如果你使用dev_dbg()或者pr_debug(), 615打å°ï¼Œpr_debug() å´ä¸ï¼›é»˜è®¤æƒ…况下它ä¸ä¼šè¢«ç¼–译,除éžå®šä¹‰äº† DEBUG 或设定了
570就能自动达到这个效果。很多å­ç³»ç»Ÿæ‹¥æœ‰Kconfig选项æ¥å¯ç”¨-DDEBUG。还有一个相关的惯例 616CONFIG_DYNAMIC_DEBUGã€‚å®žé™…è¿™åŒæ ·æ˜¯ä¸ºäº† dev_dbg(),一个相关约定是在一个已ç»å¼€å¯äº†
571是使用VERBOSE_DEBUGæ¥æ·»åŠ dev_vdbg()消æ¯åˆ°é‚£äº›å·²ç»ç”±DEBUGå¯ç”¨çš„æ¶ˆæ¯ä¹‹ä¸Šã€‚ 617DEBUG 时,使用 VERBOSE_DEBUG æ¥æ·»åŠ  dev_vdbg()。
618
619许多å­ç³»ç»Ÿæ‹¥æœ‰ Kconfig 调试选项æ¥å¼€å¯ -DDEBUG 在对应的 Makefile 里é¢ï¼›åœ¨å…¶ä»–
620情况下,特殊文件使用 #define DEBUG。当一æ¡è°ƒè¯•ä¿¡æ¯éœ€è¦è¢«æ— æ¡ä»¶æ‰“å°æ—¶ï¼Œä¾‹å¦‚,如果
621å·²ç»åŒ…å«ä¸€ä¸ªè°ƒè¯•相关的 #ifdef æ¡ä»¶ï¼Œprintk(KERN_DEBUG ...) å°±å¯è¢«ä½¿ç”¨ã€‚
572 622
573 623
574 第å四章:分é…内存 624 第å四章:分é…内存
575 625
576内核æä¾›äº†ä¸‹é¢çš„一般用途的内存分é…函数:kmalloc(),kzalloc(),kcalloc()å’Œ 626内核æä¾›äº†ä¸‹é¢çš„一般用途的内存分é…函数:
577vmalloc()。请å‚考APIæ–‡æ¡£ä»¥èŽ·å–æœ‰å…³å®ƒä»¬çš„详细信æ¯ã€‚ 627kmalloc(),kzalloc(),kmalloc_array(),kcalloc(),vmalloc() å’Œ vzalloc()。
628请å‚考 API æ–‡æ¡£ä»¥èŽ·å–æœ‰å…³å®ƒä»¬çš„详细信æ¯ã€‚
578 629
579传递结构体大å°çš„首选形弿˜¯è¿™æ ·çš„: 630传递结构体大å°çš„首选形弿˜¯è¿™æ ·çš„:
580 631
581 p = kmalloc(sizeof(*p), ...); 632 p = kmalloc(sizeof(*p), ...);
582 633
583å¦å¤–一ç§ä¼ é€’æ–¹å¼ä¸­ï¼Œsizeofçš„æ“作数是结构体的å字,这样会é™ä½Žå¯è¯»æ€§ï¼Œå¹¶ä¸”å¯èƒ½ä¼šå¼• 634å¦å¤–一ç§ä¼ é€’æ–¹å¼ä¸­ï¼Œsizeof çš„æ“作数是结构体的å字,这样会é™ä½Žå¯è¯»æ€§ï¼Œå¹¶ä¸”å¯èƒ½ä¼šå¼•
584å…¥bug。有å¯èƒ½æŒ‡é’ˆå˜é‡ç±»åž‹è¢«æ”¹å˜æ—¶ï¼Œè€Œå¯¹åº”的传递给内存分é…函数的sizeof的结果ä¸å˜ã€‚ 635å…¥ bug。有å¯èƒ½æŒ‡é’ˆå˜é‡ç±»åž‹è¢«æ”¹å˜æ—¶ï¼Œè€Œå¯¹åº”的传递给内存分é…函数的 sizeof 的结果ä¸å˜ã€‚
585 636
586强制转æ¢ä¸€ä¸ªvoid指针返回值是多余的。C语言本身ä¿è¯äº†ä»Žvoid指针到其他任何指针类型 637强制转æ¢ä¸€ä¸ª void 指针返回值是多余的。C 语言本身ä¿è¯äº†ä»Ž void 指针到其他任何指针类型
587çš„è½¬æ¢æ˜¯æ²¡æœ‰é—®é¢˜çš„。 638çš„è½¬æ¢æ˜¯æ²¡æœ‰é—®é¢˜çš„。
588 639
640分é…ä¸€ä¸ªæ•°ç»„çš„é¦–é€‰å½¢å¼æ˜¯è¿™æ ·çš„:
641
642 p = kmalloc_array(n, sizeof(...), ...);
643
644分é…ä¸€ä¸ªé›¶é•¿æ•°ç»„çš„é¦–é€‰å½¢å¼æ˜¯è¿™æ ·çš„:
645
646 p = kcalloc(n, sizeof(...), ...);
647
648两ç§å½¢å¼æ£€æŸ¥åˆ†é…å¤§å° n * sizeof(...) 的溢出,如果溢出返回 NULL。
649
589 650
590 第å五章:内è”弊病 651 第å五章:内è”弊病
591 652
592有一个常è§çš„误解是内è”函数是gccæä¾›çš„å¯ä»¥è®©ä»£ç è¿è¡Œæ›´å¿«çš„ä¸€ä¸ªé€‰é¡¹ã€‚è™½ç„¶ä½¿ç”¨å†…è” 653有一个常è§çš„误解是内è”函数是 gcc æä¾›çš„å¯ä»¥è®©ä»£ç è¿è¡Œæ›´å¿«çš„一个选项。虽然使用内è”
593函数有时候是æ°å½“çš„ï¼ˆæ¯”å¦‚ä½œä¸ºä¸€ç§æ›¿ä»£å®çš„æ–¹å¼ï¼Œè¯·çœ‹ç¬¬å二章),ä¸è¿‡å¾ˆå¤šæƒ…况䏋䏿˜¯ 654函数有时候是æ°å½“çš„ï¼ˆæ¯”å¦‚ä½œä¸ºä¸€ç§æ›¿ä»£å®çš„æ–¹å¼ï¼Œè¯·çœ‹ç¬¬å二章),ä¸è¿‡å¾ˆå¤šæƒ…况䏋䏿˜¯
594这样。inline关键字的过度使用会使内核å˜å¤§ï¼Œä»Žè€Œä½¿æ•´ä¸ªç³»ç»Ÿè¿è¡Œé€Ÿåº¦å˜æ…¢ã€‚因为大内核 655这样。inline 关键字的过度使用会使内核å˜å¤§ï¼Œä»Žè€Œä½¿æ•´ä¸ªç³»ç»Ÿè¿è¡Œé€Ÿåº¦å˜æ…¢ã€‚因为大内核
595会å ç”¨æ›´å¤šçš„æŒ‡ä»¤é«˜é€Ÿç¼“存(译注:一级缓存通常是指令缓存和数æ®ç¼“存分开的)而且会导 656会å ç”¨æ›´å¤šçš„æŒ‡ä»¤é«˜é€Ÿç¼“存(译注:一级缓存通常是指令缓存和数æ®ç¼“存分开的)而且会导
596致pagecacheçš„å¯ç”¨å†…å­˜å‡å°‘。想象一下,一次pagecache未命中就会导致一次ç£ç›˜å¯»å€ï¼Œå°† 657致 pagecache çš„å¯ç”¨å†…å­˜å‡å°‘。想象一下,一次pagecache未命中就会导致一次ç£ç›˜å¯»å€ï¼Œ
597耗时5毫秒。5毫秒的时间内CPU能执行很多很多指令。 658将耗时 5 毫秒。5 毫秒的时间内 CPU 能执行很多很多指令。
598 659
599一个基本的原则是如果一个函数有3行以上,就ä¸è¦æŠŠå®ƒå˜æˆå†…è”函数。这个原则的一个例 660一个基本的原则是如果一个函数有 3 行以上,就ä¸è¦æŠŠå®ƒå˜æˆå†…è”函数。这个原则的一个例
600å¤–æ˜¯ï¼Œå¦‚æžœä½ çŸ¥é“æŸä¸ªå‚数是一个编译时常é‡ï¼Œè€Œä¸”因为这个常é‡ä½ ç¡®å®šç¼–译器在编译时能 661å¤–æ˜¯ï¼Œå¦‚æžœä½ çŸ¥é“æŸä¸ªå‚数是一个编译时常é‡ï¼Œè€Œä¸”因为这个常é‡ä½ ç¡®å®šç¼–译器在编译时能
601优化掉你的函数的大部分代ç ï¼Œé‚£ä»ç„¶å¯ä»¥ç»™å®ƒåŠ ä¸Šinline关键字。kmalloc()内è”函数就 662优化掉你的函数的大部分代ç ï¼Œé‚£ä»ç„¶å¯ä»¥ç»™å®ƒåŠ ä¸Š inline 关键字。kmalloc() 内è”函数就
602是一个很好的例å­ã€‚ 663是一个很好的例å­ã€‚
603 664
604人们ç»å¸¸ä¸»å¼ ç»™static的而且åªç”¨äº†ä¸€æ¬¡çš„函数加上inline,如此ä¸ä¼šæœ‰ä»»ä½•æŸå¤±ï¼Œå› ä¸ºæ²¡ 665人们ç»å¸¸ä¸»å¼ ç»™ static 的而且åªç”¨äº†ä¸€æ¬¡çš„函数加上 inline,如此ä¸ä¼šæœ‰ä»»ä½•æŸå¤±ï¼Œå› ä¸ºæ²¡
605有什么好æƒè¡¡çš„ã€‚è™½ç„¶ä»ŽæŠ€æœ¯ä¸Šè¯´è¿™æ˜¯æ­£ç¡®çš„ï¼Œä½†æ˜¯å®žé™…ä¸Šè¿™ç§æƒ…况下å³ä½¿ä¸åŠ inline gcc 666有什么好æƒè¡¡çš„ã€‚è™½ç„¶ä»ŽæŠ€æœ¯ä¸Šè¯´è¿™æ˜¯æ­£ç¡®çš„ï¼Œä½†æ˜¯å®žé™…ä¸Šè¿™ç§æƒ…况下å³ä½¿ä¸åŠ  inline gcc
606也å¯ä»¥è‡ªåŠ¨ä½¿å…¶å†…è”。而且其他用户å¯èƒ½ä¼šè¦æ±‚移除inline,由此而æ¥çš„争论会抵消inline 667也å¯ä»¥è‡ªåŠ¨ä½¿å…¶å†…è”。而且其他用户å¯èƒ½ä¼šè¦æ±‚移除 inline,由此而æ¥çš„争论会抵消 inline
607自身的潜在价值,得ä¸å¿å¤±ã€‚ 668自身的潜在价值,得ä¸å¿å¤±ã€‚
608 669
609 670
@@ -613,37 +674,37 @@ vmalloc()。请å‚考APIæ–‡æ¡£ä»¥èŽ·å–æœ‰å…³å®ƒä»¬çš„详细信æ¯ã€‚
613的一个值å¯ä»¥è¡¨ç¤ºä¸ºä¸€ä¸ªé”™è¯¯ä»£ç æ•´æ•°ï¼ˆ-Exxxï¼å¤±è´¥ï¼Œ0ï¼æˆåŠŸï¼‰æˆ–è€…ä¸€ä¸ªâ€œæˆåŠŸâ€å¸ƒå°”值( 674的一个值å¯ä»¥è¡¨ç¤ºä¸ºä¸€ä¸ªé”™è¯¯ä»£ç æ•´æ•°ï¼ˆ-Exxxï¼å¤±è´¥ï¼Œ0ï¼æˆåŠŸï¼‰æˆ–è€…ä¸€ä¸ªâ€œæˆåŠŸâ€å¸ƒå°”值(
6140ï¼å¤±è´¥ï¼Œéž0ï¼æˆåŠŸï¼‰ã€‚ 6750ï¼å¤±è´¥ï¼Œéž0ï¼æˆåŠŸï¼‰ã€‚
615 676
616æ··åˆä½¿ç”¨è¿™ä¸¤ç§è¡¨è¾¾æ–¹å¼æ˜¯éš¾äºŽå‘现的bugçš„æ¥æºã€‚如果Cè¯­è¨€æœ¬èº«ä¸¥æ ¼åŒºåˆ†æ•´å½¢å’Œå¸ƒå°”åž‹å˜ 677æ··åˆä½¿ç”¨è¿™ä¸¤ç§è¡¨è¾¾æ–¹å¼æ˜¯éš¾äºŽå‘现的 bug çš„æ¥æºã€‚如果 C 语言本身严格区分整形和布尔型å˜
617é‡ï¼Œé‚£ä¹ˆç¼–译器就能够帮我们å‘现这些错误……ä¸è¿‡C语言ä¸åŒºåˆ†ã€‚为了é¿å…产生这ç§bug,请 678é‡ï¼Œé‚£ä¹ˆç¼–译器就能够帮我们å‘现这些错误……ä¸è¿‡ C 语言ä¸åŒºåˆ†ã€‚为了é¿å…äº§ç”Ÿè¿™ç§ bug,请
618éµå¾ªä¸‹é¢çš„æƒ¯ä¾‹ï¼š 679éµå¾ªä¸‹é¢çš„æƒ¯ä¾‹ï¼š
619 680
620 如果函数的åå­—æ˜¯ä¸€ä¸ªåŠ¨ä½œæˆ–è€…å¼ºåˆ¶æ€§çš„å‘½ä»¤ï¼Œé‚£ä¹ˆè¿™ä¸ªå‡½æ•°åº”è¯¥è¿”å›žé”™è¯¯ä»£ç æ•´ 681 如果函数的åå­—æ˜¯ä¸€ä¸ªåŠ¨ä½œæˆ–è€…å¼ºåˆ¶æ€§çš„å‘½ä»¤ï¼Œé‚£ä¹ˆè¿™ä¸ªå‡½æ•°åº”è¯¥è¿”å›žé”™è¯¯ä»£ç æ•´
621 数。如果是一个判断,那么函数应该返回一个“æˆåŠŸâ€å¸ƒå°”值。 682 数。如果是一个判断,那么函数应该返回一个“æˆåŠŸâ€å¸ƒå°”值。
622 683
623比如,“add workâ€æ˜¯ä¸€ä¸ªå‘½ä»¤ï¼Œæ‰€ä»¥add_work()函数在æˆåŠŸæ—¶è¿”å›ž0,在失败时返回-EBUSY。 684比如,“add work†是一个命令,所以 add_work() 函数在æˆåŠŸæ—¶è¿”å›ž 0,在失败时返回 -EBUSY。
624类似的,因为“PCI device presentâ€æ˜¯ä¸€ä¸ªåˆ¤æ–­ï¼Œæ‰€ä»¥pci_dev_present()函数在æˆåŠŸæ‰¾åˆ° 685类似的,因为 “PCI device present†是一个判断,所以 pci_dev_present() 函数在æˆåŠŸæ‰¾åˆ°
625一个匹é…的设备时应该返回1,如果找ä¸åˆ°æ—¶åº”该返回0。 686一个匹é…的设备时应该返回 1,如果找ä¸åˆ°æ—¶åº”该返回 0。
626 687
627所有导出(译注:EXPORT)的函数都必须éµå®ˆè¿™ä¸ªæƒ¯ä¾‹ï¼Œæ‰€æœ‰çš„å…¬å…±å‡½æ•°ä¹Ÿéƒ½åº”è¯¥å¦‚æ­¤ã€‚ç§ 688所有导出(译注:EXPORT)的函数都必须éµå®ˆè¿™ä¸ªæƒ¯ä¾‹ï¼Œæ‰€æœ‰çš„公共函数也都应该如此。ç§
628有(static)函数ä¸éœ€è¦å¦‚此,但是我们也推è这样åšã€‚ 689有(static)函数ä¸éœ€è¦å¦‚此,但是我们也推è这样åšã€‚
629 690
630è¿”å›žå€¼æ˜¯å®žé™…è®¡ç®—ç»“æžœè€Œä¸æ˜¯è®¡ç®—æ˜¯å¦æˆåŠŸçš„æ ‡å¿—çš„å‡½æ•°ä¸å—此惯例的é™åˆ¶ã€‚一般的,他们 691è¿”å›žå€¼æ˜¯å®žé™…è®¡ç®—ç»“æžœè€Œä¸æ˜¯è®¡ç®—æ˜¯å¦æˆåŠŸçš„æ ‡å¿—çš„å‡½æ•°ä¸å—此惯例的é™åˆ¶ã€‚一般的,他们
631通过返回一些正常值范围之外的结果æ¥è¡¨ç¤ºå‡ºé”™ã€‚å…¸åž‹çš„ä¾‹å­æ˜¯è¿”回指针的函数,他们使用 692通过返回一些正常值范围之外的结果æ¥è¡¨ç¤ºå‡ºé”™ã€‚å…¸åž‹çš„ä¾‹å­æ˜¯è¿”回指针的函数,他们使用
632NULL或者ERR_PTRæœºåˆ¶æ¥æŠ¥å‘Šé”™è¯¯ã€‚ 693NULL 或者 ERR_PTR æœºåˆ¶æ¥æŠ¥å‘Šé”™è¯¯ã€‚
633 694
634 695
635 第å七章:ä¸è¦é‡æ–°å‘æ˜Žå†…æ ¸å® 696 第å七章:ä¸è¦é‡æ–°å‘明内核å®
636 697
637头文件include/linux/kernel.h包å«äº†ä¸€äº›å®ï¼Œä½ åº”该使用它们,而ä¸è¦è‡ªå·±å†™ä¸€äº›å®ƒä»¬çš„ 698头文件 include/linux/kernel.h 包å«äº†ä¸€äº›å®ï¼Œä½ åº”该使用它们,而ä¸è¦è‡ªå·±å†™ä¸€äº›å®ƒä»¬çš„
638å˜ç§ã€‚比如,如果你需è¦è®¡ç®—ä¸€ä¸ªæ•°ç»„çš„é•¿åº¦ï¼Œä½¿ç”¨è¿™ä¸ªå® 699å˜ç§ã€‚比如,如果你需è¦è®¡ç®—一个数组的长度,使用这个å®
639 700
640 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 701 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
641 702
642类似的,如果你è¦è®¡ç®—æŸç»“构体æˆå‘˜çš„大å°ï¼Œä½¿ç”¨ 703类似的,如果你è¦è®¡ç®—æŸç»“构体æˆå‘˜çš„大å°ï¼Œä½¿ç”¨
643 704
644 #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) 705 #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
645 706
646还有å¯ä»¥åšä¸¥æ ¼çš„类型检查的min()å’Œmax()å®ï¼Œå¦‚果你需è¦å¯ä»¥ä½¿ç”¨å®ƒä»¬ã€‚ä½ å¯ä»¥è‡ªå·±çœ‹çœ‹ 707还有å¯ä»¥åšä¸¥æ ¼çš„类型检查的 min() å’Œ max() å®ï¼Œå¦‚果你需è¦å¯ä»¥ä½¿ç”¨å®ƒä»¬ã€‚ä½ å¯ä»¥è‡ªå·±çœ‹çœ‹
647那个头文件里还定义了什么你å¯ä»¥æ‹¿æ¥ç”¨çš„东西,如果有定义的è¯ï¼Œä½ å°±ä¸åº”在你的代ç é‡Œ 708那个头文件里还定义了什么你å¯ä»¥æ‹¿æ¥ç”¨çš„东西,如果有定义的è¯ï¼Œä½ å°±ä¸åº”在你的代ç é‡Œ
648è‡ªå·±é‡æ–°å®šä¹‰ã€‚ 709è‡ªå·±é‡æ–°å®šä¹‰ã€‚
649 710
@@ -653,42 +714,100 @@ NULL或者ERR_PTRæœºåˆ¶æ¥æŠ¥å‘Šé”™è¯¯ã€‚
653有一些编辑器å¯ä»¥è§£é‡ŠåµŒå…¥åœ¨æºæ–‡ä»¶é‡Œçš„由一些特殊标记标明的é…置信æ¯ã€‚比如,emacs 714有一些编辑器å¯ä»¥è§£é‡ŠåµŒå…¥åœ¨æºæ–‡ä»¶é‡Œçš„由一些特殊标记标明的é…置信æ¯ã€‚比如,emacs
654能够解释被标记æˆè¿™æ ·çš„行: 715能够解释被标记æˆè¿™æ ·çš„行:
655 716
656-*- mode: c -*- 717 -*- mode: c -*-
657 718
658或者这样的: 719或者这样的:
659 720
660/* 721 /*
661Local Variables: 722 Local Variables:
662compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c" 723 compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"
663End: 724 End:
664*/ 725 */
665 726
666Vim能够解释这样的标记: 727Vim 能够解释这样的标记:
667 728
668/* vim:set sw=8 noet */ 729 /* vim:set sw=8 noet */
669 730
670ä¸è¦åœ¨æºä»£ç ä¸­åŒ…å«ä»»ä½•这样的内容。æ¯ä¸ªäººéƒ½æœ‰ä»–自己的编辑器é…ç½®ï¼Œä½ çš„æºæ–‡ä»¶ä¸åº” 731ä¸è¦åœ¨æºä»£ç ä¸­åŒ…å«ä»»ä½•这样的内容。æ¯ä¸ªäººéƒ½æœ‰ä»–自己的编辑器é…ç½®ï¼Œä½ çš„æºæ–‡ä»¶ä¸åº”
671该覆盖别人的é…置。这包括有关缩进和模å¼é…置的标记。人们å¯ä»¥ä½¿ç”¨ä»–们自己定制的模 732该覆盖别人的é…置。这包括有关缩进和模å¼é…置的标记。人们å¯ä»¥ä½¿ç”¨ä»–们自己定制的模
672å¼ï¼Œæˆ–者使用其他å¯ä»¥äº§ç”Ÿæ­£ç¡®çš„缩进的巧妙方法。 733å¼ï¼Œæˆ–者使用其他å¯ä»¥äº§ç”Ÿæ­£ç¡®çš„缩进的巧妙方法。
673 734
674 735
736 第åä¹ç« ï¼šå†…è”æ±‡ç¼–
737
738在特定架构的代ç ä¸­ï¼Œä½ ä¹Ÿè®¸éœ€è¦å†…è”æ±‡ç¼–æ¥ä½¿ç”¨ CPU 接å£å’Œå¹³å°ç›¸å…³åŠŸèƒ½ã€‚åœ¨éœ€è¦
739è¿™ä¹ˆåšæ—¶ï¼Œä¸è¦çŠ¹è±«ã€‚ç„¶è€Œï¼Œå½“ C å¯ä»¥å®Œæˆå·¥ä½œæ—¶ï¼Œä¸è¦æ— ç«¯åœ°ä½¿ç”¨å†…è”æ±‡ç¼–。如果
740å¯èƒ½ï¼Œä½ å¯ä»¥å¹¶ä¸”应该用 C 和硬件交互。
741
742è€ƒè™‘åŽ»å†™é€šç”¨ä¸€ç‚¹çš„å†…è”æ±‡ç¼–ä½œä¸ºç®€æ˜Žçš„è¾…åŠ©å‡½æ•°ï¼Œè€Œä¸æ˜¯é‡å¤å†™ä¸‹å®ƒä»¬çš„细节。记ä½
743å†…è”æ±‡ç¼–å¯ä»¥ä½¿ç”¨ C 傿•°ã€‚
744
745大而特殊的汇编函数应该放在 .S 文件中,对应 C 的原型定义在 C 头文件中。汇编
746函数的 C 原型应该使用 “asmlinkageâ€ã€‚
747
748ä½ å¯èƒ½éœ€è¦å°†ä½ çš„æ±‡ç¼–è¯­å¥æ ‡è®°ä¸º volatile,æ¥é˜»æ­¢ GCC 在没å‘现任何副作用åŽå°±
749移除了它。你ä¸å¿…总是这样åšï¼Œè™½ç„¶ï¼Œè¿™æ ·å¯ä»¥é™åˆ¶ä¸å¿…è¦çš„优化。
750
751在写一个包å«å¤šæ¡æŒ‡ä»¤çš„å•ä¸ªå†…è”æ±‡ç¼–è¯­å¥æ—¶ï¼ŒæŠŠæ¯æ¡æŒ‡ä»¤ç”¨å¼•å·å­—符串分离,并写在
752å•独一行,在æ¯ä¸ªå­—符串结尾,除了 \n\t 结尾之外,在汇编输出中适当地缩进下
753ä¸€æ¡æŒ‡ä»¤ï¼š
754
755 asm ("magic %reg1, #42\n\t"
756 "more_magic %reg2, %reg3"
757 : /* outputs */ : /* inputs */ : /* clobbers */);
758
759
760 第二å章:æ¡ä»¶ç¼–译
761
762åªè¦å¯èƒ½ï¼Œå°±ä¸è¦åœ¨ .c 文件里é¢ä½¿ç”¨é¢„å¤„ç†æ¡ä»¶ï¼›è¿™æ ·åšè®©ä»£ç æ›´éš¾é˜…读并且逻辑难以
763跟踪。替代方案是,在头文件定义函数在这些 .c 文件中使用这类的æ¡ä»¶è¡¨è¾¾å¼ï¼Œæä¾›ç©º
764æ“作的桩版本(译注:桩程åºï¼Œæ˜¯æŒ‡ç”¨æ¥æ›¿æ¢ä¸€éƒ¨åˆ†åŠŸèƒ½çš„ç¨‹åºæ®µï¼‰åœ¨ #else 情况下,
765å†ä»Ž .c 文件中无æ¡ä»¶åœ°è°ƒç”¨è¿™äº›å‡½æ•°ã€‚编译器会é¿å…生æˆä»»ä½•桩调用的代ç ï¼Œäº§ç”Ÿä¸€è‡´
766的结果,但逻辑将更加清晰。
767
768å®å¯ç¼–è¯‘æ•´ä¸ªå‡½æ•°ï¼Œè€Œä¸æ˜¯éƒ¨åˆ†å‡½æ•°æˆ–部分表达å¼ã€‚è€Œä¸æ˜¯åœ¨ä¸€ä¸ªè¡¨è¾¾å¼æ·»åŠ  ifdef,
769è§£æžéƒ¨åˆ†æˆ–全部表达å¼åˆ°ä¸€ä¸ªå•独的辅助函数,并应用æ¡ä»¶åˆ°è¯¥å‡½æ•°å†…。
770
771如果你有一个在特定é…置中å¯èƒ½æ˜¯æœªä½¿ç”¨çš„函数或å˜é‡ï¼Œç¼–译器将警告它定义了但未使用,
772标记这个定义为 __maybe_unused è€Œä¸æ˜¯å°†å®ƒåŒ…å«åœ¨ä¸€ä¸ªé¢„å¤„ç†æ¡ä»¶ä¸­ã€‚(然而,如果
773一个函数或å˜é‡æ€»æ˜¯æœªä½¿ç”¨çš„,就直接删除它。)
774
775在代ç ä¸­ï¼Œå¯èƒ½çš„æƒ…况下,使用 IS_ENABLED 宿¥è½¬åŒ–æŸä¸ª Kconfig 标记为 C 的布尔
776表达å¼ï¼Œå¹¶åœ¨æ­£å¸¸çš„ C æ¡ä»¶ä¸­ä½¿ç”¨å®ƒï¼š
777
778 if (IS_ENABLED(CONFIG_SOMETHING)) {
779 ...
780 }
781
782编译器会无æ¡ä»¶åœ°åšå¸¸æ•°åˆå¹¶ï¼Œå°±åƒä½¿ç”¨ #ifdef é‚£æ ·ï¼ŒåŒ…å«æˆ–排除代ç å—,所以这ä¸ä¼š
783带æ¥ä»»ä½•è¿è¡Œæ—¶å¼€é”€ã€‚ç„¶è€Œï¼Œè¿™ç§æ–¹æ³•便—§å…许 C 编译器查看å—内的代ç ï¼Œå¹¶æ£€æŸ¥å®ƒçš„æ­£ç¡®
784性(语法,类型,符å·å¼•用,等等)。因此,如果æ¡ä»¶ä¸æ»¡è¶³ï¼Œä»£ç å—内的引用符å·å°†ä¸å­˜åœ¨ï¼Œ
785你必须继续使用 #ifdef。
786
787在任何有æ„义的 #if 或 #ifdef å—的末尾(超过几行),在 #endif åŒä¸€è¡Œçš„åŽé¢å†™ä¸‹
788注释,指出该æ¡ä»¶è¡¨è¾¾å¼è¢«ä½¿ç”¨ã€‚例如:
789
790 #ifdef CONFIG_SOMETHING
791 ...
792 #endif /* CONFIG_SOMETHING */
793
675 794
676 附录 I:å‚考 795 附录 I:å‚考
677 796
678The C Programming Language, 第二版, 作者Brian W. Kernighan和Denni 797The C Programming Language, 第二版
679M. Ritchie. Prentice Hall, Inc., 1988. ISBN 0-13-110362-8 (软皮), 798作者:Brian W. Kernighan 和 Denni M. Ritchie.
6800-13-110370-9 (硬皮). URL: http://cm.bell-labs.com/cm/cs/cbook/ 799Prentice Hall, Inc., 1988.
800ISBN 0-13-110362-8 (软皮), 0-13-110370-9 (硬皮).
681 801
682The Practice of Programming 作者Brian W. Kernighan和Rob Pike. Addison-Wesley, 802The Practice of Programming
683Inc., 1999. ISBN 0-201-61586-X. URL: http://cm.bell-labs.com/cm/cs/tpop/ 803作者:Brian W. Kernighan 和 Rob Pike.
804Addison-Wesley, Inc., 1999.
805ISBN 0-201-61586-X.
684 806
685cpp,gcc,gcc internalså’Œindentçš„GNU手册——和K&RåŠæœ¬æ–‡ç›¸ç¬¦åˆçš„部分,全部å¯ä»¥åœ¨ 807GNU 手册 - éµå¾ª K&R 标准和此文本 - cpp, gcc, gcc internals and indent,
686http://www.gnu.org/manual/找到 808都å¯ä»¥ä»Ž http://www.gnu.org/manual/ 找到
687 809
688WG14是C语言的国际标准化工作组,URL: http://www.open-std.org/JTC1/SC22/WG14/ 810WG14是C语言的国际标准化工作组,URL: http://www.open-std.org/JTC1/SC22/WG14/
689 811
690Kernel CodingStyle,作者greg@kroah.comå‘表于OLS 2002: 812Kernel CodingStyle,作者 greg@kroah.com å‘表于OLS 2002:
691http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/ 813http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
692
693--
694æœ€åŽæ›´æ–°äºŽ2007å¹´7月13日。
diff --git a/Makefile b/Makefile
index 8d1301ab59fd..801457b847a4 100644
--- a/Makefile
+++ b/Makefile
@@ -1412,8 +1412,11 @@ $(help-board-dirs): help-%:
1412 1412
1413# Documentation targets 1413# Documentation targets
1414# --------------------------------------------------------------------------- 1414# ---------------------------------------------------------------------------
1415%docs: scripts_basic FORCE 1415DOC_TARGETS := xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs epubdocs cleandocs
1416PHONY += $(DOC_TARGETS)
1417$(DOC_TARGETS): scripts_basic FORCE
1416 $(Q)$(MAKE) $(build)=scripts build_docproc build_check-lc_ctype 1418 $(Q)$(MAKE) $(build)=scripts build_docproc build_check-lc_ctype
1419 $(Q)$(MAKE) $(build)=Documentation -f $(srctree)/Documentation/Makefile.sphinx $@
1417 $(Q)$(MAKE) $(build)=Documentation/DocBook $@ 1420 $(Q)$(MAKE) $(build)=Documentation/DocBook $@
1418 1421
1419else # KBUILD_EXTMOD 1422else # KBUILD_EXTMOD
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 2fc8fad5195e..27757c21551a 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -59,6 +59,12 @@ Output format selection (mutually exclusive):
59 -text Output plain text format. 59 -text Output plain text format.
60 60
61Output selection (mutually exclusive): 61Output selection (mutually exclusive):
62 -export Only output documentation for symbols that have been
63 exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL()
64 in the same FILE.
65 -internal Only output documentation for symbols that have NOT been
66 exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL()
67 in the same FILE.
62 -function NAME Only output documentation for the given function(s) 68 -function NAME Only output documentation for the given function(s)
63 or DOC: section title(s). All other functions and DOC: 69 or DOC: section title(s). All other functions and DOC:
64 sections are ignored. May be specified multiple times. 70 sections are ignored. May be specified multiple times.
@@ -68,6 +74,8 @@ Output selection (mutually exclusive):
68 74
69Output selection modifiers: 75Output selection modifiers:
70 -no-doc-sections Do not output DOC: sections. 76 -no-doc-sections Do not output DOC: sections.
77 -enable-lineno Enable output of #define LINENO lines. Only works with
78 reStructuredText format.
71 79
72Other parameters: 80Other parameters:
73 -v Verbose output, more warnings and other information. 81 -v Verbose output, more warnings and other information.
@@ -206,6 +214,10 @@ my $type_struct_xml = '\\&amp;((struct\s*)*[_\w]+)';
206my $type_env = '(\$\w+)'; 214my $type_env = '(\$\w+)';
207my $type_enum_full = '\&(enum)\s*([_\w]+)'; 215my $type_enum_full = '\&(enum)\s*([_\w]+)';
208my $type_struct_full = '\&(struct)\s*([_\w]+)'; 216my $type_struct_full = '\&(struct)\s*([_\w]+)';
217my $type_typedef_full = '\&(typedef)\s*([_\w]+)';
218my $type_union_full = '\&(union)\s*([_\w]+)';
219my $type_member = '\&([_\w]+)((\.|->)[_\w]+)';
220my $type_member_func = $type_member . '\(\)';
209 221
210# Output conversion substitutions. 222# Output conversion substitutions.
211# One for each output format 223# One for each output format
@@ -274,10 +286,16 @@ my $blankline_text = "";
274# rst-mode 286# rst-mode
275my @highlights_rst = ( 287my @highlights_rst = (
276 [$type_constant, "``\$1``"], 288 [$type_constant, "``\$1``"],
277 [$type_func, "\\:c\\:func\\:`\$1`"], 289 # Note: need to escape () to avoid func matching later
290 [$type_member_func, "\\:c\\:type\\:`\$1\$2\\\\(\\\\) <\$1>`"],
291 [$type_member, "\\:c\\:type\\:`\$1\$2 <\$1>`"],
292 [$type_func, "\\:c\\:func\\:`\$1()`"],
278 [$type_struct_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], 293 [$type_struct_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"],
279 [$type_enum_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], 294 [$type_enum_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"],
280 [$type_struct, "\\:c\\:type\\:`struct \$1 <\$1>`"], 295 [$type_typedef_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"],
296 [$type_union_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"],
297 # in rst this can refer to any type
298 [$type_struct, "\\:c\\:type\\:`\$1`"],
281 [$type_param, "**\$1**"] 299 [$type_param, "**\$1**"]
282 ); 300 );
283my $blankline_rst = "\n"; 301my $blankline_rst = "\n";
@@ -303,10 +321,19 @@ my $verbose = 0;
303my $output_mode = "man"; 321my $output_mode = "man";
304my $output_preformatted = 0; 322my $output_preformatted = 0;
305my $no_doc_sections = 0; 323my $no_doc_sections = 0;
324my $enable_lineno = 0;
306my @highlights = @highlights_man; 325my @highlights = @highlights_man;
307my $blankline = $blankline_man; 326my $blankline = $blankline_man;
308my $modulename = "Kernel API"; 327my $modulename = "Kernel API";
309my $function_only = 0; 328
329use constant {
330 OUTPUT_ALL => 0, # output all symbols and doc sections
331 OUTPUT_INCLUDE => 1, # output only specified symbols
332 OUTPUT_EXCLUDE => 2, # output everything except specified symbols
333 OUTPUT_EXPORTED => 3, # output exported symbols
334 OUTPUT_INTERNAL => 4, # output non-exported symbols
335};
336my $output_selection = OUTPUT_ALL;
310my $show_not_found = 0; 337my $show_not_found = 0;
311 338
312my @build_time; 339my @build_time;
@@ -327,6 +354,7 @@ my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
327# CAVEAT EMPTOR! Some of the others I localised may not want to be, which 354# CAVEAT EMPTOR! Some of the others I localised may not want to be, which
328# could cause "use of undefined value" or other bugs. 355# could cause "use of undefined value" or other bugs.
329my ($function, %function_table, %parametertypes, $declaration_purpose); 356my ($function, %function_table, %parametertypes, $declaration_purpose);
357my $declaration_start_line;
330my ($type, $declaration_name, $return_type); 358my ($type, $declaration_name, $return_type);
331my ($newsection, $newcontents, $prototype, $brcount, %source_map); 359my ($newsection, $newcontents, $prototype, $brcount, %source_map);
332 360
@@ -344,52 +372,62 @@ my $section_counter = 0;
344 372
345my $lineprefix=""; 373my $lineprefix="";
346 374
347# states 375# Parser states
348# 0 - normal code 376use constant {
349# 1 - looking for function name 377 STATE_NORMAL => 0, # normal code
350# 2 - scanning field start. 378 STATE_NAME => 1, # looking for function name
351# 3 - scanning prototype. 379 STATE_FIELD => 2, # scanning field start
352# 4 - documentation block 380 STATE_PROTO => 3, # scanning prototype
353# 5 - gathering documentation outside main block 381 STATE_DOCBLOCK => 4, # documentation block
382 STATE_INLINE => 5, # gathering documentation outside main block
383};
354my $state; 384my $state;
355my $in_doc_sect; 385my $in_doc_sect;
356 386
357# Split Doc State 387# Inline documentation state
358# 0 - Invalid (Before start or after finish) 388use constant {
359# 1 - Is started (the /** was found inside a struct) 389 STATE_INLINE_NA => 0, # not applicable ($state != STATE_INLINE)
360# 2 - The @parameter header was found, start accepting multi paragraph text. 390 STATE_INLINE_NAME => 1, # looking for member name (@foo:)
361# 3 - Finished (the */ was found) 391 STATE_INLINE_TEXT => 2, # looking for member documentation
362# 4 - Error - Comment without header was found. Spit a warning as it's not 392 STATE_INLINE_END => 3, # done
363# proper kernel-doc and ignore the rest. 393 STATE_INLINE_ERROR => 4, # error - Comment without header was found.
364my $split_doc_state; 394 # Spit a warning as it's not
395 # proper kernel-doc and ignore the rest.
396};
397my $inline_doc_state;
365 398
366#declaration types: can be 399#declaration types: can be
367# 'function', 'struct', 'union', 'enum', 'typedef' 400# 'function', 'struct', 'union', 'enum', 'typedef'
368my $decl_type; 401my $decl_type;
369 402
370my $doc_special = "\@\%\$\&";
371
372my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start. 403my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start.
373my $doc_end = '\*/'; 404my $doc_end = '\*/';
374my $doc_com = '\s*\*\s*'; 405my $doc_com = '\s*\*\s*';
375my $doc_com_body = '\s*\* ?'; 406my $doc_com_body = '\s*\* ?';
376my $doc_decl = $doc_com . '(\w+)'; 407my $doc_decl = $doc_com . '(\w+)';
377my $doc_sect = $doc_com . '([' . $doc_special . ']?[\w\s]+):(.*)'; 408# @params and a strictly limited set of supported section names
409my $doc_sect = $doc_com .
410 '\s*(\@\w+|description|context|returns?|notes?|examples?)\s*:(.*)';
378my $doc_content = $doc_com_body . '(.*)'; 411my $doc_content = $doc_com_body . '(.*)';
379my $doc_block = $doc_com . 'DOC:\s*(.*)?'; 412my $doc_block = $doc_com . 'DOC:\s*(.*)?';
380my $doc_split_start = '^\s*/\*\*\s*$'; 413my $doc_inline_start = '^\s*/\*\*\s*$';
381my $doc_split_sect = '\s*\*\s*(@[\w\s]+):(.*)'; 414my $doc_inline_sect = '\s*\*\s*(@[\w\s]+):(.*)';
382my $doc_split_end = '^\s*\*/\s*$'; 415my $doc_inline_end = '^\s*\*/\s*$';
416my $export_symbol = '^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*;';
383 417
384my %constants;
385my %parameterdescs; 418my %parameterdescs;
419my %parameterdesc_start_lines;
386my @parameterlist; 420my @parameterlist;
387my %sections; 421my %sections;
388my @sectionlist; 422my @sectionlist;
423my %section_start_lines;
389my $sectcheck; 424my $sectcheck;
390my $struct_actual; 425my $struct_actual;
391 426
392my $contents = ""; 427my $contents = "";
428my $new_start_line = 0;
429
430# the canonical section names. see also $doc_sect above.
393my $section_default = "Description"; # default section 431my $section_default = "Description"; # default section
394my $section_intro = "Introduction"; 432my $section_intro = "Introduction";
395my $section = $section_default; 433my $section = $section_default;
@@ -437,19 +475,27 @@ while ($ARGV[0] =~ m/^-(.*)/) {
437 } elsif ($cmd eq "-module") { # not needed for XML, inherits from calling document 475 } elsif ($cmd eq "-module") { # not needed for XML, inherits from calling document
438 $modulename = shift @ARGV; 476 $modulename = shift @ARGV;
439 } elsif ($cmd eq "-function") { # to only output specific functions 477 } elsif ($cmd eq "-function") { # to only output specific functions
440 $function_only = 1; 478 $output_selection = OUTPUT_INCLUDE;
441 $function = shift @ARGV; 479 $function = shift @ARGV;
442 $function_table{$function} = 1; 480 $function_table{$function} = 1;
443 } elsif ($cmd eq "-nofunction") { # to only output specific functions 481 } elsif ($cmd eq "-nofunction") { # output all except specific functions
444 $function_only = 2; 482 $output_selection = OUTPUT_EXCLUDE;
445 $function = shift @ARGV; 483 $function = shift @ARGV;
446 $function_table{$function} = 1; 484 $function_table{$function} = 1;
485 } elsif ($cmd eq "-export") { # only exported symbols
486 $output_selection = OUTPUT_EXPORTED;
487 %function_table = ()
488 } elsif ($cmd eq "-internal") { # only non-exported symbols
489 $output_selection = OUTPUT_INTERNAL;
490 %function_table = ()
447 } elsif ($cmd eq "-v") { 491 } elsif ($cmd eq "-v") {
448 $verbose = 1; 492 $verbose = 1;
449 } elsif (($cmd eq "-h") || ($cmd eq "--help")) { 493 } elsif (($cmd eq "-h") || ($cmd eq "--help")) {
450 usage(); 494 usage();
451 } elsif ($cmd eq '-no-doc-sections') { 495 } elsif ($cmd eq '-no-doc-sections') {
452 $no_doc_sections = 1; 496 $no_doc_sections = 1;
497 } elsif ($cmd eq '-enable-lineno') {
498 $enable_lineno = 1;
453 } elsif ($cmd eq '-show-not-found') { 499 } elsif ($cmd eq '-show-not-found') {
454 $show_not_found = 1; 500 $show_not_found = 1;
455 } 501 }
@@ -467,6 +513,13 @@ sub get_kernel_version() {
467 return $version; 513 return $version;
468} 514}
469 515
516#
517sub print_lineno {
518 my $lineno = shift;
519 if ($enable_lineno && defined($lineno)) {
520 print "#define LINENO " . $lineno . "\n";
521 }
522}
470## 523##
471# dumps section contents to arrays/hashes intended for that purpose. 524# dumps section contents to arrays/hashes intended for that purpose.
472# 525#
@@ -475,28 +528,32 @@ sub dump_section {
475 my $name = shift; 528 my $name = shift;
476 my $contents = join "\n", @_; 529 my $contents = join "\n", @_;
477 530
478 if ($name =~ m/$type_constant/) { 531 if ($name =~ m/$type_param/) {
479 $name = $1;
480# print STDERR "constant section '$1' = '$contents'\n";
481 $constants{$name} = $contents;
482 } elsif ($name =~ m/$type_param/) {
483# print STDERR "parameter def '$1' = '$contents'\n"; 532# print STDERR "parameter def '$1' = '$contents'\n";
484 $name = $1; 533 $name = $1;
485 $parameterdescs{$name} = $contents; 534 $parameterdescs{$name} = $contents;
486 $sectcheck = $sectcheck . $name . " "; 535 $sectcheck = $sectcheck . $name . " ";
536 $parameterdesc_start_lines{$name} = $new_start_line;
537 $new_start_line = 0;
487 } elsif ($name eq "@\.\.\.") { 538 } elsif ($name eq "@\.\.\.") {
488# print STDERR "parameter def '...' = '$contents'\n"; 539# print STDERR "parameter def '...' = '$contents'\n";
489 $name = "..."; 540 $name = "...";
490 $parameterdescs{$name} = $contents; 541 $parameterdescs{$name} = $contents;
491 $sectcheck = $sectcheck . $name . " "; 542 $sectcheck = $sectcheck . $name . " ";
543 $parameterdesc_start_lines{$name} = $new_start_line;
544 $new_start_line = 0;
492 } else { 545 } else {
493# print STDERR "other section '$name' = '$contents'\n"; 546# print STDERR "other section '$name' = '$contents'\n";
494 if (defined($sections{$name}) && ($sections{$name} ne "")) { 547 if (defined($sections{$name}) && ($sections{$name} ne "")) {
495 print STDERR "${file}:$.: error: duplicate section name '$name'\n"; 548 print STDERR "${file}:$.: warning: duplicate section name '$name'\n";
496 ++$errors; 549 ++$warnings;
550 $sections{$name} .= $contents;
551 } else {
552 $sections{$name} = $contents;
553 push @sectionlist, $name;
554 $section_start_lines{$name} = $new_start_line;
555 $new_start_line = 0;
497 } 556 }
498 $sections{$name} = $contents;
499 push @sectionlist, $name;
500 } 557 }
501} 558}
502 559
@@ -512,15 +569,17 @@ sub dump_doc_section {
512 return; 569 return;
513 } 570 }
514 571
515 if (($function_only == 0) || 572 if (($output_selection == OUTPUT_ALL) ||
516 ( $function_only == 1 && defined($function_table{$name})) || 573 ($output_selection == OUTPUT_INCLUDE &&
517 ( $function_only == 2 && !defined($function_table{$name}))) 574 defined($function_table{$name})) ||
575 ($output_selection == OUTPUT_EXCLUDE &&
576 !defined($function_table{$name})))
518 { 577 {
519 dump_section($file, $name, $contents); 578 dump_section($file, $name, $contents);
520 output_blockhead({'sectionlist' => \@sectionlist, 579 output_blockhead({'sectionlist' => \@sectionlist,
521 'sections' => \%sections, 580 'sections' => \%sections,
522 'module' => $modulename, 581 'module' => $modulename,
523 'content-only' => ($function_only != 0), }); 582 'content-only' => ($output_selection != OUTPUT_ALL), });
524 } 583 }
525} 584}
526 585
@@ -1736,7 +1795,10 @@ sub output_blockhead_rst(%) {
1736 my ($parameter, $section); 1795 my ($parameter, $section);
1737 1796
1738 foreach $section (@{$args{'sectionlist'}}) { 1797 foreach $section (@{$args{'sectionlist'}}) {
1739 print "**$section**\n\n"; 1798 if ($output_selection != OUTPUT_INCLUDE) {
1799 print "**$section**\n\n";
1800 }
1801 print_lineno($section_start_lines{$section});
1740 output_highlight_rst($args{'sections'}{$section}); 1802 output_highlight_rst($args{'sections'}{$section});
1741 print "\n"; 1803 print "\n";
1742 } 1804 }
@@ -1753,19 +1815,14 @@ sub output_highlight_rst {
1753 die $@ if $@; 1815 die $@ if $@;
1754 1816
1755 foreach $line (split "\n", $contents) { 1817 foreach $line (split "\n", $contents) {
1756 if ($line eq "") { 1818 print $lineprefix . $line . "\n";
1757 print $lineprefix, $blankline;
1758 } else {
1759 $line =~ s/\\\\\\/\&/g;
1760 print $lineprefix, $line;
1761 }
1762 print "\n";
1763 } 1819 }
1764} 1820}
1765 1821
1766sub output_function_rst(%) { 1822sub output_function_rst(%) {
1767 my %args = %{$_[0]}; 1823 my %args = %{$_[0]};
1768 my ($parameter, $section); 1824 my ($parameter, $section);
1825 my $oldprefix = $lineprefix;
1769 my $start; 1826 my $start;
1770 1827
1771 print ".. c:function:: "; 1828 print ".. c:function:: ";
@@ -1790,29 +1847,37 @@ sub output_function_rst(%) {
1790 print $type . " " . $parameter; 1847 print $type . " " . $parameter;
1791 } 1848 }
1792 } 1849 }
1793 print ")\n\n " . $args{'purpose'} . "\n\n"; 1850 print ")\n\n";
1851 print_lineno($declaration_start_line);
1852 $lineprefix = " ";
1853 output_highlight_rst($args{'purpose'});
1854 print "\n";
1794 1855
1795 print ":Parameters:\n\n"; 1856 print "**Parameters**\n\n";
1857 $lineprefix = " ";
1796 foreach $parameter (@{$args{'parameterlist'}}) { 1858 foreach $parameter (@{$args{'parameterlist'}}) {
1797 my $parameter_name = $parameter; 1859 my $parameter_name = $parameter;
1798 #$parameter_name =~ s/\[.*//; 1860 #$parameter_name =~ s/\[.*//;
1799 $type = $args{'parametertypes'}{$parameter}; 1861 $type = $args{'parametertypes'}{$parameter};
1800 1862
1801 if ($type ne "") { 1863 if ($type ne "") {
1802 print " ``$type $parameter``\n"; 1864 print "``$type $parameter``\n";
1803 } else { 1865 } else {
1804 print " ``$parameter``\n"; 1866 print "``$parameter``\n";
1805 } 1867 }
1806 if ($args{'parameterdescs'}{$parameter_name} ne $undescribed) { 1868
1807 my $oldprefix = $lineprefix; 1869 print_lineno($parameterdesc_start_lines{$parameter_name});
1808 $lineprefix = " "; 1870
1871 if (defined($args{'parameterdescs'}{$parameter_name}) &&
1872 $args{'parameterdescs'}{$parameter_name} ne $undescribed) {
1809 output_highlight_rst($args{'parameterdescs'}{$parameter_name}); 1873 output_highlight_rst($args{'parameterdescs'}{$parameter_name});
1810 $lineprefix = $oldprefix;
1811 } else { 1874 } else {
1812 print "\n _undescribed_\n"; 1875 print " *undescribed*\n";
1813 } 1876 }
1814 print "\n"; 1877 print "\n";
1815 } 1878 }
1879
1880 $lineprefix = $oldprefix;
1816 output_section_rst(@_); 1881 output_section_rst(@_);
1817} 1882}
1818 1883
@@ -1820,10 +1885,11 @@ sub output_section_rst(%) {
1820 my %args = %{$_[0]}; 1885 my %args = %{$_[0]};
1821 my $section; 1886 my $section;
1822 my $oldprefix = $lineprefix; 1887 my $oldprefix = $lineprefix;
1823 $lineprefix = " "; 1888 $lineprefix = "";
1824 1889
1825 foreach $section (@{$args{'sectionlist'}}) { 1890 foreach $section (@{$args{'sectionlist'}}) {
1826 print ":$section:\n\n"; 1891 print "**$section**\n\n";
1892 print_lineno($section_start_lines{$section});
1827 output_highlight_rst($args{'sections'}{$section}); 1893 output_highlight_rst($args{'sections'}{$section});
1828 print "\n"; 1894 print "\n";
1829 } 1895 }
@@ -1834,24 +1900,28 @@ sub output_section_rst(%) {
1834sub output_enum_rst(%) { 1900sub output_enum_rst(%) {
1835 my %args = %{$_[0]}; 1901 my %args = %{$_[0]};
1836 my ($parameter); 1902 my ($parameter);
1903 my $oldprefix = $lineprefix;
1837 my $count; 1904 my $count;
1838 my $name = "enum " . $args{'enum'}; 1905 my $name = "enum " . $args{'enum'};
1839 1906
1840 print "\n\n.. c:type:: " . $name . "\n\n"; 1907 print "\n\n.. c:type:: " . $name . "\n\n";
1841 print " " . $args{'purpose'} . "\n\n"; 1908 print_lineno($declaration_start_line);
1909 $lineprefix = " ";
1910 output_highlight_rst($args{'purpose'});
1911 print "\n";
1842 1912
1843 print "..\n\n:Constants:\n\n"; 1913 print "**Constants**\n\n";
1844 my $oldprefix = $lineprefix; 1914 $lineprefix = " ";
1845 $lineprefix = " ";
1846 foreach $parameter (@{$args{'parameterlist'}}) { 1915 foreach $parameter (@{$args{'parameterlist'}}) {
1847 print " `$parameter`\n"; 1916 print "``$parameter``\n";
1848 if ($args{'parameterdescs'}{$parameter} ne $undescribed) { 1917 if ($args{'parameterdescs'}{$parameter} ne $undescribed) {
1849 output_highlight_rst($args{'parameterdescs'}{$parameter}); 1918 output_highlight_rst($args{'parameterdescs'}{$parameter});
1850 } else { 1919 } else {
1851 print " undescribed\n"; 1920 print " *undescribed*\n";
1852 } 1921 }
1853 print "\n"; 1922 print "\n";
1854 } 1923 }
1924
1855 $lineprefix = $oldprefix; 1925 $lineprefix = $oldprefix;
1856 output_section_rst(@_); 1926 output_section_rst(@_);
1857} 1927}
@@ -1859,30 +1929,37 @@ sub output_enum_rst(%) {
1859sub output_typedef_rst(%) { 1929sub output_typedef_rst(%) {
1860 my %args = %{$_[0]}; 1930 my %args = %{$_[0]};
1861 my ($parameter); 1931 my ($parameter);
1862 my $count; 1932 my $oldprefix = $lineprefix;
1863 my $name = "typedef " . $args{'typedef'}; 1933 my $name = "typedef " . $args{'typedef'};
1864 1934
1865 ### FIXME: should the name below contain "typedef" or not?
1866 print "\n\n.. c:type:: " . $name . "\n\n"; 1935 print "\n\n.. c:type:: " . $name . "\n\n";
1867 print " " . $args{'purpose'} . "\n\n"; 1936 print_lineno($declaration_start_line);
1937 $lineprefix = " ";
1938 output_highlight_rst($args{'purpose'});
1939 print "\n";
1868 1940
1941 $lineprefix = $oldprefix;
1869 output_section_rst(@_); 1942 output_section_rst(@_);
1870} 1943}
1871 1944
1872sub output_struct_rst(%) { 1945sub output_struct_rst(%) {
1873 my %args = %{$_[0]}; 1946 my %args = %{$_[0]};
1874 my ($parameter); 1947 my ($parameter);
1948 my $oldprefix = $lineprefix;
1875 my $name = $args{'type'} . " " . $args{'struct'}; 1949 my $name = $args{'type'} . " " . $args{'struct'};
1876 1950
1877 print "\n\n.. c:type:: " . $name . "\n\n"; 1951 print "\n\n.. c:type:: " . $name . "\n\n";
1878 print " " . $args{'purpose'} . "\n\n"; 1952 print_lineno($declaration_start_line);
1953 $lineprefix = " ";
1954 output_highlight_rst($args{'purpose'});
1955 print "\n";
1879 1956
1880 print ":Definition:\n\n"; 1957 print "**Definition**\n\n";
1881 print " ::\n\n"; 1958 print "::\n\n";
1882 print " " . $args{'type'} . " " . $args{'struct'} . " {\n"; 1959 print " " . $args{'type'} . " " . $args{'struct'} . " {\n";
1883 foreach $parameter (@{$args{'parameterlist'}}) { 1960 foreach $parameter (@{$args{'parameterlist'}}) {
1884 if ($parameter =~ /^#/) { 1961 if ($parameter =~ /^#/) {
1885 print " " . "$parameter\n"; 1962 print " " . "$parameter\n";
1886 next; 1963 next;
1887 } 1964 }
1888 1965
@@ -1903,7 +1980,8 @@ sub output_struct_rst(%) {
1903 } 1980 }
1904 print " };\n\n"; 1981 print " };\n\n";
1905 1982
1906 print ":Members:\n\n"; 1983 print "**Members**\n\n";
1984 $lineprefix = " ";
1907 foreach $parameter (@{$args{'parameterlist'}}) { 1985 foreach $parameter (@{$args{'parameterlist'}}) {
1908 ($parameter =~ /^#/) && next; 1986 ($parameter =~ /^#/) && next;
1909 1987
@@ -1912,14 +1990,14 @@ sub output_struct_rst(%) {
1912 1990
1913 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 1991 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1914 $type = $args{'parametertypes'}{$parameter}; 1992 $type = $args{'parametertypes'}{$parameter};
1915 print " `$type $parameter`" . "\n"; 1993 print_lineno($parameterdesc_start_lines{$parameter_name});
1916 my $oldprefix = $lineprefix; 1994 print "``$type $parameter``\n";
1917 $lineprefix = " ";
1918 output_highlight_rst($args{'parameterdescs'}{$parameter_name}); 1995 output_highlight_rst($args{'parameterdescs'}{$parameter_name});
1919 $lineprefix = $oldprefix;
1920 print "\n"; 1996 print "\n";
1921 } 1997 }
1922 print "\n"; 1998 print "\n";
1999
2000 $lineprefix = $oldprefix;
1923 output_section_rst(@_); 2001 output_section_rst(@_);
1924} 2002}
1925 2003
@@ -1969,9 +2047,13 @@ sub output_declaration {
1969 my $name = shift; 2047 my $name = shift;
1970 my $functype = shift; 2048 my $functype = shift;
1971 my $func = "output_${functype}_$output_mode"; 2049 my $func = "output_${functype}_$output_mode";
1972 if (($function_only==0) || 2050 if (($output_selection == OUTPUT_ALL) ||
1973 ( $function_only == 1 && defined($function_table{$name})) || 2051 (($output_selection == OUTPUT_INCLUDE ||
1974 ( $function_only == 2 && !($functype eq "function" && defined($function_table{$name})))) 2052 $output_selection == OUTPUT_EXPORTED) &&
2053 defined($function_table{$name})) ||
2054 (($output_selection == OUTPUT_EXCLUDE ||
2055 $output_selection == OUTPUT_INTERNAL) &&
2056 !($functype eq "function" && defined($function_table{$name}))))
1975 { 2057 {
1976 &$func(@_); 2058 &$func(@_);
1977 $section_counter++; 2059 $section_counter++;
@@ -2471,7 +2553,6 @@ sub dump_function($$) {
2471 2553
2472sub reset_state { 2554sub reset_state {
2473 $function = ""; 2555 $function = "";
2474 %constants = ();
2475 %parameterdescs = (); 2556 %parameterdescs = ();
2476 %parametertypes = (); 2557 %parametertypes = ();
2477 @parameterlist = (); 2558 @parameterlist = ();
@@ -2481,8 +2562,8 @@ sub reset_state {
2481 $struct_actual = ""; 2562 $struct_actual = "";
2482 $prototype = ""; 2563 $prototype = "";
2483 2564
2484 $state = 0; 2565 $state = STATE_NORMAL;
2485 $split_doc_state = 0; 2566 $inline_doc_state = STATE_INLINE_NA;
2486} 2567}
2487 2568
2488sub tracepoint_munge($) { 2569sub tracepoint_munge($) {
@@ -2545,7 +2626,7 @@ sub syscall_munge() {
2545 } 2626 }
2546} 2627}
2547 2628
2548sub process_state3_function($$) { 2629sub process_proto_function($$) {
2549 my $x = shift; 2630 my $x = shift;
2550 my $file = shift; 2631 my $file = shift;
2551 2632
@@ -2575,7 +2656,7 @@ sub process_state3_function($$) {
2575 } 2656 }
2576} 2657}
2577 2658
2578sub process_state3_type($$) { 2659sub process_proto_type($$) {
2579 my $x = shift; 2660 my $x = shift;
2580 my $file = shift; 2661 my $file = shift;
2581 2662
@@ -2657,6 +2738,7 @@ sub process_file($) {
2657 my $in_purpose = 0; 2738 my $in_purpose = 0;
2658 my $initial_section_counter = $section_counter; 2739 my $initial_section_counter = $section_counter;
2659 my ($orig_file) = @_; 2740 my ($orig_file) = @_;
2741 my $leading_space;
2660 2742
2661 if (defined($ENV{'SRCTREE'})) { 2743 if (defined($ENV{'SRCTREE'})) {
2662 $file = "$ENV{'SRCTREE'}" . "/" . $orig_file; 2744 $file = "$ENV{'SRCTREE'}" . "/" . $orig_file;
@@ -2674,6 +2756,17 @@ sub process_file($) {
2674 return; 2756 return;
2675 } 2757 }
2676 2758
2759 # two passes for -export and -internal
2760 if ($output_selection == OUTPUT_EXPORTED ||
2761 $output_selection == OUTPUT_INTERNAL) {
2762 while (<IN>) {
2763 if (/$export_symbol/o) {
2764 $function_table{$2} = 1;
2765 }
2766 }
2767 seek(IN, 0, 0);
2768 }
2769
2677 $. = 1; 2770 $. = 1;
2678 2771
2679 $section_counter = 0; 2772 $section_counter = 0;
@@ -2681,15 +2774,18 @@ sub process_file($) {
2681 while (s/\\\s*$//) { 2774 while (s/\\\s*$//) {
2682 $_ .= <IN>; 2775 $_ .= <IN>;
2683 } 2776 }
2684 if ($state == 0) { 2777 if ($state == STATE_NORMAL) {
2685 if (/$doc_start/o) { 2778 if (/$doc_start/o) {
2686 $state = 1; # next line is always the function name 2779 $state = STATE_NAME; # next line is always the function name
2687 $in_doc_sect = 0; 2780 $in_doc_sect = 0;
2781 $declaration_start_line = $. + 1;
2688 } 2782 }
2689 } elsif ($state == 1) { # this line is the function name (always) 2783 } elsif ($state == STATE_NAME) {# this line is the function name (always)
2690 if (/$doc_block/o) { 2784 if (/$doc_block/o) {
2691 $state = 4; 2785 $state = STATE_DOCBLOCK;
2692 $contents = ""; 2786 $contents = "";
2787 $new_start_line = $. + 1;
2788
2693 if ( $1 eq "" ) { 2789 if ( $1 eq "" ) {
2694 $section = $section_intro; 2790 $section = $section_intro;
2695 } else { 2791 } else {
@@ -2702,7 +2798,12 @@ sub process_file($) {
2702 $identifier = $1; 2798 $identifier = $1;
2703 } 2799 }
2704 2800
2705 $state = 2; 2801 $state = STATE_FIELD;
2802 # if there's no @param blocks need to set up default section
2803 # here
2804 $contents = "";
2805 $section = $section_default;
2806 $new_start_line = $. + 1;
2706 if (/-(.*)/) { 2807 if (/-(.*)/) {
2707 # strip leading/trailing/multiple spaces 2808 # strip leading/trailing/multiple spaces
2708 $descr= $1; 2809 $descr= $1;
@@ -2740,13 +2841,25 @@ sub process_file($) {
2740 print STDERR "${file}:$.: warning: Cannot understand $_ on line $.", 2841 print STDERR "${file}:$.: warning: Cannot understand $_ on line $.",
2741 " - I thought it was a doc line\n"; 2842 " - I thought it was a doc line\n";
2742 ++$warnings; 2843 ++$warnings;
2743 $state = 0; 2844 $state = STATE_NORMAL;
2744 } 2845 }
2745 } elsif ($state == 2) { # look for head: lines, and include content 2846 } elsif ($state == STATE_FIELD) { # look for head: lines, and include content
2746 if (/$doc_sect/o) { 2847 if (/$doc_sect/i) { # case insensitive for supported section names
2747 $newsection = $1; 2848 $newsection = $1;
2748 $newcontents = $2; 2849 $newcontents = $2;
2749 2850
2851 # map the supported section names to the canonical names
2852 if ($newsection =~ m/^description$/i) {
2853 $newsection = $section_default;
2854 } elsif ($newsection =~ m/^context$/i) {
2855 $newsection = $section_context;
2856 } elsif ($newsection =~ m/^returns?$/i) {
2857 $newsection = $section_return;
2858 } elsif ($newsection =~ m/^\@return$/) {
2859 # special: @return is a section, not a param description
2860 $newsection = $section_return;
2861 }
2862
2750 if (($contents ne "") && ($contents ne "\n")) { 2863 if (($contents ne "") && ($contents ne "\n")) {
2751 if (!$in_doc_sect && $verbose) { 2864 if (!$in_doc_sect && $verbose) {
2752 print STDERR "${file}:$.: warning: contents before sections\n"; 2865 print STDERR "${file}:$.: warning: contents before sections\n";
@@ -2759,14 +2872,16 @@ sub process_file($) {
2759 $in_doc_sect = 1; 2872 $in_doc_sect = 1;
2760 $in_purpose = 0; 2873 $in_purpose = 0;
2761 $contents = $newcontents; 2874 $contents = $newcontents;
2875 $new_start_line = $.;
2876 while ((substr($contents, 0, 1) eq " ") ||
2877 substr($contents, 0, 1) eq "\t") {
2878 $contents = substr($contents, 1);
2879 }
2762 if ($contents ne "") { 2880 if ($contents ne "") {
2763 while ((substr($contents, 0, 1) eq " ") ||
2764 substr($contents, 0, 1) eq "\t") {
2765 $contents = substr($contents, 1);
2766 }
2767 $contents .= "\n"; 2881 $contents .= "\n";
2768 } 2882 }
2769 $section = $newsection; 2883 $section = $newsection;
2884 $leading_space = undef;
2770 } elsif (/$doc_end/) { 2885 } elsif (/$doc_end/) {
2771 if (($contents ne "") && ($contents ne "\n")) { 2886 if (($contents ne "") && ($contents ne "\n")) {
2772 dump_section($file, $section, xml_escape($contents)); 2887 dump_section($file, $section, xml_escape($contents));
@@ -2780,7 +2895,7 @@ sub process_file($) {
2780 } 2895 }
2781 2896
2782 $prototype = ""; 2897 $prototype = "";
2783 $state = 3; 2898 $state = STATE_PROTO;
2784 $brcount = 0; 2899 $brcount = 0;
2785# print STDERR "end of doc comment, looking for prototype\n"; 2900# print STDERR "end of doc comment, looking for prototype\n";
2786 } elsif (/$doc_content/) { 2901 } elsif (/$doc_content/) {
@@ -2791,6 +2906,7 @@ sub process_file($) {
2791 dump_section($file, $section, xml_escape($contents)); 2906 dump_section($file, $section, xml_escape($contents));
2792 $section = $section_default; 2907 $section = $section_default;
2793 $contents = ""; 2908 $contents = "";
2909 $new_start_line = $.;
2794 } else { 2910 } else {
2795 $contents .= "\n"; 2911 $contents .= "\n";
2796 } 2912 }
@@ -2801,87 +2917,86 @@ sub process_file($) {
2801 $declaration_purpose .= " " . xml_escape($1); 2917 $declaration_purpose .= " " . xml_escape($1);
2802 $declaration_purpose =~ s/\s+/ /g; 2918 $declaration_purpose =~ s/\s+/ /g;
2803 } else { 2919 } else {
2804 $contents .= $1 . "\n"; 2920 my $cont = $1;
2921 if ($section =~ m/^@/ || $section eq $section_context) {
2922 if (!defined $leading_space) {
2923 if ($cont =~ m/^(\s+)/) {
2924 $leading_space = $1;
2925 } else {
2926 $leading_space = "";
2927 }
2928 }
2929
2930 $cont =~ s/^$leading_space//;
2931 }
2932 $contents .= $cont . "\n";
2805 } 2933 }
2806 } else { 2934 } else {
2807 # i dont know - bad line? ignore. 2935 # i dont know - bad line? ignore.
2808 print STDERR "${file}:$.: warning: bad line: $_"; 2936 print STDERR "${file}:$.: warning: bad line: $_";
2809 ++$warnings; 2937 ++$warnings;
2810 } 2938 }
2811 } elsif ($state == 5) { # scanning for split parameters 2939 } elsif ($state == STATE_INLINE) { # scanning for inline parameters
2812 # First line (state 1) needs to be a @parameter 2940 # First line (state 1) needs to be a @parameter
2813 if ($split_doc_state == 1 && /$doc_split_sect/o) { 2941 if ($inline_doc_state == STATE_INLINE_NAME && /$doc_inline_sect/o) {
2814 $section = $1; 2942 $section = $1;
2815 $contents = $2; 2943 $contents = $2;
2944 $new_start_line = $.;
2816 if ($contents ne "") { 2945 if ($contents ne "") {
2817 while ((substr($contents, 0, 1) eq " ") || 2946 while ((substr($contents, 0, 1) eq " ") ||
2818 substr($contents, 0, 1) eq "\t") { 2947 substr($contents, 0, 1) eq "\t") {
2819 $contents = substr($contents, 1); 2948 $contents = substr($contents, 1);
2820 } 2949 }
2821 $contents .= "\n"; 2950 $contents .= "\n";
2822 } 2951 }
2823 $split_doc_state = 2; 2952 $inline_doc_state = STATE_INLINE_TEXT;
2824 # Documentation block end */ 2953 # Documentation block end */
2825 } elsif (/$doc_split_end/) { 2954 } elsif (/$doc_inline_end/) {
2826 if (($contents ne "") && ($contents ne "\n")) { 2955 if (($contents ne "") && ($contents ne "\n")) {
2827 dump_section($file, $section, xml_escape($contents)); 2956 dump_section($file, $section, xml_escape($contents));
2828 $section = $section_default; 2957 $section = $section_default;
2829 $contents = ""; 2958 $contents = "";
2830 } 2959 }
2831 $state = 3; 2960 $state = STATE_PROTO;
2832 $split_doc_state = 0; 2961 $inline_doc_state = STATE_INLINE_NA;
2833 # Regular text 2962 # Regular text
2834 } elsif (/$doc_content/) { 2963 } elsif (/$doc_content/) {
2835 if ($split_doc_state == 2) { 2964 if ($inline_doc_state == STATE_INLINE_TEXT) {
2836 $contents .= $1 . "\n"; 2965 $contents .= $1 . "\n";
2837 } elsif ($split_doc_state == 1) { 2966 # nuke leading blank lines
2838 $split_doc_state = 4; 2967 if ($contents =~ /^\s*$/) {
2968 $contents = "";
2969 }
2970 } elsif ($inline_doc_state == STATE_INLINE_NAME) {
2971 $inline_doc_state = STATE_INLINE_ERROR;
2839 print STDERR "Warning(${file}:$.): "; 2972 print STDERR "Warning(${file}:$.): ";
2840 print STDERR "Incorrect use of kernel-doc format: $_"; 2973 print STDERR "Incorrect use of kernel-doc format: $_";
2841 ++$warnings; 2974 ++$warnings;
2842 } 2975 }
2843 } 2976 }
2844 } elsif ($state == 3) { # scanning for function '{' (end of prototype) 2977 } elsif ($state == STATE_PROTO) { # scanning for function '{' (end of prototype)
2845 if (/$doc_split_start/) { 2978 if (/$doc_inline_start/) {
2846 $state = 5; 2979 $state = STATE_INLINE;
2847 $split_doc_state = 1; 2980 $inline_doc_state = STATE_INLINE_NAME;
2848 } elsif ($decl_type eq 'function') { 2981 } elsif ($decl_type eq 'function') {
2849 process_state3_function($_, $file); 2982 process_proto_function($_, $file);
2850 } else { 2983 } else {
2851 process_state3_type($_, $file); 2984 process_proto_type($_, $file);
2852 } 2985 }
2853 } elsif ($state == 4) { 2986 } elsif ($state == STATE_DOCBLOCK) {
2854 # Documentation block 2987 if (/$doc_end/)
2855 if (/$doc_block/) {
2856 dump_doc_section($file, $section, xml_escape($contents));
2857 $contents = "";
2858 $function = "";
2859 %constants = ();
2860 %parameterdescs = ();
2861 %parametertypes = ();
2862 @parameterlist = ();
2863 %sections = ();
2864 @sectionlist = ();
2865 $prototype = "";
2866 if ( $1 eq "" ) {
2867 $section = $section_intro;
2868 } else {
2869 $section = $1;
2870 }
2871 }
2872 elsif (/$doc_end/)
2873 { 2988 {
2874 dump_doc_section($file, $section, xml_escape($contents)); 2989 dump_doc_section($file, $section, xml_escape($contents));
2990 $section = $section_default;
2875 $contents = ""; 2991 $contents = "";
2876 $function = ""; 2992 $function = "";
2877 %constants = ();
2878 %parameterdescs = (); 2993 %parameterdescs = ();
2879 %parametertypes = (); 2994 %parametertypes = ();
2880 @parameterlist = (); 2995 @parameterlist = ();
2881 %sections = (); 2996 %sections = ();
2882 @sectionlist = (); 2997 @sectionlist = ();
2883 $prototype = ""; 2998 $prototype = "";
2884 $state = 0; 2999 $state = STATE_NORMAL;
2885 } 3000 }
2886 elsif (/$doc_content/) 3001 elsif (/$doc_content/)
2887 { 3002 {
@@ -2898,7 +3013,7 @@ sub process_file($) {
2898 } 3013 }
2899 if ($initial_section_counter == $section_counter) { 3014 if ($initial_section_counter == $section_counter) {
2900 print STDERR "${file}:1: warning: no structured comments found\n"; 3015 print STDERR "${file}:1: warning: no structured comments found\n";
2901 if (($function_only == 1) && ($show_not_found == 1)) { 3016 if (($output_selection == OUTPUT_INCLUDE) && ($show_not_found == 1)) {
2902 print STDERR " Was looking for '$_'.\n" for keys %function_table; 3017 print STDERR " Was looking for '$_'.\n" for keys %function_table;
2903 } 3018 }
2904 if ($output_mode eq "xml") { 3019 if ($output_mode eq "xml") {