Commit a7cacfb0 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'docs-6.2' of git://git.lwn.net/linux

Pull documentation updates from Jonathan Corbet:
 "This was a not-too-busy cycle for documentation; highlights include:

   - The beginnings of a set of translations into Spanish, headed up by
     Carlos Bilbao

   - More Chinese translations

   - A change to the Sphinx "alabaster" theme by default for HTML
     generation.

     Unlike the previous default (Read the Docs), alabaster is shipped
     with Sphinx by default, reducing the number of other dependencies
     that need to be installed. It also (IMO) produces a cleaner and
     more readable result.

   - The ability to render the documentation into the texinfo format
     (something Sphinx could always do, we just never wired it up until
     now)

  Plus the usual collection of typo fixes, build-warning fixes, and
  minor updates"

* tag 'docs-6.2' of git://git.lwn.net/linux: (67 commits)
  Documentation/features: Use loongarch instead of loong
  Documentation/features-refresh.sh: Only sed the beginning "arch" of ARCH_DIR
  docs/zh_CN: Fix '.. only::' directive's expression
  docs/sp_SP: Add memory-barriers.txt Spanish translation
  docs/zh_CN/LoongArch: Update links of LoongArch ISA Vol1 and ELF psABI
  docs/LoongArch: Update links of LoongArch ISA Vol1 and ELF psABI
  Documentation/features: Update feature lists for 6.1
  Documentation: Fixed a typo in bootconfig.rst
  docs/sp_SP: Add process coding-style translation
  docs/sp_SP: Add kernel-docs.rst Spanish translation
  docs: Create translations/sp_SP/process/, move submitting-patches.rst
  docs: Add book to process/kernel-docs.rst
  docs: Retire old resources from kernel-docs.rst
  docs: Update maintainer of kernel-docs.rst
  Documentation: riscv: Document the sv57 VM layout
  Documentation: USB: correct possessive "its" usage
  math64: fix kernel-doc return value warnings
  math64: add kernel-doc for DIV64_U64_ROUND_UP
  math64: favor kernel-doc from header files
  doc: add texinfodocs and infodocs targets
  ...
parents 96f42635 cc8c418b
......@@ -95,6 +95,15 @@ htmldocs:
@$(srctree)/scripts/sphinx-pre-install --version-check
@+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,html,$(var),,$(var)))
texinfodocs:
@$(srctree)/scripts/sphinx-pre-install --version-check
@+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,texinfo,$(var),texinfo,$(var)))
# Note: the 'info' Make target is generated by sphinx itself when
# running the texinfodocs target define above.
infodocs: texinfodocs
$(MAKE) -C $(BUILDDIR)/texinfo info
linkcheckdocs:
@$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,linkcheck,$(var),,$(var)))
......@@ -143,6 +152,8 @@ cleandocs:
dochelp:
@echo ' Linux kernel internal documentation in different formats from ReST:'
@echo ' htmldocs - HTML'
@echo ' texinfodocs - Texinfo'
@echo ' infodocs - Info'
@echo ' latexdocs - LaTeX'
@echo ' pdfdocs - PDF'
@echo ' epubdocs - EPUB'
......
......@@ -229,7 +229,7 @@ In addition to the kernel command line, the boot config can be used for
passing the kernel parameters. All the key-value pairs under ``kernel``
key will be passed to kernel cmdline directly. Moreover, the key-value
pairs under ``init`` will be passed to init process via the cmdline.
The parameters are concatinated with user-given kernel cmdline string
The parameters are concatenated with user-given kernel cmdline string
as the following order, so that the command line parameter can override
bootconfig parameters (this depends on how the subsystem handles parameters
but in general, earlier parameter will be overwritten by later one.)::
......
==========================================================
Linux support for random number generator in i8xx chipsets
==========================================================
=================================
Hardware random number generators
=================================
Introduction
============
......
......@@ -14,13 +14,7 @@ for potentially reduced swap I/O. This trade-off can also result in a
significant performance improvement if reads from the compressed cache are
faster than reads from a swap device.
.. note::
Zswap is a new feature as of v3.11 and interacts heavily with memory
reclaim. This interaction has not been fully explored on the large set of
potential configurations and workloads that exist. For this reason, zswap
is a work in progress and should be considered experimental.
Some potential benefits:
Some potential benefits:
* Desktop/laptop users with limited RAM capacities can mitigate the
performance impact of swapping.
......
......@@ -2,8 +2,6 @@
Documentation for /proc/sys/fs/
===============================
kernel version 2.2.10
Copyright (c) 1998, 1999, Rik van Riel <riel@nl.linux.org>
Copyright (c) 2009, Shen Feng<shen@cn.fujitsu.com>
......@@ -12,58 +10,40 @@ For general info and legal blurb, please look in intro.rst.
------------------------------------------------------------------------------
This file contains documentation for the sysctl files in
/proc/sys/fs/ and is valid for Linux kernel version 2.2.
This file contains documentation for the sysctl files and directories
in ``/proc/sys/fs/``.
The files in this directory can be used to tune and monitor
miscellaneous and general things in the operation of the Linux
kernel. Since some of the files _can_ be used to screw up your
kernel. Since some of the files *can* be used to screw up your
system, it is advisable to read both documentation and source
before actually making adjustments.
1. /proc/sys/fs
===============
Currently, these files are in /proc/sys/fs:
- aio-max-nr
- aio-nr
- dentry-state
- dquot-max
- dquot-nr
- file-max
- file-nr
- inode-max
- inode-nr
- inode-state
- nr_open
- overflowuid
- overflowgid
- pipe-user-pages-hard
- pipe-user-pages-soft
- protected_fifos
- protected_hardlinks
- protected_regular
- protected_symlinks
- suid_dumpable
- super-max
- super-nr
Currently, these files might (depending on your configuration)
show up in ``/proc/sys/fs``:
.. contents:: :local:
aio-nr & aio-max-nr
-------------------
aio-nr is the running total of the number of events specified on the
io_setup system call for all currently active aio contexts. If aio-nr
reaches aio-max-nr then io_setup will fail with EAGAIN. Note that
raising aio-max-nr does not result in the pre-allocation or re-sizing
of any kernel data structures.
``aio-nr`` shows the current system-wide number of asynchronous io
requests. ``aio-max-nr`` allows you to change the maximum value
``aio-nr`` can grow to. If ``aio-nr`` reaches ``aio-nr-max`` then
``io_setup`` will fail with ``EAGAIN``. Note that raising
``aio-max-nr`` does not result in the
pre-allocation or re-sizing of any kernel data structures.
dentry-state
------------
From linux/include/linux/dcache.h::
This file shows the values in ``struct dentry_stat``, as defined in
``linux/include/linux/dcache.h``::
struct dentry_stat_t dentry_stat {
int nr_dentry;
......@@ -76,95 +56,84 @@ From linux/include/linux/dcache.h::
Dentries are dynamically allocated and deallocated.
nr_dentry shows the total number of dentries allocated (active
+ unused). nr_unused shows the number of dentries that are not
``nr_dentry`` shows the total number of dentries allocated (active
+ unused). ``nr_unused shows`` the number of dentries that are not
actively used, but are saved in the LRU list for future reuse.
Age_limit is the age in seconds after which dcache entries
can be reclaimed when memory is short and want_pages is
nonzero when shrink_dcache_pages() has been called and the
``age_limit`` is the age in seconds after which dcache entries
can be reclaimed when memory is short and ``want_pages`` is
nonzero when ``shrink_dcache_pages()`` has been called and the
dcache isn't pruned yet.
nr_negative shows the number of unused dentries that are also
``nr_negative`` shows the number of unused dentries that are also
negative dentries which do not map to any files. Instead,
they help speeding up rejection of non-existing files provided
by the users.
dquot-max & dquot-nr
--------------------
The file dquot-max shows the maximum number of cached disk
quota entries.
The file dquot-nr shows the number of allocated disk quota
entries and the number of free disk quota entries.
If the number of free cached disk quotas is very low and
you have some awesome number of simultaneous system users,
you might want to raise the limit.
file-max & file-nr
------------------
The value in file-max denotes the maximum number of file-
The value in ``file-max`` denotes the maximum number of file-
handles that the Linux kernel will allocate. When you get lots
of error messages about running out of file handles, you might
want to increase this limit.
Historically,the kernel was able to allocate file handles
dynamically, but not to free them again. The three values in
file-nr denote the number of allocated file handles, the number
``file-nr`` denote the number of allocated file handles, the number
of allocated but unused file handles, and the maximum number of
file handles. Linux 2.6 always reports 0 as the number of free
file handles. Linux 2.6 and later always reports 0 as the number of free
file handles -- this is not an error, it just means that the
number of allocated file handles exactly matches the number of
used file handles.
Attempts to allocate more file descriptors than file-max are
reported with printk, look for "VFS: file-max limit <number>
reached".
Attempts to allocate more file descriptors than ``file-max`` are
reported with ``printk``, look for::
VFS: file-max limit <number> reached
nr_open
-------
This denotes the maximum number of file-handles a process can
allocate. Default value is 1024*1024 (1048576) which should be
enough for most machines. Actual limit depends on RLIMIT_NOFILE
resource limit.
in the kernel logs.
inode-max, inode-nr & inode-state
---------------------------------
inode-nr & inode-state
----------------------
As with file handles, the kernel allocates the inode structures
dynamically, but can't free them yet.
The value in inode-max denotes the maximum number of inode
handlers. This value should be 3-4 times larger than the value
in file-max, since stdin, stdout and network sockets also
need an inode struct to handle them. When you regularly run
out of inodes, you need to increase this value.
The file inode-nr contains the first two items from
inode-state, so we'll skip to that file...
The file ``inode-nr`` contains the first two items from
``inode-state``, so we'll skip to that file...
Inode-state contains three actual numbers and four dummies.
The actual numbers are, in order of appearance, nr_inodes,
nr_free_inodes and preshrink.
``inode-state`` contains three actual numbers and four dummies.
The actual numbers are, in order of appearance, ``nr_inodes``,
``nr_free_inodes`` and ``preshrink``.
Nr_inodes stands for the number of inodes the system has
allocated, this can be slightly more than inode-max because
Linux allocates them one pageful at a time.
``nr_inodes`` stands for the number of inodes the system has
allocated.
Nr_free_inodes represents the number of free inodes (?) and
preshrink is nonzero when the nr_inodes > inode-max and the
``nr_free_inodes`` represents the number of free inodes (?) and
preshrink is nonzero when the
system needs to prune the inode list instead of allocating
more.
mount-max
---------
This denotes the maximum number of mounts that may exist
in a mount namespace.
nr_open
-------
This denotes the maximum number of file-handles a process can
allocate. Default value is 1024*1024 (1048576) which should be
enough for most machines. Actual limit depends on ``RLIMIT_NOFILE``
resource limit.
overflowgid & overflowuid
-------------------------
......@@ -192,7 +161,7 @@ pipe-user-pages-soft
Maximum total number of pages a non-privileged user may allocate for pipes
before the pipe size gets limited to a single page. Once this limit is reached,
new pipes will be limited to a single page in size for this user in order to
limit total memory usage, and trying to increase them using fcntl() will be
limit total memory usage, and trying to increase them using ``fcntl()`` will be
denied until usage goes below the limit again. The default value allows to
allocate up to 1024 pipes at their default size. When set to 0, no limit is
applied.
......@@ -207,7 +176,7 @@ file.
When set to "0", writing to FIFOs is unrestricted.
When set to "1" don't allow O_CREAT open on FIFOs that we don't own
When set to "1" don't allow ``O_CREAT`` open on FIFOs that we don't own
in world writable sticky directories, unless they are owned by the
owner of the directory.
......@@ -221,7 +190,7 @@ protected_hardlinks
A long-standing class of security issues is the hardlink-based
time-of-check-time-of-use race, most commonly seen in world-writable
directories like /tmp. The common method of exploitation of this flaw
directories like ``/tmp``. The common method of exploitation of this flaw
is to cross privilege boundaries when following a given hardlink (i.e. a
root process follows a hardlink created by another user). Additionally,
on systems without separated partitions, this stops unauthorized users
......@@ -239,13 +208,13 @@ This protection is based on the restrictions in Openwall and grsecurity.
protected_regular
-----------------
This protection is similar to protected_fifos, but it
This protection is similar to `protected_fifos`_, but it
avoids writes to an attacker-controlled regular file, where a program
expected to create one.
When set to "0", writing to regular files is unrestricted.
When set to "1" don't allow O_CREAT open on regular files that we
When set to "1" don't allow ``O_CREAT`` open on regular files that we
don't own in world writable sticky directories, unless they are
owned by the owner of the directory.
......@@ -257,7 +226,7 @@ protected_symlinks
A long-standing class of security issues is the symlink-based
time-of-check-time-of-use race, most commonly seen in world-writable
directories like /tmp. The common method of exploitation of this flaw
directories like ``/tmp``. The common method of exploitation of this flaw
is to cross privilege boundaries when following a given symlink (i.e. a
root process follows a symlink belonging to another user). For a likely
incomplete list of hundreds of examples across the years, please see:
......@@ -272,23 +241,25 @@ follower match, or when the directory owner matches the symlink's owner.
This protection is based on the restrictions in Openwall and grsecurity.
suid_dumpable:
--------------
suid_dumpable
-------------
This value can be used to query and set the core dump mode for setuid
or otherwise protected/tainted binaries. The modes are
= ========== ===============================================================
0 (default) traditional behaviour. Any process which has changed
0 (default) Traditional behaviour. Any process which has changed
privilege levels or is execute only will not be dumped.
1 (debug) all processes dump core when possible. The core dump is
1 (debug) All processes dump core when possible. The core dump is
owned by the current user and no security is applied. This is
intended for system debugging situations only.
Ptrace is unchecked.
This is insecure as it allows regular users to examine the
memory contents of privileged processes.
2 (suidsafe) any binary which normally would not be dumped is dumped
anyway, but only if the "core_pattern" kernel sysctl is set to
2 (suidsafe) Any binary which normally would not be dumped is dumped
anyway, but only if the ``core_pattern`` kernel sysctl (see
:ref:`Documentation/admin-guide/sysctl/kernel.rst <core_pattern>`)
is set to
either a pipe handler or a fully qualified path. (For more
details on this limitation, see CVE-2006-2451.) This mode is
appropriate when administrators are attempting to debug
......@@ -301,36 +272,11 @@ or otherwise protected/tainted binaries. The modes are
= ========== ===============================================================
super-max & super-nr
--------------------
These numbers control the maximum number of superblocks, and
thus the maximum number of mounted filesystems the kernel
can have. You only need to increase super-max if you need to
mount more filesystems than the current value in super-max
allows you to.
aio-nr & aio-max-nr
-------------------
aio-nr shows the current system-wide number of asynchronous io
requests. aio-max-nr allows you to change the maximum value
aio-nr can grow to.
mount-max
---------
This denotes the maximum number of mounts that may exist
in a mount namespace.
2. /proc/sys/fs/binfmt_misc
===========================
Documentation for the files in /proc/sys/fs/binfmt_misc is
Documentation for the files in ``/proc/sys/fs/binfmt_misc`` is
in Documentation/admin-guide/binfmt-misc.rst.
......@@ -343,28 +289,32 @@ creation of a user space library that implements the POSIX message queues
API (as noted by the MSG tag in the POSIX 1003.1-2001 version of the System
Interfaces specification.)
The "mqueue" filesystem contains values for determining/setting the amount of
resources used by the file system.
The "mqueue" filesystem contains values for determining/setting the
amount of resources used by the file system.
/proc/sys/fs/mqueue/queues_max is a read/write file for setting/getting the
maximum number of message queues allowed on the system.
``/proc/sys/fs/mqueue/queues_max`` is a read/write file for
setting/getting the maximum number of message queues allowed on the
system.
/proc/sys/fs/mqueue/msg_max is a read/write file for setting/getting the
maximum number of messages in a queue value. In fact it is the limiting value
for another (user) limit which is set in mq_open invocation. This attribute of
a queue must be less or equal then msg_max.
``/proc/sys/fs/mqueue/msg_max`` is a read/write file for
setting/getting the maximum number of messages in a queue value. In
fact it is the limiting value for another (user) limit which is set in
``mq_open`` invocation. This attribute of a queue must be less than
or equal to ``msg_max``.
/proc/sys/fs/mqueue/msgsize_max is a read/write file for setting/getting the
maximum message size value (it is every message queue's attribute set during
its creation).
``/proc/sys/fs/mqueue/msgsize_max`` is a read/write file for
setting/getting the maximum message size value (it is an attribute of
every message queue, set during its creation).
/proc/sys/fs/mqueue/msg_default is a read/write file for setting/getting the
default number of messages in a queue value if attr parameter of mq_open(2) is
NULL. If it exceed msg_max, the default value is initialized msg_max.
``/proc/sys/fs/mqueue/msg_default`` is a read/write file for
setting/getting the default number of messages in a queue value if the
``attr`` parameter of ``mq_open(2)`` is ``NULL``. If it exceeds
``msg_max``, the default value is initialized to ``msg_max``.
/proc/sys/fs/mqueue/msgsize_default is a read/write file for setting/getting
the default message size value if attr parameter of mq_open(2) is NULL. If it
exceed msgsize_max, the default value is initialized msgsize_max.
``/proc/sys/fs/mqueue/msgsize_default`` is a read/write file for
setting/getting the default message size value if the ``attr``
parameter of ``mq_open(2)`` is ``NULL``. If it exceeds
``msgsize_max``, the default value is initialized to ``msgsize_max``.
4. /proc/sys/fs/epoll - Configuration options for the epoll interface
=====================================================================
......@@ -378,7 +328,7 @@ Every epoll file descriptor can store a number of files to be monitored
for event readiness. Each one of these monitored files constitutes a "watch".
This configuration option sets the maximum number of "watches" that are
allowed for each user.
Each "watch" costs roughly 90 bytes on a 32bit kernel, and roughly 160 bytes
on a 64bit one.
The current default value for max_user_watches is the 1/25 (4%) of the
available low memory, divided for the "watch" cost in bytes.
Each "watch" costs roughly 90 bytes on a 32-bit kernel, and roughly 160 bytes
on a 64-bit one.
The current default value for ``max_user_watches`` is 4% of the
available low memory, divided by the "watch" cost in bytes.
......@@ -139,6 +139,8 @@ Highest valid capability of the running kernel. Exports
``CAP_LAST_CAP`` from the kernel.
.. _core_pattern:
core_pattern
============
......
......@@ -14,18 +14,20 @@ Orion family
Flavors:
- 88F5082
- 88F5181
- 88F5181L
- 88F5182
- 88F5181 a.k.a Orion-1
- 88F5181L a.k.a Orion-VoIP
- 88F5182 a.k.a Orion-NAS
- Datasheet: https://web.archive.org/web/20210124231420/http://csclub.uwaterloo.ca/~board/ts7800/MV88F5182-datasheet.pdf
- Programmer's User Guide: https://web.archive.org/web/20210124231536/http://csclub.uwaterloo.ca/~board/ts7800/MV88F5182-opensource-manual.pdf
- User Manual: https://web.archive.org/web/20210124231631/http://csclub.uwaterloo.ca/~board/ts7800/MV88F5182-usermanual.pdf
- Functional Errata: https://web.archive.org/web/20210704165540/https://www.digriz.org.uk/ts78xx/88F5182_Functional_Errata.pdf
- 88F5281
- 88F5281 a.k.a Orion-2
- Datasheet: https://web.archive.org/web/20131028144728/http://www.ocmodshop.com/images/reviews/networking/qnap_ts409u/marvel_88f5281_data_sheet.pdf
- 88F6183
- 88F6183 a.k.a Orion-1-90
Homepage:
https://web.archive.org/web/20080607215437/http://www.marvell.com/products/media/index.jsp
Core:
Feroceon 88fr331 (88f51xx) or 88fr531-vd (88f52xx) ARMv5 compatible
Linux kernel mach directory:
......
......@@ -194,6 +194,24 @@ finally:
else:
version = release = "unknown version"
#
# HACK: there seems to be no easy way for us to get at the version and
# release information passed in from the makefile...so go pawing through the
# command-line options and find it for ourselves.
#
def get_cline_version():
c_version = c_release = ''
for arg in sys.argv:
if arg.startswith('version='):
c_version = arg[8:]
elif arg.startswith('release='):
c_release = arg[8:]
if c_version:
if c_release:
return c_version + '-' + c_release
return c_version
return version # Whatever we came up with before
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
......@@ -247,7 +265,7 @@ highlight_language = 'none'
# a list of builtin themes.
# Default theme
html_theme = 'sphinx_rtd_theme'
html_theme = 'alabaster'
html_css_files = []
if "DOCS_THEME" in os.environ:
......@@ -278,8 +296,12 @@ if html_theme == 'sphinx_rtd_theme' or html_theme == 'sphinx_rtd_dark_mode':
# Add color-specific RTD normal mode
html_css_files.append('theme_rtd_colors.css')
html_theme_options = {
'navigation_depth': -1,
}
except ImportError:
html_theme = 'classic'
html_theme = 'alabaster'
if "DOCS_CSS" in os.environ:
css = os.environ["DOCS_CSS"].split(" ")
......@@ -295,127 +317,29 @@ if major <= 1 and minor < 8:
for l in html_css_files:
html_context['css_files'].append('_static/' + l)
if html_theme == 'classic':
if html_theme == 'alabaster':
html_theme_options = {
'rightsidebar': False,
'stickysidebar': True,
'collapsiblesidebar': True,
'externalrefs': False,
'footerbgcolor': "white",
'footertextcolor': "white",
'sidebarbgcolor': "white",
'sidebarbtncolor': "black",
'sidebartextcolor': "black",
'sidebarlinkcolor': "#686bff",
'relbarbgcolor': "#133f52",
'relbartextcolor': "white",
'relbarlinkcolor': "white",
'bgcolor': "white",
'textcolor': "black",
'headbgcolor': "#f2f2f2",
'headtextcolor': "#20435c",
'headlinkcolor': "#c60f0f",
'linkcolor': "#355f7c",
'visitedlinkcolor': "#355f7c",
'codebgcolor': "#3f3f3f",
'codetextcolor': "white",
'bodyfont': "serif",
'headfont': "sans-serif",
'description': get_cline_version(),
'page_width': '65em',
'sidebar_width': '15em',
'font_size': 'inherit',
'font_family': 'serif',
}
sys.stderr.write("Using %s theme\n" % html_theme)
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['sphinx-static']
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
html_use_smartypants = False
# Custom sidebar templates, maps document names to template names.
# Note that the RTD theme ignores this.
html_sidebars = { '**': ['searchbox.html', 'localtoc.html', 'sourcelink.html']}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr'
#html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# Now only 'ja' uses this config value
#html_search_options = {'type': 'default'}
# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
#html_search_scorer = 'scorer.js'
# Note that the RTD theme ignores this
html_sidebars = { '**': ["about.html", 'searchbox.html', 'localtoc.html', 'sourcelink.html']}
# Output file base name for HTML help builder.
htmlhelp_basename = 'TheLinuxKerneldoc'
......@@ -558,19 +482,6 @@ texinfo_documents = [
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
# -- Options for Epub output ----------------------------------------------
# Bibliographic Dublin Core info.
......@@ -579,67 +490,9 @@ epub_author = author
epub_publisher = author
epub_copyright = copyright
# The basename for the epub file. It defaults to the project name.
#epub_basename = project
# The HTML theme for the epub output. Since the default themes are not
# optimized for small screen space, using the same theme for HTML and epub
# output is usually not wise. This defaults to 'epub', a theme designed to save
# visual space.
#epub_theme = 'epub'
# The language of the text. It defaults to the language option
# or 'en' if the language is not set.
#epub_language = ''
# The scheme of the identifier. Typical schemes are ISBN or URL.
#epub_scheme = ''
# The unique identifier of the text. This can be a ISBN number
# or the project homepage.
#epub_identifier = ''
# A unique identification for the text.
#epub_uid = ''
# A tuple containing the cover image and cover page html template filenames.
#epub_cover = ()
# A sequence of (type, uri, title) tuples for the guide element of content.opf.
#epub_guide = ()
# HTML files that should be inserted before the pages created by sphinx.
# The format is a list of tuples containing the path and title.
#epub_pre_files = []
# HTML files that should be inserted after the pages created by sphinx.
# The format is a list of tuples containing the path and title.
#epub_post_files = []
# A list of files that should not be packed into the epub file.
epub_exclude_files = ['search.html']
# The depth of the table of contents in toc.ncx.
#epub_tocdepth = 3
# Allow duplicate toc entries.
#epub_tocdup = True
# Choose between 'default' and 'includehidden'.
#epub_tocscope = 'default'
# Fix unsupported image types using the Pillow.
#epub_fix_images = False
# Scale large images.
#epub_max_image_width = 0
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#epub_show_urls = 'inline'
# If false, no index is generated.
#epub_use_index = True
#=======
# rst2pdf
#
......
......@@ -171,9 +171,6 @@ Division Functions
.. kernel-doc:: include/linux/math64.h
:internal:
.. kernel-doc:: lib/math/div64.c
:functions: div_s64_rem div64_u64_rem div64_u64 div64_s64
.. kernel-doc:: lib/math/gcd.c
:export:
......
......@@ -147,11 +147,9 @@ section of ``make help``. The generated documentation is placed in
format-specific subdirectories under ``Documentation/output``.
To generate documentation, Sphinx (``sphinx-build``) must obviously be
installed. For prettier HTML output, the Read the Docs Sphinx theme
(``sphinx_rtd_theme``) is used if available. For PDF output you'll also need
``XeLaTeX`` and ``convert(1)`` from ImageMagick
(https://www.imagemagick.org).\ [#ink]_
All of these are widely available and packaged in distributions.
installed. For PDF output you'll also need ``XeLaTeX`` and ``convert(1)``
from ImageMagick (https://www.imagemagick.org).\ [#ink]_ All of these are
widely available and packaged in distributions.
To pass extra options to Sphinx, you can use the ``SPHINXOPTS`` make
variable. For example, use ``make SPHINXOPTS=-v htmldocs`` to get more verbose
......@@ -160,12 +158,8 @@ output.
It is also possible to pass an extra DOCS_CSS overlay file, in order to customize
the html layout, by using the ``DOCS_CSS`` make variable.
By default, the build will try to use the Read the Docs sphinx theme:
https://github.com/readthedocs/sphinx_rtd_theme
If the theme is not available, it will fall-back to the classic one.
By default, the "Alabaster" theme is used to build the HTML documentation;
this theme is bundled with Sphinx and need not be installed separately.
The Sphinx theme can be overridden by using the ``DOCS_THEME`` make variable.
There is another make variable ``SPHINXDIRS``, which is useful when test
......
......@@ -287,12 +287,16 @@ IIO
devm_iio_device_register()
devm_iio_dmaengine_buffer_setup()
devm_iio_kfifo_buffer_setup()
devm_iio_kfifo_buffer_setup_ext()
devm_iio_map_array_register()
devm_iio_triggered_buffer_setup()
devm_iio_triggered_buffer_setup_ext()
devm_iio_trigger_alloc()
devm_iio_trigger_register()
devm_iio_channel_get()
devm_iio_channel_get_all()
devm_iio_hw_consumer_alloc()
devm_fwnode_iio_channel_get_by_name()
INPUT
devm_input_allocate_device()
......@@ -339,7 +343,10 @@ IRQ
LED
devm_led_classdev_register()
devm_led_classdev_register_ext()
devm_led_classdev_unregister()
devm_led_trigger_register()
devm_of_led_get()
MDIO
devm_mdiobus_alloc()
......@@ -403,6 +410,7 @@ POWER
devm_reboot_mode_unregister()
PWM
devm_pwmchip_add()
devm_pwm_get()
devm_fwnode_pwm_get()
......
......@@ -189,7 +189,7 @@ eisa_bus.enable_dev
initialize the device in such conditions.
eisa_bus.disable_dev
A comma-separated list of slots to be enabled, even if the firmware
A comma-separated list of slots to be disabled, even if the firmware
set the card as enabled. The driver won't be called to handle this
device.
......
......@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | ok |
| ia64: | ok |
| loong: | ok |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -10,10 +10,10 @@
| arc: | ok |
| arm: | ok |
| arm64: | ok |
| csky: | TODO |
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |
......
......@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | ok |
| ia64: | ok |
| loong: | ok |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |
......@@ -25,7 +25,7 @@
| s390: | ok |
| sh: | TODO |
| sparc: | TODO |
| um: | TODO |
| um: | ok |
| x86: | ok |
| xtensa: | ok |
-----------------------
......@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |
......
......@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | ok |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | ok |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | ok |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | ok |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |
......
......@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | ok |
| loong: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | ok |
| loong: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |
......
......@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |
......
......@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | ok |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | ok |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |
......
......@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | ok |
| ia64: | TODO |
| loong: | ok |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | ok |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | ok |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -10,10 +10,10 @@
| arc: | TODO |
| arm: | TODO |
| arm64: | ok |
| csky: | TODO |
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | ok |
| ia64: | TODO |
| loong: | ok |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -36,7 +36,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |
......
......@@ -13,7 +13,7 @@
| csky: | .. |
| hexagon: | .. |
| ia64: | TODO |
| loong: | ok |
| loongarch: | ok |
| m68k: | .. |
| microblaze: | .. |
| mips: | TODO |
......
......@@ -60,7 +60,7 @@ for F_FILE in Documentation/features/*/*/arch-support.txt; do
echo " | arch |status|" >> $T_FILE
echo " -----------------------" >> $T_FILE
for ARCH_DIR in arch/*/; do
ARCH=$(echo $ARCH_DIR | sed -e 's/arch//g' | sed -e 's/\///g')
ARCH=$(echo $ARCH_DIR | sed -e 's/^arch//g' | sed -e 's/\///g')
K_FILES=$(find $ARCH_DIR -name "Kconfig*")
K_GREP=$(grep "$K" $K_FILES)
#
......
......@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | ok |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | ok |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | ok |
| ia64: | TODO |
| loong: | ok |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | ok |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | ok |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | .. |
| loong: | ok |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | ok |
| loong: | ok |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | ok |
| loong: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |
......
......@@ -13,7 +13,7 @@
| csky: | .. |
| hexagon: | .. |
| ia64: | TODO |
| loong: | ok |
| loongarch: | ok |
| m68k: | .. |
| microblaze: | .. |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | TODO |
| m68k: | .. |
| microblaze: | .. |
| mips: | TODO |
......
......@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | TODO |
| loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |
......
......@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | ok |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
| loong: | ok |
| loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
......
......@@ -155,8 +155,8 @@ any code which does so in the mainline. Note that all files created with
debugfs_create_blob() are read-only.
If you want to dump a block of registers (something that happens quite
often during development, even if little such code reaches mainline.
Debugfs offers two functions: one to make a registers-only file, and
often during development, even if little such code reaches mainline),
debugfs offers two functions: one to make a registers-only file, and
another to insert a register block in the middle of another sequential
file::
......@@ -183,7 +183,7 @@ The "base" argument may be 0, but you may want to build the reg32 array
using __stringify, and a number of register names (macros) are actually
byte offsets over a base for the register block.
If you want to dump an u32 array in debugfs, you can create file with::
If you want to dump a u32 array in debugfs, you can create a file with::
struct debugfs_u32_array {
u32 *array;
......@@ -197,7 +197,7 @@ If you want to dump an u32 array in debugfs, you can create file with::
The "array" argument wraps a pointer to the array's data and the number
of its elements. Note: Once array is created its size can not be changed.
There is a helper function to create device related seq_file::
There is a helper function to create a device-related seq_file::
void debugfs_create_devm_seqfile(struct device *dev,
const char *name,
......
......@@ -245,7 +245,8 @@ It's slow but very precise.
Ngid NUMA group ID (0 if none)
Pid process id
PPid process id of the parent process
TracerPid PID of process tracing this process (0 if not)
TracerPid PID of process tracing this process (0 if not, or
the tracer is outside of the current pid namespace)
Uid Real, effective, saved set, and file system UIDs
Gid Real, effective, saved set, and file system GIDs
FDSize number of file descriptor slots currently allocated
......
......@@ -12,10 +12,10 @@ Mike Murphy <mamurph@cs.clemson.edu>
:Original: 10 January 2003
What it is:
~~~~~~~~~~~
What it is
~~~~~~~~~~
sysfs is a ram-based filesystem initially based on ramfs. It provides
sysfs is a RAM-based filesystem initially based on ramfs. It provides
a means to export kernel data structures, their attributes, and the
linkages between them to userspace.
......@@ -43,7 +43,7 @@ userspace. Top-level directories in sysfs represent the common
ancestors of object hierarchies; i.e. the subsystems the objects
belong to.
Sysfs internally stores a pointer to the kobject that implements a
sysfs internally stores a pointer to the kobject that implements a
directory in the kernfs_node object associated with the directory. In
the past this kobject pointer has been used by sysfs to do reference
counting directly on the kobject whenever the file is opened or closed.
......@@ -55,7 +55,7 @@ Attributes
~~~~~~~~~~
Attributes can be exported for kobjects in the form of regular files in
the filesystem. Sysfs forwards file I/O operations to methods defined
the filesystem. sysfs forwards file I/O operations to methods defined
for the attributes, providing a means to read and write kernel
attributes.
......@@ -72,8 +72,8 @@ you publicly humiliated and your code rewritten without notice.
An attribute definition is simply::
struct attribute {
char * name;
struct module *owner;
char *name;
struct module *owner;
umode_t mode;
};
......@@ -138,7 +138,7 @@ __ATTR_WO(name):
assumes a name_store only and is restricted to mode
0200 that is root write access only.
__ATTR_RO_MODE(name, mode):
fore more restrictive RO access currently
for more restrictive RO access; currently
only use case is the EFI System Resource Table
(see drivers/firmware/efi/esrt.c)
__ATTR_RW(name):
......@@ -207,7 +207,7 @@ IOW, they should take only an object, an attribute, and a buffer as parameters.
sysfs allocates a buffer of size (PAGE_SIZE) and passes it to the
method. Sysfs will call the method exactly once for each read or
method. sysfs will call the method exactly once for each read or
write. This forces the following behavior on the method
implementations:
......@@ -221,7 +221,7 @@ implementations:
be called again, rearmed, to fill the buffer.
- On write(2), sysfs expects the entire buffer to be passed during the
first write. Sysfs then passes the entire buffer to the store() method.
first write. sysfs then passes the entire buffer to the store() method.
A terminating null is added after the data on stores. This makes
functions like sysfs_streq() safe to use.
......@@ -237,7 +237,7 @@ Other notes:
- Writing causes the show() method to be rearmed regardless of current
file position.
- The buffer will always be PAGE_SIZE bytes in length. On i386, this
- The buffer will always be PAGE_SIZE bytes in length. On x86, this
is 4096.
- show() methods should return the number of bytes printed into the
......@@ -253,7 +253,7 @@ Other notes:
through, be sure to return an error.
- The object passed to the methods will be pinned in memory via sysfs
referencing counting its embedded object. However, the physical
reference counting its embedded object. However, the physical
entity (e.g. device) the object represents may not be present. Be
sure to have a way to check this, if necessary.
......@@ -295,8 +295,12 @@ The top level sysfs directory looks like::
dev/
devices/
firmware/
net/
fs/
hypervisor/
kernel/
module/
net/
power/
devices/ contains a filesystem representation of the device tree. It maps
directly to the internal kernel device tree, which is a hierarchy of
......@@ -317,15 +321,18 @@ span multiple bus types).
fs/ contains a directory for some filesystems. Currently each
filesystem wanting to export attributes must create its own hierarchy
below fs/ (see ./fuse.txt for an example).
below fs/ (see ./fuse.rst for an example).
module/ contains parameter values and state information for all
loaded system modules, for both builtin and loadable modules.
dev/ contains two directories char/ and block/. Inside these two
dev/ contains two directories: char/ and block/. Inside these two
directories there are symlinks named <major>:<minor>. These symlinks
point to the sysfs directory for the given device. /sys/dev provides a
quick way to lookup the sysfs interface for a device from the result of
a stat(2) operation.
More information can driver-model specific features can be found in
More information on driver-model specific features can be found in
Documentation/driver-api/driver-model/.
......@@ -335,7 +342,7 @@ TODO: Finish this section.
Current Interfaces
~~~~~~~~~~~~~~~~~~
The following interface layers currently exist in sysfs:
The following interface layers currently exist in sysfs.
devices (include/linux/device.h)
......
......@@ -61,7 +61,7 @@ Memory Map
The efi_memmap table is preserved unmodified because the original
boot-time information is required for kexec.
Kernel Identify Mappings
Kernel Identity Mappings
========================
Linux/ia64 identity mappings are done with large pages, currently
......
......@@ -375,15 +375,15 @@ Developer web site of Loongson and LoongArch (Software and Documentation):
Documentation of LoongArch ISA:
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.00-CN.pdf (in Chinese)
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-CN.pdf (in Chinese)
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.00-EN.pdf (in English)
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-EN.pdf (in English)
Documentation of LoongArch ELF psABI:
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v1.00-CN.pdf (in Chinese)
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.00-CN.pdf (in Chinese)
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v1.00-EN.pdf (in English)
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.00-EN.pdf (in English)
Linux kernel repository of Loongson and LoongArch:
......
......@@ -3,9 +3,6 @@
Index of Further Kernel Documentation
=====================================
Initial Author: Juan-Mariano de Goyeneche (<jmseyas@dit.upm.es>;
email address is defunct now.)
The need for a document like this one became apparent in the
linux-kernel mailing list as the same questions, asking for pointers
to information, appeared again and again.
......@@ -31,7 +28,9 @@ All documents are cataloged with the following fields: the document's
.. note::
The documents on each section of this document are ordered by its
published date, from the newest to the oldest.
published date, from the newest to the oldest. The maintainer(s) should
periodically retire resources as they become obsolte or outdated; with
the exception of foundational books.
Docs at the Linux Kernel tree
-----------------------------
......@@ -61,24 +60,6 @@ On-line docs
a brief description of some of the acronyms and terms you may hear
during discussion of the Linux kernel".
* Title: **Tracing the Way of Data in a TCP Connection through the Linux Kernel**
:Author: Richard Sailer
:URL: https://archive.org/details/linux_kernel_data_flow_short_paper
:Date: 2016
:Keywords: Linux Kernel Networking, TCP, tracing, ftrace
:Description: A seminar paper explaining ftrace and how to use it for
understanding linux kernel internals,
illustrated at tracing the way of a TCP packet through the kernel.
:Abstract: *This short paper outlines the usage of ftrace a tracing framework
as a tool to understand a running Linux system.
Having obtained a trace-log a kernel hacker can read and understand
source code more determined and with context.
In a detailed example this approach is demonstrated in tracing
and the way of data in a TCP Connection through the kernel.
Finally this trace-log is used as base for more a exact conceptual
exploration and description of the Linux TCP/IP implementation.*
* Title: **The Linux Kernel Module Programming Guide**
:Author: Peter Jay Salzman, Michael Burian, Ori Pomerantz, Bob Mottram,
......@@ -91,379 +72,16 @@ On-line docs
programming. Lots of examples. Currently the new version is being
actively maintained at https://github.com/sysprog21/lkmpg.
* Title: **On submitting kernel Patches**
:Author: Andi Kleen
:URL: http://halobates.de/on-submitting-kernel-patches.pdf
:Date: 2008
:Keywords: patches, review process, types of submissions, basic rules, case studies
:Description: This paper gives several experience values on what types of patches
there are and how likely they get merged.
:Abstract:
[...]. This paper examines some common problems for
submitting larger changes and some strategies to avoid problems.
* Title: **Linux Device Drivers, Third Edition**
:Author: Jonathan Corbet, Alessandro Rubini, Greg Kroah-Hartman
:URL: https://lwn.net/Kernel/LDD3/
:Date: 2005
:Description: A 600-page book covering the (2.6.10) driver
programming API and kernel hacking in general. Available under the
Creative Commons Attribution-ShareAlike 2.0 license.
:note: You can also :ref:`purchase a copy from O'Reilly or elsewhere <ldd3_published>`.
* Title: **Writing an ALSA Driver**
:Author: Takashi Iwai <tiwai@suse.de>
:URL: https://www.kernel.org/doc/html/latest/sound/kernel-api/writing-an-alsa-driver.html
:Date: 2005
:Keywords: ALSA, sound, soundcard, driver, lowlevel, hardware.
:Description: Advanced Linux Sound Architecture for developers,
both at kernel and user-level sides. ALSA is the Linux kernel
sound architecture in the 2.6 kernel version.
* Title: **Linux PCMCIA Programmer's Guide**
:Author: David Hinds.
:URL: http://pcmcia-cs.sourceforge.net/ftp/doc/PCMCIA-PROG.html
:Date: 2003
:Keywords: PCMCIA.
:Description: "This document describes how to write kernel device
drivers for the Linux PCMCIA Card Services interface. It also
describes how to write user-mode utilities for communicating with
Card Services.
* Title: **How NOT to write kernel drivers**
:Author: Arjan van de Ven.
:URL: https://landley.net/kdocs/ols/2002/ols2002-pages-545-555.pdf
:Date: 2002
:Keywords: driver.
:Description: Programming bugs and Do-nots in kernel driver development
:Abstract: *Quit a few tutorials, articles and books give an introduction
on how to write Linux kernel drivers. Unfortunately the things one
should NOT do in Linux kernel code is either only a minor appendix
or, more commonly, completely absent. This paper tries to briefly touch
the areas in which the most common and serious bugs and do-nots are
encountered.*
* Title: **Global spinlock list and usage**
:Author: Rick Lindsley.
:URL: http://lse.sourceforge.net/lockhier/global-spin-lock
:Date: 2001
:Keywords: spinlock.
:Description: This is an attempt to document both the existence and
usage of the spinlocks in the Linux 2.4.5 kernel. Comprehensive
list of spinlocks showing when they are used, which functions
access them, how each lock is acquired, under what conditions it
is held, whether interrupts can occur or not while it is held...
* Title: **A Linux vm README**
:Author: Kanoj Sarcar.
:URL: http://kos.enix.org/pub/linux-vmm.html
:Date: 2001
:Keywords: virtual memory, mm, pgd, vma, page, page flags, page
cache, swap cache, kswapd.
:Description: Telegraphic, short descriptions and definitions
relating the Linux virtual memory implementation.
* Title: **Video4linux Drivers, Part 1: Video-Capture Device**
:Author: Alan Cox.
:URL: http://www.linux-mag.com/id/406
:Date: 2000
:Keywords: video4linux, driver, video capture, capture devices,
camera driver.
:Description: The title says it all.
* Title: **Video4linux Drivers, Part 2: Video-capture Devices**
:Author: Alan Cox.
:URL: http://www.linux-mag.com/id/429
:Date: 2000
:Keywords: video4linux, driver, video capture, capture devices,
camera driver, control, query capabilities, capability, facility.
:Description: The title says it all.
* Title: **Linux IP Networking. A Guide to the Implementation and Modification of the Linux Protocol Stack.**
:Author: Glenn Herrin.
:URL: http://www.cs.unh.edu/cnrg/gherrin
:Date: 2000
:Keywords: network, networking, protocol, IP, UDP, TCP, connection,
socket, receiving, transmitting, forwarding, routing, packets,
modules, /proc, sk_buff, FIB, tags.
:Description: Excellent paper devoted to the Linux IP Networking,
explaining anything from the kernel's to the user space
configuration tools' code. Very good to get a general overview of
the kernel networking implementation and understand all steps
packets follow from the time they are received at the network
device till they are delivered to applications. The studied kernel
code is from 2.2.14 version. Provides code for a working packet
dropper example.
* Title: **How To Make Sure Your Driver Will Work On The Power Macintosh**
:Author: Paul Mackerras.
:URL: http://www.linux-mag.com/id/261
:Date: 1999
:Keywords: Mac, Power Macintosh, porting, drivers, compatibility.
:Description: The title says it all.
* Title: **An Introduction to SCSI Drivers**
:Author: Alan Cox.
:URL: http://www.linux-mag.com/id/284
:Date: 1999
:Keywords: SCSI, device, driver.
:Description: The title says it all.
* Title: **Advanced SCSI Drivers And Other Tales**
:Author: Alan Cox.
:URL: http://www.linux-mag.com/id/307
:Date: 1999
:Keywords: SCSI, device, driver, advanced.
:Description: The title says it all.
* Title: **Writing Linux Mouse Drivers**
:Author: Alan Cox.
:URL: http://www.linux-mag.com/id/330
:Date: 1999
:Keywords: mouse, driver, gpm.
:Description: The title says it all.
* Title: **More on Mouse Drivers**
:Author: Alan Cox.
:URL: http://www.linux-mag.com/id/356
:Date: 1999
:Keywords: mouse, driver, gpm, races, asynchronous I/O.
:Description: The title still says it all.
* Title: **Writing Video4linux Radio Driver**
:Author: Alan Cox.
:URL: http://www.linux-mag.com/id/381
:Date: 1999
:Keywords: video4linux, driver, radio, radio devices.
:Description: The title says it all.
* Title: **I/O Event Handling Under Linux**
:Author: Richard Gooch.
:URL: https://web.mit.edu/~yandros/doc/io-events.html
:Date: 1999
:Keywords: IO, I/O, select(2), poll(2), FDs, aio_read(2), readiness
event queues.
:Description: From the Introduction: "I/O Event handling is about
how your Operating System allows you to manage a large number of
open files (file descriptors in UNIX/POSIX, or FDs) in your
application. You want the OS to notify you when FDs become active
(have data ready to be read or are ready for writing). Ideally you
want a mechanism that is scalable. This means a large number of
inactive FDs cost very little in memory and CPU time to manage".
* Title: **(nearly) Complete Linux Loadable Kernel Modules. The definitive guide for hackers, virus coders and system administrators.**
:Author: pragmatic/THC.
:URL: http://packetstormsecurity.org/docs/hack/LKM_HACKING.html
:Date: 1999
:Keywords: syscalls, intercept, hide, abuse, symbol table.
:Description: Interesting paper on how to abuse the Linux kernel in
order to intercept and modify syscalls, make
files/directories/processes invisible, become root, hijack ttys,
write kernel modules based virus... and solutions for admins to
avoid all those abuses.
:Notes: For 2.0.x kernels. Gives guidances to port it to 2.2.x
kernels.
* Name: **Linux Virtual File System**
:Author: Peter J. Braam.
:URL: http://www.coda.cs.cmu.edu/doc/talks/linuxvfs/
:Date: 1998
:Keywords: slides, VFS, inode, superblock, dentry, dcache.
:Description: Set of slides, presumably from a presentation on the
Linux VFS layer. Covers version 2.1.x, with dentries and the
dcache.
* Title: **The Venus kernel interface**
:Author: Peter J. Braam.
:URL: http://www.coda.cs.cmu.edu/doc/html/kernel-venus-protocol.html
:Date: 1998
:Keywords: coda, filesystem, venus, cache manager.
:Description: "This document describes the communication between
Venus and kernel level file system code needed for the operation
of the Coda filesystem. This version document is meant to describe
the current interface (version 1.0) as well as improvements we
envisage".
* Title: **Design and Implementation of the Second Extended Filesystem**
:Author: Rémy Card, Theodore Ts'o, Stephen Tweedie.
:URL: https://web.mit.edu/tytso/www/linux/ext2intro.html
:Date: 1998
:Keywords: ext2, linux fs history, inode, directory, link, devices,
VFS, physical structure, performance, benchmarks, ext2fs library,
ext2fs tools, e2fsck.
:Description: Paper written by three of the top ext2 hackers.
Covers Linux filesystems history, ext2 motivation, ext2 features,
design, physical structure on disk, performance, benchmarks,
e2fsck's passes description... A must read!
:Notes: This paper was first published in the Proceedings of the
First Dutch International Symposium on Linux, ISBN 90-367-0385-9.
* Title: **The Linux RAID-1, 4, 5 Code**
:Author: Ingo Molnar, Gadi Oxman and Miguel de Icaza.
:URL: http://www.linuxjournal.com/article.php?sid=2391
:Date: 1997
:Keywords: RAID, MD driver.
:Description: Linux Journal Kernel Korner article.
:Abstract: *A description of the implementation of the RAID-1,
RAID-4 and RAID-5 personalities of the MD device driver in the
Linux kernel, providing users with high performance and reliable,
secondary-storage capability using software*.
* Title: **Linux Kernel Hackers' Guide**
:Author: Michael K. Johnson.
:URL: https://www.tldp.org/LDP/khg/HyperNews/get/khg.html
:Date: 1997
:Keywords: device drivers, files, VFS, kernel interface, character vs
block devices, hardware interrupts, scsi, DMA, access to user memory,
memory allocation, timers.
:Description: A guide designed to help you get up to speed on the
concepts that are not intuitively obvious, and to document the internal
structures of Linux.
* Title: **Dynamic Kernels: Modularized Device Drivers**
:Author: Alessandro Rubini.
:URL: http://www.linuxjournal.com/article.php?sid=1219
:Date: 1996
:Keywords: device driver, module, loading/unloading modules,
allocating resources.
:Description: Linux Journal Kernel Korner article.
:Abstract: *This is the first of a series of four articles
co-authored by Alessandro Rubini and Georg Zezchwitz which present
a practical approach to writing Linux device drivers as kernel
loadable modules. This installment presents an introduction to the
topic, preparing the reader to understand next month's
installment*.
* Title: **Dynamic Kernels: Discovery**
:Author: Alessandro Rubini.
:URL: http://www.linuxjournal.com/article.php?sid=1220
:Date: 1996
:Keywords: character driver, init_module, clean_up module,
autodetection, mayor number, minor number, file operations,
open(), close().
:Description: Linux Journal Kernel Korner article.
:Abstract: *This article, the second of four, introduces part of
the actual code to create custom module implementing a character
device driver. It describes the code for module initialization and
cleanup, as well as the open() and close() system calls*.
* Title: **The Devil's in the Details**
:Author: Georg v. Zezschwitz and Alessandro Rubini.
:URL: http://www.linuxjournal.com/article.php?sid=1221
:Date: 1996
:Keywords: read(), write(), select(), ioctl(), blocking/non
blocking mode, interrupt handler.
:Description: Linux Journal Kernel Korner article.
:Abstract: *This article, the third of four on writing character
device drivers, introduces concepts of reading, writing, and using
ioctl-calls*.
* Title: **Dissecting Interrupts and Browsing DMA**
:Author: Alessandro Rubini and Georg v. Zezschwitz.
:URL: https://www.linuxjournal.com/article.php?sid=1222
:Date: 1996
:Keywords: interrupts, irqs, DMA, bottom halves, task queues.
:Description: Linux Journal Kernel Korner article.
:Abstract: *This is the fourth in a series of articles about
writing character device drivers as loadable kernel modules. This
month, we further investigate the field of interrupt handling.
Though it is conceptually simple, practical limitations and
constraints make this an ''interesting'' part of device driver
writing, and several different facilities have been provided for
different situations. We also investigate the complex topic of
DMA*.
* Title: **Device Drivers Concluded**
:Author: Georg v. Zezschwitz.
:URL: https://www.linuxjournal.com/article.php?sid=1287
:Date: 1996
:Keywords: address spaces, pages, pagination, page management,
demand loading, swapping, memory protection, memory mapping, mmap,
virtual memory areas (VMAs), vremap, PCI.
:Description: Finally, the above turned out into a five articles
series. This latest one's introduction reads: "This is the last of
five articles about character device drivers. In this final
section, Georg deals with memory mapping devices, beginning with
an overall description of the Linux memory management concepts".
* Title: **Network Buffers And Memory Management**
:Author: Alan Cox.
:URL: https://www.linuxjournal.com/article.php?sid=1312
:Date: 1996
:Keywords: sk_buffs, network devices, protocol/link layer
variables, network devices flags, transmit, receive,
configuration, multicast.
:Description: Linux Journal Kernel Korner.
:Abstract: *Writing a network device driver for Linux is fundamentally
simple---most of the complexity (other than talking to the
hardware) involves managing network packets in memory*.
* Title: **Analysis of the Ext2fs structure**
:Author: Louis-Dominique Dubeau.
:URL: https://teaching.csse.uwa.edu.au/units/CITS2002/fs-ext2/
:Date: 1994
:Keywords: ext2, filesystem, ext2fs.
:Description: Description of ext2's blocks, directories, inodes,
bitmaps, invariants...
Published books
---------------
* Title: **Linux Treiber entwickeln**
:Author: Jürgen Quade, Eva-Katharina Kunst
:Publisher: dpunkt.verlag
:Date: Oct 2015 (4th edition)
:Pages: 688
:ISBN: 978-3-86490-288-8
:Note: German. The third edition from 2011 is
much cheaper and still quite up-to-date.
* Title: **Linux Kernel Networking: Implementation and Theory**
:Author: Rami Rosen
:Publisher: Apress
:Date: December 22, 2013
:Pages: 648
:ISBN: 978-1430261964
* Title: **Embedded Linux Primer: A practical Real-World Approach, 2nd Edition**
* Title: **Linux Kernel Programming: A Comprehensive Guide to Kernel Internals, Writing Kernel Modules, and Kernel Synchronization**
:Author: Christopher Hallinan
:Publisher: Pearson
:Date: November, 2010
:Pages: 656
:ISBN: 978-0137017836
:Author: Kaiwan N. Billimoria
:Publisher: Packt Publishing Ltd
:Date: 2021
:Pages: 754
:ISBN: 978-1789953435
* Title: **Linux Kernel Development, 3rd Edition**
......@@ -472,14 +90,7 @@ Published books
:Date: July, 2010
:Pages: 440
:ISBN: 978-0672329463
* Title: **Essential Linux Device Drivers**
:Author: Sreekrishnan Venkateswaran
:Published: Prentice Hall
:Date: April, 2008
:Pages: 744
:ISBN: 978-0132396554
:Notes: Foundational book
.. _ldd3_published:
......@@ -490,68 +101,10 @@ Published books
:Date: 2005
:Pages: 636
:ISBN: 0-596-00590-3
:Notes: Further information in
:Notes: Foundational book. Further information in
http://www.oreilly.com/catalog/linuxdrive3/
PDF format, URL: https://lwn.net/Kernel/LDD3/
* Title: **Linux Kernel Internals**
:Author: Michael Beck
:Publisher: Addison-Wesley
:Date: 1997
:ISBN: 0-201-33143-8 (second edition)
* Title: **Programmation Linux 2.0 API systeme et fonctionnement du noyau**
:Author: Remy Card, Eric Dumas, Franck Mevel
:Publisher: Eyrolles
:Date: 1997
:Pages: 520
:ISBN: 2-212-08932-5
:Notes: French
* Title: **The Design and Implementation of the 4.4 BSD UNIX Operating System**
:Author: Marshall Kirk McKusick, Keith Bostic, Michael J. Karels,
John S. Quarterman
:Publisher: Addison-Wesley
:Date: 1996
:ISBN: 0-201-54979-4
* Title: **Unix internals -- the new frontiers**
:Author: Uresh Vahalia
:Publisher: Prentice Hall
:Date: 1996
:Pages: 600
:ISBN: 0-13-101908-2
* Title: **Programming for the real world - POSIX.4**
:Author: Bill O. Gallmeister
:Publisher: O'Reilly & Associates, Inc
:Date: 1995
:Pages: 552
:ISBN: I-56592-074-0
:Notes: Though not being directly about Linux, Linux aims to be
POSIX. Good reference.
* Title: **UNIX Systems for Modern Architectures: Symmetric Multiprocessing and Caching for Kernel Programmers**
:Author: Curt Schimmel
:Publisher: Addison Wesley
:Date: June, 1994
:Pages: 432
:ISBN: 0-201-63338-8
* Title: **The Design and Implementation of the 4.3 BSD UNIX Operating System**
:Author: Samuel J. Leffler, Marshall Kirk McKusick, Michael J
Karels, John S. Quarterman
:Publisher: Addison-Wesley
:Date: 1989 (reprinted with corrections on October, 1990)
:ISBN: 0-201-06196-1
* Title: **The Design of the UNIX Operating System**
:Author: Maurice J. Bach
......@@ -559,6 +112,7 @@ Published books
:Date: 1986
:Pages: 471
:ISBN: 0-13-201757-1
:Notes: Foundational book
Miscellaneous
-------------
......@@ -577,7 +131,7 @@ Miscellaneous
:Keywords: latest kernel news.
:Description: The title says it all. There's a fixed kernel section
summarizing developers' work, bug fixes, new features and versions
produced during the week. Published every Thursday.
produced during the week.
* Name: **The home page of Linux-MM**
......@@ -614,7 +168,8 @@ Miscellaneous
-------
Document last updated on Tue 2016-Sep-20
This document was originally based on:
This document is based on:
https://www.dit.upm.es/~jmseyas/linux/kernel/hackers-docs.html
and written by Juan-Mariano de Goyeneche
......@@ -97,3 +97,39 @@ RISC-V Linux Kernel SV48
ffffffff00000000 | -4 GB | ffffffff7fffffff | 2 GB | modules, BPF
ffffffff80000000 | -2 GB | ffffffffffffffff | 2 GB | kernel
__________________|____________|__________________|_________|____________________________________________________________
RISC-V Linux Kernel SV57
------------------------
::
========================================================================================================================
Start addr | Offset | End addr | Size | VM area description
========================================================================================================================
| | | |
0000000000000000 | 0 | 00ffffffffffffff | 64 PB | user-space virtual memory, different per mm
__________________|____________|__________________|_________|___________________________________________________________
| | | |
0100000000000000 | +64 PB | feffffffffffffff | ~16K PB | ... huge, almost 64 bits wide hole of non-canonical
| | | | virtual memory addresses up to the -64 PB
| | | | starting offset of kernel mappings.
__________________|____________|__________________|_________|___________________________________________________________
|
| Kernel-space virtual memory, shared between all processes:
____________________________________________________________|___________________________________________________________
| | | |
ff1bfffffee00000 | -57 PB | ff1bfffffeffffff | 2 MB | fixmap
ff1bffffff000000 | -57 PB | ff1bffffffffffff | 16 MB | PCI io
ff1c000000000000 | -57 PB | ff1fffffffffffff | 1 PB | vmemmap
ff20000000000000 | -56 PB | ff5fffffffffffff | 16 PB | vmalloc/ioremap space
ff60000000000000 | -40 PB | ffdeffffffffffff | 32 PB | direct mapping of all physical memory
ffdf000000000000 | -8 PB | fffffffeffffffff | 8 PB | kasan
__________________|____________|__________________|_________|____________________________________________________________
|
| Identical layout to the 39-bit one from here on:
____________________________________________________________|____________________________________________________________
| | | |
ffffffff00000000 | -4 GB | ffffffff7fffffff | 2 GB | modules, BPF
ffffffff80000000 | -2 GB | ffffffffffffffff | 2 GB | kernel
__________________|____________|__________________|_________|____________________________________________________________
/* SPDX-License-Identifier: GPL-2.0 */
/*
* CSS tweaks for the Alabaster theme
*/
/* Shrink the headers a bit */
div.body h1 { font-size: 180%; }
div.body h2 { font-size: 150%; }
div.body h3 { font-size: 130%; }
/* Tighten up the layout slightly */
div.body { padding: 0 15px 0 10px; }
div.sphinxsidebarwrapper { padding: 1em 0.4em; }
div.sphinxsidebar { font-size: inherit; }
/* Tweak document margins and don't force width */
div.document {
margin: 20px 10px 0 10px;
width: auto;
}
/*
* Parameters for the display of function prototypes and such included
* from C source files.
*/
dl.function, dl.struct, dl.enum { margin-top: 2em; background-color: #ecf0f3; }
/* indent lines 2+ of multi-line function prototypes */
dl.function dt { margin-left: 10em; text-indent: -10em; }
dt.sig-object { font-size: larger; }
div.kernelindent { margin-left: 2em; margin-right: 4em; }
# jinja2>=3.1 is not compatible with Sphinx<4.0
jinja2<3.1
sphinx_rtd_theme
Sphinx==2.4.4
......@@ -12,6 +12,7 @@ Translations
it_IT/index
ko_KR/index
ja_JP/index
sp_SP/index
.. _translations_disclaimer:
......
......@@ -86,9 +86,14 @@ info ページ( info gcc )を見てください。
--------
Linux カーネルのソースコードは GPL ライセンスの下でリリースされていま
す。ライセンスの詳細については、ソースツリーのメインディレクトリに存在
する、COPYING のファイルを見てください。もしライセンスについてさらに質
問があれば、Linux Kernel メーリングリストに質問するのではなく、どうぞ
す。ソースツリーのメインディレクトリにある COPYING のファイルを見てく
ださい。Linux カーネルのライセンスルールとソースコード内の
`SPDX <https://spdx.org/>`_ 識別子の使い方は
:ref:`Documentation/process/license-rules.rst <kernel_licensing>`
に説明されています。
もしライセンスについてさらに質問があれば、
Linux Kernel メーリングリストに質問するのではなく、どうぞ
法律家に相談してください。メーリングリストの人達は法律家ではなく、法的
問題については彼らの声明はあてにするべきではありません。
......@@ -111,7 +116,7 @@ linux-api@vger.kernel.org に送ることを勧めます。
以下はカーネルソースツリーに含まれている読んでおくべきファイルの一覧で
す-
README
:ref:`Documentation/admin-guide/README.rst <readme>`
このファイルは Linuxカーネルの簡単な背景とカーネルを設定(訳注
configure )し、生成(訳注 build )するために必要なことは何かが書かれ
ています。 カーネルに関して初めての人はここからスタートすると良い
......@@ -145,7 +150,8 @@ linux-api@vger.kernel.org に送ることを勧めます。
この他にパッチを作る方法についてのよくできた記述は-
"The Perfect Patch"
http://www.ozlabs.org/~akpm/stuff/tpp.txt
https://www.ozlabs.org/~akpm/stuff/tpp.txt
"Linux kernel patch submission format"
https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html
......@@ -237,13 +243,6 @@ Linux カーネルソースツリーの中に含まれる、きれいにし、
れるための基礎を学ぶことができ、そしてもしあなたがまだアイディアを持っ
ていない場合には、次にやる仕事の方向性が見えてくるかもしれません。
もしあなたが、すでにひとまとまりコードを書いていて、カーネルツリーに入
れたいと思っていたり、それに関する適切な支援を求めたい場合、カーネルメ
ンターズプロジェクトはそのような皆さんを助けるためにできました。ここに
はメーリングリストがあり、以下から参照できます -
https://selenic.com/mailman/listinfo/kernel-mentors
実際に Linux カーネルのコードについて修正を加える前に、どうやってその
コードが動作するのかを理解することが必要です。そのためには、特別なツー
ルの助けを借りてでも、それを直接よく読むことが最良の方法です(ほとんど
......@@ -280,9 +279,11 @@ https://kernel.org のリポジトリに存在します。
大きな変更は git(カーネルのソース管理ツール、詳細は
http://git-scm.com/ 参照) を使って送るのが好ましいやり方ですが、パッ
チファイルの形式のまま送るのでも十分です。
- 2週間後、-rc1 カーネルがリリースされ、この後にはカーネル全体の安定
性に影響をあたえるような新機能は含まない類のパッチしか取り込むこと
はできません。新しいドライバ(もしくはファイルシステム)のパッチは
- 2週間後 -rc1 カーネルがリリースされ、新しいカーネルを可能な限り堅牢に
することに焦点が移ります。この期間のパッチのほとんどは退行を修正する
ものとなります。以前から存在していたバグは退行には当たらないため、
送るのは重要な修正だけにしてください。
新しいドライバ (もしくはファイルシステム) のパッチは
-rc1 の後で受け付けられることもあることを覚えておいてください。な
ぜなら、変更が独立していて、追加されたコードの外の領域に影響を与え
ない限り、退行のリスクは無いからです。-rc1 がリリースされた後、
......@@ -308,9 +309,12 @@ Andrew Morton が Linux-kernel メーリングリストにカーネルリリー
バージョン番号が3つの数字に分かれているカーネルは -stable カーネルです。
これには最初の2つのバージョン番号の数字に対応した、
メインラインリリースで見つかったセキュリティ問題や
ジャーメインラインリリースで見つかったセキュリティ問題や
重大な後戻りに対する比較的小さい重要な修正が含まれます。
メジャー安定版シリーズのそれぞれのリリースは
バージョン番号の3番目を増加させ、最初の2つの番号は同じ値を保ちます。
これは、開発/実験的バージョンのテストに協力することに興味が無く、最新
の安定したカーネルを使いたいユーザに推奨するブランチです。
......@@ -366,16 +370,10 @@ linux-next の実行テストを行う冒険好きなテスターは大いに歓
バグレポート
-------------
https://bugzilla.kernel.org は Linux カーネル開発者がカーネルのバグを追跡する
場所です。ユーザは見つけたバグの全てをこのツールで報告すべきです。どう
kernel bugzilla を使うかの詳細は、以下を参照してください -
https://bugzilla.kernel.org/page.cgi?id=faq.html
メインカーネルソースディレクトリにあるファイル
admin-guide/reporting-bugs.rstはカーネルバグらしいものについてどうレポー
トするかの良いテンプレートであり、問題の追跡を助けるためにカーネル開発
者にとってどんな情報が必要なのかの詳細が書かれています。
'Documentation/admin-guide/reporting-issues.rst'
は、カーネルバグらしきものの報告の仕方、および、カーネル開発者が問題を
追跡する際の手がかりとなる情報についての詳細を説明しています。
バグレポートの管理
-------------------
......@@ -388,15 +386,13 @@ admin-guide/reporting-bugs.rstはカーネルバグらしいものについて
道です、なぜなら多くの人は他人のバグの修正に時間を浪費することを好まな
いからです。
すでにレポートされたバグのために仕事をするためには、
https://bugzilla.kernel.org に行ってください。もし今後のバグレポートに
ついてアドバイスを受けたいのであれば、bugme-new メーリングリスト(新し
いバグレポートだけがここにメールされる) または bugme-janitor メーリン
グリスト(bugzilla の変更毎にここにメールされる)を購読できます。
https://lists.linux-foundation.org/mailman/listinfo/bugme-new
https://lists.linux-foundation.org/mailman/listinfo/bugme-janitors
すでにレポートされたバグの作業をするためには、興味のあるサブシステムを
見つけ、そのサブシステムのバグの報告先 (多くの場合メーリングリスト、
稀にバグトラッカー) を MAINTAINERS ファイルで調べてください。
そのアーカイブで最近の報告を検索し、できそうなものに力を貸してください。
https://bugzilla.kernel.org でバグ報告を調べようとする人もいるでしょう。
これは限られた一部のサブシステムのバグ報告と追跡に利用されるとともに、
とりわけ、カーネル全体に対するバグの登録先となっています。
メーリングリスト
----------------
......@@ -621,7 +617,7 @@ Linux カーネルコミュニティは、一度に大量のコードの塊を
ントの ChangeLog セクションを見てください -
"The Perfect Patch"
http://www.ozlabs.org/~akpm/stuff/tpp.txt
https://www.ozlabs.org/~akpm/stuff/tpp.txt
これらはどれも、実行することが時にはとても困難です。これらの例を完璧に
実施するには数年かかるかもしれません。これは継続的な改善のプロセスであ
......
:orphan:
.. warning::
Si tiene alguna duda sobre la exactitud del contenido de esta
traducción, la única referencia válida es la documentación oficial en
inglés.
.. include:: ./disclaimer-sp.rst
:Original: :ref:`Documentation/process/howto.rst <process_howto>`
:Translator: Carlos Bilbao <carlos.bilbao@amd.com>
.. _sp_process_howto:
Cómo participar en el desarrollo del kernel de Linux
====================================================
Este documento es el principal punto de partida. Contiene instrucciones
sobre cómo convertirse en desarrollador del kernel de Linux y explica cómo
trabajar con el y en su desarrollo. El documento no tratará ningún aspecto
técnico relacionado con la programación del kernel, pero le ayudará
guiándole por el camino correcto.
Si algo en este documento quedara obsoleto, envíe parches al maintainer de
este archivo, que se encuentra en la parte superior del documento.
Introducción
------------
¿De modo que quiere descubrir como convertirse en un/a desarrollador/a del
kernel de Linux? Tal vez su jefe le haya dicho, "Escriba un driver de
Linux para este dispositivo." El objetivo de este documento en enseñarle
todo cuanto necesita para conseguir esto, describiendo el proceso por el
que debe pasar, y con indicaciones de como trabajar con la comunidad.
También trata de explicar las razones por las cuales la comunidad trabaja
de la forma en que lo hace.
El kernel esta principalmente escrito en C, con algunas partes que son
dependientes de la arquitectura en ensamblador. Un buen conocimiento de C
es necesario para desarrollar en el kernel. Lenguaje ensamblador (en
cualquier arquitectura) no es necesario excepto que planee realizar
desarrollo de bajo nivel para dicha arquitectura. Aunque no es un perfecto
sustituto para una educación sólida en C y/o años de experiencia, los
siguientes libros sirven, como mínimo, como referencia:
- "The C Programming Language" de Kernighan e Ritchie [Prentice Hall]
- "Practical C Programming" de Steve Oualline [O'Reilly]
- "C: A Reference Manual" de Harbison and Steele [Prentice Hall]
El kernel está escrito usando GNU C y la cadena de herramientas GNU. Si
bien se adhiere al estándar ISO C89, utiliza una serie de extensiones que
no aparecen en dicho estándar. El kernel usa un C independiente de entorno,
sin depender de la biblioteca C estándar, por lo que algunas partes del
estándar C no son compatibles. Divisiones de long long arbitrarios o
de coma flotante no son permitidas. En ocasiones, puede ser difícil de
entender las suposiciones que el kernel hace respecto a la cadena de
herramientas y las extensiones que usa, y desafortunadamente no hay
referencia definitiva para estas. Consulte las páginas de información de
gcc (`info gcc`) para obtener información al respecto.
Recuerde que está tratando de aprender a trabajar con una comunidad de
desarrollo existente. Es un grupo diverso de personas, con altos estándares
de código, estilo y procedimiento. Estas normas han sido creadas a lo
largo del tiempo en función de lo que se ha encontrado que funciona mejor
para un equipo tan grande y geográficamente disperso. Trate de aprender
tanto como le sea posible acerca de estos estándares antes de tiempo, ya
que están bien documentados; no espere que la gente se adapte a usted o a
la forma de hacer las cosas en su empresa.
Cuestiones legales
------------------
El código fuente del kernel de Linux se publica bajo licencia GPL. Por
favor, revise el archivo COPYING, presente en la carpeta principal del
código fuente, para detalles de la licencia. Si tiene alguna otra pregunta
sobre licencias, contacte a un abogado, no pregunte en listas de discusión
del kernel de Linux. La gente en estas listas no son abogadas, y no debe
confiar en sus opiniones en materia legal.
Para preguntas y respuestas más frecuentes sobre la licencia GPL, consulte:
https://www.gnu.org/licenses/gpl-faq.html
Documentación
--------------
El código fuente del kernel de Linux tiene una gran variedad de documentos
que son increíblemente valiosos para aprender a interactuar con la
comunidad del kernel. Cuando se agregan nuevas funciones al kernel, se
recomienda que se incluyan nuevos archivos de documentación que expliquen
cómo usar la función. Cuando un cambio en el kernel hace que la interfaz
que el kernel expone espacio de usuario cambie, se recomienda que envíe la
información o un parche en las páginas del manual que expliquen el cambio
a mtk.manpages@gmail.com, y CC la lista linux-api@vger.kernel.org.
Esta es la lista de archivos que están en el código fuente del kernel y son
de obligada lectura:
:ref:`Documentation/admin-guide/README.rst <readme>`
Este archivo ofrece una breve descripción del kernel de Linux y
describe lo que es necesario hacer para configurar y compilar el
kernel. Quienes sean nuevos en el kernel deben comenzar aquí.
:ref:`Documentation/process/changes.rst <changes>`
Este archivo proporciona una lista de los niveles mínimos de varios
paquetes que son necesarios para construir y ejecutar el kernel
exitosamente.
:ref:`Documentation/process/coding-style.rst <codingstyle>`
Esto describe el estilo de código del kernel de Linux y algunas de los
razones detrás de esto. Se espera que todo el código nuevo siga las
directrices de este documento. La mayoría de los maintainers solo
aceptarán parches si se siguen estas reglas, y muchas personas solo
revisan el código si tiene el estilo adecuado.
:ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
Este archivo describe en gran detalle cómo crear con éxito y enviar un
parche, que incluye (pero no se limita a):
- Contenidos del correo electrónico (email)
- Formato del email
- A quien se debe enviar
Seguir estas reglas no garantiza el éxito (ya que todos los parches son
sujetos a escrutinio de contenido y estilo), pero en caso de no seguir
dichas reglas, el fracaso es prácticamente garantizado.
Otras excelentes descripciones de cómo crear parches correctamente son:
"The Perfect Patch"
https://www.ozlabs.org/~akpm/stuff/tpp.txt
"Linux kernel patch submission format"
https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html
:ref:`Documentation/process/stable-api-nonsense.rst <stable_api_nonsense>`
Este archivo describe la lógica detrás de la decisión consciente de
no tener una API estable dentro del kernel, incluidas cosas como:
- Capas intermedias del subsistema (por compatibilidad?)
- Portabilidad de drivers entre sistemas operativos
- Mitigar el cambio rápido dentro del árbol de fuentes del kernel (o
prevenir cambios rápidos)
Este documento es crucial para comprender la filosofía del desarrollo
de Linux y es muy importante para las personas que se mudan a Linux
tras desarrollar otros sistemas operativos.
:ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
Si cree que ha encontrado un problema de seguridad en el kernel de
Linux, siga los pasos de este documento para ayudar a notificar a los
desarrolladores del kernel y ayudar a resolver el problema.
:ref:`Documentation/process/management-style.rst <managementstyle>`
Este documento describe cómo operan los maintainers del kernel de Linux
y los valores compartidos detrás de sus metodologías. Esta es una
lectura importante para cualquier persona nueva en el desarrollo del
kernel (o cualquier persona que simplemente sienta curiosidad por
el campo IT), ya que clarifica muchos conceptos erróneos y confusiones
comunes sobre el comportamiento único de los maintainers del kernel.
:ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
Este archivo describe las reglas sobre cómo se suceden las versiones
del kernel estable, y qué hacer si desea obtener un cambio en una de
estas publicaciones.
:ref:`Documentation/process/kernel-docs.rst <kernel_docs>`
Una lista de documentación externa relativa al desarrollo del kernel.
Por favor consulte esta lista si no encuentra lo que están buscando
dentro de la documentación del kernel.
:ref:`Documentation/process/applying-patches.rst <applying_patches>`
Una buena introducción que describe exactamente qué es un parche y cómo
aplicarlo a las diferentes ramas de desarrollo del kernel.
El kernel también tiene una gran cantidad de documentos que pueden ser
generados automáticamente desde el propio código fuente o desde
ReStructuredText markups (ReST), como este. Esto incluye un descripción
completa de la API en el kernel y reglas sobre cómo manejar cerrojos
(locking) correctamente.
Todos estos documentos se pueden generar como PDF o HTML ejecutando::
make pdfdocs
make htmldocs
respectivamente desde el directorio fuente principal del kernel.
Los documentos que utilizan el markup ReST se generarán en
Documentation/output. También se pueden generar en formatos LaTeX y ePub
con::
make latexdocs
make epubdocs
Convertirse en un/a desarrollador/a de kernel
---------------------------------------------
Si no sabe nada sobre el desarrollo del kernel de Linux, debería consultar
el proyecto Linux KernelNewbies:
https://kernelnewbies.org
Consiste en una útil lista de correo donde puede preguntar casi cualquier
tipo de pregunta básica de desarrollo del kernel (asegúrese de buscar en
los archivos primero, antes de preguntar algo que ya ha sido respondido en
el pasado.) También tiene un canal IRC que puede usar para hacer preguntas
en tiempo real, y una gran cantidad de documentación útil para ir
aprendiendo sobre el desarrollo del kernel de Linux.
El sitio web tiene información básica sobre la organización del código,
subsistemas, y proyectos actuales (tanto dentro como fuera del árbol).
También describe alguna información logística básica, como cómo compilar
un kernel y aplicar un parche.
Si no sabe por dónde quiere empezar, pero quieres buscar alguna tarea que
comenzar a hacer para unirse a la comunidad de desarrollo del kernel,
acuda al proyecto Linux Kernel Janitor:
https://kernelnewbies.org/KernelJanitors
Es un gran lugar para comenzar. Describe una lista de problemas
relativamente simples que deben limpiarse y corregirse dentro del código
fuente del kernel de Linux árbol de fuentes. Trabajando con los
desarrolladores a cargo de este proyecto, aprenderá los conceptos básicos
para incluir su parche en el árbol del kernel de Linux, y posiblemente
descubrir en la dirección en que trabajar a continuación, si no tiene ya
una idea.
Antes de realizar cualquier modificación real al código del kernel de
Linux, es imperativo entender cómo funciona el código en cuestión. Para
este propósito, nada es mejor que leerlo directamente (lo más complicado
está bien comentado), tal vez incluso con la ayuda de herramientas
especializadas. Una de esas herramientas que se recomienda especialmente
es el proyecto Linux Cross-Reference, que es capaz de presentar el código
fuente en un formato de página web indexada y autorreferencial. Una
excelente puesta al día del repositorio del código del kernel se puede
encontrar en:
https://elixir.bootlin.com/
El proceso de desarrollo
------------------------
El proceso de desarrollo del kernel de Linux consiste actualmente de
diferentes "branches" (ramas) con muchos distintos subsistemas específicos
a cada una de ellas. Las diferentes ramas son:
- El código principal de Linus (mainline tree)
- Varios árboles estables con múltiples major numbers
- Subsistemas específicos
- linux-next, para integración y testing
Mainline tree (Árbol principal)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
El mainline tree es mantenido por Linus Torvalds, y puede encontrarse en
https://kernel.org o en su repo. El proceso de desarrollo es el siguiente:
- Tan pronto como se lanza un nuevo kernel, se abre una ventana de dos
semanas, durante este período de tiempo, los maintainers pueden enviar
grandes modificaciones a Linus, por lo general los parches que ya se
han incluido en el linux-next durante unas semanas. La forma preferida
de enviar grandes cambios es usando git (la herramienta de
administración de código fuente del kernel, más información al respecto
en https://git-scm.com/), pero los parches simples también son validos.
- Después de dos semanas, se lanza un kernel -rc1 y la atención se centra
en hacer el kernel nuevo lo más estable ("solido") posible. La mayoría
de los parches en este punto deben arreglar una regresión. Los errores
que siempre han existido no son regresiones, por lo tanto, solo envíe
este tipo de correcciones si son importantes. Tenga en cuenta que se
podría aceptar un controlador (o sistema de archivos) completamente
nuevo después de -rc1 porque no hay riesgo de causar regresiones con
tal cambio, siempre y cuando el cambio sea autónomo y no afecte áreas
fuera del código que se está agregando. git se puede usar para enviar
parches a Linus después de que se lance -rc1, pero los parches también
deben ser enviado a una lista de correo pública para su revisión.
- Se lanza un nuevo -rc cada vez que Linus considera que el árbol git
actual esta en un estado razonablemente sano y adecuado para la prueba.
La meta es lanzar un nuevo kernel -rc cada semana.
- El proceso continúa hasta que el kernel se considera "listo", y esto
puede durar alrededor de 6 semanas.
Vale la pena mencionar lo que Andrew Morton escribió en las listas de
correo del kernel de Linux, sobre lanzamientos del kernel (traducido):
*"Nadie sabe cuándo se publicara un nuevo kernel, pues esto sucede
según el estado de los bugs, no de una cronología preconcebida."*
Varios árboles estables con múltiples major numbers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Los kernels con versiones de 3 partes son kernels estables. Estos contienen
correcciones relativamente pequeñas y críticas para problemas de seguridad
o importantes regresiones descubiertas para una publicación de código.
Cada lanzamiento en una gran serie estable incrementa la tercera parte de
la versión número, manteniendo las dos primeras partes iguales.
Esta es la rama recomendada para los usuarios que quieren la versión
estable más reciente del kernel, y no están interesados en ayudar a probar
versiones en desarrollo/experimentales.
Los árboles estables son mantenidos por el equipo "estable"
<stable@vger.kernel.org>, y se liberan (publican) según lo dicten las
necesidades. El período de liberación normal es de aproximadamente dos
semanas, pero puede ser más largo si no hay problemas apremiantes. Un
problema relacionado con la seguridad, en cambio, puede causar un
lanzamiento casi instantáneamente.
El archivo :ref:`Documentación/proceso/stable-kernel-rules.rst <stable_kernel_rules>`
en el árbol del kernel documenta qué tipos de cambios son aceptables para
el árbol estable y cómo funciona el proceso de lanzamiento.
Subsistemas específicos
~~~~~~~~~~~~~~~~~~~~~~~~
Los maintainers de los diversos subsistemas del kernel --- y también muchos
desarrolladores de subsistemas del kernel --- exponen su estado actual de
desarrollo en repositorios fuente. De esta manera, otros pueden ver lo que
está sucediendo en las diferentes áreas del kernel. En áreas donde el
desarrollo es rápido, se le puede pedir a un desarrollador que base sus
envíos en tal árbol del subsistema del kernel, para evitar conflictos entre
este y otros trabajos ya en curso.
La mayoría de estos repositorios son árboles git, pero también hay otros
SCM en uso, o colas de parches que se publican como series quilt. Las
direcciones de estos repositorios de subsistemas se enumeran en el archivo
MAINTAINERS. Muchos de estos se pueden ver en https://git.kernel.org/.
Antes de que un parche propuesto se incluya con dicho árbol de subsistemas,
es sujeto a revisión, que ocurre principalmente en las listas de correo
(ver la sección respectiva a continuación). Para varios subsistemas del
kernel, esta revisión se rastrea con la herramienta patchwork. Patchwork
ofrece una interfaz web que muestra publicaciones de parches, cualquier
comentario sobre un parche o revisiones a él, y los maintainers pueden
marcar los parches como en revisión, aceptado, o rechazado. La mayoría de
estos sitios de trabajo de parches se enumeran en
https://patchwork.kernel.org/.
linux-next, para integración y testing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Antes de que las actualizaciones de los árboles de subsistemas se combinen
con el árbol principal, necesitan probar su integración. Para ello, existe
un repositorio especial de pruebas en el que se encuentran casi todos los
árboles de subsistema, actualizado casi a diario:
https://git.kernel.org/?p=linux/kernel/git/next/linux-next.git
De esta manera, linux-next ofrece una perspectiva resumida de lo que se
espera que entre en el kernel principal en el próximo período de "merge"
(fusión de código). Los testers aventureros son bienvenidos a probar
linux-next en ejecución.
Reportar bugs
-------------
El archivo 'Documentación/admin-guide/reporting-issues.rst' en el
directorio principal del kernel describe cómo informar un posible bug del
kernel y detalles sobre qué tipo de información necesitan los
desarrolladores del kernel para ayudar a rastrear la fuente del problema.
Gestión de informes de bugs
------------------------------
Una de las mejores formas de poner en práctica sus habilidades de hacking
es arreglando errores reportados por otras personas. No solo ayudará a
hacer el kernel más estable, también aprenderá a solucionar problemas del
mundo real y mejora sus habilidades, y otros desarrolladores se darán
cuenta de tu presencia. La corrección de errores es una de las mejores
formas de ganar méritos entre desarrolladores, porque no a muchas personas
les gusta perder el tiempo arreglando los errores de otras personas.
Para trabajar en informes de errores ya reportados, busque un subsistema
que le interese. Verifique el archivo MAINTAINERS donde se informan los
errores de ese subsistema; con frecuencia será una lista de correo, rara
vez un rastreador de errores (bugtracker). Busque en los archivos de dicho
lugar para informes recientes y ayude donde lo crea conveniente. También es
posible que desee revisar https://bugzilla.kernel.org para informes de
errores; solo un puñado de subsistemas del kernel lo emplean activamente
para informar o rastrear; sin embargo, todos los errores para todo el kernel
se archivan allí.
Listas de correo
-----------------
Como se explica en algunos de los documentos anteriores, la mayoría de
desarrolladores del kernel participan en la lista de correo del kernel de
Linux. Detalles sobre cómo para suscribirse y darse de baja de la lista se
pueden encontrar en:
http://vger.kernel.org/vger-lists.html#linux-kernel
Existen archivos de la lista de correo en la web en muchos lugares
distintos. Utilice un motor de búsqueda para encontrar estos archivos. Por
ejemplo:
http://dir.gmane.org/gmane.linux.kernel
Es muy recomendable que busque en los archivos sobre el tema que desea
tratar, antes de publicarlo en la lista. Un montón de cosas ya discutidas
en detalle solo se registran en los archivos de la lista de correo.
La mayoría de los subsistemas individuales del kernel también tienen sus
propias lista de correo donde hacen sus esfuerzos de desarrollo. Revise el
archivo MAINTAINERS para obtener referencias de lo que estas listas para
los diferentes grupos.
Muchas de las listas están alojadas en kernel.org. La información sobre
estas puede ser encontrada en:
http://vger.kernel.org/vger-lists.html
Recuerde mantener buenos hábitos de comportamiento al usar las listas.
Aunque un poco cursi, la siguiente URL tiene algunas pautas simples para
interactuar con la lista (o cualquier lista):
http://www.albion.com/netiquette/
Si varias personas responden a su correo, el CC (lista de destinatarios)
puede hacerse bastante grande. No elimine a nadie de la lista CC: sin una
buena razón, o no responda solo a la dirección de la lista. Acostúmbrese
a recibir correos dos veces, una del remitente y otra de la lista, y no
intente ajustar esto agregando encabezados de correo astutos, a la gente no
le gustará.
Recuerde mantener intacto el contexto y la atribución de sus respuestas,
mantenga las líneas "El hacker John Kernel escribió ...:" en la parte
superior de su respuesta, y agregue sus declaraciones entre las secciones
individuales citadas en lugar de escribiendo en la parte superior del
correo electrónico.
Si incluye parches en su correo, asegúrese de que sean texto legible sin
formato como se indica en :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`.
Los desarrolladores del kernel no quieren lidiar con archivos adjuntos o
parches comprimidos; y pueden querer comentar líneas individuales de su
parche, que funciona sólo de esa manera. Asegúrese de emplear un programa
de correo que no altere los espacios ni los tabuladores. Una buena primera
prueba es enviarse el correo a usted mismo, e intentar aplicar su
propio parche. Si eso no funciona, arregle su programa de correo o
reemplace hasta que funcione.
Sobretodo, recuerde de ser respetuoso con otros subscriptores.
Colaborando con la comunidad
----------------------------
El objetivo de la comunidad del kernel es proporcionar el mejor kernel
posible. Cuando envíe un parche para su aceptación, se revisará en sus
méritos técnicos solamente. Entonces, ¿qué deberías ser?
- críticas
- comentarios
- peticiones de cambios
- peticiones de justificaciones
- silencio
Recuerde, esto es parte de introducir su parche en el kernel. Tiene que ser
capaz de recibir críticas y comentarios sobre sus parches, evaluar
a nivel técnico y re-elaborar sus parches o proporcionar razonamiento claro
y conciso de por qué no se deben hacer tales cambios. Si no hay respuestas
a su publicación, espere unos días e intente de nuevo, a veces las cosas se
pierden dado el gran volumen.
¿Qué no debería hacer?
- esperar que su parche se acepte sin preguntas
- actuar de forma defensiva
- ignorar comentarios
- enviar el parche de nuevo, sin haber aplicados los cambios pertinentes
En una comunidad que busca la mejor solución técnica posible, siempre habrá
diferentes opiniones sobre lo beneficioso que es un parche. Tiene que ser
cooperativo y estar dispuesto a adaptar su idea para que encaje dentro
del kernel, o al menos esté dispuesto a demostrar que su idea vale la pena.
Recuerde, estar equivocado es aceptable siempre y cuando estés dispuesto a
trabajar hacia una solución que sea correcta.
Es normal que las respuestas a su primer parche sean simplemente una lista
de una docena de cosas que debe corregir. Esto **no** implica que su
parche no será aceptado, y **no** es personal. Simplemente corrija todos
los problemas planteados en su parche, y envié otra vez.
Diferencias entre la comunidad kernel y las estructuras corporativas
--------------------------------------------------------------------
La comunidad del kernel funciona de manera diferente a la mayoría de los
entornos de desarrollo tradicionales en empresas. Aquí hay una lista de
cosas que puede intentar hacer para evitar problemas:
Cosas buenas que decir respecto a los cambios propuestos:
- "Esto arregla múltiples problemas."
- "Esto elimina 2000 lineas de código."
- "Aquí hay un parche que explica lo que intento describir."
- "Lo he testeado en 5 arquitecturas distintas..."
- "Aquí hay una serie de parches menores que..."
- "Esto mejora el rendimiento en maquinas típicas..."
Cosas negativas que debe evitar decir:
- "Lo hicimos así en AIX/ptx/Solaris, de modo que debe ser bueno..."
- "Llevo haciendo esto 20 años, de modo que..."
- "Esto lo necesita mi empresa para ganar dinero"
- "Esto es para la linea de nuestros productos Enterprise"
- "Aquí esta el documento de 1000 paginas describiendo mi idea"
- "Llevo 6 meses trabajando en esto..."
- "Aquí esta un parche de 5000 lineas que..."
- "He rescrito todo el desastre actual, y aquí esta..."
- "Tengo un deadline, y este parche debe aplicarse ahora."
Otra forma en que la comunidad del kernel es diferente a la mayoría de los
entornos de trabajo tradicionales en ingeniería de software, es la
naturaleza sin rostro de interacción. Una de las ventajas de utilizar el
correo electrónico y el IRC como formas principales de comunicación es la
no discriminación por motivos de género o raza. El entorno de trabajo del
kernel de Linux acepta a mujeres y minorías porque todo lo que eres es una
dirección de correo electrónico. El aspecto internacional también ayuda a
nivelar el campo de juego porque no puede adivinar el género basado en
el nombre de una persona. Un hombre puede llamarse Andrea y una mujer puede
llamarse Pat. La mayoría de las mujeres que han trabajado en el kernel de
Linux y han expresado una opinión han tenido experiencias positivas.
La barrera del idioma puede causar problemas a algunas personas que no se
sientes cómodas con el inglés. Un buen dominio del idioma puede ser
necesario para transmitir ideas correctamente en las listas de correo, por
lo que le recomendamos que revise sus correos electrónicos para asegurarse
de que tengan sentido en inglés antes de enviarlos.
Divida sus cambios
---------------------
La comunidad del kernel de Linux no acepta con gusto grandes fragmentos de
código, sobretodo a la vez. Los cambios deben introducirse correctamente,
discutidos y divididos en pequeñas porciones individuales. Esto es casi
exactamente lo contrario de lo que las empresas están acostumbradas a hacer.
Su propuesta también debe introducirse muy temprano en el proceso de
desarrollo, de modo que pueda recibir comentarios sobre lo que está
haciendo. También deje que la comunidad sienta que está trabajando con
ellos, y no simplemente usándolos como un vertedero para su función. Sin
embargo, no envíe 50 correos electrónicos a una vez a una lista de correo,
su serie de parches debe casi siempre ser más pequeña que eso.
Las razones para dividir las cosas son las siguientes:
1) Los cambios pequeños aumentan la probabilidad de que sus parches sean
aplicados, ya que no requieren mucho tiempo o esfuerzo para verificar su
exactitud. Un parche de 5 líneas puede ser aplicado por un maintainer
con apenas una segunda mirada. Sin embargo, un parche de 500 líneas
puede tardar horas en ser revisado en términos de corrección (el tiempo
que toma es exponencialmente proporcional al tamaño del parche, o algo
así).
Los parches pequeños también facilitan la depuración cuando algo falla.
Es mucho más fácil retirar los parches uno por uno que diseccionar un
parche muy grande después de haber sido aplicado (y roto alguna cosa).
2) Es importante no solo enviar pequeños parches, sino también reescribir
y simplificar (o simplemente reordenar) los parches antes de enviarlos.
Esta es una analogía del desarrollador del kernel Al Viro (traducida):
*"Piense en un maestro que califica la tarea de un estudiante de
matemáticas. El maestro no quiere ver los intentos y errores del
estudiante antes de que se les ocurriera la solución. Quiere ver la
respuesta más limpia y elegante. Un buen estudiante lo sabe, y nunca
presentaría su trabajo intermedio antes de tener la solución final.*
*Lo mismo ocurre con el desarrollo del kernel. Los maintainers y
revisores no quieren ver el proceso de pensamiento detrás de la solución
al problema que se está resolviendo. Quieren ver un solución simple y
elegante."*
Puede resultar un reto mantener el equilibrio entre presentar una solución
elegante y trabajar junto a la comunidad, discutiendo su trabajo inacabado.
Por lo tanto, es bueno comenzar temprano en el proceso para obtener
"feedback" y mejorar su trabajo, pero también mantenga sus cambios en
pequeños trozos que pueden ser aceptados, incluso cuando toda su labor no
está listo para inclusión en un momento dado.
También tenga en cuenta que no es aceptable enviar parches para su
inclusión que están sin terminar y serán "arreglados más tarde".
Justifique sus cambios
----------------------
Además de dividir sus parches, es muy importante que deje a la comunidad de
Linux sabe por qué deberían agregar este cambio. Nuevas características
debe justificarse como necesarias y útiles.
Documente sus cambios
---------------------
Cuando envíe sus parches, preste especial atención a lo que dice en el
texto de su correo electrónico. Esta información se convertirá en el
ChangeLog del parche, y se conservará para que todos la vean, todo el
tiempo. Debe describir el parche por completo y contener:
- por qué los cambios son necesarios
- el diseño general de su propuesta
- detalles de implementación
- resultados de sus experimentos
Para obtener más detalles sobre cómo debería quedar todo esto, consulte la
sección ChangeLog del documento:
"The Perfect Patch"
https://www.ozlabs.org/~akpm/stuff/tpp.txt
Todas estas cuestiones son a veces son muy difíciles de conseguir. Puede
llevar años perfeccionar estas prácticas (si es que lo hace). Es un proceso
continuo de mejora que requiere mucha paciencia y determinación. Pero no se
rinda, es posible. Muchos lo han hecho antes, y cada uno tuvo que comenzar
exactamente donde está usted ahora.
----------
Gracias a Paolo Ciarrocchi que permitió que la sección "Development Process"
se basara en el texto que había escrito (https://lwn.net/Articles/94386/),
y a Randy Dunlap y Gerrit Huizenga por algunas de la lista de cosas que
debes y no debes decir. También gracias a Pat Mochel, Hanna Linder, Randy
Dunlap, Kay Sievers, Vojtech Pavlik, Jan Kara, Josh Boyer, Kees Cook,
Andrew Morton, Andi Kleen, Vadim Lobanov, Jesper Juhl, Adrian Bunk,
Keri Harris, Frans Pop, David A. Wheeler, Junio Hamano, Michael Kerrisk y
Alex Shepard por su revisión, comentarios y contribuciones. Sin su ayuda,
este documento no hubiera sido posible.
Maintainer: Greg Kroah-Hartman <greg@kroah.com>
=====================
Traducción al español
=====================
.. raw:: latex
\kerneldocCJKoff
:maintainer: Carlos Bilbao <carlos.bilbao@amd.com>
.. _sp_disclaimer:
Advertencia
===========
El objetivo de esta traducción es facilitar la lectura y comprensión para
aquellos que no entiendan inglés o duden de sus interpretaciones, o
simplemente para aquellos que prefieran leer en el idioma español. Sin
embargo, tenga en cuenta que la *única* documentación oficial es la que
está en inglés: :ref:`linux_doc`
La propagación simultánea de la traducción de una modificación en
:ref:`linux_doc` es altamente improbable. Los maintainers y colaboradores
de la traducción intentan mantener sus traducciones al día, en tanto les
es posible. Por tanto, no existe ninguna garantía de que una traducción
esté actualizada con las últimas modificaciones. Si lo que lee en una
traducción no se corresponde con lo que ve en el código fuente, informe
al maintainer de la traducción y, si puede, consulte la documentación en
inglés.
Una traducción no es una * bifurcación * de la documentación oficial, por
lo que los usuarios no encontrarán aquí ninguna información que no sea la
versión oficial. Cualquier adición, supresión o modificación de los
contenidos deberá ser realizada anteriormente en los documentos en inglés.
Posteriormente, y cuando sea posible, dicho cambio debería aplicarse
también a las traducciones. Los maintainers de las traducciones aceptan
contribuciones que son puramente de interés relativo a la traducción (por
ejemplo, nuevas traducciones, actualizaciones, correcciones, etc.).
Las traducciones tratan de ser lo más precisas posible pero no es posible
convertir directamente un idioma a otro. Cada idioma tiene su propia
gramática, y una cultura tras ella, por lo tanto, la traducción de una
oración al inglés se podría modificar para adaptarla al español. Por esta
razón, cuando lea esta traducción, puede encontrar algunas diferencias en
la forma, pero todavía transmiten el mensaje original. A pesar de la gran
difusión del inglés en el idioma hablado, cuando sea posible, expresiones
en inglés serán reemplazadas por las palabras correspondientes en español.
Si necesita ayuda para comunicarse con la comunidad de Linux pero no se
siente cómodo escribiendo en inglés, puede pedir ayuda al maintainer para
obtener una traducción.
Muchos países hablan español, cada uno con su propia cultura, expresiones,
y diferencias gramaticales en ocasiones significativas. Las traducciones de
los maintainers pueden utilizar el español con el que dichos maintainers se
sientan más cómodos. En principio, estas pequeñas diferencias no deberían
suponer una gran barrera para hablantes de distintas versiones del español,
pero en caso de duda se puede consultar a los maintainers.
La documentación del kernel Linux
=================================
Este es el nivel superior de la documentación del kernel en idioma español.
La traducción es incompleta, y podría encontrar advertencias que indiquen
la falta de una traducción o de un grupo de traducciones.
En términos más generales, la documentación, como el kernel mismo, están en
constante desarrollo. Las mejoras en la documentación siempre son
bienvenidas; de modo que, si desea ayudar, únase a la lista de correo
linux-doc en vger.kernel.org.
Traducciones al español
=======================
.. toctree::
:maxdepth: 1
howto
process/index
wrappers/memory-barriers
This source diff could not be displayed because it is too large. You can view the blob instead.
.. include:: ../disclaimer-sp.rst
:Original: :ref:`Documentation/process/coding-style.rst <submittingpatches>`
:Translator: Carlos Bilbao <carlos.bilbao@amd.com>
.. _sp_codingstyle:
Estilo en el código del kernel Linux
=====================================
Este es un breve documento que describe el estilo preferido en el código
del kernel Linux. El estilo de código es muy personal y no **forzaré** mi
puntos de vista sobre nadie, pero esto vale para todo lo que tengo que
mantener, y preferiría que para la mayoría de otras cosas también. Por
favor, por lo menos considere los argumentos expuestos aquí.
En primer lugar, sugeriría imprimir una copia de los estándares de código
GNU, y NO leerlo. Quémelos, es un gran gesto simbólico.
De todos modos, aquí va:
1) Sangría
-----------
Las tabulaciones tienen 8 caracteres y, por lo tanto, las sangrías también
tienen 8 caracteres. Hay movimientos heréticos que intentan hacer sangría
de 4 (¡o incluso 2!) caracteres de longitud, y eso es similar a tratar de
definir el valor de PI como 3.
Justificación: La idea detrás de la sangría es definir claramente dónde
comienza y termina un bloque de control. Especialmente, cuando ha estado
buscando en su pantalla durante 20 horas seguidas, le resultará mucho más
fácil ver cómo funciona la sangría si tiene sangrías grandes.
Bueno, algunas personas dirán que tener sangrías de 8 caracteres hace que
el código se mueva demasiado a la derecha y dificulta la lectura en una
pantalla de terminal de 80 caracteres. La respuesta a eso es que si
necesita más de 3 niveles de sangría, está en apuros de todos modos y
debería arreglar su programa.
En resumen, las sangrías de 8 caracteres facilitan la lectura y tienen la
ventaja añadida de advertirle cuando está anidando sus funciones demasiado
profundo. Preste atención a esa advertencia.
La forma preferida de facilitar múltiples niveles de sangría en una
declaración de switch es para alinear el ``switch`` y sus etiquetas
``case`` subordinadas en la misma columna, en lugar de hacer ``doble
sangría`` (``double-indenting``) en etiquetas ``case``. Por ejemplo:
.. code-block:: c
switch (suffix) {
case 'G':
case 'g':
mem <<= 30;
break;
case 'M':
case 'm':
mem <<= 20;
break;
case 'K':
case 'k':
mem <<= 10;
fallthrough;
default:
break;
}
No ponga varias declaraciones en una sola línea a menos que tenga algo que
ocultar:
.. code-block:: c
if (condición) haz_esto;
haz_otra_cosa;
No use comas para evitar el uso de llaves:
.. code-block:: c
if (condición)
haz_esto(), haz_eso();
Siempre use llaves para múltiples declaraciones:
.. code-block:: c
if (condición) {
haz_esto();
haz_eso();
}
Tampoco ponga varias asignaciones en una sola línea. El estilo de código
del kernel es súper simple. Evite las expresiones engañosas.
Aparte de los comentarios, la documentación y excepto en Kconfig, los
espacios nunca se utilizan para la sangría, y el ejemplo anterior se rompe
deliberadamente.
Consiga un editor decente y no deje espacios en blanco al final de las
líneas.
2) Rompiendo líneas y strings largos
------------------------------------
El estilo de código tiene todo que ver con la legibilidad y la
mantenibilidad usando herramientas disponibles comúnmente.
El límite preferido en la longitud de una sola línea es de 80 columnas.
Las declaraciones de más de 80 columnas deben dividirse en partes, a menos
que exceder las 80 columnas aumente significativamente la legibilidad y no
oculte información.
Los descendientes siempre son sustancialmente más cortos que el padre y
se colocan sustancialmente a la derecha. Un estilo muy usado es alinear
descendientes a un paréntesis de función abierto.
Estas mismas reglas se aplican a los encabezados de funciones con una larga
lista de argumentos.
Sin embargo, nunca rompa los strings visibles para el usuario, como los
mensajes printk, porque eso rompe la capacidad de grep a estos.
3) Colocación de llaves y espacios
----------------------------------
El otro problema que siempre surge en el estilo C es la colocación de
llaves. A diferencia del tamaño de la sangría, existen pocas razones
técnicas para elegir una estrategia de ubicación sobre la otra, pero la
forma preferida, como mostraron los profetas Kernighan y Ritchie, es poner
la llave de apertura en la línea, y colocar la llave de cierre primero,
así:
.. code-block:: c
if (x es verdad) {
hacemos y
}
Esto se aplica a todos los bloques de declaraciones que no son funciones
(if, switch, for, while, do). Por ejemplo:
.. code-block:: c
switch (action) {
case KOBJ_ADD:
return "add";
case KOBJ_REMOVE:
return "remove";
case KOBJ_CHANGE:
return "change";
default:
return NULL;
}
Sin embargo, hay un caso especial, a saber, las funciones: tienen la llave
de apertura al comienzo de la siguiente línea, así:
.. code-block:: c
int funcion(int x)
{
cuerpo de la función
}
Gente hereje de todo el mundo ha afirmado que esta inconsistencia es...
bueno... inconsistente, pero todas las personas sensatas saben que
(a) K&R tienen **razón** y (b) K&R tienen razón. Además, las funciones son
especiales de todos modos (no puede anidarlas en C).
Tenga en cuenta que la llave de cierre está vacía en su línea propia,
**excepto** en los casos en que es seguida por una continuación de la misma
declaración, es decir, un ``while`` en una sentencia do o un ``else`` en
una sentencia if, como en:
.. code-block:: c
do {
cuerpo del bucle do
} while (condition);
y
.. code-block:: c
if (x == y) {
..
} else if (x > y) {
...
} else {
....
}
Justificación: K&R.
Además, tenga en cuenta que esta colocación de llaves también minimiza el
número de líneas vacías (o casi vacías), sin pérdida de legibilidad. Así,
como el suministro de nuevas líneas en su pantalla no es un recurso
renovable (piense en pantallas de terminal de 25 líneas), tienes más líneas
vacías para poner comentarios.
No use llaves innecesariamente donde una sola declaración sea suficiente.
.. code-block:: c
if (condition)
accion();
y
.. code-block:: none
if (condición)
haz_esto();
else
haz_eso();
Esto no aplica si solo una rama de una declaración condicional es una sola
declaración; en este último caso utilice llaves en ambas ramas:
.. code-block:: c
if (condición) {
haz_esto();
haz_eso();
} else {
en_otro_caso();
}
Además, use llaves cuando un bucle contenga más de una declaración simple:
.. code-block:: c
while (condición) {
if (test)
haz_eso();
}
3.1) Espacios
*************
El estilo del kernel Linux para el uso de espacios depende (principalmente)
del uso de función versus uso de palabra clave. Utilice un espacio después
de (la mayoría de) las palabras clave. Las excepciones notables son sizeof,
typeof, alignof y __attribute__, que parecen algo así como funciones (y
generalmente se usan con paréntesis en Linux, aunque no son requeridos en
el idioma, como en: ``sizeof info`` después de que ``struct fileinfo info;``
se declare).
Así que use un espacio después de estas palabras clave::
if, switch, case, for, do, while
pero no con sizeof, typeof, alignof, o __attribute__. Por ejemplo,
.. code-block:: c
s = sizeof(struct file);
No agregue espacios alrededor (dentro) de expresiones entre paréntesis.
Este ejemplo es **malo**:
.. code-block:: c
s = sizeof( struct file );
Al declarar datos de puntero o una función que devuelve un tipo de puntero,
el uso preferido de ``*`` es adyacente al nombre del dato o nombre de la
función y no junto al nombre del tipo. Ejemplos:
.. code-block:: c
char *linux_banner;
unsigned long long memparse(char *ptr, char **retptr);
char *match_strdup(substring_t *s);
Use un espacio alrededor (a cada lado de) la mayoría de los operadores
binarios y ternarios, como cualquiera de estos::
= + - < > * / % | & ^ <= >= == != ? :
pero sin espacio después de los operadores unarios::
& * + - ~ ! sizeof typeof alignof __attribute__ defined
sin espacio antes de los operadores unarios de incremento y decremento del
sufijo::
++ --
y sin espacio alrededor de los operadores de miembros de estructura ``.`` y
``->``.
No deje espacios en blanco al final de las líneas. Algunos editores con
``inteligente`` sangría insertarán espacios en blanco al comienzo de las
nuevas líneas como sea apropiado, para que pueda comenzar a escribir la
siguiente línea de código de inmediato. Sin embargo, algunos de estos
editores no eliminan los espacios en blanco si finalmente no termina
poniendo una línea de código allí, como si dejara una línea en blanco. Como
resultado, termina con líneas que contienen espacios en blanco al final.
Git le advertirá sobre los parches que introducen espacios en blanco al
final y puede, opcionalmente, eliminar los espacios en blanco finales por
usted; sin embargo, si se aplica una serie de parches, esto puede hacer que
los parches posteriores de la serie fallen al cambiar sus líneas de
contexto.
4) Nomenclatura
---------------
C es un lenguaje espartano, y sus convenciones de nomenclatura deberían
seguir su ejemplo. A diferencia de los programadores de Modula-2 y Pascal,
los programadores de C no usan nombres cuquis como
EstaVariableEsUnContadorTemporal. Un programador de C lo llamaría
variable ``tmp``, que es mucho más fácil de escribir, y no es mas difícil
de comprender.
SIN EMBARGO, mientras que los nombres de mayúsculas y minúsculas están mal
vistos, los nombres descriptivos para las variables globales son
imprescindibles. Llamar a una función global ``foo`` es un delito.
Una variable GLOBAL (para usar solo si **realmente** las necesita) necesita
tener un nombre descriptivo, al igual que las funciones globales. Si tiene
una función que cuenta el número de usuarios activos, debe llamar a esta
``contar_usuarios_activos()`` o similar, **no** debe llamarlo ``cntusr()``.
Codificar el tipo de una función en el nombre (lo llamado notación húngara)
es estúpido: el compilador conoce los tipos de todos modos y puede
verificar estos, y solo confunde al programador.
Los nombres de las variables LOCALES deben ser breves y directos. Si usted
tiene algún contador aleatorio de tipo entero, probablemente debería
llamarse ``i``. Llamarlo ``loop_counter`` no es productivo, si no hay
posibilidad de ser mal entendido. De manera similar, ``tmp`` puede ser casi
cualquier tipo de variable que se utiliza para contener un valor temporal.
Si tiene miedo de mezclar los nombres de las variables locales, tiene otro
problema, que se denomina síndrome de
función-crecimiento-desequilibrio-de-hormona. Vea el capítulo 6 (Funciones).
Para nombres de símbolos y documentación, evite introducir nuevos usos de
'master / slave' (maestro / esclavo) (o 'slave' independientemente de
'master') y 'lista negra / lista blanca' (backlist / whitelist).
Los reemplazos recomendados para 'maestro / esclavo' son:
'{primary,main} / {secondary,replica,subordinate}'
'{initiator,requester} / {target,responder}'
'{controller,host} / {device,worker,proxy}'
'leader / follower'
'director / performer'
Los reemplazos recomendados para 'backlist / whitelist' son:
'denylist / allowlist'
'blocklist / passlist'
Las excepciones para la introducción de nuevos usos son mantener en espacio
de usuario una ABI/API, o al actualizar la especificación del código de un
hardware o protocolo existente (a partir de 2020) que requiere esos
términos. Para nuevas especificaciones, traduzca el uso de la terminología
de la especificación al estándar de código del kernel donde sea posible.
5) Typedefs
-----------
Por favor no use cosas como ``vps_t``.
Es un **error** usar typedef para estructuras y punteros. cuando ve un
.. code-block:: c
vps_t a;
en el código fuente, ¿qué significa?
En cambio, si dice
.. code-block:: c
struct virtual_container *a;
puede decir qué es ``a`` en realidad.
Mucha gente piensa que los typedefs ``ayudan a la legibilidad``. No. Son
útiles solamente para:
(a) objetos totalmente opacos (donde el typedef se usa activamente para
**ocultar** cuál es el objeto).
Ejemplo: ``pte_t`` etc. objetos opacos a los que solo puede acceder
usando las funciones de acceso adecuadas.
.. note::
La opacidad y las ``funciones de acceso`` no son buenas por sí
mismas. La razón por la que los tenemos para cosas como pte_t, etc.
es que hay real y absolutamente **cero** información accesible de
forma portátil allí.
(b) Tipos enteros claros, donde la abstracción **ayuda** a evitar
confusiones, ya sea ``int`` o ``long``.
u8/u16/u32 son definiciones tipográficas perfectamente correctas
aunque encajan en la categoría (d) mejor que aquí.
.. note::
De nuevo - debe haber una **razón** para esto. si algo es
``unsigned long``, entonces no hay razón para hacerlo
typedef unsigned long mis_flags_t;
pero si hay una razón clara de por qué bajo ciertas circunstancias
podría ser un ``unsigned int`` y bajo otras configuraciones podría
ser ``unsigned long``, entonces, sin duda, adelante y use un typedef.
(c) cuando lo use para crear literalmente un tipo **nuevo** para
comprobación de tipos.
(d) Nuevos tipos que son idénticos a los tipos estándar C99, en ciertas
circunstancias excepcionales.
Aunque sólo costaría un corto período de tiempo para los ojos y
cerebro para acostumbrarse a los tipos estándar como ``uint32_t``,
algunas personas se oponen a su uso de todos modos.
Por lo tanto, los tipos ``u8/u16/u32/u64`` específicos de Linux y sus
equivalentes con signo, que son idénticos a los tipos estándar son
permitidos, aunque no son obligatorios en el nuevo código de su
elección.
Al editar código existente que ya usa uno u otro conjunto de tipos,
debe ajustarse a las opciones existentes en ese código.
(e) Tipos seguros para usar en el espacio de usuario.
En ciertas estructuras que son visibles para el espacio de usuario, no
podemos requerir tipos C99 y o utilizat el ``u32`` anterior. Por lo
tanto, usamos __u32 y tipos similares en todas las estructuras que se
comparten con espacio de usuario.
Tal vez también haya otros casos, pero la regla básicamente debería ser
NUNCA JAMÁS use un typedef a menos que pueda coincidir claramente con una
de estas reglas.
En general, un puntero o una estructura que tiene elementos que pueden
ser razonablemente accedidos directamente, **nunca** deben ser un typedef.
6) Funciones
------------
Las funciones deben ser cortas y dulces, y hacer una sola cosa. Deberían
caber en una o dos pantallas de texto (el tamaño de pantalla ISO/ANSI es
80x24, como todos sabemos), y hacer una cosa y hacerla bien.
La longitud máxima de una función es inversamente proporcional a la
complejidad y el nivel de sangría de esa función. Entonces, si tiene una
función conceptualmente simple que es solo una larga (pero simple)
declaración de case, donde tiene que hacer un montón de pequeñas cosas para
un montón de diferentes casos, está bien tener una función más larga.
Sin embargo, si tiene una función compleja y sospecha que un estudiante de
primer año de secundaria menos que dotado podría no comprender de qué se
trata la función, debe adherirse a los límites máximos tanto más de
cerca. Use funciones auxiliares con nombres descriptivos (puede pedirle al
compilador que los alinee si cree que es crítico para el rendimiento, y
probablemente lo hará mejor de lo que usted hubiera hecho).
Otra medida de la función es el número de variables locales. Estas no deben
exceder de 5 a 10, o está haciendo algo mal. Piense de nuevo en la función
y divida en partes más pequeñas. Un cerebro humano puede generalmente
realiza un seguimiento de aproximadamente 7 cosas diferentes, cualquier
elemento más y se confunde. Usted sabe que es brillante, pero tal vez le
gustaría entender lo que hizo dentro de 2 semanas.
En los archivos fuente, separe las funciones con una línea en blanco. Si la
función es exportada, la macro **EXPORT** debería ponerse inmediatamente
después de la función de cierre de línea de llave. Por ejemplo:
.. code-block:: c
int sistema_corriendo(void)
{
return estado_sistema == SISTEMA_CORRIENDO;
}
EXPORT_SYMBOL(sistema_corriendo);
6.1) Prototipos de funciones
****************************
En los prototipos de funciones, incluya nombres de parámetros con sus tipos
de datos. Aunque esto no es requerido por el lenguaje C, se prefiere en
Linux porque es una forma sencilla de añadir información valiosa para el
lector.
No utilice la palabra clave ``extern`` con declaraciones de función ya que
esto hace las líneas más largas y no es estrictamente necesario.
Al escribir prototipos de funciones, mantenga el `orden de los elementos regular
<https://lore.kernel.org/mm-commits/CAHk-=wiOCLRny5aifWNhr621kYrJwhfURsa0vFPeUEm8mF0ufg@mail.gmail.com/>`_.
Por ejemplo, usando este ejemplo de declaración de función::
__init void * __must_check action(enum magic value, size_t size, u8 count,
char *fmt, ...) __printf(4, 5) __malloc;
El orden preferido de elementos para un prototipo de función es:
- clase de almacenamiento (a continuación, ``static __always_inline``,
teniendo en cuenta que ``__always_inline`` es técnicamente un atributo
pero se trata como ``inline``)
- atributos de clase de almacenamiento (aquí, ``__init`` -- es decir,
declaraciones de sección, pero también cosas como ``__cold``)
- tipo de retorno (aquí, ``void *``)
- atributos de tipo de retorno (aquí, ``__must_check``)
- nombre de la función (aquí, ``action``)
- parámetros de la función (aquí, ``(enum magic value, size_t size, u8 count, char *fmt, ...)``,
teniendo en cuenta que los nombres de los parámetros siempre deben
incluirse)
- atributos de parámetros de función (aquí, ``__printf(4, 5)``)
- atributos de comportamiento de la función (aquí, ``__malloc``)
Tenga en cuenta que para una **definición** de función (es decir, el cuerpo
real de la función), el compilador no permite atributos de parámetros de
función después de parámetros de la función. En estos casos, deberán ir
tras los atributos de clase (por ejemplo, tenga en cuenta el cambio de
posición de ``__printf(4, 5)`` a continuación, en comparación con el
ejemplo de **declaración** anterior)::
static __always_inline __init __printf(4, 5) void * __must_check action(enum magic value,
size_t size, u8 count, char *fmt, ...) __malloc
{
...
}
7) Salida centralizada de funciones
-----------------------------------
Aunque desaprobado por algunas personas, el equivalente de la instrucción
goto es utilizado con frecuencia por los compiladores, en forma de
instrucción de salto incondicional.
La declaración goto es útil cuando una función sale desde múltiples
ubicaciones y se deben realizar algunos trabajos comunes, como la limpieza.
Si no se necesita limpieza, entonces simplemente haga return directamente.
Elija nombres de etiquetas que digan qué hace el goto o por qué existe el
goto. Un ejemplo de un buen nombre podría ser ``out_free_buffer:``
(``salida_liberar_buffer``) si al irse libera ``buffer``. Evite usar
nombres GW-BASIC como ``err1:`` y ``err2:``, ya que tendría que volver a
numerarlos si alguna vez agrega o elimina rutas de salida, y hacen que sea
difícil de verificar que sean correctos, de todos modos.
La razón para usar gotos es:
- Las declaraciones incondicionales son más fáciles de entender y seguir.
- se reduce el anidamiento
- errores al no actualizar los puntos de salida individuales al hacer
modificaciones son evitados
- ahorra el trabajo del compilador de optimizar código redundante ;)
.. code-block:: c
int fun(int a)
{
int result = 0;
char *buffer;
buffer = kmalloc(SIZE, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
if (condition1) {
while (loop1) {
...
}
result = 1;
goto out_free_buffer;
}
...
out_free_buffer:
kfree(buffer);
return result;
}
Un tipo común de error a tener en cuenta es "un error de error" que es algo
así:
.. code-block:: c
err:
kfree(foo->bar);
kfree(foo);
return ret;
El error en este código es que en algunas rutas de salida, ``foo`` es NULL.
Normalmente la solución para esto es dividirlo en dos etiquetas de error
``err_free_bar:`` y ``err_free_foo:``:
.. code-block:: c
err_free_bar:
kfree(foo->bar);
err_free_foo:
kfree(foo);
return ret;
Idealmente, debería simular errores para probar todas las rutas de salida.
8) Comentarios
--------------
Los comentarios son buenos, pero también existe el peligro de comentar
demasiado. NUNCA trate de explicar CÓMO funciona su código en un
comentario: es mucho mejor escribir el código para que el
**funcionamiento** sea obvio y es una pérdida de tiempo explicar código mal
escrito.
Generalmente, desea que sus comentarios digan QUÉ hace su código, no CÓMO.
Además, trate de evitar poner comentarios dentro del cuerpo de una función:
si la función es tan compleja que necesita comentar por separado partes de
esta, probablemente debería volver al capítulo 6 una temporada. Puede
hacer pequeños comentarios para notar o advertir sobre algo particularmente
inteligente (o feo), pero trate de evitar el exceso. En su lugar, ponga los
comentarios al principio de la función, diga a la gente lo que hace y
posiblemente POR QUÉ hace esto.
Al comentar las funciones de la API del kernel, utilice el formato
kernel-doc. Consulte los archivos en :ref:`Documentation/doc-guide/ <doc_guide>`
y ``scripts/kernel-doc`` para más detalles.
El estilo preferido para comentarios largos (de varias líneas) es:
.. code-block:: c
/*
* Este es el estilo preferido para comentarios
* multilínea en el código fuente del kernel Linux.
* Por favor, utilícelo constantemente.
*
* Descripción: Una columna de asteriscos en el lado izquierdo,
* con líneas iniciales y finales casi en blanco.
*/
Para archivos en net/ y drivers/net/, el estilo preferido para comentarios
largos (multi-linea) es un poco diferente.
.. code-block:: c
/* El estilo de comentario preferido para archivos en net/ y drivers/net
* se asemeja a esto.
*
* Es casi lo mismo que el estilo de comentario generalmente preferido,
* pero no hay una línea inicial casi en blanco.
*/
También es importante comentar los datos, ya sean tipos básicos o
derivados. Para este fin, use solo una declaración de datos por línea (sin
comas para múltiples declaraciones de datos). Esto le deja espacio para un
pequeño comentario sobre cada elemento, explicando su uso.
9) Has hecho un desastre
---------------------------
Está bien, todos lo hacemos. Probablemente un antiguo usuario de Unix le
haya dicho que ``GNU emacs`` formatea automáticamente las fuentes C por
usted, y ha notado que sí, lo hace, pero los por defecto que tiene son
menos que deseables (de hecho, son peores que los aleatorios) escribiendo -
un número infinito de monos escribiendo en GNU emacs nunca harán un buen
programa).
Por lo tanto, puede deshacerse de GNU emacs o cambiarlo y usar valores más
sanos. Para hacer esto último, puede pegar lo siguiente en su archivo
.emacs:
.. code-block:: none
(defun c-lineup-arglist-tabs-only (ignored)
"Line up argument lists by tabs, not spaces"
(let* ((anchor (c-langelem-pos c-syntactic-element))
(column (c-langelem-2nd-pos c-syntactic-element))
(offset (- (1+ column) anchor))
(steps (floor offset c-basic-offset)))
(* (max steps 1)
c-basic-offset)))
(dir-locals-set-class-variables
'linux-kernel
'((c-mode . (
(c-basic-offset . 8)
(c-label-minimum-indentation . 0)
(c-offsets-alist . (
(arglist-close . c-lineup-arglist-tabs-only)
(arglist-cont-nonempty .
(c-lineup-gcc-asm-reg c-lineup-arglist-tabs-only))
(arglist-intro . +)
(brace-list-intro . +)
(c . c-lineup-C-comments)
(case-label . 0)
(comment-intro . c-lineup-comment)
(cpp-define-intro . +)
(cpp-macro . -1000)
(cpp-macro-cont . +)
(defun-block-intro . +)
(else-clause . 0)
(func-decl-cont . +)
(inclass . +)
(inher-cont . c-lineup-multi-inher)
(knr-argdecl-intro . 0)
(label . -1000)
(statement . 0)
(statement-block-intro . +)
(statement-case-intro . +)
(statement-cont . +)
(substatement . +)
))
(indent-tabs-mode . t)
(show-trailing-whitespace . t)
))))
(dir-locals-set-directory-class
(expand-file-name "~/src/linux-trees")
'linux-kernel)
Esto hará que emacs funcione mejor con el estilo de código del kernel para
C en archivos bajo ``~/src/linux-trees``.
Pero incluso si no logra que emacs realice un formateo correcto, no todo
está perdido: use ``indent``.
Ahora bien, de nuevo, la sangría de GNU tiene la misma configuración de
muerte cerebral que GNU emacs tiene, por lo que necesita darle algunas
opciones de línea de comando. Sin embargo, eso no es tan malo, porque
incluso los creadores de GNU indent reconocen la autoridad de K&R (la gente
de GNU no es mala, solo están gravemente equivocados en este asunto), por
lo que simplemente de a la sangría las opciones ``-kr -i8`` (significa
``K&R, guiones de 8 caracteres``), o use ``scripts/Lindent``, que indenta
con ese estilo.
``indent`` tiene muchas opciones, y especialmente cuando se trata de
comentar reformateos, es posible que desee echar un vistazo a la página del
manual. Pero recuerde: ``indent`` no es la solución para una mala
programación.
Tenga en cuenta que también puede usar la herramienta ``clang-format`` para
ayudarlo con estas reglas, para volver a formatear rápidamente partes de su
código automáticamente, y revisar archivos completos para detectar errores
de estilo del código, errores tipográficos y posibles mejoras. También es
útil para ordenar ``#includes``, para alinear variables/macros, para
redistribuir texto y otras tareas similares. Vea el archivo
:ref:`Documentation/process/clang-format.rst <clangformat>` para más
detalles.
10) Archivos de configuración de Kconfig
----------------------------------------
Para todos los archivos de configuración de Kconfig* en todo el árbol
fuente, la sangría es algo diferente. Las líneas bajo una definición
``config`` están indentadas con una tabulación, mientras que el texto de
ayuda tiene una sangría adicional de dos espacios. Ejemplo::
config AUDIT
bool "Soporte para auditar"
depends on NET
help
Habilita la infraestructura de auditoría que se puede usar con otro
subsistema kernel, como SELinux (que requiere esto para
registro de salida de mensajes avc). No hace auditoría de llamadas al
sistema sin CONFIG_AUDITSYSCALL.
Características seriamente peligrosas (como soporte de escritura para
ciertos filesystems) deben anunciar esto de forma destacada en su cadena de
solicitud::
config ADFS_FS_RW
bool "ADFS write support (DANGEROUS)"
depends on ADFS_FS
...
Para obtener la documentación completa sobre los archivos de configuración,
consulte el archivo Documentation/kbuild/kconfig-language.rst.
11) Estructuras de datos
------------------------
Las estructuras de datos que tienen visibilidad fuera del contexto de un
solo subproceso en el que son creadas y destruidas, siempre debe tener
contadores de referencia. En el kernel, la recolección de basura no existe
(y fuera, la recolección de basura del kernel es lenta e ineficiente), lo
que significa que absolutamente **tiene** para hacer referencia y contar
todos sus usos.
El conteo de referencias significa que puede evitar el bloqueo y permite
que múltiples usuarios tengan acceso a la estructura de datos en paralelo -
y no tengan que preocuparse de que la estructura, de repente, desaparezca
debajo de su control, solo porque durmieron o hicieron otra cosa por un
tiempo.
Tenga en cuenta que el bloqueo **no** reemplaza el recuento de referencia.
El bloqueo se utiliza para mantener la coherencia de las estructuras de
datos, mientras que la referencia y contar es una técnica de gestión de
memoria. Por lo general, ambos son necesarios, y no deben confundirse entre
sí.
De hecho, muchas estructuras de datos pueden tener dos niveles de conteo de
referencias, cuando hay usuarios de diferentes ``clases``. El conteo de
subclases cuenta el número de usuarios de la subclase y disminuye el conteo
global solo una vez, cuando el recuento de subclases llega a cero.
Se pueden encontrar ejemplos de este tipo de ``recuento de referencias de
niveles múltiples`` en la gestión de memoria (``struct mm_struct``:
mm_users y mm_count), y en código del sistema de archivos
(``struct super_block``: s_count y s_active).
Recuerde: si otro hilo puede encontrar su estructura de datos y usted no
tiene un recuento de referencias, es casi seguro que tiene un error.
12) Macros, Enums y RTL
------------------------
Los nombres de macros que definen constantes y etiquetas en enumeraciones
(enums) están en mayúsculas.
.. code-block:: c
#define CONSTANTE 0x12345
Se prefieren los enums cuando se definen varias constantes relacionadas.
Se aprecian los nombres de macro en MAYÚSCULAS, pero las macros que se
asemejan a funciones puede ser nombradas en minúscula.
Generalmente, las funciones en línea son preferibles a las macros que se
asemejan a funciones.
Las macros con varias instrucciones deben contenerse en un bloque do-while:
.. code-block:: c
#define macrofun(a, b, c) \
do { \
if (a == 5) \
haz_esto(b, c); \
} while (0)
Cosas a evitar al usar macros:
1) macros que afectan el flujo de control:
.. code-block:: c
#define FOO(x) \
do { \
if (blah(x) < 0) \
return -EBUGGERED; \
} while (0)
es una **muy** mala idea. Parece una llamada de función pero sale de la
función de ``llamada``; no rompa los analizadores internos de aquellos que
leerán el código.
2) macros que dependen de tener una variable local con un nombre mágico:
.. code-block:: c
#define FOO(val) bar(index, val)
puede parecer algo bueno, pero es confuso como el infierno cuando uno lee
el código, y es propenso a romperse por cambios aparentemente inocentes.
3) macros con argumentos que se usan como valores l: FOO(x) = y; le van
a morder si alguien, por ejemplo, convierte FOO en una función en línea.
4) olvidarse de la precedencia: las macros que definen constantes usando
expresiones deben encerrar la expresión entre paréntesis. Tenga cuidado con
problemas similares con macros usando parámetros.
.. code-block:: c
#define CONSTANTE 0x4000
#define CONSTEXP (CONSTANTE | 3)
5) colisiones de espacio de nombres ("namespace") al definir variables
locales en macros que se asemejan a funciones:
.. code-block:: c
#define FOO(x) \
({ \
typeof(x) ret; \
ret = calc_ret(x); \
(ret); \
})
ret es un nombre común para una variable local -es menos probable que
__foo_ret colisione (coincida) con una variable existente.
El manual de cpp trata las macros de forma exhaustiva. El manual interno de
gcc también cubre RTL, que se usa frecuentemente con lenguaje ensamblador
en el kernel.
13) Imprimir mensajes del kernel
--------------------------------
A los desarrolladores del kernel les gusta ser vistos como alfabetizados.
Cuide la ortografía de los mensajes del kernel para causar una buena
impresión. No utilice contracciones incorrectas como ``dont``; use
``do not`` o ``don't`` en su lugar. Haga sus mensajes concisos, claros e
inequívocos.
Los mensajes del kernel no tienen que terminar con un punto.
Imprimir números entre paréntesis (%d) no agrega valor y debe evitarse.
Hay varias modelos de macros de diagnóstico de driver en <linux/dev_printk.h>
que debe usar para asegurarse de que los mensajes coincidan con el
dispositivo correcto y driver, y están etiquetados con el nivel correcto:
dev_err(), dev_warn(), dev_info(), y así sucesivamente. Para mensajes que
no están asociados con un dispositivo particular, <linux/printk.h> define
pr_notice(), pr_info(), pr_warn(), pr_err(), etc.
Crear buenos mensajes de depuración puede ser todo un desafío; y una vez
los tiene, pueden ser de gran ayuda para la resolución remota de problemas.
Sin embargo, la impresión de mensajes de depuración se maneja de manera
diferente a la impresión de otros mensajes que no son de depuración.
Mientras que las otras funciones pr_XXX() se imprimen incondicionalmente,
pr_debug() no lo hace; se compila fuera por defecto, a menos que DEBUG sea
definido o se establezca CONFIG_DYNAMIC_DEBUG. Eso es cierto para dev_dbg()
también, y una convención relacionada usa VERBOSE_DEBUG para agregar
mensajes dev_vdbg() a los ya habilitados por DEBUG.
Muchos subsistemas tienen opciones de depuración de Kconfig para activar
-DDEBUG en el Makefile correspondiente; en otros casos, los archivos
usan #define DEBUG. Y cuando un mensaje de depuración debe imprimirse
incondicionalmente, por ejemplo si es ya dentro de una sección #ifdef
relacionada con la depuración, printk(KERN_DEBUG ...) puede ser usado.
14) Reservando memoria
----------------------
El kernel proporciona los siguientes asignadores de memoria de propósito
general: kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc() y
vzalloc(). Consulte la documentación de la API para obtener más información.
a cerca de ellos. :ref:`Documentation/core-api/memory-allocation.rst
<memory_allocation>`
La forma preferida para pasar el tamaño de una estructura es la siguiente:
.. code-block:: c
p = kmalloc(sizeof(*p), ...);
La forma alternativa donde se deletrea el nombre de la estructura perjudica
la legibilidad, y presenta una oportunidad para un error cuando se cambia
el tipo de variable de puntero, pero el tamaño correspondiente de eso que
se pasa a un asignador de memoria no.
Convertir el valor devuelto, que es un puntero vacío, es redundante. La
conversión desde el puntero vacío a cualquier otro tipo de puntero está
garantizado por la programación en idioma C.
La forma preferida para asignar una matriz es la siguiente:
.. code-block:: c
p = kmalloc_array(n, sizeof(...), ...);
La forma preferida para asignar una matriz a cero es la siguiente:
.. code-block:: c
p = kcalloc(n, sizeof(...), ...);
Ambos casos verifican el desbordamiento en el tamaño de asignación n *
sizeof (...), y devuelven NULL si esto ocurrió.
Todas estas funciones de asignación genéricas emiten un volcado de pila
(" stack dump") en caso de fallo cuando se usan sin __GFP_NOWARN, por lo
que no sirve de nada emitir un mensaje de fallo adicional cuando se
devuelva NULL.
15) La enfermedad de inline
----------------------------
Parece haber una común percepción errónea de que gcc tiene una magica
opción "hazme más rápido" de aceleración, llamada ``inline`` (en línea).
Mientras que el uso de inlines puede ser apropiado (por ejemplo, como un
medio para reemplazar macros, consulte el Capítulo 12), muy a menudo no lo
es. El uso abundante de la palabra clave inline conduce a una mayor kernel,
que a su vez ralentiza el sistema en su conjunto, debido a una mayor huella
de icache para la CPU, y sencillamente porque hay menos memoria disponible
para el pagecache. Solo piense en esto; un fallo en la memoria caché de la
página provoca una búsqueda de disco, que tarda fácilmente 5 milisegundos.
Hay MUCHOS ciclos de CPU que puede entrar en estos 5 milisegundos.
Una razonable regla general es no poner funciones inline que tengan más de
3 líneas de código en ellas. Una excepción a esta regla son los casos en
que se sabe que un parámetro es una constante en tiempo de compilación, y
como resultado de esto, usted *sabe*, el compilador podrá optimizar la
mayor parte de su función en tiempo de compilación. Para un buen ejemplo de
este último caso, véase la función en línea kmalloc().
A menudo, la gente argumenta que agregar funciones en línea que son
estáticas y se usan solo una vez, es siempre una victoria ya que no hay
perdida de espacio. Mientras esto es técnicamente correcto, gcc es capaz de
incorporarlos automáticamente sin ayuda, y esta el problema de
mantenimiento de eliminar el inline, cuando un segundo usuario supera el
valor potencial de la pista que le dice a gcc que haga algo que habría
hecho de todos modos.
16) Valores devueltos por función y sus nombres
-----------------------------------------------
Las funciones pueden devolver valores de muchos tipos diferentes, y uno de
lo más común es un valor que indica si la función tuvo éxito o ha fallado.
Dicho valor se puede representar como un número entero de código de error
(-Exxx = falla, 0 = éxito) o un booleano ``con éxito`` (0 = falla, distinto
de cero = éxito).
La mezcla de estos dos tipos de representaciones es una fuente fértil de
errores difíciles de encontrar. Si el lenguaje C incluyera una fuerte
distinción entre enteros y booleanos, el compilador encontraría estos
errores por nosotros... pero no lo hace. Para ayudar a prevenir tales
errores, siga siempre esta convención::
Si el nombre de una función es una acción o un comando imperativo,
la función debe devolver un número entero de código de error. si el nombre
es un predicado, la función debe devolver un valor booleano "exitoso".
Por ejemplo, ``agregar trabajo`` es un comando, y la función
agregar_trabajo() devuelve 0 en caso de éxito o -EBUSY en caso de fracaso.
De la misma manera, ``dispositivo PCI presente`` es un predicado, y la
función pci_dev_present() devuelve 1 si tiene éxito en encontrar un
dispositivo coincidente o 0 si no es así.
Todas las funciones EXPORTed (exportadas) deben respetar esta convención,
al igual que todas las funciones publicas. Las funciones privadas
(estáticas) no lo necesitan, pero es recomendado que lo hagan.
Las funciones cuyo valor devuelto es el resultado real de un cálculo, en
lugar de una indicación de si el cómputo tuvo éxito, no están sujetas a
esta regla. Generalmente indican fallo al devolver valores fuera del rango
de resultados. Los ejemplos típicos serían funciones que devuelven
punteros; estos usan NULL o el mecanismo ERR_PTR para informar de fallos.
17) Usando bool
----------------
El tipo bool del kernel Linux es un alias para el tipo C99 _Bool. Los
valores booleanos pueden solo evaluar a 0 o 1, y la conversión implícita o
explícita a bool convierte automáticamente el valor en verdadero o falso.
Cuando se utilizan tipos booleanos,
!! no se necesita construcción, lo que elimina una clase de errores.
Cuando se trabaja con valores booleanos, se deben usar las definiciones
verdadera y falsa, en lugar de 1 y 0.
Los tipos de devolución de función bool y las variables de pila siempre
se pueden usar cuando esto sea adecuado. Se recomienda el uso de bool para
mejorar la legibilidad y, a menudo, es una mejor opción que 'int' para
almacenar valores booleanos.
No use bool si el diseño de la línea de caché o el tamaño del valor son
importantes, ya que su tamaño y la alineación varía según la arquitectura
compilada. Las estructuras que son optimizadas para la alineación y el
tamaño no debe usar bool.
Si una estructura tiene muchos valores verdadero/falso, considere
consolidarlos en un bitfield con miembros de 1 bit, o usando un tipo de
ancho fijo apropiado, como u8.
De manera similar, para los argumentos de función, se pueden consolidar
muchos valores verdaderos/falsos en un solo argumento bit a bit 'flags' y
'flags' a menudo, puede ser una alternativa de argumento más legible si los
sitios de llamada tienen constantes desnudas de tipo verdaderas/falsas.
De lo contrario, el uso limitado de bool en estructuras y argumentos puede
mejorar la legibilidad.
18) No reinvente las macros del kernel
---------------------------------------
El archivo de cabecera include/linux/kernel.h contiene una serie de macros
que debe usar, en lugar de programar explícitamente alguna variante de
estos por usted mismo. Por ejemplo, si necesita calcular la longitud de una
matriz, aproveche la macro
.. code-block:: c
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
De manera similar, si necesita calcular el tamaño de algún miembro de la
estructura, use
.. code-block:: c
#define sizeof_field(t, f) (sizeof(((t*)0)->f))
También hay macros min() y max() que realizan una verificación estricta de
tipos si lo necesita. Siéntase libre de leer detenidamente ese archivo de
encabezado para ver qué más ya está definido y que no debe reproducir en su
código.
19) Editores modeline y otros desastres
---------------------------------------
Algunos editores pueden interpretar la información de configuración
incrustada en los archivos fuente, indicado con marcadores especiales. Por
ejemplo, emacs interpreta las líneas marcadas como esto:
.. code-block:: c
-*- mode: c -*-
O así:
.. code-block:: c
/*
Local Variables:
compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"
End:
*/
Vim interpreta los marcadores que se ven así:
.. code-block:: c
/* vim:set sw=8 noet */
No incluya ninguno de estos en los archivos fuente. La gente tiene sus
propias configuraciones del editor, y sus archivos de origen no deben
anularlos. Esto incluye marcadores para sangría y configuración de modo.
La gente puede usar su propio modo personalizado, o puede tener algún otro
método mágico para que la sangría funcione correctamente.
20) Ensamblador inline
-----------------------
En el código específico de arquitectura, es posible que deba usar
ensamblador en línea para interactuar con funcionalidades de CPU o
plataforma. No dude en hacerlo cuando sea necesario. Sin embargo, no use
ensamblador en línea de forma gratuita cuando C puede hacer el trabajo.
Puede y debe empujar el hardware desde C cuando sea posible.
Considere escribir funciones auxiliares simples que envuelvan bits comunes
de ensamblador, en lugar de escribirlos repetidamente con ligeras
variaciones. Recuerde que el ensamblador en línea puede usar parámetros C.
Las funciones de ensamblador grandes y no triviales deben ir en archivos .S,
con su correspondientes prototipos de C definidos en archivos de encabezado
en C. Los prototipos de C para el ensamblador deben usar ``asmlinkage``.
Es posible que deba marcar su declaración asm como volátil, para evitar que
GCC la elimine si GCC no nota ningún efecto secundario. No siempre es
necesario hacerlo, sin embargo, y hacerlo innecesariamente puede limitar la
optimización.
Al escribir una sola declaración de ensamblador en línea que contiene
múltiples instrucciones, ponga cada instrucción en una línea separada en
una string separada, y termine cada string excepto la última con ``\n\t``
para indentar correctamente la siguiente instrucción en la salida en
ensamblador:
.. code-block:: c
asm ("magic %reg1, #42\n\t"
"more_magic %reg2, %reg3"
: /* outputs */ : /* inputs */ : /* clobbers */);
21) Compilación condicional
---------------------------
Siempre que sea posible, no use condicionales de preprocesador (#if,
#ifdef) en archivos .c; de lo contrario, el código es más difícil de leer y
la lógica más difícil de seguir. En cambio, use dichos condicionales en un
archivo de encabezado que defina funciones para usar en esos archivos .c,
proporcionando versiones de código auxiliar sin operación en el caso #else,
y luego llame a estas funciones incondicionalmente desde archivos .c. El
compilador evitará generar cualquier código para las llamadas restantes,
produciendo resultados idénticos, pero la lógica es fácil de seguir.
Prefiera compilar funciones completas, en lugar de porciones de funciones o
porciones de expresiones. En lugar de poner un ifdef en una expresión,
divida la totalidad de la expresión con una función de ayuda independiente
y aplique el condicional a esa función.
Si tiene una función o variable que puede potencialmente quedar sin usar en
una configuración en particular, y el compilador advertiría sobre su
definición sin usar, marque la definición como __maybe_unused en lugar de
envolverla en un preprocesador condicional. (Sin embargo, si una función o
variable *siempre* acaba sin ser usada, bórrela.)
Dentro del código, cuando sea posible, use la macro IS_ENABLED para
convertir un símbolo Kconfig en una expresión booleana de C, y utilícelo en
un condicional de C normal:
.. code-block:: c
if (IS_ENABLED(CONFIG_SOMETHING)) {
...
}
El compilador "doblará"" constantemente el condicional e incluirá o
excluirá el bloque de código al igual que con un #ifdef, por lo que esto no
agregará ningún tiempo de gastos generales en ejecución. Sin embargo, este
enfoque todavía permite que el compilador de C vea el código dentro del
bloque, y verifique que sea correcto (sintaxis, tipos, símbolo, referencias,
etc.). Por lo tanto, aún debe usar un #ifdef si el código dentro del bloque
hace referencia a símbolos que no existirán si no se cumple la condición.
Al final de cualquier bloque #if o #ifdef no trivial (más de unas pocas
líneas), incluya un comentario después de #endif en la misma línea,
anotando la expresión condicional utilizada. Por ejemplo:
.. code-block:: c
#ifdef CONFIG_SOMETHING
...
#endif /* CONFIG_SOMETHING */
22) No rompa el kernel
-----------------------
En general, la decisión de romper el kernel pertenece al usuario, más que
al desarrollador del kernel.
Evite el panic()
****************
panic() debe usarse con cuidado y principalmente solo durante el arranque
del sistema. panic() es, por ejemplo, aceptable cuando se queda sin memoria
durante el arranque y no puede continuar.
Use WARN() en lugar de BUG()
****************************
No agregue código nuevo que use cualquiera de las variantes BUG(), como
BUG(), BUG_ON() o VM_BUG_ON(). En su lugar, use una variante WARN*(),
preferiblemente WARN_ON_ONCE(), y posiblemente con código de recuperación.
El código de recuperación no es requerido si no hay una forma razonable de
recuperar, al menos parcialmente.
"Soy demasiado perezoso para tener en cuenta los errores" no es una excusa
para usar BUG(). Importantes corrupciones internas sin forma de continuar
aún pueden usar BUG(), pero necesitan una buena justificación.
Use WARN_ON_ONCE() en lugar de WARN() o WARN_ON()
*************************************************
Generalmente, se prefiere WARN_ON_ONCE() a WARN() o WARN_ON(), porque es
común que una condición de advertencia dada, si ocurre, ocurra varias
veces. Esto puede llenar el registro del kernel, e incluso puede ralentizar
el sistema lo suficiente como para que el registro excesivo se convierta en
su propio, adicional problema.
No haga WARN a la ligera
************************
WARN*() está diseñado para situaciones inesperadas que nunca deberían
suceder. Las macros WARN*() no deben usarse para nada que se espera que
suceda durante un funcionamiento normal. No hay "checkeos" previos o
posteriores a la condición, por ejemplo. De nuevo: WARN*() no debe usarse
para una condición esperada que vaya a activarse fácilmente, por ejemplo,
mediante acciones en el espacio del usuario. pr_warn_once() es una
alternativa posible, si necesita notificar al usuario de un problema.
No se preocupe sobre panic_on_warn de usuarios
**********************************************
Algunas palabras más sobre panic_on_warn: Recuerde que ``panic_on_warn`` es
una opción disponible del kernel, y que muchos usuarios configuran esta
opción. Esta es la razón por la que hay un artículo de "No haga WARN a la
ligera", arriba. Sin embargo, la existencia de panic_on_warn de usuarios no
es una razón válida para evitar el uso juicioso de WARN*(). Esto se debe a
que quien habilita panic_on_warn, explícitamente pidió al kernel que
fallara si se dispara un WARN*(), y tales usuarios deben estar preparados
para afrontar las consecuencias de un sistema que es algo más probable que
se rompa.
Use BUILD_BUG_ON() para aserciones en tiempo de compilación
***********************************************************
El uso de BUILD_BUG_ON() es aceptable y recomendado, porque es una aserción
en tiempo de compilación, que no tiene efecto en tiempo de ejecución.
Apéndice I) Referencias
-----------------------
The C Programming Language, Segunda edicion
por Brian W. Kernighan and Dennis M. Ritchie.
Prentice Hall, Inc., 1988.
ISBN 0-13-110362-8 (paperback), 0-13-110370-9 (hardback).
The Practice of Programming
por Brian W. Kernighan and Rob Pike.
Addison-Wesley, Inc., 1999.
ISBN 0-201-61586-X.
manuales GCC - en cumplimiento con K&R y este texto - para cpp, gcc,
detalles de gcc y sangría, todo disponible en https://www.gnu.org/manual/
WG14 es el grupo de trabajo de estandarización internacional de la
programación en lenguaje C, URL: http://www.open-std.org/JTC1/SC22/WG14/
:ref:`process/coding-style.rst <codingstyle>` del kernel, por greg@kroah.com at OLS 2002:
http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
.. raw:: latex
\renewcommand\thesection*
\renewcommand\thesubsection*
.. include:: ../disclaimer-sp.rst
.. _sp_process_index:
.. toctree::
:maxdepth: 1
submitting-patches
kernel-docs
coding-style
.. include:: ../disclaimer-sp.rst
:Original: :ref:`Documentation/process/kernel-docs.rst <kernel_docs>`
:Translator: Carlos Bilbao <carlos.bilbao@amd.com>
.. _sp_kernel_docs:
Índice de documentación adicional del kernel
============================================
La necesidad de un documento como este se hizo evidente en la lista de
correo de linux-kernel cuando las mismas preguntas, solicitando sugerencias
e información, aparecieron una y otra vez.
Afortunadamente, a medida que más y más gente accede a GNU/Linux, más
desarrolladores se interesan por el kernel. Sin embargo, leer las fuentes
no siempre es suficiente. Es fácil entender el código, pero se pierden los
conceptos, la filosofía y decisiones de diseño detrás de dicho código.
Desafortunadamente, no existen muchos documentos disponibles para que los
principiantes comiencen. Y, aunque existieran, no habría ningún lugar
"conocido" que les pudiera seguir la pista. Estas líneas tratan de cubrir
esta carencia.
POR FAVOR, si conoce algún documento que no figura aquí, o si escribe un
nuevo documento, incluya una referencia aquí, siguiendo el proceso de envío
de parches del kernel. Cualquier corrección, idea o comentario también es
bienvenida.
Todos los documentos se catalogan con los siguientes campos: el "Título",
el "Autor"/es, la "URL" donde se encuentran, algunas "Palabras clave"
útiles para buscar temas específicos, y una breve "Descripción" del
documento en cuestión.
.. note::
Los documentos de cada sección en este documento están ordenados por su
fecha de publicación, del más reciente al más antiguo. Los maintainers
deben ir retirando recursos obsoletos o anticuados.
Documentos en el árbol del kernel Linux
-----------------------------------------
Los libros de Sphinx deben compilarse con ``make {htmldocs | pdfdocs | epubdocs}``.
* Título: **linux/Documentation**
:Autor: Many.
:Ubicación: Documentation/
:Palabras Clave: archivos de texto, Sphinx.
:Descripción: Documentación que viene con las fuentes del kernel,
dentro del directorio Documentation. Algunas páginas de este documento
(incluido este documento en sí) se han trasladado allí, y podrían
estar más actualizadas que la versión web.
Documentos en línea
-------------------
* Título: **Linux Kernel Mailing List Glossary**
:Autor: various
:URL: https://kernelnewbies.org/KernelGlossary
:Fecha: rolling version
:Palabras Clave: glosario terminos, linux-kernel.
:Descripción: De la Introducción: "This glossary is intended as
a brief description of some of the acronyms and terms you may hear
during discussion of the Linux kernel".
* Título: **The Linux Kernel Module Programming Guide**
:Autor: Peter Jay Salzman, Michael Burian, Ori Pomerantz, Bob Mottram,
Jim Huang.
:URL: https://sysprog21.github.io/lkmpg/
:Fecha: 2021
:Palabras Clave: modules, GPL book, /proc, ioctls, system calls,
interrupt handlers, llamadas al sistema, interrupciones.
:Descripción: Un muy buen libro GPL sobre el tema de la programación
de módulos. Muchos ejemplos. Actualmente la nueva versión está
siendo mantenida activamente ent https://github.com/sysprog21/lkmpg.
Libros publicados
-----------------
* Título: **Linux Kernel Programming: A Comprehensive Guide to Kernel Internals, Writing Kernel Modules, and Kernel Synchronization**
:Autor: Kaiwan N. Billimoria
:Publica: Packt Publishing Ltd
:Fecha: 2021
:Paginas: 754
:ISBN: 978-1789953435
* Título: **Linux Kernel Development, 3rd Edition**
:Autor: Robert Love
:Publica: Addison-Wesley
:Fecha: July, 2010
:Paginas: 440
:ISBN: 978-0672329463
:Notas: Libro fundacional
.. _sp_ldd3_published:
* Título: **Linux Device Drivers, 3rd Edition**
:Authors: Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman
:Publica: O'Reilly & Associates
:Fecha: 2005
:Paginas: 636
:ISBN: 0-596-00590-3
:Notas: Libro fundacional. Más información en
http://www.oreilly.com/catalog/linuxdrive3/
formato PDF, URL: https://lwn.net/Kernel/LDD3/
* Título: **The Design of the UNIX Operating System**
:Autor: Maurice J. Bach
:Publica: Prentice Hall
:Fecha: 1986
:Paginas: 471
:ISBN: 0-13-201757-1
:Notas: Libro fundacional
Recursos varios
---------------
* Título: **Cross-Referencing Linux**
:URL: https://elixir.bootlin.com/
:Palabras Clave: Browsing source code.
:Descripción: Otro navegador de código fuente del kernel Linux que se
encuentra en la web. Muchas referencias cruzadas a variables y
funciones. Puedes ver dónde se definen y dónde se utilizan.
* Título: **Linux Weekly News**
:URL: https://lwn.net
:Palabras Clave: latest kernel news, noticias del kernel Linux.
:Descripción: El título lo dice todo (Noticias Semanales de Linux).
Hay una sección fija sobre el kernel, resumiendo el trabajo de sus
desarrolladores, correcciones de errores, nuevas funciones y
versiones, producido durante la semana.
* Título: **The home page of Linux-MM**
:Autor: The Linux-MM team.
:URL: https://linux-mm.org/
:Palabras Clave: memory management, Linux-MM, mm patches, TODO, docs,
mailing list, administración de memoria, Linux-MM, parches mm, listas
de correo.
:Descripción: Sitio dedicado al desarrollo de la gestión de memoria
de Linux. Parches relacionados con la memoria, HOWTOs, enlaces,
desarrolladores de mm... ¡Si está interesado en el desarrollo de la
gestión de memoria no te lo pierdas!
* Título: **Kernel Newbies IRC Channel and Website**
:URL: https://www.kernelnewbies.org
:Palabras Clave: IRC, newbies, channel, asking doubts, canal, dudas,
novatos, preguntar.
:Descripción: #kernelnewbies en irc.oftc.net.
#kernelnewbies es una red de IRC dedicada al hacker del kernel
'novato'. La audiencia se compone principalmente de personas que
quieren aprender sobre el kernel, trabajar en proyectos del kernel
o hackers profesionales del kernel que quieren ayudar a la gente
menos experimentada.
#kernelnewbies es parte de la red OFTC IRC.
Pruebe con irc.oftc.net como su servidor y luego haga /join
#kernelnewbies.
El sitio web kernelnewbies también alberga artículos, documentos, FAQs...
* Título: **linux-kernel mailing list archives and search engines**
:URL: http://vger.kernel.org/vger-lists.html
:URL: http://www.uwsg.indiana.edu/hypermail/linux/kernel/index.html
:URL: http://groups.google.com/group/mlist.linux.kernel
:Palabras Clave: linux-kernel, archives, buscar, search, archivos.
:Descripción: Algunos de los archivadores de listas de correo del
kernel de Linux. Si usted tiene uno mejor/otro, por favor hágamelo
saber.
-------
Este documento se basaba originalmente en:
https://www.dit.upm.es/~jmseyas/linux/kernel/hackers-docs.html
escrito por Juan-Mariano de Goyenche
.. include:: ../disclaimer-sp.rst
:Original: :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
:Translator: Carlos Bilbao <carlos.bilbao@amd.com>
.. _sp_submittingpatches:
Envío de parches: la guía esencial para incluir su código en el kernel
=======================================================================
Para una persona o empresa que desee enviar un cambio al kernel Linux,
el proceso puede en ocasiones resultar desalentador si no se está
familiarizado con "el sistema". Este texto es una colección de sugerencias
que pueden aumentar considerablemente las posibilidades de que se acepte su
cambio.
Este documento contiene una gran cantidad de sugerencias en un formato
relativamente conciso. Para obtener información detallada sobre cómo
funciona el proceso de desarrollo del kernel, consulte
Documentation/process/development-process.rst. Además, lea
Documentation/process/submit-checklist.rst para obtener una lista de
elementos a verificar antes de enviar código. Para los parches de
"binding" del árbol de dispositivos, lea
Documentation/devicetree/bindings/submitting-patches.rst.
Esta documentación asume que está usando ``git`` para preparar sus parches.
Si no está familiarizado con ``git``, le recomendamos que aprenda a
usarlo, le hará la vida como desarrollador del kernel y en general mucho
más sencilla.
Algunos subsistemas y árboles de mantenimiento cuentan con información
adicional sobre su flujo de trabajo y expectativas, consulte
:ref:`Documentation/process/maintainer-handbooks.rst <maintainer_handbooks_main>`.
Obtenga el código fuente actual
--------------------------------
Si no tiene a mano un repositorio con el código fuente actual del kernel,
use ``git`` para obtener uno. Querrá comenzar con el repositorio principal,
que se puede descargar con::
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
Tenga en cuenta, sin embargo, que es posible que no desee desarrollar con
el árbol principal directamente. La mayoría de los maintainers de
subsistemas usan sus propios árboles de código fuente y quieren ver parches
preparados para esos árboles. Revise el campo **T:** para el subsistema
en el archivo MAINTAINERS para encontrar dicho árbol, o simplemente
pregunte al maintainer si el árbol no está listado allí.
.. _sp_describe_changes:
Describa sus cambios
---------------------
Describa su problema. Sea su parche una corrección de un error de una
línea o 5000 líneas para una nuevo "feature", debe haber un problema
subyacente que le motivó a hacer ese trabajo. Convenza al revisor de que
hay un problema que merece la pena solucionar y de que tiene sentido que
lea más allá del primer párrafo.
Describa el impacto relativo al usuario. Cosas que estropeen el kernel y
los bloqueos son bastante convincentes, pero no todos los errores son tan
evidentes. Incluso si se detectó un problema durante la revisión del
código, describa el impacto que cree pueda tener en los usuarios. Tenga en
cuenta que la mayoría de instalaciones de Linux ejecutan kernels desde
árboles estables secundarios o árboles específicos de proveedor/producto
que seleccionan ("cherry-pick") solo parches específicos de upstream, así
que incluya cualquier cosa que pueda ayudar a dirigir su cambio
aguas abajo: circunstancias que producen cierta situación, extractos de
dmesg, descripciones del error fatal, regresiones de rendimiento, picos de
latencia, bloqueos, etc.
Cuantifique optimizaciones y beneficios/perdidas. Si asegura mejoras en
rendimiento, consumo de memoria, huella del stack o tamaño de binario,
incluya números que lo respalden. Pero también describa costes no obvios.
Las optimizaciones generalmente no son gratuitas, sino un equilibrio entre
CPU, memoria y legibilidad; o, cuando se trata de heurísticas, entre
diferentes cargas de trabajo. Describa las desventajas esperadas de su
optimización para que el revisor pueda comparar las perdidas con los
beneficios.
Una vez establecido el problema, describa lo que realmente está haciendo
al respecto en detalles técnicos. Es importante describir el cambio en
lenguaje sencillo para que el revisor verifique que el código se está
comportando como se pretende.
El maintainer le agradecerá que escriba la descripción de su parche en un
formato que se pueda incorporar fácilmente en la gestión del código fuente
del sistema, ``git``, como un "commit log" (registros de los commits).
Consulte :ref:`sp_the_canonical_patch_format`.
Resuelva solo un problema por parche. Si su descripción comienza a ser muy
larga, eso es una señal de que probablemente necesite dividir su parche.
Lea :ref:`split_changes`.
Cuando envíe o vuelva a enviar un parche o una serie de parches, incluya la
descripción completa del parche y justificación del mismo. No se limite a
decir que esa es la versión N del parche (serie). No espere que el
maintainer del subsistema referencie versiones de parches anteriores o use
referencias URL para encontrar la descripción del parche y colocarla en el
parche. Es decir, el parche (serie) y su descripción deben ser
independientes. Esto beneficia tanto a los maintainers como a los
revisores. Algunos revisores probablemente ni siquiera recibieran versiones
anteriores del parche.
Describa sus cambios en la forma imperativa, por ejemplo, "hacer que xyzzy
haga frotz" en lugar de "[Este parche] hace que xyzzy haga frotz" o "[Yo]
Cambié xyzzy para que haga frotz", como si estuviera dando órdenes al
código fuente para cambiar su comportamiento.
Si desea hacer referencia a un commit específico, no se limite a hacer
referencia al ID SHA-1 del commit. Incluya también el resumen de una línea
del commit, para que sea más fácil para los revisores saber de qué se
trata.
Ejemplo::
Commit e21d2170f36602ae2708 ("video: quitar platform_set_drvdata()
innecesario") eliminó innecesario platform_set_drvdata(), pero dejó la
variable "dev" sin usar, bórrese.
También debe asegurarse de utilizar al menos los primeros doce caracteres
del identificador SHA-1. El repositorio del kernel contiene muchos *muchos*
objetos, por lo que las colisiones con identificaciones más cortas son una
posibilidad real. Tenga en cuenta que, aunque no hay colisión con su
identificación de seis caracteres ahora, esa condición puede cambiar dentro
de cinco años.
Si las discusiones relacionadas o cualquier otra información relativa al
cambio se pueden encontrar en la web, agregue las etiquetas 'Link:' que
apunten a estos. En caso de que su parche corrija un error, por poner un
ejemplo, agregue una etiqueta con una URL que haga referencia al informe en
los archivos de las listas de correo o un rastreador de errores; si el
parche es el resultado de alguna discusión anterior de la lista de correo o
algo documentado en la web, referencie esto.
Cuando se vincule a archivos de listas de correo, preferiblemente use el
servicio de archivador de mensajes lore.kernel.org. Para crear la URL del
enlace, utilice el contenido del encabezado ("header") ``Message-Id`` del
mensaje sin los corchetes angulares que lo rodean.
Por ejemplo::
Link: https://lore.kernel.org/r/30th.anniversary.repost@klaava.Helsinki.FI/
Verifique el enlace para asegurarse de que realmente funciona y apunta al
mensaje correspondiente.
Sin embargo, intente que su explicación sea comprensible sin recursos
externos. Además de dar una URL a un archivo o error de la lista de correo,
resuma los puntos relevantes de la discusión que condujeron al parche tal y
como se envió.
Si su parche corrige un error en un commit específico, por ejemplo
encontró un problema usando ``git bisect``, utilice la etiqueta 'Fixes:'
con los primeros 12 caracteres del ID SHA-1 y el resumen de una línea. No
divida la etiqueta en varias líneas, las etiquetas están exentas de la
regla "ajustar a 75 columnas" para simplificar análisis de scripts. Por
ejemplo::
Fixes: 54a4f0239f2e ("KVM: MMU: hacer que kvm_mmu_zap_page()
devuelva la cantidad de páginas que realmente liberó")
Las siguientes configuraciones de ``git config`` se pueden usar para
agregar un bonito formato y generar este estilo con los comandos
``git log`` o ``git show``::
[core]
abbrev = 12
[pretty]
fixes = Fixes: %h (\"%s\")
Un ejemplo de uso::
$ git log -1 --pretty=fixes 54a4f0239f2e
Fixes: 54a4f0239f2e ("KVM: MMU: hacer que kvm_mmu_zap_page() devuelva la cantidad de páginas que realmente liberó")
.. _sp_split_changes:
Separe sus cambios
-------------------
Separe cada **cambio lógico** en un parche separado.
Por ejemplo, si sus cambios incluyen correcciones de errores y mejoras en
el rendimiento de un controlador, separe esos cambios en dos o más parches.
Si sus cambios incluyen una actualización de la API y una nueva controlador
que usa esta nueva API, sepárelos en dos parches.
Por otro lado, si realiza un solo cambio en numerosos archivos, agrupe esos
cambios en un solo parche. Por lo tanto, un solo cambio lógico estará
contenido en un solo parche.
El punto a recordar es que cada parche debe realizar un cambio que puede
ser verificado por los revisores fácilmente. Cada parche debe ser
justificable por sus propios méritos.
Si un parche depende de otro parche para que un cambio sea completo, eso
está bien. Simplemente incluya que **"este parche depende del parche X"**
en la descripción de su parche.
Cuando divida su cambio en una serie de parches, tenga especial cuidado en
asegurarse de que el kernel se compila y ejecuta correctamente después de
cada parche en la serie. Los desarrolladores que usan ``git bisect``
para rastrear un problema pueden terminar dividiendo su serie de parches en
cualquier punto; no le agradecerán si introdujo errores a la mitad.
Si no puede condensar su conjunto de parches en un conjunto más pequeño de
parches, solo publique, más o menos 15 a la vez, y espere la revisión e
integración.
Revise el estilo en sus cambios
--------------------------------
Revise su parche para ver si hay violaciones de estilo básico, cuyos
detalles pueden ser encontrados en Documentation/process/coding-style.rst.
No hacerlo simplemente desperdicia el tiempo de los revisores y su parche
será rechazado, probablemente sin siquiera ser leído.
Una excepción importante es cuando se mueve código de un archivo a otro.
En tal caso, en absoluto debe modificar el código movido en el mismo parche
en que lo mueve. Esto divide claramente el acto de mover el código y sus
cambios. Esto ayuda mucho a la revisión de la diferencias reales y permite
que las herramientas rastreen mejor el historial del código en sí.
Verifique sus parches con el verificador de estilo de parches antes de
enviarlos (scripts/checkpatch.pl). Tenga en cuenta, sin embargo, que el
verificador de estilo debe ser visto como una guía, no como un reemplazo
del juicio humano. Si su código es mejor con una violación entonces
probablemente sea mejor dejarlo estar.
El verificador informa a tres niveles:
- ERROR: cosas que es muy probable que estén mal
- WARNING: Advertencia. Cosas que requieren una revisión cuidadosa
- CHECK: Revisar. Cosas que requieren pensarlo
Debe poder justificar todas las violaciones que permanezcan en su parche.
Seleccione los destinatarios de su parche
------------------------------------------
Siempre debe incluir en copia a los apropiados maintainers del subsistema
en cualquier parche con código que mantengan; revise a través del archivo
MAINTAINERS y el historial de revisión del código fuente para ver quiénes
son esos maintainers. El script scripts/get_maintainer.pl puede ser muy
útil en este paso (pase rutas a sus parches como argumentos para
scripts/get_maintainer.pl). Si no puede encontrar un maintainer del
subsistema en el que está trabajando, Andrew Morton
(akpm@linux-foundation.org) sirve como maintainer de último recurso.
Normalmente, también debe elegir al menos una lista de correo para recibir
una copia de su conjunto de parches. linux-kernel@vger.kernel.org debe
usarse de forma predeterminada para todos los parches, pero el volumen en
esta lista ha hecho que muchos desarrolladores se desconecten. Busque en el
archivo MAINTAINERS una lista específica de los subsistemas; su parche
probablemente recibirá más atención allí. Sin embargo, no envíe spam a
listas no relacionadas.
Muchas listas relacionadas con el kernel están alojadas en vger.kernel.org;
puedes encontrar un listado de estas en
http://vger.kernel.org/vger-lists.html. Existen listas relacionadas con el
kernel alojadas en otros lugares, no obstante.
¡No envíe más de 15 parches a la vez a las listas de correo de vger!
Linus Torvalds es el árbitro final de todos los cambios aceptados en el
kernel de Linux. Su dirección de correo electrónico es
<torvalds@linux-foundation.org>. Recibe muchos correos electrónicos y, en
este momento, muy pocos parches pasan por Linus directamente, por lo que
normalmente debe hacer todo lo posible para -evitar- enviarle un correo
electrónico.
Si tiene un parche que corrige un error de seguridad explotable, envíe ese
parche a security@kernel.org. Para errores graves, se debe mantener un
poco de discreción y permitir que los distribuidores entreguen el parche a
los usuarios; en esos casos, obviamente, el parche no debe enviarse a
ninguna lista pública. Revise también
Documentation/admin-guide/security-bugs.rst.
Los parches que corrigen un error grave en un kernel en uso deben dirigirse
hacia los maintainers estables poniendo una línea como esta::
CC: stable@vger.kernel.org
en el área de sign-off de su parche (es decir, NO un destinatario de correo
electrónico). También debe leer
Documentation/process/stable-kernel-rules.rst además de este documento.
Si los cambios afectan las interfaces del kernel para el usuario, envíe al
maintainer de las MAN-PAGES (como se indica en el archivo MAINTAINERS) un
parche de páginas de manual, o al menos una notificación del cambio, para
que alguna información se abra paso en las páginas del manual. Los cambios
de la API del espacio de usuario también deben copiarse en
linux-api@vger.kernel.org.
Sin MIME, enlaces, compresión o archivos adjuntos. Solo texto plano
--------------------------------------------------------------------
Linus y otros desarrolladores del kernel deben poder leer y comentar sobre
los cambios que está enviando. Es importante para un desarrollador kernel
poder "citar" sus cambios, utilizando herramientas estándar de correo
electrónico, de modo que puedan comentar sobre partes específicas de su
código.
Por este motivo, todos los parches deben enviarse por correo electrónico
"inline". La forma más sencilla de hacerlo es con ``git send-email``, que
es muy recomendable. Un tutorial interactivo para ``git send-email`` está
disponible en https://git-send-email.io.
Si elige no usar ``git send-email``:
.. warning::
Tenga cuidado con el ajuste de palabras de su editor que corrompe su
parche, si elige cortar y pegar su parche.
No adjunte el parche como un archivo adjunto MIME, comprimido o no. Muchas
populares aplicaciones de correo electrónico no siempre transmiten un MIME
archivo adjunto como texto sin formato, por lo que es imposible comentar
en su código. Linus también necesita un poco más de tiempo para procesar un
archivo adjunto MIME, disminuyendo la probabilidad de que se acepte su
cambio adjunto en MIME.
Excepción: si su proveedor de correo está destrozando parches, entonces
alguien puede pedir que los vuelva a enviar usando MIME.
Consulte Documentation/process/email-clients.rst para obtener sugerencias
sobre cómo configurar su cliente de correo electrónico para que envíe sus
parches intactos.
Responda a los comentarios de revisión
---------------------------------------
Es casi seguro que su parche recibirá comentarios de los revisores sobre
maneras en que se pueda mejorar el parche, en forma de respuesta a su
correo electrónico. Debe responder a esos comentarios; ignorar a los
revisores es una buena manera de ser ignorado de vuelta. Simplemente puede
responder a sus correos electrónicos para contestar a sus comentarios.
Revisiones a los comentarios o preguntas que no conduzcan a un cambio de
código deben casi con certeza generar un comentario o una entrada en el
"changelog" para que el próximo revisor entienda lo que está pasando.
Asegúrese de decirles a los revisores qué cambios está haciendo y de
agradecerles que dediquen su tiempo. La revisión del código es un proceso
agotador y lento, y los revisores a veces se ponen de mal humor. Sin
embargo, incluso en ese caso, responda cortésmente y aborde los problemas
que hayan señalado. Al enviar un siguiente versión, agregue un
``patch changelog`` (registro de cambios en los parches) a la carta de
presentación ("cover letter") o a parches individuales explicando la
diferencia con la presentación anterior (ver
:ref:`sp_the_canonical_patch_format`).
Consulte Documentation/process/email-clients.rst para obtener
recomendaciones sobre clientes de correo electrónico y normas de etiqueta
en la lista de correo.
.. _sp_resend_reminders:
No se desanime o impaciente
---------------------------
Después de haber entregado su cambio, sea paciente y espere. Los revisores
son personas ocupadas y es posible que no lleguen a su parche de inmediato.
Érase una vez, los parches solían desaparecer en el vacío sin comentarios,
pero el proceso de desarrollo funciona mejor que eso ahora. Debería
recibir comentarios dentro de una semana más o menos; si eso no sucede,
asegúrese de que ha enviado sus parches al lugar correcto. Espere un mínimo
de una semana antes de volver a enviar o hacer ping a los revisores,
posiblemente más durante periodos de mucho trabajo ocupados como "merge
windows".
También está bien volver a enviar el parche o la serie de parches después
de un par de semanas con la palabra "RESEND" (reenviar) añadida a la línea
de asunto::
[PATCH Vx RESEND] sub/sys: Resumen condensado de parche
No incluya "RESEND" cuando envíe una versión modificada de su parche o
serie de parches: "RESEND" solo se aplica al reenvío de un parche o serie
de parches que no hayan sido modificados de ninguna manera con respecto a
la presentación anterior.
Incluya PATCH en el asunto
--------------------------
Debido al alto tráfico de correo electrónico a Linus y al kernel de Linux,
es común prefijar su línea de asunto con [PATCH]. Esto le permite a Linus
y otros desarrolladores del kernel distinguir más fácilmente los parches de
otras discusiones por correo electrónico.
``git send-email`` lo hará automáticamente.
Firme su trabajo: el Certificado de Origen del Desarrollador
------------------------------------------------------------
Para mejorar el seguimiento de quién hizo qué, especialmente con parches
que pueden filtrarse hasta su destino final a través de varias capas de
maintainers, hemos introducido un procedimiento de "sign-off" (aprobación)
en parches que se envían por correo electrónico.
La aprobación es una simple línea al final de la explicación del parche,
que certifica que usted lo escribió o que tiene derecho a enviarlo como un
parche de código abierto. Las reglas son bastante simples: si usted puede
certificar lo siguiente:
Certificado de Origen del Desarrollador 1.1
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Al hacer una contribución a este proyecto, certifico que:
(a) La contribución fue creada en su totalidad o en parte por mí y
tengo derecho a enviarlo bajo la licencia de código abierto
indicada en el documento; o
(b) La contribución se basa en trabajo previo que, hasta donde yo
soy consciente, está cubierto por una licencia de código
abierto apropiada y tengo el derecho bajo esa licencia de
presentar tal trabajo con modificaciones, ya sean creadas en su
totalidad o en parte por mí, bajo la misma licencia de código
(salvo que sea permitido presentar bajo una licencia diferente),
tal y como se indica en el documento; o
(c) La contribución me fue proporcionada directamente por alguna
otra persona que certificó (a), (b) o (c) y no he modificado
esto.
(d) Entiendo y acepto que este proyecto y la contribución
son públicos y que un registro de la contribución (incluyendo
toda la información personal que envío con él, incluida mi
firma) es mantenida indefinidamente y puede ser redistribuida
de manera consistente con este proyecto o la(s) licencia(s) de
código abierto involucradas.
entonces simplemente incluya una línea que rece::
Signed-off-by: Random J Developer <random@developer.example.org>
usando su nombre real (lamentablemente, no pseudónimos ni contribuciones
anónimas). Esto se hará por usted automáticamente si usa ``git commit -s``.
Las reversiones de código también deben incluir "Signed-off-by".
``git revert -s`` hace eso por usted.
Algunas personas también ponen etiquetas adicionales al final. Simplemente
serán ignoradas por ahora, pero puede hacer esto para marcar procedimientos
internos de su empresa o simplemente señalar algún detalle especial sobre
la firma.
Cualquier otro SoB (Signed-off-by:) después del SoB del autor es de
personas que manipulen y transporten el parche, pero no participaron en su
desarrollo. Las cadenas de SoB deben reflejar la ruta **real** del parche
de cómo se propagó a los maintainers y, en última instancia, a Linus, con
la primera entrada de SoB que señala la autoría principal de un solo autor.
Cuándo usar Acked-by:, Cc: y Co-developed-by por:
-------------------------------------------------
La etiqueta Signed-off-by: indica que el firmante estuvo involucrado en el
desarrollo del parche, o que él/ella se encontraba en el camino de entrega
del parche.
Si una persona no estuvo directamente involucrada en la preparación o
administración de un parche pero desea expresar y registrar su aprobación,
entonces puede pedir que se agregue una línea Acked-by: al registro de
cambios del parche.
Acked-by: a menudo lo usa el maintainer del código afectado cuando ese
maintainer no contribuyó ni envió el parche.
Acked-by: no es tan formal como Signed-off-by:. Es una manera de marcar que
el "acker" ha revisado al menos ese parche y ha indicado su aceptación. Por
los merge de parches a veces convertirán manualmente el "sí, me parece bien"
de un acker en un Acked-by: (pero tenga en cuenta que por lo general es
mejor pedir un acuse de recibo explícito).
Acked-by: no necesariamente indica el reconocimiento de todo el parche.
Por ejemplo, si un parche afecta a varios subsistemas y tiene un
Acked-by: de un maintainer del subsistema, entonces esto generalmente
indica el reconocimiento de solo la parte que afecta el código de ese
maintainer. Buen juicio debe ejercitarse aquí. En caso de duda, la gente
debe consultar la discusión original en los archivos de la lista de correo.
Si una persona ha tenido la oportunidad de comentar un parche, pero no lo
ha hecho, puede incluir opcionalmente una etiqueta ``Cc:`` al parche.
Esta es la única etiqueta que se puede agregar sin una acción explícita por
parte de la persona a la que se nombre - pero debe indicar que esta persona
fue copiada en el parche. Esta etiqueta documenta que las partes
potencialmente interesadas han sido incluidas en la discusión.
Co-developed-by: establece que el parche fue co-creado por múltiples
desarrolladores; se utiliza para dar atribución a los coautores (además del
autor atribuido por la etiqueta From:) cuando varias personas trabajan en
un solo parche. Ya que Co-developed-by: denota autoría, cada
Co-developed-by: debe ser inmediatamente seguido de Signed-off-by: del
coautor asociado. Se mantiene el procedimiento estándar, es decir, el orden
de las etiquetas Signed-off-by: debe reflejar el historial cronológico del
parche en la medida de lo posible, independientemente de si el autor se
atribuye a través de From: o Co-developed-by:. Cabe destacar que el último
Signed-off-by: siempre debe ser del desarrollador que envía el parche.
Tenga en cuenta que la etiqueta From: es opcional cuando el autor From: es
también la persona (y correo electrónico) enumerados en la línea From: del
encabezado del correo electrónico.
Ejemplo de un parche enviado por el From: autor::
<changelog>
Co-developed-by: Primer coautor <primer@coauthor.example.org>
Signed-off-by: Primer coautor <primer@coauthor.example.org>
Co-developed-by: Segundo coautor <segundo@coautor.ejemplo.org>
Signed-off-by: Segundo coautor <segundo@coautor.ejemplo.org>
Signed-off-by: Autor del From <from@author.example.org>
Ejemplo de un parche enviado por un Co-developed-by: autor::
From: Autor del From <from@author.example.org>
<changelog>
Co-developed-by: Co-Autor aleatorio <aleatorio@coauthor.example.org>
Signed-off-by: Coautor aleatorio <aleatorio@coauthor.example.org>
Signed-off-by: Autor del From <from@author.example.org>
Co-developed-by: Coautor que envió <sub@coauthor.example.org>
Signed-off-by: Coautor que envía <sub@coauthor.example.org>
Uso de Reported-by:, Tested-by:, Reviewed-by:, Suggested-by: y Fixes:
----------------------------------------------------------------------
La etiqueta Reported-by (Reportado-por) otorga crédito a las personas que
encuentran errores y los reportan. Por favor, tenga en cuenta que si se
informó de un error en privado, debe pedir primero permiso antes de usar la
etiqueta Reported-by. La etiqueta está destinada a errores; por favor no la
use para acreditar peticiones de características.
Una etiqueta Tested-by: indica que el parche se probó con éxito (en algún
entorno) por la persona nombrada. Esta etiqueta informa a los maintainers
de que se han realizado algunas pruebas, proporciona un medio para ubicar
"testers" (gente que pruebe) otros parches futuros y asegura el crédito
para los testers.
Reviewed-by: en cambio, indica que el parche ha sido revisado y encontrado
aceptable de acuerdo con la Declaración del Revisor:
Declaración de Supervisión del Revisor
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Al ofrecer mi etiqueta Reviewed-by:, afirmo que:
(a) He llevado a cabo una revisión técnica de este parche para
evaluar su idoneidad y preparación para su inclusión en
el kernel principal.
(b) Cualquier problema, inquietud o pregunta relacionada con el parche
han sido comunicados al remitente. Estoy satisfecho
con la respuesta del remitente a mis comentarios.
(c) Si bien puede haber cosas que podrían mejorarse con esta
entrega, creo que es, en este momento, (1) una
modificación valiosa al kernel, y (2) libre de conocidas
cuestiones que argumentarían en contra de su inclusión.
(d) Si bien he revisado el parche y creo que es correcto,
no hago (a menos que se indique explícitamente en otro lugar) ninguna
garantía o avales de que logrará su definido
propósito o función en cualquier situación dada.
Una etiqueta Reviewed-by es una declaración de opinión de que el parche es
una modificación apropiada al kernel sin que haya ningún problema grave
a nivel técnico. Cualquier revisor interesado (que haya hecho el trabajo)
puede ofrecer una etiqueta Reviewed-by para un parche. Esta etiqueta sirve
para dar crédito a revisores e informar a los maintainers del grado de
revisión que se ha hecho en el parche. Las etiquetas Reviewed-by, cuando
las otorgan revisores conocidos por entender del tema y realizar
revisiones exhaustivas, normalmente aumentan la probabilidad de que su
parche entre en el kernel.
Las etiquetas Tested-by y Reviewed-by, una vez recibidas en la lista de
correo por el tester o revisor, deben ser incluidas por el autor de los
parches pertinentes al enviar próximas versiones. Sin embargo, si el parche
ha cambiado sustancialmente en la siguiente versión, es posible que estas
etiquetas ya no sean aplicables y, por lo tanto, deben eliminarse. Por lo
general, se debe mencionar la eliminación de las etiquetas Tested-by o
Reviewed-by de alguien en el registro de cambios del parche (después del
separador '---').
Una etiqueta Suggested-by: indica que la idea del parche es sugerida por la
persona nombrada y asegura el crédito a la persona por la idea. Tenga en
cuenta que esto no debe agregarse sin el permiso del "reporter",
especialmente si la idea no fue publicada en un foro público. Dicho esto,
si diligentemente acreditamos a los reporters de ideas, con suerte, se
sentirán inspirados para ayudarnos nuevamente en el futuro.
Una etiqueta Fixes: indica que el parche corrige un problema en un commit
anterior. Esto se utiliza para facilitar descubrir dónde se originó un
error, lo que puede ayudar a revisar una corrección de errores. Esta
etiqueta también ayuda al equipo del kernel estable a determinar qué
versiones estables del kernel deberían recibir su corrección. Este es el
método preferido para indicar un error corregido por el parche. Revise
:ref:`describe_changes` para más detalles.
Nota: Adjuntar una etiqueta Fixes: no subvierte las reglas estables del
proceso del kernel ni el requisito de CC: stable@vger.kernel.org en todos
los parches candidatos de ramas estables. Para obtener más información, lea
Documentation/process/stable-kernel-rules.rst.
.. _sp_the_canonical_patch_format:
Formato de parche canónico
---------------------------
Esta sección describe cómo debe darse formato al propio parche. Tenga en
cuenta que, si tiene sus parches almacenados en un repositorio ``git``, el
parche con formato adecuado se puede obtener con ``git format-patch``. Las
herramientas no pueden crear el texto necesario, sin embargo, así que lea
las instrucciones a continuación de todos modos.
La línea de asunto del parche canónico es::
Asunto: [PATCH 001/123] subsistema: frase de resumen
El cuerpo del mensaje del parche canónico contiene lo siguiente:
- Una línea ``from`` que especifica el autor del parche, seguida de una
línea vacía (solo es necesario si la persona que envía el parche no es
el autor).
- El cuerpo de la explicación, línea envuelta en 75 columnas, que se
copiara en el registro de cambios permanente para describir este parche.
- Una línea vacía.
- Las líneas ``Signed-off-by:``, descritas anteriormente, que
también vaya en el registro de cambios.
- Una línea de marcador que contiene simplemente ``---``.
- Cualquier comentario adicional que no sea adecuado para el registro de
cambios.
- El parche real (output de ``diff``).
El formato de la línea de asunto hace que sea muy fácil ordenar los correos
electrónicos alfabéticamente por línea de asunto - prácticamente cualquier
lector de correo electrónico permite esto, ya que debido a que el número de
secuencia se rellena con ceros, el orden numérico y alfabético es el mismo.
El ``subsistema`` en el asunto del correo electrónico debe identificar qué
área o subsistema del kernel está siendo parcheado.
La ``frase de resumen`` en el Asunto del correo electrónico debe describir
de forma concisa el parche que contiene ese correo electrónico. La
``frase resumen`` no debe ser un nombre de archivo. No use la mismo ``frase
resumen`` para cada parche en una serie completa de parches (donde una
`` serie de parches`` (patch series) es una secuencia ordenada de múltiples
parches relacionados).
Tenga en cuenta que la ``frase de resumen`` de su correo electrónico se
convierte en un identificador global único para ese parche. Se propaga por
hasta el registro de cambios de ``git``. La ``frase resumida`` se puede
usar más adelante en discusiones de desarrolladores que se refieran al
parche. La gente querrá buscar en Google la ``frase de resumen`` para leer
la discusión al respecto del parche. También será lo único que la gente
podrá ver rápidamente cuando, dos o tres meses después, estén pasando por
quizás miles de parches usando herramientas como ``gitk`` o ``git log
--oneline``.
Por estas razones, el ``resumen`` no debe tener más de 70-75 caracteres, y
debe describir tanto lo que cambia el parche como por qué el parche podría
ser necesario. Es un reto ser tanto sucinto como descriptivo, pero eso es
lo que un resumen bien escrito debería hacer.
La ``frase de resumen`` puede estar precedida por etiquetas encerradas en
corchetes: "Asunto: [PATCH <etiqueta>...] <frase de resumen>". Las
etiquetas no se consideran parte de la frase de resumen, pero describen
cómo debería ser tratado el parche. Las etiquetas comunes pueden incluir un
descriptor de versión si las múltiples versiones del parche se han enviado
en respuesta a comentarios (es decir, "v1, v2, v3") o "RFC" para indicar
una solicitud de comentarios.
Si hay cuatro parches en una serie de parches, los parches individuales
pueden enumerarse así: 1/4, 2/4, 3/4, 4/4. Esto asegura que los
desarrolladores entiendan el orden en que se deben aplicar los parches y
que han revisado o aplicado todos los parches de la serie de parches.
Aquí hay algunos buenos ejemplos de Asuntos::
Asunto: [PATCH 2/5] ext2: mejorar la escalabilidad de la búsqueda de mapas de bits
Asunto: [PATCH v2 27/01] x86: corregir el seguimiento de eflags
Asunto: [PATCH v2] sub/sys: resumen conciso del parche
Asunto: [PATCH v2 M/N] sub/sys: resumen conciso del parche
La línea ``from`` debe ser la primera línea en el cuerpo del mensaje,
y tiene la forma::
From: Autor del parche <autor@ejemplo.com>
La línea ``From`` especifica quién será acreditado como el autor del parche
en el registro de cambios permanente. Si falta la línea ``from``, entonces
la línea ``From:`` del encabezado del correo electrónico se usará para
determinar el autor del parche en el registro de cambios.
La explicación estará incluida en el commit del changelog permanente, por
lo que debería tener sentido para un lector competente que hace mucho tiempo
ha olvidado los detalles de la discusión que podrían haber llevado a
este parche. Incluidos los síntomas del fallo que el parche trate
(mensajes de registro del kernel, mensajes de oops, etc.) son especialmente
útiles para personas que podrían estar buscando en los registros de
commits en busca de la aplicación del parche. El texto debe estar escrito
con tal detalle que cuando se lea semanas, meses o incluso años después,
pueda dar al lector la información necesaria y detalles para comprender el
razonamiento de **por qué** se creó el parche.
Si un parche corrige una falla de compilación, puede que no sea necesario
incluir _todos_ los errores de compilación; pero lo suficiente como para
que sea probable que alguien que busque el parche puede encontrarlo. Como
en la ``frase de resumen``, es importante ser tanto sucinto como
descriptivo.
La línea marcadora ``---`` cumple el propósito esencial de marcar para
herramientas de manejo de parches donde termina el mensaje de registro de
cambios.
Un buen uso de los comentarios adicionales después del marcador ``---`` es
para ``diffstat``, para mostrar qué archivos han cambiado, y el número de
líneas insertadas y eliminadas por archivo. Un ``diffstat`` es
especialmente útil en parches más grandes. Si va a incluir un ``diffstat``
después del marcador ``---``, utilice las opciones ``diffstat``
``-p 1 -w 70`` para que los nombres de archivo se enumeran desde la parte
superior del árbol de fuentes del kernel y no use demasiado espacio
horizontal (que encaje fácilmente en 80 columnas, tal vez con alguna
indentación). (``git`` genera diffstats apropiados por defecto).
Otros comentarios relevantes solo en el momento o para el maintainer, pero
no adecuados para el registro de cambios permanente, también debe ir aquí.
Un buen ejemplo de tales comentarios podría ser ``registros de cambios de
parches`` que describen qué ha cambiado entre la versión v1 y v2 del
parche.
Por favor, ponga esta información **después** de la línea ``---`` que
separa el registro de cambios del resto del parche. La información de la
versión no forma parte del registro de cambios que se incluye con el árbol
git. Es información adicional para los revisores. Si se coloca encima de la
etiquetas de commit, necesita interacción manual para eliminarlo. Si esta
debajo de la línea de separación, se quita automáticamente al aplicar el
parche::
<mensaje de commit>
...
Signed-off-by: Autor <autor@correo>
---
V2 -> V3: función auxiliar redundante eliminada
V1 -> V2: estilo de código limpio y comentarios de revisión abordados
ruta/al/archivo | 5+++--
...
Revise más detalles sobre el formato de parche adecuado en las siguientes
referencias
.. _sp_backtraces:
Retrocesos en mensajes de confirmación
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Los "backtraces" (deshacer el camino) ayuda a documentar la cadena de
llamadas que conducen a un problema. Sin embargo, no todos los rastreos son
útiles. Por ejemplo, las tempranas cadenas de llamadas de inicio son únicas
y obvias. Sin embargo, al copiar la salida completa de dmesg textualmente,
incluye información que distrae, como marcas de tiempo, listas de módulos,
registro y volcados de pila.
Por lo tanto, los backtraces más útiles deben contener los datos
relevantes de la información vertida, lo que hace que sea más fácil
centrarse en el verdadero tema. Este es un ejemplo de un backtrace bien
recortado::
error de acceso de MSR no verificado: WRMSR a 0xd51 (intentó escribir 0x0000000000000064)
en rIP: 0xffffffffae059994 (native_write_msr+0x4/0x20)
Rastreo de llamadas:
mba_wrmsr
update_domains
rdtgroup_mkdir
.. _sp_explicit_in_reply_to:
In-Reply-To explicitos en las cabeceras
---------------------------------------
Puede ser útil agregar manualmente encabezados In-Reply-To: a un parche
(por ejemplo, al usar ``git send-email``) para asociar el parche con una
discusión anterior relevante, por ejemplo para vincular una corrección de
errores al correo electrónico con el informe de errores. Sin embargo, para
una serie de parches múltiples, generalmente es mejor evitar usar
In-Reply-To: para vincular a versiones anteriores de la serie. De esta
forma, varias versiones del parche no se convierten en un inmanejable
bosque de referencias en clientes de correo electrónico. Si un enlace es
útil, puede usar el redirector https://lore.kernel.org/ (por ejemplo, en
el texto de la carta de introducción del correo electrónico) para vincular
a una versión anterior de la serie de parches.
Proporcionar información de árbol base
--------------------------------------
Cuando otros desarrolladores reciben sus parches y comienzan el proceso de
revisión, a menudo es útil para ellos saber en qué parte del historial del
árbol deben colocar su trabajo. Esto es particularmente útil para CI
automatizado de procesos que intentan ejecutar una serie de pruebas para
establecer la calidad de su envío antes de que el maintainer comience la
revisión.
Si está utilizando ``git format-patch`` para generar sus parches, puede
incluir automáticamente la información del árbol base en su envío usando el
parámetro ``--base``. La forma más fácil y conveniente de usar esta opción
es con "topical branches" (ramas de temas)::
$ git checkout -t -b my-topical-branch master
Branch 'my-topical-branch' set up to track local branch 'master'.
Switched to a new branch 'my-topical-branch'
[realice sus cambios y ediciones]
$ git format-patch --base=auto --cover-letter -o outgoing/ master
outgoing/0000-cover-letter.patch
outgoing/0001-First-Commit.patch
outgoing/...
Cuando abra ``outgoing/0000-cover-letter.patch`` para editar, tenga en
cuenta que tendrá el tráiler ``base-commit:`` al final, que proporciona al
revisor y a las herramientas de CI suficiente información para realizar
correctamente ``git am`` sin preocuparse por los conflictos::
$ git checkout -b patch-review [base-commit-id]
Switched to a new branch 'patch-review'
$ git am patches.mbox
Applying: First Commit
Applying: ...
Consulte ``man git-format-patch`` para obtener más información al respecto
de esta opción.
.. Note::
La función ``--base`` se introdujo en la versión 2.9.0 de git.
Si no está utilizando git para dar forma a sus parches, aún puede incluir
el mismo tráiler ``base-commit`` para indicar el hash de confirmación del
árbol en que se basa su trabajo. Debe agregarlo en la carta de presentación
o en el primer parche de la serie y debe colocarse ya sea bajo la línea
``---`` o en la parte inferior de todos los demás contenido, justo antes de
su firma del correo electrónico.
Referencias
-----------
"The perfect patch" (tpp) por Andrew Morton.
<https://www.ozlabs.org/~akpm/stuff/tpp.txt>
"Linux kernel patch submission format" por Jeff Garzik.
<https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html>
"How to piss off a kernel subsystem maintainer" por Greg Kroah-Hartman.
<http://www.kroah.com/log/linux/maintainer.html>
<http://www.kroah.com/log/linux/maintainer-02.html>
<http://www.kroah.com/log/linux/maintainer-03.html>
<http://www.kroah.com/log/linux/maintainer-04.html>
<http://www.kroah.com/log/linux/maintainer-05.html>
<http://www.kroah.com/log/linux/maintainer-06.html>
NO!!!! Gente, no mas bombas enormes de parches a linux-kernel@vger.kernel.org!
<https://lore.kernel.org/r/20050711.125305.08322243.davem@davemloft.net>
Kernel Documentation/process/coding-style.rst
Email de Linus Torvalds sobre la forma canónica de los parches:
<https://lore.kernel.org/r/Pine.LNX.4.58.0504071023190.28951@ppc970.osdl.org>
"On submitting kernel patches" por Andi Kleen
Algunas estrategias para conseguir incluir cambios complicados o
controvertidos.
http://halobates.de/on-submitting-patches.pdf
.. SPDX-License-Identifier: GPL-2.0
This is a simple wrapper to bring memory-barriers.txt (Spanish
translation) into the RST world until such a time as that file can be
converted directly.
====================================
Barreras de Memoria del kernel Linux
====================================
.. raw:: latex
\footnotesize
.. include:: ../memory-barriers.txt
:literal:
.. raw:: latex
\normalsize
.. SPDX-License-Identifier: GPL-2.0+
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/core-api/errseq.rst
:翻译:
周彬彬 Binbin Zhou <zhoubinbin@loongson.cn>
:校译:
吴想成 Wu Xiangcheng <bobwxc@email.cn>
================
errseq_t数据类型
================
``errseq_t`` 是一种在一个地方记录错误的方法,并允许任意数量的 ``订阅者`` 判断自上
次采样点以来是否发生了变化。
最初的用例是跟踪文件同步系统调用( ``fsync``, ``fdatasync``, ``msync`` 和
``sync_file_range`` )的错误,但它也可以用于其他情况。
它被实现为一个无符号的32位值。低位被指定保存错误代码(在1和MAX_ERRNO之间)。高位
用作计数器。这里是用原子操作而不是锁来完成的,因此可以从任何上下文中调用这些函数。
请注意,如果频繁记录新错误,则存在冲突风险,因为我们用作计数器的位很少。
为了缓解这种情况,错误值和计数器之间的位被用作一个标志,以判断自记录新值以来是否
对该值进行了采样。这使我们能够避免在上次记录错误后没有人取样的情况下碰撞计数器。
因此,我们得到了一个类似这样的值:
+--------------------------------------+------+------------------------+
| 31..13 | 12 | 11..0 |
+--------------------------------------+------+------------------------+
| 计数器 | 标志 | 错误值 |
+--------------------------------------+------+------------------------+
总体思路是让 ``观察者`` 对errseq_t值进行采样,并将其保留为运行游标。该值稍后可用
于判断自采样完成后是否发生了任何新错误,并原子地记录检查时的状态。这使得我们能在
一个地方记录错误,然后有许多 ``观察者`` 可以判断自上次检查以来该值是否发生了变化。
新的errseq_t应始终清零。全零的errseq_t值是从未出现错误的特殊(但常见)情况。因此,
如果您希望知道自首次初始化以来是否曾经有过错误集,则全零值被用作 ``纪元`` 。
API的使用方法
=============
让我给你们讲一个关于员工drone的故事。现在,他总体上是个好员工,但公司有点...管理
繁重。他今天必须向77名主管汇报,明天 ``大老板`` 要从外地赶来,他肯定也会考验这个
可怜的家伙。
他们都把工作交给他去做---多到他都记不住谁交给他什么了,但这并不是什么大问题。主管
们只想知道他什么时候完成他们迄今为止交给他的所有工作,以及自从他们上次询问以来他
是否犯了任何错误。
他可能在他们实际上并没有交给他的工作上犯了错误,但他无法在那么详细的层面上记录事
情,他所能记得的只是他最近犯的错误。
下面是我们 ``worker_drone`` 的表达式::
struct worker_drone {
errseq_t wd_err; /* 用来记录错误 */
};
每天, ``worker_drone`` 都是以一张白纸开始的::
struct worker_drone wd;
wd.wd_err = (errseq_t)0;
主管们进来后对当天的工作进行初步了解。他们并不关心在他们观察开始之前发生的任何事
情::
struct supervisor {
errseq_t s_wd_err; /* wd_err的私有“游标” */
spinlock_t s_wd_err_lock; /* 保护s_wd_err */
}
struct supervisor su;
su.s_wd_err = errseq_sample(&wd.wd_err);
spin_lock_init(&su.s_wd_err_lock);
现在他们开始给他布置任务。每隔几分钟,他们就要求他完成迄今为止交给他的所有工作。
然后问他是否有犯任何错误::
spin_lock(&su.su_wd_err_lock);
err = errseq_check_and_advance(&wd.wd_err, &su.s_wd_err);
spin_unlock(&su.su_wd_err_lock);
到目前为止,它只是不断返回0。
现在,这家公司的老板非常吝啬,给了他不合格的设备来完成他的工作。偶尔设备会出现故
障,导致他犯错。他重重地叹了一口气,并把它记录下来::
errseq_set(&wd.wd_err, -EIO);
...然后继续工作。主管们最终会再次检查,他们在下次检查时都会发现这个错误。后续的调
用将返回0,直到记录下另一个错误,此时将向每个调用报告一次。
请注意,主管们无法知道他们犯了多少错误,只能知道自上次检查以来是否犯了一个错误,
以及记录的最新值。
偶尔,大老板会来抽查,要求员工为他做一次性的工作。他并不像主管们那样全职观察员工,
但他确实需要知道在他的工作处理过程中是否发生了错误。
他只需对员工当前的errseq_t进行采样,然后用它来判断后来是否发生了错误::
errseq_t since = errseq_sample(&wd.wd_err);
/* 提交一些工作,等待完成 */
err = errseq_check(&wd.wd_err, since);
由于他只是要在那个点之后丢弃 ``since`` ,所以他不需要在这里推进它。同时他也不需要
任何锁,因为它不能被其他人使用。
序列化更新errseq_t游标
======================
请注意,errseq_t API在check_and_advance_operation期间不保护errseq_t游标。只有典型
的错误代码是被原子化处理的。在多任务同时使用同一个errseq_t游标的情况下,对该游标
的更新进行序列化是很重要的。
如果不这样做,那么游标就有可能向后移动。在这种情况下,同一个错误可能被报告多次。
因此,通常先执行errseq_check检查是否有任何变化,然后在获取锁后才执行
errseq_check_and_advance。例如::
if (errseq_check(&wd.wd_err, READ_ONCE(su.s_wd_err)) {
/* su.s_wd_err被s_wd_err_lock保护 */
spin_lock(&su.s_wd_err_lock);
err = errseq_check_and_advance(&wd.wd_err, &su.s_wd_err);
spin_unlock(&su.s_wd_err_lock);
}
这就避免了自上次检查以来没有任何变化的常见情况下的自旋锁。
函数
====
该API在以下内核代码中:
lib/errseq.c
......@@ -48,12 +48,12 @@
circular-buffers
generic-radix-tree
packing
this_cpu_ops
Todolist:
=======
Todolist:
this_cpu_ops
timekeeping
errseq
......
.. SPDX-License-Identifier: GPL-2.0+
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/core-api/this_cpu_ops.rst
:翻译:
周彬彬 Binbin Zhou <zhoubinbin@loongson.cn>
:校译:
吴想成 Wu Xiangcheng <bobwxc@email.cn>
============
this_cpu操作
============
:作者: Christoph Lameter, 2014年8月4日
:作者: Pranith Kumar, 2014年8月2日
this_cpu操作是一种优化访问与当前执行处理器相关的每CPU变量的方法。这是通过使用段寄
存器(或专用寄存器,cpu在其中永久存储特定处理器的每CPU区域的起始)来完成的。
this_cpu操作将每CPU变量的偏移量添加到处理器特定的每CPU基址上,并将该操作编码到对
每CPU变量进行操作的指令中。
这意味着在偏移量的计算和对数据的操作之间不存在原子性问题。因此,没有必要禁用抢占
或中断来确保处理器在计算地址和数据操作之间不被改变。
读取-修改-写入操作特别值得关注。通常处理器具有特殊的低延迟指令,可以在没有典型同
步开销的情况下运行,但仍提供某种宽松的原子性保证。例如,x86可以执行RMW(读取,
修改,写入)指令,如同inc/dec/cmpxchg,而无需锁前缀和相关的延迟损失。
对没有锁前缀的变量的访问是不同步的,也不需要同步,因为我们处理的是当前执行的处理
器所特有的每CPU数据。只有当前的处理器可以访问该变量,因此系统中的其他处理器不存在
并发性问题。
请注意,远程处理器对每CPU区域的访问是特殊情况,可能会影响通过 ``this_cpu_*`` 的本
地RMW操作的性能和正确性(远程写操作)。
this_cpu操作的主要用途是优化计数器操作。
定义了以下具有隐含抢占保护的this_cpu()操作。可以使用这些操作而不用担心抢占和中断::
this_cpu_read(pcp)
this_cpu_write(pcp, val)
this_cpu_add(pcp, val)
this_cpu_and(pcp, val)
this_cpu_or(pcp, val)
this_cpu_add_return(pcp, val)
this_cpu_xchg(pcp, nval)
this_cpu_cmpxchg(pcp, oval, nval)
this_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
this_cpu_sub(pcp, val)
this_cpu_inc(pcp)
this_cpu_dec(pcp)
this_cpu_sub_return(pcp, val)
this_cpu_inc_return(pcp)
this_cpu_dec_return(pcp)
this_cpu操作的内部工作
----------------------
在x86上,fs:或gs:段寄存器包含每CPU区域的基址。这样就可以简单地使用段覆盖,将每CPU
相对地址重定位到处理器适当的每CPU区域。所以对每CPU基址的重定位是通过段寄存器前缀
在指令中编码完成的。
例如::
DEFINE_PER_CPU(int, x);
int z;
z = this_cpu_read(x);
产生的单指令为::
mov ax, gs:[x]
而不是像每CPU操作那样,先是一系列的地址计算,然后从该地址获取。在this_cpu_ops之前,
这样的序列还需要先禁用/启用抢占功能,以防止内核在计算过程中将线程移动到不同的处理
器上。
请思考下面this_cpu操作::
this_cpu_inc(x)
这将产生如下单指令(无锁前缀!)::
inc gs:[x]
而不是在没有段寄存器的情况下所需要的以下操作::
int *y;
int cpu;
cpu = get_cpu();
y = per_cpu_ptr(&x, cpu);
(*y)++;
put_cpu();
请注意,这些操作只能用于为特定处理器保留的每CPU数据。如果不在上下文代码中禁用抢占,
``this_cpu_inc()`` 将仅保证每CPU的某一个计数器被正确地递增,但不能保证操作系统不
会在this_cpu指令执行的前后直接移动该进程。一般来说,这意味着每个处理器的单个计数
器的值是没有意义的。所有每CPU计数器的总和才是唯一有意义的值。
每CPU变量的使用是出于性能的考虑。如果多个处理器同时处理相同的代码路径,可以避免缓
存行跳转。每个处理器都有自己的每CPU变量,因此不会发生并发缓存行更新。为这种优化必
须付出的代价是,当需要计数器的值时要将每CPU计数器相加。
特殊的操作
----------
::
y = this_cpu_ptr(&x)
使用每CPU变量的偏移量(&x!),并返回属于当前执行处理器的每CPU变量的地址。
``this_cpu_ptr`` 避免了通用 ``get_cpu``/``put_cpu`` 序列所需的多个步骤。没有可用
的处理器编号。相反,本地每CPU区域的偏移量只是简单地添加到每CPU偏移量上。
请注意,这个操作通常是在抢占被禁用后再在代码段中使用。然后该指针用来访问临界区中
的本地每CPU数据。当重新启用抢占时,此指针通常不再有用,因为它可能不再指向当前处理
器的每CPU数据。
每CPU变量和偏移量
-----------------
每CPU变量相对于每CPU区域的起始点是有偏移的。它们没有地址,尽管代码里看起来像有一
样。不能直接对偏移量解引用,必须用处理器每CPU区域基指针加上偏移量,以构成有效地址。
因此,在每CPU操作的上下文之外使用x或&x是无效的,这种行为通常会被当作一个空指针的
解引用来处理。
::
DEFINE_PER_CPU(int, x);
在每CPU操作的上下文中,上面表达式说明x是一个每CPU变量。大多数this_cpu操作都需要一
个cpu变量。
::
int __percpu *p = &x;
&x和p是每CPU变量的偏移量。 ``this_cpu_ptr()`` 使用每CPU变量的偏移量,这让它看起来
有点奇怪。
每CPU结构体字段的操作
---------------------
假设我们有一个每CPU结构::
struct s {
int n,m;
};
DEFINE_PER_CPU(struct s, p);
这些字段的操作非常简单::
this_cpu_inc(p.m)
z = this_cpu_cmpxchg(p.m, 0, 1);
如果我们有一个相对于结构体s的偏移量::
struct s __percpu *ps = &p;
this_cpu_dec(ps->m);
z = this_cpu_inc_return(ps->n);
如果我们后面不使用 ``this_cpu ops`` 来操作字段,则指针的计算可能需要使用
``this_cpu_ptr()``::
struct s *pp;
pp = this_cpu_ptr(&p);
pp->m--;
z = pp->n++;
this_cpu ops的变体
------------------
this_cpu的操作是中断安全的。一些架构不支持这些每CPU的本地操作。在这种情况下,该操
作必须被禁用中断的代码所取代,然后做那些保证是原子的操作,再重新启用中断。当然这
样做是很昂贵的。如果有其他原因导致调度器不能改变我们正在执行的处理器,那么就没有
理由禁用中断了。为此,我们提供了以下__this_cpu操作。
这些操作不能保证并发中断或抢占。如果在中断上下文中不使用每CPU变量并且调度程序无法
抢占,那么它们是安全的。如果在操作进行时仍有中断发生,并且中断也修改了变量,则无
法保证RMW操作是安全的::
__this_cpu_read(pcp)
__this_cpu_write(pcp, val)
__this_cpu_add(pcp, val)
__this_cpu_and(pcp, val)
__this_cpu_or(pcp, val)
__this_cpu_add_return(pcp, val)
__this_cpu_xchg(pcp, nval)
__this_cpu_cmpxchg(pcp, oval, nval)
__this_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
__this_cpu_sub(pcp, val)
__this_cpu_inc(pcp)
__this_cpu_dec(pcp)
__this_cpu_sub_return(pcp, val)
__this_cpu_inc_return(pcp)
__this_cpu_dec_return(pcp)
将增加x,并且不会回退到在无法通过地址重定位和同一指令中的读取-修改-写入操作实现原
子性的平台上禁用中断的代码。
&this_cpu_ptr(pp)->n 对比 this_cpu_ptr(&pp->n)
----------------------------------------------
第一个操作使用偏移量并形成一个地址,然后再加上n字段的偏移量。这可能会导致编译器产
生两条加法指令。
第二个操作先加上两个偏移量,然后进行重定位。恕我直言,第二种形式看起来更干净,而
且更容易与 ``()`` 结合。第二种形式也与 ``this_cpu_read()`` 和大家的使用方式一致。
远程访问每CPU数据
-----------------
每CPU数据结构被设计为由一个CPU独占使用。如果您按预期使用变量,则 ``this_cpu_ops()``
保证是 ``原子的`` ,因为没有其他CPU可以访问这些数据结构。
在某些特殊情况下,您可能需要远程访问每CPU数据结构。通常情况下,进行远程读访问是安
全的,这经常是为了统计计数器值。远程写访问可能会出现问题,因为this_cpu操作没有锁
语义。远程写可能会干扰this_cpu RMW操作。
除非绝对必要,否则强烈建议不要对每CPU数据结构进行远程写访问。请考虑使用IPI来唤醒
远程CPU,并对其每CPU区域进行更新。
要远程访问每CPU数据结构,通常使用 ``per_cpu_ptr()`` 函数::
DEFINE_PER_CPU(struct data, datap);
struct data *p = per_cpu_ptr(&datap, cpu);
这清楚地表明,我们正准备远程访问每CPU区域。
您还可以执行以下操作以将datap偏移量转换为地址::
struct data *p = this_cpu_ptr(&datap);
但是,将通过this_cpu_ptr计算的指针传递给其他cpu是不寻常的,应该避免。
远程访问通常只用于读取另一个cpu的每CPU数据状态。由于this_cpu操作宽松的同步要求,
写访问可能会导致奇特的问题。
下面的情况说明了写入操作的一些问题,由于两个每CPU变量共享一个缓存行,但宽松的同步
仅应用于更新缓存行的一个进程。
考虑以下示例::
struct test {
atomic_t a;
int b;
};
DEFINE_PER_CPU(struct test, onecacheline);
如果一个处理器远程更新字段 ``a`` ,而本地处理器将使用this_cpu ops来更新字段 ``b`` ,
会发生什么情况,这一点值得注意。应避免在同一缓存行内同时访问数据。此外,可能还需
要进行代价高昂的同步。在这种情况下,通常建议使用IPI,而不是远程写入另一个处理器的
每CPU区域。
即使在远程写很少的情况下,请记住远程写将从最有可能访问它的处理器中逐出缓存行。如
果处理器唤醒时发现每CPU区域缺少本地缓存行,其性能和唤醒时间将受到影响。
......@@ -19,7 +19,7 @@
contributing
maintainer-profile
.. only:: 子项目与HTML
.. only:: subproject and html
目录
====
......
......@@ -71,6 +71,7 @@ TODOList:
dev-tools/index
dev-tools/testing-overview
kernel-hacking/index
rust/index
TODOList:
......@@ -90,12 +91,12 @@ TODOList:
admin-guide/index
admin-guide/reporting-issues.rst
userspace-api/index
TODOList:
* 内核构建系统 <kbuild/index>
* 用户空间工具 <tools/index>
* userspace-api/index
也可参考独立于内核文档的 `Linux 手册页 <https://www.kernel.org/doc/man-pages/>`_ 。
......@@ -124,13 +125,13 @@ TODOList:
其他文档
--------
有几份未排序的文档似乎不适合放在文档的其他部分,或者可能需要进行一些调整和/或
有几份未分类的文档似乎不适合放在文档的其他部分,或者可能需要进行一些调整和/或
转换为reStructureText格式,也有可能太旧。
TODOList:
* staging/index
.. toctree::
:maxdepth: 2
staging/index
索引和表格
----------
......
......@@ -338,15 +338,15 @@ Loongson与LoongArch的开发者网站(软件与文档资源):
LoongArch指令集架构的文档:
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.00-CN.pdf (中文版)
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-CN.pdf (中文版)
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.00-EN.pdf (英文版)
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-EN.pdf (英文版)
LoongArch的ELF psABI文档:
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v1.00-CN.pdf (中文版)
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.00-CN.pdf (中文版)
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v1.00-EN.pdf (英文版)
https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.00-EN.pdf (英文版)
Loongson与LoongArch的Linux内核源码仓库:
......
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/rust/arch-support.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
架构支持
========
目前,Rust编译器(``rustc``)使用LLVM进行代码生成,这限制了可以支持的目标架构。此外,对
使用LLVM/Clang构建内核的支持也有所不同(请参见 Documentation/kbuild/llvm.rst )。这
种支持对于使用 ``libclang`` 的 ``bindgen`` 来说是必需的。
下面是目前可以工作的架构的一般总结。支持程度与 ``MAINTAINERS`` 文件中的``S`` 值相对应:
============ ================ ==============================================
架构 支持水平 限制因素
============ ================ ==============================================
``x86`` Maintained 只有 ``x86_64``
============ ================ ==============================================
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/rust/coding-guidelines.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
编码指南
========
本文档描述了如何在内核中编写Rust代码。
风格和格式化
------------
代码应该使用 ``rustfmt`` 进行格式化。这样一来,一个不时为内核做贡献的人就不需要再去学
习和记忆一个样式指南了。更重要的是,审阅者和维护者不需要再花时间指出风格问题,这样就可以
减少补丁落地所需的邮件往返。
.. note:: ``rustfmt`` 不检查注释和文档的约定。因此,这些仍然需要照顾到。
使用 ``rustfmt`` 的默认设置。这意味着遵循Rust的习惯性风格。例如,缩进时使用4个空格而
不是制表符。
在输入、保存或提交时告知编辑器/IDE进行格式化是很方便的。然而,如果因为某些原因需要在某
个时候重新格式化整个内核Rust的源代码,可以运行以下程序::
make LLVM=1 rustfmt
也可以检查所有的东西是否都是格式化的(否则就打印一个差异),例如对于一个CI,用::
make LLVM=1 rustfmtcheck
像内核其他部分的 ``clang-format`` 一样, ``rustfmt`` 在单个文件上工作,并且不需要
内核配置。有时,它甚至可以与破碎的代码一起工作。
注释
----
“普通”注释(即以 ``//`` 开头,而不是 ``///`` 或 ``//!`` 开头的代码文档)的写法与文
档注释相同,使用Markdown语法,尽管它们不会被渲染。这提高了一致性,简化了规则,并允许在
这两种注释之间更容易地移动内容。比如说:
.. code-block:: rust
// `object` is ready to be handled now.
f(object);
此外,就像文档一样,注释在句子的开头要大写,并以句号结束(即使是单句)。这包括 ``// SAFETY:``,
``// TODO:`` 和其他“标记”的注释,例如:
.. code-block:: rust
// FIXME: The error should be handled properly.
注释不应该被用于文档的目的:注释是为了实现细节,而不是为了用户。即使源文件的读者既是API
的实现者又是用户,这种区分也是有用的。事实上,有时同时使用注释和文档是很有用的。例如,用
于 ``TODO`` 列表或对文档本身的注释。对于后一种情况,注释可以插在中间;也就是说,离要注
释的文档行更近。对于其他情况,注释会写在文档之后,例如:
.. code-block:: rust
/// Returns a new [`Foo`].
///
/// # Examples
///
// TODO: Find a better example.
/// ```
/// let foo = f(42);
/// ```
// FIXME: Use fallible approach.
pub fn f(x: i32) -> Foo {
// ...
}
一种特殊的注释是 ``// SAFETY:`` 注释。这些注释必须出现在每个 ``unsafe`` 块之前,它们
解释了为什么该块内的代码是正确/健全的,即为什么它在任何情况下都不会触发未定义行为,例如:
.. code-block:: rust
// SAFETY: `p` is valid by the safety requirements.
unsafe { *p = 0; }
``// SAFETY:`` 注释不能与代码文档中的 ``# Safety`` 部分相混淆。 ``# Safety`` 部
分指定了(函数)调用者或(特性)实现者需要遵守的契约。
``// SAFETY:`` 注释显示了为什么一个(函数)调用者或(特性)实现者实际上尊重了
``# Safety`` 部分或语言参考中的前提条件。
代码文档
--------
Rust内核代码不像C内核代码那样被记录下来(即通过kernel-doc)。取而代之的是用于记录Rust
代码的常用系统:rustdoc工具,它使用Markdown(一种轻量级的标记语言)。
要学习Markdown,外面有很多指南。例如:
https://commonmark.org/help/
一个记录良好的Rust函数可能是这样的:
.. code-block:: rust
/// Returns the contained [`Some`] value, consuming the `self` value,
/// without checking that the value is not [`None`].
///
/// # Safety
///
/// Calling this method on [`None`] is *[undefined behavior]*.
///
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
///
/// # Examples
///
/// ```
/// let x = Some("air");
/// assert_eq!(unsafe { x.unwrap_unchecked() }, "air");
/// ```
pub unsafe fn unwrap_unchecked(self) -> T {
match self {
Some(val) => val,
// SAFETY: The safety contract must be upheld by the caller.
None => unsafe { hint::unreachable_unchecked() },
}
}
这个例子展示了一些 ``rustdoc`` 的特性和内核中遵循的一些惯例:
- 第一段必须是一个简单的句子,简要地描述被记录的项目的作用。进一步的解释必须放在额
外的段落中。
- 不安全的函数必须在 ``# Safety`` 部分记录其安全前提条件。
- 虽然这里没有显示,但如果一个函数可能会恐慌,那么必须在 ``# Panics`` 部分描述发
生这种情况的条件。
请注意,恐慌应该是非常少见的,只有在有充分理由的情况下才会使用。几乎在所有的情况下,
都应该使用一个可失败的方法,通常是返回一个 ``Result``。
- 如果提供使用实例对读者有帮助的话,必须写在一个叫做``# Examples``的部分。
- Rust项目(函数、类型、常量……)必须有适当的链接(``rustdoc`` 会自动创建一个
链接)。
- 任何 ``unsafe`` 的代码块都必须在前面加上一个 ``// SAFETY:`` 的注释,描述里面
的代码为什么是正确的。
虽然有时原因可能看起来微不足道,但写这些注释不仅是记录已经考虑到的问题的好方法,
最重要的是,它提供了一种知道没有额外隐含约束的方法。
要了解更多关于如何编写Rust和拓展功能的文档,请看看 ``rustdoc`` 这本书,网址是:
https://doc.rust-lang.org/rustdoc/how-to-write-documentation.html
命名
----
Rust内核代码遵循通常的Rust命名空间:
https://rust-lang.github.io/api-guidelines/naming.html
当现有的C语言概念(如宏、函数、对象......)被包装成Rust抽象时,应该使用尽可能接近C语
言的名称,以避免混淆,并在C语言和Rust语言之间来回切换时提高可读性。例如,C语言中的
``pr_info`` 这样的宏在Rust中的命名是一样的。
说到这里,应该调整大小写以遵循Rust的命名惯例,模块和类型引入的命名间隔不应该在项目名称
中重复。例如,在包装常量时,如:
.. code-block:: c
#define GPIO_LINE_DIRECTION_IN 0
#define GPIO_LINE_DIRECTION_OUT 1
在Rust中的等价物可能是这样的(忽略文档)。:
.. code-block:: rust
pub mod gpio {
pub enum LineDirection {
In = bindings::GPIO_LINE_DIRECTION_IN as _,
Out = bindings::GPIO_LINE_DIRECTION_OUT as _,
}
}
也就是说, ``GPIO_LINE_DIRECTION_IN`` 的等价物将被称为 ``gpio::LineDirection::In`` 。
特别是,它不应该被命名为 ``gpio::gpio_line_direction::GPIO_LINE_DIRECTION_IN`` 。
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/rust/general-information.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
基本信息
========
本文档包含了在内核中使用Rust支持时需要了解的有用信息。
代码文档
--------
Rust内核代码使用其内置的文档生成器 ``rustdoc`` 进行记录。
生成的HTML文档包括集成搜索、链接项(如类型、函数、常量)、源代码等。它们可以在以下地址阅读
(TODO:当在主线中时链接,与其他文档一起生成):
http://kernel.org/
这些文档也可以很容易地在本地生成和阅读。这相当快(与编译代码本身的顺序相同),而且不需要特
殊的工具或环境。这有一个额外的好处,那就是它们将根据所使用的特定内核配置进行定制。要生成它
们,请使用 ``rustdoc`` 目标,并使用编译时使用的相同调用,例如::
make LLVM=1 rustdoc
要在你的网络浏览器中本地阅读该文档,请运行如::
xdg-open rust/doc/kernel/index.html
要了解如何编写文档,请看 coding-guidelines.rst 。
额外的lints
-----------
虽然 ``rustc`` 是一个非常有用的编译器,但一些额外的lints和分析可以通过 ``clippy``
(一个Rust linter)来实现。要启用它,请将CLIPPY=1传递到用于编译的同一调用中,例如::
make LLVM=1 CLIPPY=1
请注意,Clippy可能会改变代码生成,因此在构建产品内核时不应该启用它。
抽象和绑定
----------
抽象是用Rust代码包装来自C端的内核功能。
为了使用来自C端的函数和类型,需要创建绑定。绑定是Rust对那些来自C端的函数和类型的声明。
例如,人们可以在Rust中写一个 ``Mutex`` 抽象,它从C端包装一个 ``Mutex结构体`` ,并
通过绑定调用其函数。
抽象并不能用于所有的内核内部API和概念,但随着时间的推移,我们打算扩大覆盖范围。“Leaf”
模块(例如,驱动程序)不应该直接使用C语言的绑定。相反,子系统应该根据需要提供尽可能安
全的抽象。
有条件的编译
------------
Rust代码可以访问基于内核配置的条件性编译:
.. code-block:: rust
#[cfg(CONFIG_X)] // Enabled (`y` or `m`)
#[cfg(CONFIG_X="y")] // Enabled as a built-in (`y`)
#[cfg(CONFIG_X="m")] // Enabled as a module (`m`)
#[cfg(not(CONFIG_X))] // Disabled
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/rust/index.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
Rust
====
与内核中的Rust有关的文档。若要开始在内核中使用Rust,请阅读quick-start.rst指南。
.. toctree::
:maxdepth: 1
quick-start
general-information
coding-guidelines
arch-support
.. only:: subproject and html
Indices
=======
* :ref:`genindex`
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/rust/quick-start.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
快速入门
========
本文介绍了如何开始使用Rust进行内核开发。
构建依赖
--------
本节描述了如何获取构建所需的工具。
其中一些依赖也许可以从Linux发行版中获得,包名可能是 ``rustc`` , ``rust-src`` ,
``rust-bindgen`` 等。然而,在写这篇文章的时候,它们很可能还不够新,除非发行版跟踪最
新的版本。
为了方便检查是否满足要求,可以使用以下目标::
make LLVM=1 rustavailable
这会触发与Kconfig用来确定是否应该启用 ``RUST_IS_AVAILABLE`` 相同的逻辑;不过,如
果Kconfig认为不该启用,它会列出未满足的条件。
rustc
*****
需要一个特定版本的Rust编译器。较新的版本可能会也可能不会工作,因为就目前而言,内核依赖
于一些不稳定的Rust特性。
如果使用的是 ``rustup`` ,请进入检出的源代码目录并运行::
rustup override set $(scripts/min-tool-version.sh rustc)
或者从以下网址获取一个独立的安装程序或安装 ``rustup`` :
https://www.rust-lang.org
Rust标准库源代码
****************
Rust标准库的源代码是必需的,因为构建系统会交叉编译 ``core`` 和 ``alloc`` 。
如果正在使用 ``rustup`` ,请运行::
rustup component add rust-src
这些组件是按工具链安装的,因此以后升级Rust编译器版本需要重新添加组件。
否则,如果使用独立的安装程序,可以将Rust仓库克隆到工具链的安装文件夹中::
git clone --recurse-submodules \
--branch $(scripts/min-tool-version.sh rustc) \
https://github.com/rust-lang/rust \
$(rustc --print sysroot)/lib/rustlib/src/rust
在这种情况下,以后升级Rust编译器版本需要手动更新这个克隆的仓库。
libclang
********
``bindgen`` 使用 ``libclang`` (LLVM的一部分)来理解内核中的C代码,这意味着需要安
装LLVM;同在开启 ``CC=clang`` 或 ``LLVM=1`` 时编译内核一样。
Linux发行版中可能会有合适的包,所以最好先检查一下。
适用于部分系统和架构的二进制文件也可到以下网址下载:
https://releases.llvm.org/download.html
或者自行构建LLVM,这需要相当长的时间,但并不是一个复杂的过程:
https://llvm.org/docs/GettingStarted.html#getting-the-source-code-and-building-llvm
请参阅 Documentation/kbuild/llvm.rst 了解更多信息,以及获取预构建版本和发行包
的进一步方法。
bindgen
*******
内核的C端绑定是在构建时使用 ``bindgen`` 工具生成的。这需要特定的版本。
通过以下方式安装它(注意,这将从源码下载并构建该工具)::
cargo install --locked --version $(scripts/min-tool-version.sh bindgen) bindgen
开发依赖
--------
本节解释了如何获取开发所需的工具。也就是说,在构建内核时不需要这些工具。
rustfmt
*******
``rustfmt`` 工具被用来自动格式化所有的Rust内核代码,包括生成的C绑定(详情请见
coding-guidelines.rst )。
如果使用的是 ``rustup`` ,它的 ``默认`` 配置文件已经安装了这个工具,因此不需要做什么。
如果使用的是其他配置文件,可以手动安装该组件::
rustup component add rustfmt
独立的安装程序也带有 ``rustfmt`` 。
clippy
******
``clippy`` 是一个Rust linter。运行它可以为Rust代码提供额外的警告。它可以通过向 ``make``
传递 ``CLIPPY=1`` 来运行(关于细节,详见 general-information.rst )。
如果正在使用 ``rustup`` ,它的 ``默认`` 配置文件已经安装了这个工具,因此不需要做什么。
如果使用的是另一个配置文件,该组件可以被手动安装::
rustup component add clippy
独立的安装程序也带有 ``clippy`` 。
cargo
*****
``cargo`` 是Rust的本地构建系统。目前需要它来运行测试,因为它被用来构建一个自定义的标准
库,其中包含了内核中自定义 ``alloc`` 所提供的设施。测试可以使用 ``rusttest`` Make 目标
来运行。
如果使用的是 ``rustup`` ,所有的配置文件都已经安装了该工具,因此不需要再做什么。
独立的安装程序也带有 ``cargo`` 。
rustdoc
*******
``rustdoc`` 是Rust的文档工具。它为Rust代码生成漂亮的HTML文档(详情请见 general-information.rst )。
``rustdoc`` 也被用来测试文档化的Rust代码中提供的例子(称为doctests或文档测试)。
``rusttest`` 是本功能的Make目标。
如果使用的是 ``rustup`` ,所有的配置文件都已经安装了这个工具,因此不需要做什么。
独立的安装程序也带有 ``rustdoc`` 。
rust-analyzer
*************
`rust-analyzer <https://rust-analyzer.github.io/>`_ 语言服务器可以和许多编辑器
一起使用,以实现语法高亮、补全、转到定义和其他功能。
``rust-analyzer`` 需要一个配置文件, ``rust-project.json``, 它可以由 ``rust-analyzer``
Make 目标生成。
配置
----
Rust支持(CONFIG_RUST)需要在 ``General setup`` 菜单中启用。在其他要求得到满足的情
况下,该选项只有在找到合适的Rust工具链时才会显示(见上文)。相应的,这将使依赖Rust的其
他选项可见。
之后,进入::
Kernel hacking
-> Sample kernel code
-> Rust samples
并启用一些内置或可加载的样例模块。
构建
----
用完整的LLVM工具链构建内核是目前支持的最佳设置。即::
make LLVM=1
对于不支持完整LLVM工具链的架构,使用::
make CC=clang
使用GCC对某些配置也是可行的,但目前它是非常试验性的。
折腾
----
要想深入了解,请看 ``samples/rust/`` 下的样例源代码、 ``rust/`` 下的Rust支持代码和
``Kernel hacking`` 下的 ``Rust hacking`` 菜单。
如果使用的是GDB/Binutils,而Rust符号没有被demangled,原因是工具链还不支持Rust的新v0
mangling方案。有几个办法可以解决:
- 安装一个较新的版本(GDB >= 10.2, Binutils >= 2.36)。
- 一些版本的GDB(例如vanilla GDB 10.1)能够使用嵌入在调试信息(``CONFIG_DEBUG_INFO``)
中的pre-demangled的名字。
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/staging/index.rst
:翻译:
李睿 Rui Li <me@lirui.org>
未分类文档
==========
.. toctree::
:maxdepth: 2
xz
TODOList:
* crc32
* lzo
* remoteproc
* rpmsg
* speculation
* static-keys
* tee
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/staging/xz.rst
:翻译:
李睿 Rui Li <me@lirui.org>
===================
Linux中的XZ数据压缩
===================
介绍
====
XZ是一种通用的数据压缩格式,其具有高压缩率和相对快的解压速度。主要的压缩算法(
过滤器)是LZMA2。额外的过滤器可以被用来进一步提高压缩率,比如用来提高可执行数据
压缩率的Branch/Call/Jump (BCJ)过滤器。
XZ解压器在Linux中被称作XZ Embedded。它支持LZMA2过滤器和可选的BCJ过滤器,并支持
CRC32完整性校验。你可以在XZ Embedded的主页<https://tukaani.org/xz/embedded.html>
中找到最新版本和关于在Linux内核之外使用源码的信息。
对于用户空间来说,XZ Utils提供了类似于zlib的压缩库和类似于gzip的命令行工具。
XZ Utils可以从<https://tukaani.org/xz/>下载。
内核中的XZ相关组件
==================
xz_dec模块为XZ解压器提供了单次调用(缓冲区到缓冲区)和多次调用(有状态)的
API。xz_dec模块的用法记录在include/linux/xz.h中。
xz_dec_test模块用于测试xz_dec。除非你想魔改XZ解压器,否则xz_dec_test是
没有用的。xz_dec_test会动态分配一个字符设备主设备号,你可以从用户空间向它
写入.xz文件,解压的输出会被丢弃。关注dmesg可以找到xz_dec_test输出的诊断信息。
详细内容请查看xz_dec_test的源码。
为了解压内核镜像、初始ram文件系统和初始ram磁盘,lib/decompress_unxz.c实现
了一个包装函数。它的API与其他 decompress_*.c 文件相同,那些API定义在
include/linux/decompress/generic.h中。
scripts/xz_wrap.sh是一个XZ Utils中的xz命令行工具包装器。这个包装器会
设置合适的压缩选项来压缩内核镜像。
在内核的makefiles中,提供了使用$(call if_needed)的两个命令。内核镜像应该
使用$(call if_needed,xzkern)来压缩,它会使用BCJ过滤器和一个大LZMA2字典。
它还会附加一个四字节的包含源文件大小的预告,这会在启动代码中被用到。其他文件
应该使用$(call if_needed,xzmisc)来压缩,它会使用1 MiB的LZMA2字典并禁用
BCJ过滤器。
关于压缩选项的说明
==================
因为XZ Embedded只支持没有完整性校验的数据流或者CRC32,请确保你在编码未来将被
内核解码的文件时没有使用其他完整性校验方式。使用liblzma时,你需要使用LZMA_CHECK_NONE
或LZMA_CHECK_CRC32。使用xz命令行工具时,使用--check=none或--check=crc32。
除非有其他环节会验证解压数据的完整性,否则强烈使用CRC32。双重验证可能会浪费
CPU周期。请注意头部总是会包含用于解压器验证的CRC32,你只能修改或禁用解压后数据
的完整性校验方式。
在用户中间中,LZMA2通常使用几兆字节大小的字典。解码器需要在RAM中放置字典,
因此大字典不能被用于那些意在被内核解码的文件。1 MiB在内核中大概是可接受的最大
字典大小(可能对初始ram文件系统也适用)。XZ Utils中的预设值可能并不适合创建
内核文件,所以请别犹豫使用自定义设置。比如::
xz --check=crc32 --lzma2=dict=512KiB inputfile
使用上面字典大小的一个例外是在单一调用模式下使用解码器。解压内核自身就是一个例
子。在单一调用模式下,内存用量并不和字典大小有关,这种情况就是使用大字典的好地
方:为了最大化压缩,字典至少应该和解压后的数据一样大。
未来计划
========
如果有人认为有用的话,可能会考虑创建一个受限的XZ编码器。LZMA2的压缩速率比Deflate
或LZO等要慢,即使在最快的配置选项下。所以并不清楚LZMA2编码器是否需要并入内核。
有计划在解压代码中支持有限的随机访问读数据。不知道这能否在内核中有任何用,但是我
知道这会在一些Linux内核以外的嵌入式项目中有用。
.xz文件格式规范的一致性
=======================
在一些边缘情况下,为了简化事情牺牲了尽早地检测错误。因为并不会导致安全问题,实际
上是没有关系的。但在测试代码的时候知道这一点很好,比如测试来自XZ Utils的文件。
报告错误
========
请在报告错误前确认是否已经在上游修复。可以从<https://tukaani.org/xz/embedded.html>
获取最新的源码。
可以通过联系<lasse.collin@tukaani.org>或者访问Freenode上的#tukaani
联系Larhzu。我并不经常阅读LKML或者其他内核相关的邮件列表,所以如果要告知我什么事情
,你应该通过我的私人邮箱或者IRC联系我。
请不要因为内核中XZ的实现或关于XZ Utils的问题打扰Igor Pavlov。虽然这两种实现
包含了建立在Igor Pavlov的代码上的重要源码,但并不由他维护和提供支持。
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../../disclaimer-zh_CN.rst
:Original: Documentation/userspace-api/accelerators/ocxl.rst
:翻译:
李睿 Rui Li <me@lirui.org>
=====================================
OpenCAPI (开放相干加速器处理器接口)
=====================================
*OpenCAPI: Open Coherent Accelerator Processor Interface*
OpenCAPI是处理器和加速器之间的一个接口,致力于达到低延迟和高带宽。该规范
由 `OpenCAPI Consortium <http://opencapi.org/>`_ 开发。
它允许加速器(可以是FPGA、ASIC等)使用虚拟地址连贯地访问主机内存。一个OpenCAPI
设备也可以托管它自己的内存,并可以由主机访问。
OpenCAPI在Linux中称为“ocxl”,它作为“cxl”(用于powerpc的IBM CAPI接口的驱动)的
开放、处理器无关的演进,这么命名是为了避免与ISDN CAPI子系统相混淆。
高层视角
========
OpenCAPI定义了一个在物理链路层上实现的数据链路层(TL)和传输层(TL)。任何
实现DL和TL的处理器或者设备都可以开始共享内存。
::
+-----------+ +-------------+
| | | |
| | | Accelerated |
| Processor | | Function |
| | +--------+ | Unit | +--------+
| |--| Memory | | (AFU) |--| Memory |
| | +--------+ | | +--------+
+-----------+ +-------------+
| |
+-----------+ +-------------+
| TL | | TLX |
+-----------+ +-------------+
| |
+-----------+ +-------------+
| DL | | DLX |
+-----------+ +-------------+
| |
| PHY |
+---------------------------------------+
Processor:处理器
Memory:内存
Accelerated Function Unit:加速函数单元
设备发现
========
OpenCAPI依赖一个在设备上实现的与PCI类似的配置空间。因此主机可以通过查询
配置空间来发现AFU。
OpenCAPI设备在Linux中被当作类PCI设备(有一些注意事项)。固件需要对硬件进行
抽象,就好像它是一个PCI链路。许多已有的PCI架构被重用:在模拟标准PCI时,
设备被扫描并且BAR(基址寄存器)被分配。像“lspci”的命令因此可以被用于查看
哪些设备可用。
配置空间定义了可以在物理适配器上可以被找到的AFU,比如它的名字、支持多少内
存上下文、内存映射IO(MMIO)区域的大小等。
MMIO
====
OpenCAPI为每个AFU定义了两个MMIO区域:
* 全局MMIO区域,保存和整个AFU相关的寄存器。
* 每个进程的MMIO区域,对于每个上下文固定大小。
AFU中断
=======
OpenCAPI拥有AFU向主机进程发送中断的可能性。它通过定义在传输层的“intrp_req”
来完成,指定一个定义中断的64位对象句柄。
驱动允许一个进程分配中断并获取可以传递给AFU的64位对象句柄。
字符设备
========
驱动为每个在物理设备上发现的AFU创建一个字符设备。一个物理设备可能拥有多个
函数,一个函数可以拥有多个AFU。不过编写这篇文档之时,只对导出一个AFU的设备
测试过。
字符设备可以在 /dev/ocxl/ 中被找到,其命名为:
/dev/ocxl/<AFU 名称>.<位置>.<索引>
<AFU 名称> 是一个最长20个字符的名称,和在AFU配置空间中找到的相同。
<位置>由驱动添加,可在系统有不止一个相同的OpenCAPI设备时帮助区分设备。
<索引>也是为了在少见情况下帮助区分AFU,即设备携带多个同样的AFU副本时。
Sysfs类
=======
添加了代表AFU的ocxl类。查看/sys/class/ocxl。布局在
Documentation/ABI/testing/sysfs-class-ocxl 中描述。
用户API
=======
打开
----
基于在配置空间中找到的AFU定义,AFU可能支持在多个内存上下文中工作,这种情况
下相关的字符设备可以被不同进程多次打开。
ioctl
-----
OCXL_IOCTL_ATTACH:
附加调用进程的内存上下文到AFU,以允许AFU访问其内存。
OCXL_IOCTL_IRQ_ALLOC:
分配AFU中断,返回标识符。
OCXL_IOCTL_IRQ_FREE:
释放之前分配的AFU中断。
OCXL_IOCTL_IRQ_SET_FD:
将一个事件文件描述符和AFU中断关联,因此用户进程可以在AFU发送中断时收到通
知。
OCXL_IOCTL_GET_METADATA:
从卡中获取配置信息,比如内存映射IO区域的大小、AFU版本和当前上下文的进程
地址空间ID(PASID)。
OCXL_IOCTL_ENABLE_P9_WAIT:
允许AFU唤醒执行“等待”的用户空间进程。返回信息给用户空间,允许其配置AFU。
注意这只在POWER9上可用。
OCXL_IOCTL_GET_FEATURES:
报告用户空间可用的影响OpenCAPI的CPU特性。
mmap
----
一个进程可以mmap每个进程的MMIO区域来和AFU交互。
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../../disclaimer-zh_CN.rst
:Original: Documentation/userspace-api/ebpf/index.rst
:翻译:
李睿 Rui Li <me@lirui.org>
eBPF 用户空间API
================
eBPF是一种在Linux内核中提供沙箱化运行环境的机制,它可以在不改变内核源码或加载
内核模块的情况下扩展运行时和编写工具。eBPF程序能够被附加到各种内核子系统中,包
括网络,跟踪和Linux安全模块(LSM)等。
关于eBPF的内部内核文档,请查看 Documentation/bpf/index.rst 。
.. toctree::
:maxdepth: 1
syscall
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../../disclaimer-zh_CN.rst
:Original: Documentation/userspace-api/ebpf/syscall.rst
:翻译:
李睿 Rui Li <me@lirui.org>
eBPF Syscall
------------
:作者:
- Alexei Starovoitov <ast@kernel.org>
- Joe Stringer <joe@wand.net.nz>
- Michael Kerrisk <mtk.manpages@gmail.com>
bpf syscall的主要信息可以在 `man-pages`_ 中的 `bpf(2)`_ 找到。
bpf() 子命令参考
~~~~~~~~~~~~~~~~
子命令在以下内核代码中:
include/uapi/linux/bpf.h
.. Links:
.. _man-pages: https://www.kernel.org/doc/man-pages/
.. _bpf(2): https://man7.org/linux/man-pages/man2/bpf.2.html
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/userspace-api/futex2.rst
:翻译:
李睿 Rui Li <me@lirui.org>
======
futex2
======
:作者: André Almeida <andrealmeid@collabora.com>
futex,或者称为快速用户互斥锁(fast user mutex),是一组允许用户空间创建高性能同步
机制的系统调用,比如用户空间中的互斥锁,信号量和条件变量。C标准库,如glibc,使用它作
为实现更多高级接口的方式,如pthreads。
futex2是初代futex系统调用的后续版本,旨在克服原有接口的限制。
用户API
=======
``futex_waitv()``
-----------------
等待一个futex数组,可由其中任意一个唤醒::
futex_waitv(struct futex_waitv *waiters, unsigned int nr_futexes,
unsigned int flags, struct timespec *timeout, clockid_t clockid)
struct futex_waitv {
__u64 val;
__u64 uaddr;
__u32 flags;
__u32 __reserved;
};
用户空间设置一个struct futex_waitv数组(最多128项),设置 ``uaddr`` 为等待的
地址, ``val`` 为期望值, ``flags`` 为指定的类型(如private)和futex的大小。
``__reserved`` 需要置为0,但是它可用作未来扩展。指向数组第一个元素的指针作为
``waiters`` 传递。如果 ``waiters`` 或任何的 ``uaddr`` 地址无效,将返回 ``-EFAULT`` 。
如果用户空间拥有32位的指针,那么需要做显式转换来保证高位清零。 ``uintptr_t`` 设计
得很精巧,在32/64位的指针上都正常工作。
``nr_futexes`` 指定了数组的大小。不在[1,128]区间内的值会使系统调用返回 ``-EINVAL`` 。
系统调用的 ``flags`` 参数需要置0,但可用作未来扩展。
对于每个 ``waiters`` 数组中的项,在 ``uaddr`` 的当前值会和 ``val`` 比较。如果
不一致,系统调用会撤销截至目前完成的所有工作,并返回 ``-EAGAIN`` 。如果所有测试
和验证都通过,系统调用会等待直到以下情况之一发生:
- 指定的timeout超时,返回 ``-ETIMEOUT`` 。
- 一个信号被传递给睡眠中的任务,返回 ``-ERESTARTSYS`` 。
- 某个列表中的futex被唤醒,返回那个被唤醒的futex的索引。
关于如何使用接口的例子可以在 ``tools/testing/selftests/futex/functional/futex_waitv.c``
中找到。
超时
----
``struct timespec *timeout`` 是一个指向绝对超时时间的可选参数。你需要在 ``clockid``
参数中指定要使用的时钟类型。支持 ``CLOCK_MONOTONIC`` 和 ``CLOCK_REALTIME`` 。这个
系统调用只接受64位的timespec结构体。
futex的类型
-----------
futex既可以是私有的也可以是共享的。私有用于多个进程共享同样的内存空间,并且futex的虚拟
地址对所有进程都是一样的。这允许在内核中进行优化。要使用私有futex,需要在futex标志中指定
``FUTEX_PRIVATE_FLAG`` 。对于那些不在同一内存空间共享的进程,可以让同一个futex拥有不同
的虚拟地址(例如使用基于文件的共享内存),这需要不同的内部机制来使得正确进入队列。这是默认
的行为,而且对私有futex和共享futex都适用。
futex可以是不同的大小:8,16,32或64位。目前只支持32位大小的futex,并且需要通过 ``FUTEX_32``
标志指定。
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/userspace-api/index.rst
:翻译:
李睿 Rui Li <me@lirui.org>
=========================
Linux 内核用户空间API指南
=========================
.. _man-pages: https://www.kernel.org/doc/man-pages/
尽管许多用户空间API的文档被记录在别处(特别是在 man-pages_ 项目中),
在代码树中仍然可以找到有关用户空间的部分信息。这个手册意在成为这些信息
聚集的地方。
.. class:: toc-title
目录
.. toctree::
:maxdepth: 2
no_new_privs
seccomp_filter
accelerators/ocxl
ebpf/index
sysfs-platform_profile
futex2
TODOList:
* landlock
* unshare
* spec_ctrl
* ioctl/index
* iommu
* media/index
* netlink/index
* vduse
.. only:: subproject and html
Indices
=======
* :ref:`genindex`
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/userspace-api/no_new_privs.rst
:翻译:
李睿 Rui Li <me@lirui.org>
============
无新权限标志
============
execve系统调用可以给一个新启动的程序授予它的父程序本没有的权限。最明显的两个
例子就是setuid/setgid控制程序和文件的能力。为了避免父程序也获得这些权限,内
核和用户代码必须小心避免任何父程序可以颠覆子程序的情况。比如:
- 程序在setuid后,动态装载器处理 ``LD_*`` 环境变量的不同方式。
- 对于非特权程序,chroot是不允许的,因为这会允许 ``/etc/passwd`` 在继承
chroot的程序眼中被替换。
- 执行代码对ptrace有特殊处理。
这些都是临时性的修复。 ``no_new_privs`` 位(从 Linux 3.5 起)是一个新的通
用的机制来保证一个进程安全地修改其执行环境并跨execve持久化。任何任务都可以设
置 ``no_new_privs`` 。一旦该位被设置,它会在fork、clone和execve中继承下去
,并且不能被撤销。在 ``no_new_privs`` 被设置的情况下, ``execve()`` 将保证
不会授予权限去做任何没有execve调用就不能做的事情。比如, setuid 和 setgid
位不会再改变 uid 或 gid;文件能力不会被添加到授权集合中,并且Linux安全模块(
LSM)不会在execve调用后放松限制。
设置 ``no_new_privs`` 使用::
prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
不过要小心,Linux安全模块(LSM)也可能不会在 ``no_new_privs`` 模式下收紧约束。
(这意味着一个一般的服务启动器在执行守护进程前就去设置 ``no_new_privs`` 可能
会干扰基于LSM的沙箱。)
请注意, ``no_new_privs`` 并不能阻止不涉及 ``execve()`` 的权限变化。一个拥有
适当权限的任务仍然可以调用 ``setuid(2)`` 并接收 SCM_RIGHTS 数据报。
目前来说, ``no_new_privs`` 有两大使用场景:
- 为seccomp模式2沙箱安装的过滤器会跨execve持久化,并能够改变新执行程序的行为。
非特权用户因此在 ``no_new_privs`` 被设置的情况下只允许安装这样的过滤器。
- ``no_new_privs`` 本身就能被用于减少非特权用户的攻击面。如果所有以某个 uid
运行的程序都设置了 ``no_new_privs`` ,那么那个 uid 将无法通过攻击 setuid,
setgid 和使用文件能力的二进制来提权;它需要先攻击一些没有被设置 ``no_new_privs``
位的东西。
将来,其他潜在的危险的内核特性可能被非特权任务利用,即使 ``no_new_privs`` 被置位。
原则上,当 ``no_new_privs`` 被置位时, ``unshare(2)`` 和 ``clone(2)`` 的几个选
项将是安全的,并且 ``no_new_privs`` 加上 ``chroot`` 是可以被认为比 chroot本身危
险性小得多的。
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/userspace-api/seccomp_filter.rst
:翻译:
李睿 Rui Li <me@lirui.org>
==================================
Seccomp BPF (基于过滤器的安全计算)
==================================
*Seccomp: SECure COMPuting*
介绍
====
大量系统调用被暴露给每个用户空间进程,但其中又有许多系统调用在进程的整个生命
周期中都没被使用。随着系统调用的改变和成熟,缺陷被找到并消除。允许某一部分应
用程序仅能访问一部分系统调用是有好处的,这会缩小内核暴露给应用程序的面积。
系统调用过滤器就是为这些应用程序而生的。
Seccomp过滤提供了一种为进程指定一个处理系统调用的过滤器的方法。这个过滤器体
现为一个伯克利包过滤器(BPF)程序,就像套接字过滤器一样,不同在于前者处理的
数据和正在进行的系统调用有关:系统调用号和系统调用参数。这样使用一种长期与
用户空间和直接数据打交道的语言来表达系统调用过滤成为了可能。
此外,BPF让seccomp用户不再成为在系统调用干预框架(system call interposition
frameworks)中常见的检查-使用竞态攻击(TOCTOU)的受害者。BPF程序可能无法解引
用指针,这就限制了所有过滤器仅能直接评估系统调用参数。
这不是什么
==========
系统调用过滤并不是一个沙箱。它提供了一种明确定义的机制来最小化内核暴露面。它
旨在成为一个沙箱开发者使用的工具。除此之外,逻辑行为和信息流的策略应该结合其他
系统加固手段或者可能由你选择的内核安全模块(LSM)来管理。易于表达的动态过滤器
为这条路提供了更多选择(比如避免病态的大小或者选择允许 socketcall() 中的多路
系统调用),但将其理解为更完整的沙箱解决方案是错误的。
用法
====
添加了一个额外的seccomp模式,它可以使用和严格seccomp相同的 prctl(2) 调用来启用。
如果架构有 ``CONFIG_HAVE_ARCH_SECCOMP_FILTER`` 标志,那么可以添加以下过滤器:
``PR_SET_SECCOMP``:
现在需要添加一个额外的参数来指定使用BPF程序的新过滤器。
BPF程序将在反应系统调用号、参数和其他元数据的seccomp_data结构体之上执行。
BPF程序必须返回允许的值之一来告知内核应该采取什么行动。
用法::
prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, prog);
'prog' 参数是一个指向 sock_fprog 结构体的指针,其中包含了过滤器程序。如
果程序是无效的,该调用会返回 -1 并设置 errno 为 ``EINVAL`` 。
如果 ``fork`` / ``clone`` 和 ``execve`` 被 @prog 所允许,任何子进程都将
受到和父进程相同的过滤器和系统调用ABI的约束。
在调用之前,进程必须调用 ``prctl(PR_SET_NO_NEW_PRIVS, 1)`` 或者在它的
命名空间内以 ``CAP_SYS_ADMIN`` 权限运行。如果以上条件不满足,会返回
``-EACCES`` 。这一要求保证了过滤器程序不能用于比安装过滤器的进程拥有更高
权限的子进程。
另外,如果 ``prctl(2)`` 被安装的过滤器所允许,就可以叠加额外的过滤器。这会增
加评估时间,但是可以进一步降低执行进程时的攻击面。
以上调用在成功时返回0,失败时返回一个非零的值。
返回值
======
一个seccomp过滤器可能返回下列任意值。如果多个过滤器存在,评估一个指定系统调用的
返回值总会使用最高优先级的值。(比如 ``SECCOMP_RET_KILL_PROCESS`` 总是被优先
返回。)
按照优先级排序,它们是:
``SECCOMP_RET_KILL_PROCESS``:
使得整个进程立即结束而不执行系统调用。进程的退出状态 (``status & 0x7f``) 将
是 ``SIGSYS`` ,而不是 ``SIGKILL`` 。
``SECCOMP_RET_KILL_THREAD``:
使得线程立即结束而不执行系统调用。线程的退出状态 (``status & 0x7f``) 将是
是 ``SIGSYS`` ,而不是 ``SIGKILL`` 。
``SECCOMP_RET_TRAP``:
使得内核向触发进程发送一个 ``SIGSYS`` 信号而不执行系统调用。
``siginfo->si_call_addr`` 会展示系统调用指令的位置, ``siginfo->si_syscall``
和 ``siginfo->si_arch`` 会指出试图进行的系统调用。程序计数器会和发生了系统
调用的一样(即它不会指向系统调用指令)。返回值寄存器会包含一个与架构相关的值——
如果恢复执行,需要将其设为合理的值。(架构依赖性是因为将其替换为 ``-ENOSYS``
会导致一些有用的信息被覆盖。)
返回值的 ``SECCOMP_RET_DATA`` 部分会作为 ``si_errno`` 传递。
由seccomp触发的 ``SIGSYS`` 会有一个 ``SYS_SECCOMP`` 的 si_code 。
``SECCOMP_RET_ERRNO``:
使得返回值的低16位作为errno传递给用户空间,而不执行系统调用。
``SECCOMP_RET_USER_NOTIF``:
使得一个 ``struct seccomp_notif`` 消息被发送到已附加的用户空间通知文件描述
符。如果没有被附加则返回 ``-ENOSYS`` 。下面会讨论如何处理用户通知。
``SECCOMP_RET_TRACE``:
当返回的时候,这个值会使得内核在执行系统调用前尝试去通知一个基于 ``ptrace()``
的追踪器。如果没有追踪器, ``-ENOSYS`` 会返回给用户空间,并且系统调用不会执行。
如果追踪器通过 ``ptrace(PTRACE_SETOPTIONS)`` 请求了 ``PTRACE_O_TRACESECCOMP``,
那么它会收到 ``PTRACE_EVENT_SECCOMP`` 通知。BPF程序返回值的 ``SECCOMP_RET_DATA``
部分会通过 ``PTRACE_GETEVENTMSG`` 提供给追踪器。
追踪器可以通过改变系统调用号到-1来跳过系统调用。或者追踪器可以改变系统调用号到
一个有效值来改变请求的系统调用。如果追踪器请求跳过系统调用,那么系统调用将返回
追踪器放在返回值寄存器中的值。
在追踪器被通知后,seccomp检查不会再次运行。(这意味着基于seccomp的沙箱必须禁止
ptrace的使用,甚至其他沙箱进程也不行,除非非常小心;ptrace可以通过这个机制来逃
逸。)
``SECCOMP_RET_LOG``:
使得系统调用在被记录之后再运行。这应该被应用开发者用来检查他们的程序需要哪些
系统调用,而不需要反复通过多个测试和开发周期来建立清单。
只有在 actions_logged sysctl 字符串中出现 "log" 时,这个操作才会被记录。
``SECCOMP_RET_ALLOW``:
使得系统调用被执行。
如果多个追踪器存在,评估系统调用的返回值将永远使用最高优先级的值。
优先级只通过 ``SECCOMP_RET_ACTION`` 掩码来决定。当多个过滤器返回相同优先级的返回
值时,只有来自最近安装的过滤器的 ``SECCOMP_RET_DATA`` 会被返回。
隐患
====
最需要避免的隐患是在过滤系统调用号时却不检查架构值。因为在任何支持多个系统调用
约定的架构上,系统调用号可能根据具体调用而不同。如果不同调用约定中的调用号有重叠,
那么过滤器的检查可能被滥用。请总是检查架构值!
例子
====
``samples/seccomp/`` 文件夹包含了x86专用和更通用的使用高层宏接口来生成BPF程序的
例子。
用户空间通知
============
``SECCOMP_RET_USER_NOTIF`` 返回值会让seccomp过滤器传递一个特定的系统调用给用户
空间处理。这可能会对像容器管理器的程序有用,它们希望拦截特定的系统调用(如 ``mount()``,
``finit_module()`` 等等)并改变其行为。
传递 ``SECCOMP_FILTER_FLAG_NEW_LISTENER`` 参数给 ``seccomp()`` 系统调用可以取
得通知文件描述符:
.. code-block:: c
fd = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_NEW_LISTENER, &prog);
成功情况下会返回一个对过滤器监听的文件描述符,然后可以通过 ``SCM_RIGHTS`` 或类似
的方式传递。需要注意的是,过滤器文件描述符针对的是一个特定的过滤器而不是特定的进程。
所以如果这个进程后来fork了,来自两个进程的通知都会出现在同一个过滤器文件描述符中。
对于过滤器文件描述符的读写也是同步的,所以一个过滤器文件描述符可以安全地拥有多个读者。
seccomp通知文件描述符由两个结构体组成:
.. code-block:: c
struct seccomp_notif_sizes {
__u16 seccomp_notif;
__u16 seccomp_notif_resp;
__u16 seccomp_data;
};
struct seccomp_notif {
__u64 id;
__u32 pid;
__u32 flags;
struct seccomp_data data;
};
struct seccomp_notif_resp {
__u64 id;
__s64 val;
__s32 error;
__u32 flags;
};
``struct seccomp_notif_sizes`` 结构体可以用于确定seccomp通知中各种结构体的大小。
``struct seccomp_data`` 的大小可能未来会改变,所以需要使用下面的代码:
.. code-block:: c
struct seccomp_notif_sizes sizes;
seccomp(SECCOMP_GET_NOTIF_SIZES, 0, &sizes);
来决定需要分配的多种结构体的大小。请查看 samples/seccomp/user-trap.c 中的例子。
用户可以通过 ``ioctl(SECCOMP_IOCTL_NOTIF_RECV)`` (或 ``poll()``) 读取seccomp
通知文件描述符来接收一个 ``struct seccomp_notif`` ,其中包含五个成员:结构体的
输入长度,每个过滤器唯一的 ``id`` , 触发请求进程的 ``pid`` (如果进程的pid命名空
间对于监听者的pid命名空间不可见的话,可能为0)。通知还包含传递给seccomp的 ``data``
和一个过滤器标志。在调用ioctl前结构体应该被清空。
之后用户空间可以根据这些信息决定做什么,并通过 ``ioctl(SECCOMP_IOCTL_NOTIF_SEND)``
发送一个响应,表示应该给用户空间返回什么。 ``struct seccomp_notif_resp`` 的 ``id``
成员应该和 ``struct seccomp_notif`` 的 ``id`` 一致。
用户空间也可以通过 ``ioctl(SECCOMP_IOCTL_NOTIF_ADDFD)`` 向通知进程添加文件描述
符。 ``struct seccomp_notif_addfd`` 的 ``id`` 成员应该和 ``struct seccomp_notif``
的 ``id`` 保持一致。 ``newfd_flags`` 标志可以被用于在通知进程的文件描述符上设置
O_CLOEXEC 等标志。如果监督者(supervisor)向文件描述符注入一个特定的数字,可以使用
``SECCOMP_ADDFD_FLAG_SETFD`` 标志,并设置 ``newfd`` 成员为要使用的特定数字。
如果文件描述符已经在通知进程中打开,那它将被替换。监督者也可以添加一个文件描述符,
并使用 ``SECCOMP_ADDFD_FLAG_SEND`` 标志原子响应,返回值将是注入的文件描述符编号。
通知进程可以被抢占,导致通知被终止。这可能在尝试代表通知进程执行长时间且通常可重试
(如挂载文件系统)的操作时导致问题。另外,在安装过滤器的时候,
``SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV`` 可以被设置。这个标志使得当监督者收到用
户通知时,通知进程会忽略非致命信号,直到响应被发送。在用户空间收到通知之前发出的信号
将被正常处理。
值得注意的是, ``struct seccomp_data`` 包含了系统调用寄存器参数的值,但是不包含指向
内存的指针。进程的内存可以通过 ``ptrace()`` 或 ``/proc/pid/mem`` 由合适的特权跟踪
访问。但是,需要注意避免之前提到的TOCTOU攻击:所有从被跟踪者内存中读到的参数都应该先
读到追踪器的内存中,再做出策略决定。这样就可以对系统调用的参数做原子决定。
Sysctls
=======
Seccomp的sysctl文件可以在 ``/proc/sys/kernel/seccomp/`` 文件夹中找到。这里有对文件
夹中每个文件的描述:
``actions_avail``:
以字符串形式保存seccomp返回值(参考上文的 ``SECCOMP_RET_*`` 宏)的只读有序
列表。从左往右按照最少许可返回值到最多许可返回值排序。
这个列表代表了内核支持的seccomp返回值集合。一个用户空间程序可以使用这个列表来在
程序建立时确定在 ``seccomp.h`` 中找到的动作是否和当前运行内核实际支持的动作有所
不同。
``actions_logged``:
允许被记录的seccomp返回值(参考上文的 ``SECCOMP_RET_*`` 宏)的可读写有序列表。
对文件写入不需要是有序的,但从文件读取将采用与actions_avail sysctl一致的方式排序。
``allow`` 字符串在 ``actions_logged`` sysctl中不被接收,因为不可能记录
``SECCOMP_RET_ALLOW`` 动作。尝试向sysctl写入 ``allow`` 会导致返回一个EINVAL。
添加架构支持
============
请查看 ``arch/Kconfig`` 了解权威要求。总的来说如果一个架构同时支持ptrace_event和
seccomp,那么它将可以通过较小的修改支持seccomp过滤器: ``SIGSYS`` 支持和seccomp
返回值检查。然后必须将 ``CONFIG_HAVE_ARCH_SECCOMP_FILTER`` 添加到它的架构特定
的Kconfig中。
注意事项
========
vDSO可能导致一些系统调用完全在用户空间中运行,当你在不同机器上跑程序时可能导致回退
到真正系统调用的意外发生。为了在x86上最小化这些意外的发生,请确保你在测试时把
``/sys/devices/system/clocksource/clocksource0/current_clocksource`` 设置为
``acpi_pm`` 之类的值。
在x86-64上,vsyscall模拟默认开启。(vsyscalls是vDSO调用的传统变体。)目前,模拟
vsyscalls会遵守seccomp,但是有一些奇怪情况:
- ``SECCOMP_RET_TRAP`` 的返回值会设置一个指向给定vsyscall入口的 ``si_call_addr``,
而不是'syscall'指令之后的地址。任何想重新开始调用的代码都需要注意 (a) ret指令
已被模拟,(b) 试图恢复系统调用将再次触发标准vsyscall模拟安全检查,使得恢复系统
调用在大部分情况下没有意义。
- ``SECCOMP_RET_TRACE`` 的返回值将像往常一样给追踪器发出信号,但是系统调用可能不能
使用orig_rax寄存器改变为另一个系统调用。可能只能改变为-1来跳过当前模拟的调用。
任何其他改变都可能终止进程。追踪器看到的rip值将是系统调用的入口地址;这和正常行为
不同。追踪器禁止修改rip或者rsp。(不要依赖其他改变来终止进程,它们可能正常工作。
比如在一些内核中,选择一个只存在于未来内核中的系统调用将被正确模拟,返回一个
``-ENOSYS`` 。)
要检测这个古怪的行为,可以检查 ``addr & ~0x0C00 == 0xFFFFFFFFFF600000``。(对于
``SECCOMP_RET_TRACE`` ,使用rip。对于 ``SECCOMP_RET_TRAP`` ,使用
``siginfo->si_call_addr`` 。)不要检测其他条件:未来内核可能会改进vsyscall模拟,
当前内核在vsyscall=native模式下会有不同表现,但在这些情况下, ``0xF...F600{0,4,8,C}00``
处的指令将不是系统调用。
请注意,现代系统根本不可能使用vsyscalls —— 它们是一种遗留功能,而且比标准系统调用
慢得多。 新的代码将使用vDSO,而vDSO发出的系统调用与正常的系统调用没有区别。
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/userspace-api/sysfs-platform_profile.rst
:翻译:
李睿 Rui Li <me@lirui.org>
==========================================================
平台配置文件选择(如 /sys/firmware/acpi/platform_profile)
==========================================================
现代系统中平台性能、温度、风扇和其他硬件相关的特性通常是可以动态配置的。平台
配置通常会根据当前的状态由一些自动机制(很可能存在于内核之外)来自动调整。
这些平台自动调整机制通常能够被配置成多个平台配置文件中的一个,要么偏向节能运
行,要么偏向性能运行。
platform_profile属性的目的是提供一个通用的sysfs API来选择这些平台自动配置
机制的配置文件。
需要注意的是,这个API只能用作选择平台配置文件,用来监测所产生的性能特征并不
是其目标。监测性能最好使用设备/供应商提供的工具,比如turbostat。
具体来说,当选择高性能配置文件时,真实能达到的性能可能受制于多种因素,比如:
其他组件的发热,房间温度,笔记本底部的自由空气流动等。让用户空间知道任何阻碍
达到要求性能水平的局部最优条件,显然不是这个API的目标。
由于数字本身并不能代表一个配置文件会调整的多个变量(功耗,发热等),这个API
使用字符串来描述多种配置文件。为了保证用户空间能够获得一致的体验,
sysfs-platform_profile ABI 文档定义了一个固定的配置文件名集合。驱动程序
*必须* 将它们内置的配置文件表示映射到这个固定的集合中。
如果映射时没有很好的匹配,可以添加一个新的配置文件名称。驱动希望引入的新配置
文件名称时必须:
1. 解释为什么无法使用已有的配置文件名称。
2. 添加一个新的配置文件名称,以及预期行为的清晰描述,保存到
sysfs-platform_profile ABI文档中。
Credits for the Simple Linux USB Driver:
The following people have contributed to this code (in alphabetical
order by last name). I'm sure this list should be longer, its
order by last name). I'm sure this list should be longer, it's
difficult to maintain, add yourself with a patch if desired.
Georg Acher <acher@informatik.tu-muenchen.de>
......@@ -126,7 +126,7 @@ THANKS file in Inaky's driver):
- Jochen Karrer <karrer@wpfd25.physik.uni-wuerzburg.de>, for
pointing out mortal bugs and giving advice.
- Edmund Humemberger <ed@atnet.at>, for it's great work on
- Edmund Humemberger <ed@atnet.at>, for his great work on
public relationships and general management stuff for the
Linux-USB effort.
......@@ -136,7 +136,7 @@ THANKS file in Inaky's driver):
- Ric Klaren <ia_ric@cs.utwente.nl> for doing nice
introductory documents (competing with Alberto's :).
- Christian Groessler <cpg@aladdin.de>, for it's help on those
- Christian Groessler <cpg@aladdin.de>, for his help on those
itchy bits ... :)
- Paul MacKerras for polishing OHCI and pushing me harder for
......
......@@ -49,7 +49,7 @@ level it would look like this::
$ ( cd /dev/ffs-hid && hid-daemon ) &
On kernel level the gadget checks ffs_data->dev_name to identify
whether it's FunctionFS designed for MTP ("mtp") or HID ("hid").
whether its FunctionFS is designed for MTP ("mtp") or HID ("hid").
If no "functions" module parameters is supplied, the driver accepts
just one function with any name.
......
......@@ -9,7 +9,7 @@ The Multifunction Composite Gadget (or g_multi) is a composite gadget
that makes extensive use of the composite framework to provide
a... multifunction gadget.
In it's standard configuration it provides a single USB configuration
In its standard configuration it provides a single USB configuration
with RNDIS[1] (that is Ethernet), USB CDC[2] ACM (that is serial) and
USB Mass Storage functions.
......
......@@ -47,10 +47,11 @@ $(BUILDDIR)/lirc.h.rst: ${UAPI}/lirc.h ${PARSER} $(SRC_DIR)/lirc.h.rst.exception
# Media build rules
.PHONY: all html epub xml latex
.PHONY: all html texinfo epub xml latex
all: $(IMGDOT) $(BUILDDIR) ${TARGETS}
html: all
texinfo: all
epub: all
xml: all
latex: $(IMGPDF) all
......
......@@ -10048,6 +10048,11 @@ F: Documentation/hwmon/ina2xx.rst
F: drivers/hwmon/ina2xx.c
F: include/linux/platform_data/ina2xx.h
INDEX OF FURTHER KERNEL DOCUMENTATION
M: Carlos Bilbao <carlos.bilbao@amd.com>
S: Maintained
F: Documentation/process/kernel-docs.rst
INDUSTRY PACK SUBSYSTEM (IPACK)
M: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
M: Jens Taprogge <jens.taprogge@taprogge.org>
......@@ -19396,6 +19401,11 @@ W: https://linuxtv.org
Q: http://patchwork.linuxtv.org/project/linux-media/list/
F: drivers/media/dvb-frontends/sp2*
SPANISH DOCUMENTATION
M: Carlos Bilbao <carlos.bilbao@amd.com>
S: Maintained
F: Documentation/translations/sp_SP/
SPARC + UltraSPARC (sparc/sparc64)
M: "David S. Miller" <davem@davemloft.net>
L: sparclinux@vger.kernel.org
......
......@@ -1787,7 +1787,7 @@ $(help-board-dirs): help-%:
# Documentation targets
# ---------------------------------------------------------------------------
DOC_TARGETS := xmldocs latexdocs pdfdocs htmldocs epubdocs cleandocs \
linkcheckdocs dochelp refcheckdocs
linkcheckdocs dochelp refcheckdocs texinfodocs infodocs
PHONY += $(DOC_TARGETS)
$(DOC_TARGETS):
$(Q)$(MAKE) $(build)=Documentation $@
......
......@@ -29,7 +29,7 @@ static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
return dividend / divisor;
}
/*
/**
* div_s64_rem - signed 64bit divide with 32bit divisor with remainder
* @dividend: signed 64bit dividend
* @divisor: signed 32bit divisor
......@@ -43,7 +43,7 @@ static inline s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
return dividend / divisor;
}
/*
/**
* div64_u64_rem - unsigned 64bit divide with 64bit divisor and remainder
* @dividend: unsigned 64bit dividend
* @divisor: unsigned 64bit divisor
......@@ -57,7 +57,7 @@ static inline u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder)
return dividend / divisor;
}
/*
/**
* div64_u64 - unsigned 64bit divide with 64bit divisor
* @dividend: unsigned 64bit dividend
* @divisor: unsigned 64bit divisor
......@@ -69,7 +69,7 @@ static inline u64 div64_u64(u64 dividend, u64 divisor)
return dividend / divisor;
}
/*
/**
* div64_s64 - signed 64bit divide with 64bit divisor
* @dividend: signed 64bit dividend
* @divisor: signed 64bit divisor
......@@ -120,6 +120,8 @@ extern s64 div64_s64(s64 dividend, s64 divisor);
* This is the most common 64bit divide and should be used if possible,
* as many 32bit archs can optimize this variant better than a full 64bit
* divide.
*
* Return: dividend / divisor
*/
#ifndef div_u64
static inline u64 div_u64(u64 dividend, u32 divisor)
......@@ -133,6 +135,8 @@ static inline u64 div_u64(u64 dividend, u32 divisor)
* div_s64 - signed 64bit divide with 32bit divisor
* @dividend: signed 64bit dividend
* @divisor: signed 32bit divisor
*
* Return: dividend / divisor
*/
#ifndef div_s64
static inline s64 div_s64(s64 dividend, s32 divisor)
......@@ -284,6 +288,16 @@ static inline u64 mul_u64_u32_div(u64 a, u32 mul, u32 divisor)
u64 mul_u64_u64_div_u64(u64 a, u64 mul, u64 div);
/**
* DIV64_U64_ROUND_UP - unsigned 64bit divide with 64bit divisor rounded up
* @ll: unsigned 64bit dividend
* @d: unsigned 64bit divisor
*
* Divide unsigned 64bit dividend by unsigned 64bit divisor
* and round up.
*
* Return: dividend / divisor rounded up
*/
#define DIV64_U64_ROUND_UP(ll, d) \
({ u64 _tmp = (d); div64_u64((ll) + _tmp - 1, _tmp); })
......@@ -300,7 +314,7 @@ u64 mul_u64_u64_div_u64(u64 a, u64 mul, u64 div);
#define DIV64_U64_ROUND_CLOSEST(dividend, divisor) \
({ u64 _tmp = (divisor); div64_u64((dividend) + _tmp / 2, _tmp); })
/*
/**
* DIV_U64_ROUND_CLOSEST - unsigned 64bit divide with 32bit divisor rounded to nearest integer
* @dividend: unsigned 64bit dividend
* @divisor: unsigned 32bit divisor
......@@ -313,7 +327,7 @@ u64 mul_u64_u64_div_u64(u64 a, u64 mul, u64 div);
#define DIV_U64_ROUND_CLOSEST(dividend, divisor) \
({ u32 _tmp = (divisor); div_u64((u64)(dividend) + _tmp / 2, _tmp); })
/*
/**
* DIV_S64_ROUND_CLOSEST - signed 64bit divide with 32bit divisor rounded to nearest integer
* @dividend: signed 64bit dividend
* @divisor: signed 32bit divisor
......
......@@ -63,12 +63,6 @@ uint32_t __attribute__((weak)) __div64_32(uint64_t *n, uint32_t base)
EXPORT_SYMBOL(__div64_32);
#endif
/**
* div_s64_rem - signed 64bit divide with 64bit divisor and remainder
* @dividend: 64bit dividend
* @divisor: 64bit divisor
* @remainder: 64bit remainder
*/
#ifndef div_s64_rem
s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
{
......@@ -89,7 +83,7 @@ s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
EXPORT_SYMBOL(div_s64_rem);
#endif
/**
/*
* div64_u64_rem - unsigned 64bit divide with 64bit divisor and remainder
* @dividend: 64bit dividend
* @divisor: 64bit divisor
......@@ -129,7 +123,7 @@ u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder)
EXPORT_SYMBOL(div64_u64_rem);
#endif
/**
/*
* div64_u64 - unsigned 64bit divide with 64bit divisor
* @dividend: 64bit dividend
* @divisor: 64bit divisor
......@@ -163,11 +157,6 @@ u64 div64_u64(u64 dividend, u64 divisor)
EXPORT_SYMBOL(div64_u64);
#endif
/**
* div64_s64 - signed 64bit divide with 64bit divisor
* @dividend: 64bit dividend
* @divisor: 64bit divisor
*/
#ifndef div64_s64
s64 div64_s64(s64 dividend, s64 divisor)
{
......
......@@ -866,48 +866,53 @@ sub output_function_rst(%) {
print "\n";
}
print "**Parameters**\n\n";
#
# Put our descriptive text into a container (thus an HTML <div>) to help
# set the function prototypes apart.
#
print ".. container:: kernelindent\n\n";
$lineprefix = " ";
print $lineprefix . "**Parameters**\n\n";
foreach $parameter (@{$args{'parameterlist'}}) {
my $parameter_name = $parameter;
$parameter_name =~ s/\[.*//;
$type = $args{'parametertypes'}{$parameter};
if ($type ne "") {
print "``$type``\n";
print $lineprefix . "``$type``\n";
} else {
print "``$parameter``\n";
print $lineprefix . "``$parameter``\n";
}
print_lineno($parameterdesc_start_lines{$parameter_name});
$lineprefix = " ";
if (defined($args{'parameterdescs'}{$parameter_name}) &&
$args{'parameterdescs'}{$parameter_name} ne $undescribed) {
output_highlight_rst($args{'parameterdescs'}{$parameter_name});
} else {
print " *undescribed*\n";
print $lineprefix . "*undescribed*\n";
}
$lineprefix = " ";
print "\n";
}
$lineprefix = $oldprefix;
output_section_rst(@_);
$lineprefix = $oldprefix;
}
sub output_section_rst(%) {
my %args = %{$_[0]};
my $section;
my $oldprefix = $lineprefix;
$lineprefix = "";
foreach $section (@{$args{'sectionlist'}}) {
print "**$section**\n\n";
print $lineprefix . "**$section**\n\n";
print_lineno($section_start_lines{$section});
output_highlight_rst($args{'sections'}{$section});
print "\n";
}
print "\n";
$lineprefix = $oldprefix;
}
sub output_enum_rst(%) {
......@@ -915,6 +920,7 @@ sub output_enum_rst(%) {
my ($parameter);
my $oldprefix = $lineprefix;
my $count;
my $outer;
if ($sphinx_major < 3) {
my $name = "enum " . $args{'enum'};
......@@ -924,22 +930,25 @@ sub output_enum_rst(%) {
print "\n\n.. c:enum:: " . $name . "\n\n";
}
print_lineno($declaration_start_line);
$lineprefix = " ";
$lineprefix = " ";
output_highlight_rst($args{'purpose'});
print "\n";
print "**Constants**\n\n";
$lineprefix = " ";
print ".. container:: kernelindent\n\n";
$outer = $lineprefix . " ";
$lineprefix = $outer . " ";
print $outer . "**Constants**\n\n";
foreach $parameter (@{$args{'parameterlist'}}) {
print "``$parameter``\n";
print $outer . "``$parameter``\n";
if ($args{'parameterdescs'}{$parameter} ne $undescribed) {
output_highlight_rst($args{'parameterdescs'}{$parameter});
} else {
print " *undescribed*\n";
print $lineprefix . "*undescribed*\n";
}
print "\n";
}
print "\n";
$lineprefix = $oldprefix;
output_section_rst(@_);
}
......@@ -982,18 +991,19 @@ sub output_struct_rst(%) {
}
}
print_lineno($declaration_start_line);
$lineprefix = " ";
$lineprefix = " ";
output_highlight_rst($args{'purpose'});
print "\n";
print "**Definition**\n\n";
print "::\n\n";
print ".. container:: kernelindent\n\n";
print $lineprefix . "**Definition**::\n\n";
my $declaration = $args{'definition'};
$declaration =~ s/\t/ /g;
print " " . $args{'type'} . " " . $args{'struct'} . " {\n$declaration };\n\n";
$lineprefix = $lineprefix . " ";
$declaration =~ s/\t/$lineprefix/g;
print $lineprefix . $args{'type'} . " " . $args{'struct'} . " {\n$declaration" . $lineprefix . "};\n\n";
print "**Members**\n\n";
$lineprefix = " ";
print $lineprefix . "**Members**\n\n";
foreach $parameter (@{$args{'parameterlist'}}) {
($parameter =~ /^#/) && next;
......@@ -1003,8 +1013,10 @@ sub output_struct_rst(%) {
($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
$type = $args{'parametertypes'}{$parameter};
print_lineno($parameterdesc_start_lines{$parameter_name});
print "``" . $parameter . "``\n";
print $lineprefix . "``" . $parameter . "``\n";
$lineprefix = " ";
output_highlight_rst($args{'parameterdescs'}{$parameter_name});
$lineprefix = " ";
print "\n";
}
print "\n";
......
......@@ -362,7 +362,6 @@ sub give_debian_hints()
{
my %map = (
"python-sphinx" => "python3-sphinx",
"sphinx_rtd_theme" => "python3-sphinx-rtd-theme",
"ensurepip" => "python3-venv",
"virtualenv" => "virtualenv",
"dot" => "graphviz",
......@@ -397,7 +396,6 @@ sub give_redhat_hints()
{
my %map = (
"python-sphinx" => "python3-sphinx",
"sphinx_rtd_theme" => "python3-sphinx_rtd_theme",
"virtualenv" => "python3-virtualenv",
"dot" => "graphviz",
"convert" => "ImageMagick",
......@@ -475,7 +473,6 @@ sub give_opensuse_hints()
{
my %map = (
"python-sphinx" => "python3-sphinx",
"sphinx_rtd_theme" => "python3-sphinx_rtd_theme",
"virtualenv" => "python3-virtualenv",
"dot" => "graphviz",
"convert" => "ImageMagick",
......@@ -523,7 +520,6 @@ sub give_mageia_hints()
{
my %map = (
"python-sphinx" => "python3-sphinx",
"sphinx_rtd_theme" => "python3-sphinx_rtd_theme",
"virtualenv" => "python3-virtualenv",
"dot" => "graphviz",
"convert" => "ImageMagick",
......@@ -567,7 +563,6 @@ sub give_mageia_hints()
sub give_arch_linux_hints()
{
my %map = (
"sphinx_rtd_theme" => "python-sphinx_rtd_theme",
"virtualenv" => "python-virtualenv",
"dot" => "graphviz",
"convert" => "imagemagick",
......@@ -598,7 +593,6 @@ sub give_arch_linux_hints()
sub give_gentoo_hints()
{
my %map = (
"sphinx_rtd_theme" => "dev-python/sphinx_rtd_theme",
"virtualenv" => "dev-python/virtualenv",
"dot" => "media-gfx/graphviz",
"convert" => "media-gfx/imagemagick",
......@@ -895,7 +889,6 @@ sub recommend_sphinx_version($)
$verbose_warn_install = 0;
add_package("python-sphinx", 0);
check_python_module("sphinx_rtd_theme", 1);
check_distros();
......@@ -968,7 +961,6 @@ sub check_needs()
check_perl_module("Pod::Usage", 0);
check_program("make", 0);
check_program("gcc", 0);
check_python_module("sphinx_rtd_theme", 1) if (!$virtualenv);
check_program("dot", 1);
check_program("convert", 1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment