diff options
30 files changed, 2653 insertions, 430 deletions
diff --git a/Documentation/.gitignore b/Documentation/.gitignore new file mode 100644 index 000000000000..e74fec8693b2 --- /dev/null +++ b/Documentation/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | output | ||
2 | *.pyc | ||
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index cd077ca0e1b8..cb9a6c6fa83b 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX | |||
@@ -255,10 +255,10 @@ kbuild/ | |||
255 | - directory with info about the kernel build process. | 255 | - directory with info about the kernel build process. |
256 | kdump/ | 256 | kdump/ |
257 | - directory with mini HowTo on getting the crash dump code to work. | 257 | - directory with mini HowTo on getting the crash dump code to work. |
258 | kernel-doc-nano-HOWTO.txt | ||
259 | - mini HowTo on generation and location of kernel documentation files. | ||
260 | kernel-docs.txt | 258 | kernel-docs.txt |
261 | - listing of various WWW + books that document kernel internals. | 259 | - listing of various WWW + books that document kernel internals. |
260 | kernel-documentation.rst | ||
261 | - how to write and format reStructuredText kernel documentation | ||
262 | kernel-parameters.txt | 262 | kernel-parameters.txt |
263 | - summary listing of command line / boot prompt args for the kernel. | 263 | - summary listing of command line / boot prompt args for the kernel. |
264 | kernel-per-CPU-kthreads.txt | 264 | kernel-per-CPU-kthreads.txt |
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle index 9a70ddd16584..a096836723ca 100644 --- a/Documentation/CodingStyle +++ b/Documentation/CodingStyle | |||
@@ -458,7 +458,7 @@ of the function, telling people what it does, and possibly WHY it does | |||
458 | it. | 458 | it. |
459 | 459 | ||
460 | When commenting the kernel API functions, please use the kernel-doc format. | 460 | When commenting the kernel API functions, please use the kernel-doc format. |
461 | See the files Documentation/kernel-doc-nano-HOWTO.txt and scripts/kernel-doc | 461 | See the files Documentation/kernel-documentation.rst and scripts/kernel-doc |
462 | for details. | 462 | for details. |
463 | 463 | ||
464 | Linux style for comments is the C89 "/* ... */" style. | 464 | Linux style for comments is the C89 "/* ... */" style. |
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index d70f9b68174e..01bab5014a4a 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile | |||
@@ -6,6 +6,8 @@ | |||
6 | # To add a new book the only step required is to add the book to the | 6 | # To add a new book the only step required is to add the book to the |
7 | # list of DOCBOOKS. | 7 | # list of DOCBOOKS. |
8 | 8 | ||
9 | ifeq ($(IGNORE_DOCBOOKS),) | ||
10 | |||
9 | DOCBOOKS := z8530book.xml device-drivers.xml \ | 11 | DOCBOOKS := z8530book.xml device-drivers.xml \ |
10 | kernel-hacking.xml kernel-locking.xml deviceiobook.xml \ | 12 | kernel-hacking.xml kernel-locking.xml deviceiobook.xml \ |
11 | writing_usb_driver.xml networking.xml \ | 13 | writing_usb_driver.xml networking.xml \ |
@@ -33,10 +35,6 @@ PDF_METHOD = $(prefer-db2x) | |||
33 | PS_METHOD = $(prefer-db2x) | 35 | PS_METHOD = $(prefer-db2x) |
34 | 36 | ||
35 | 37 | ||
36 | ### | ||
37 | # The targets that may be used. | ||
38 | PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs cleandocs | ||
39 | |||
40 | targets += $(DOCBOOKS) | 38 | targets += $(DOCBOOKS) |
41 | BOOKS := $(addprefix $(obj)/,$(DOCBOOKS)) | 39 | BOOKS := $(addprefix $(obj)/,$(DOCBOOKS)) |
42 | xmldocs: $(BOOKS) | 40 | xmldocs: $(BOOKS) |
@@ -63,6 +61,9 @@ installmandocs: mandocs | |||
63 | sort -k 2 -k 1 | uniq -f 1 | sed -e 's: :/:' | \ | 61 | sort -k 2 -k 1 | uniq -f 1 | sed -e 's: :/:' | \ |
64 | xargs install -m 644 -t /usr/local/man/man9/ | 62 | xargs install -m 644 -t /usr/local/man/man9/ |
65 | 63 | ||
64 | # no-op for the DocBook toolchain | ||
65 | epubdocs: | ||
66 | |||
66 | ### | 67 | ### |
67 | #External programs used | 68 | #External programs used |
68 | KERNELDOCXMLREF = $(srctree)/scripts/kernel-doc-xml-ref | 69 | KERNELDOCXMLREF = $(srctree)/scripts/kernel-doc-xml-ref |
@@ -216,10 +217,24 @@ silent_gen_xml = : | |||
216 | -e "s/>/\\>/g"; \ | 217 | -e "s/>/\\>/g"; \ |
217 | echo "</programlisting>") > $@ | 218 | echo "</programlisting>") > $@ |
218 | 219 | ||
220 | else | ||
221 | |||
222 | # Needed, due to cleanmediadocs | ||
223 | include Documentation/DocBook/media/Makefile | ||
224 | |||
225 | htmldocs: | ||
226 | pdfdocs: | ||
227 | psdocs: | ||
228 | xmldocs: | ||
229 | installmandocs: | ||
230 | |||
231 | endif # IGNORE_DOCBOOKS | ||
232 | |||
233 | |||
219 | ### | 234 | ### |
220 | # Help targets as used by the top-level makefile | 235 | # Help targets as used by the top-level makefile |
221 | dochelp: | 236 | dochelp: |
222 | @echo ' Linux kernel internal documentation in different formats:' | 237 | @echo ' Linux kernel internal documentation in different formats (DocBook):' |
223 | @echo ' htmldocs - HTML' | 238 | @echo ' htmldocs - HTML' |
224 | @echo ' pdfdocs - PDF' | 239 | @echo ' pdfdocs - PDF' |
225 | @echo ' psdocs - Postscript' | 240 | @echo ' psdocs - Postscript' |
@@ -228,8 +243,11 @@ dochelp: | |||
228 | @echo ' installmandocs - install man pages generated by mandocs' | 243 | @echo ' installmandocs - install man pages generated by mandocs' |
229 | @echo ' cleandocs - clean all generated DocBook files' | 244 | @echo ' cleandocs - clean all generated DocBook files' |
230 | @echo | 245 | @echo |
231 | @echo 'make DOCBOOKS="s1.xml s2.xml" [target] Generate only docs s1.xml s2.xml' | 246 | @echo ' make DOCBOOKS="s1.xml s2.xml" [target] Generate only docs s1.xml s2.xml' |
232 | @echo ' valid values for DOCBOOKS are: $(DOCBOOKS)' | 247 | @echo ' valid values for DOCBOOKS are: $(DOCBOOKS)' |
248 | @echo | ||
249 | @echo " make IGNORE_DOCBOOKS=1 [target] Don't generate docs from Docbook" | ||
250 | @echo ' This is useful to generate only the ReST docs (Sphinx)' | ||
233 | 251 | ||
234 | 252 | ||
235 | ### | 253 | ### |
diff --git a/Documentation/Makefile.sphinx b/Documentation/Makefile.sphinx new file mode 100644 index 000000000000..d8d13c92a178 --- /dev/null +++ b/Documentation/Makefile.sphinx | |||
@@ -0,0 +1,78 @@ | |||
1 | # -*- makefile -*- | ||
2 | # Makefile for Sphinx documentation | ||
3 | # | ||
4 | |||
5 | # You can set these variables from the command line. | ||
6 | SPHINXBUILD = sphinx-build | ||
7 | SPHINXOPTS = | ||
8 | PAPER = | ||
9 | BUILDDIR = $(obj)/output | ||
10 | |||
11 | # User-friendly check for sphinx-build | ||
12 | HAVE_SPHINX := $(shell if which $(SPHINXBUILD) >/dev/null 2>&1; then echo 1; else echo 0; fi) | ||
13 | |||
14 | ifeq ($(HAVE_SPHINX),0) | ||
15 | |||
16 | .DEFAULT: | ||
17 | $(warning The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed and in PATH, or set the SPHINXBUILD make variable to point to the full path of the '$(SPHINXBUILD)' executable.) | ||
18 | @echo " SKIP Sphinx $@ target." | ||
19 | |||
20 | else ifneq ($(DOCBOOKS),) | ||
21 | |||
22 | # Skip Sphinx build if the user explicitly requested DOCBOOKS. | ||
23 | .DEFAULT: | ||
24 | @echo " SKIP Sphinx $@ target (DOCBOOKS specified)." | ||
25 | |||
26 | else # HAVE_SPHINX | ||
27 | |||
28 | # User-friendly check for rst2pdf | ||
29 | HAVE_RST2PDF := $(shell if python -c "import rst2pdf" >/dev/null 2>&1; then echo 1; else echo 0; fi) | ||
30 | |||
31 | # Internal variables. | ||
32 | PAPEROPT_a4 = -D latex_paper_size=a4 | ||
33 | PAPEROPT_letter = -D latex_paper_size=letter | ||
34 | KERNELDOC = $(srctree)/scripts/kernel-doc | ||
35 | KERNELDOC_CONF = -D kerneldoc_srctree=$(srctree) -D kerneldoc_bin=$(KERNELDOC) | ||
36 | ALLSPHINXOPTS = -D version=$(KERNELVERSION) -D release=$(KERNELRELEASE) -d $(BUILDDIR)/.doctrees $(KERNELDOC_CONF) $(PAPEROPT_$(PAPER)) -c $(srctree)/$(src) $(SPHINXOPTS) $(srctree)/$(src) | ||
37 | # the i18n builder cannot share the environment and doctrees with the others | ||
38 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . | ||
39 | |||
40 | quiet_cmd_sphinx = SPHINX $@ | ||
41 | cmd_sphinx = $(SPHINXBUILD) -b $2 $(ALLSPHINXOPTS) $(BUILDDIR)/$2 | ||
42 | |||
43 | htmldocs: | ||
44 | $(call cmd,sphinx,html) | ||
45 | |||
46 | pdfdocs: | ||
47 | ifeq ($(HAVE_RST2PDF),0) | ||
48 | $(warning The Python 'rst2pdf' module was not found. Make sure you have the module installed to produce PDF output.) | ||
49 | @echo " SKIP Sphinx $@ target." | ||
50 | else # HAVE_RST2PDF | ||
51 | $(call cmd,sphinx,pdf) | ||
52 | endif # HAVE_RST2PDF | ||
53 | |||
54 | epubdocs: | ||
55 | $(call cmd,sphinx,epub) | ||
56 | |||
57 | xmldocs: | ||
58 | $(call cmd,sphinx,xml) | ||
59 | |||
60 | # no-ops for the Sphinx toolchain | ||
61 | sgmldocs: | ||
62 | psdocs: | ||
63 | mandocs: | ||
64 | installmandocs: | ||
65 | cleanmediadocs: | ||
66 | |||
67 | cleandocs: | ||
68 | $(Q)rm -rf $(BUILDDIR) | ||
69 | |||
70 | dochelp: | ||
71 | @echo ' Linux kernel internal documentation in different formats (Sphinx):' | ||
72 | @echo ' htmldocs - HTML' | ||
73 | @echo ' pdfdocs - PDF' | ||
74 | @echo ' epubdocs - EPUB' | ||
75 | @echo ' xmldocs - XML' | ||
76 | @echo ' cleandocs - clean all generated files' | ||
77 | |||
78 | endif # HAVE_SPHINX | ||
diff --git a/Documentation/bcache.txt b/Documentation/bcache.txt index 32b6c3189d98..a9259b562d5c 100644 --- a/Documentation/bcache.txt +++ b/Documentation/bcache.txt | |||
@@ -1,4 +1,4 @@ | |||
1 | Say you've got a big slow raid 6, and an X-25E or three. Wouldn't it be | 1 | Say you've got a big slow raid 6, and an ssd or three. Wouldn't it be |
2 | nice if you could use them as cache... Hence bcache. | 2 | nice if you could use them as cache... Hence bcache. |
3 | 3 | ||
4 | Wiki and git repositories are at: | 4 | Wiki and git repositories are at: |
@@ -8,7 +8,7 @@ Wiki and git repositories are at: | |||
8 | 8 | ||
9 | It's designed around the performance characteristics of SSDs - it only allocates | 9 | It's designed around the performance characteristics of SSDs - it only allocates |
10 | in erase block sized buckets, and it uses a hybrid btree/log to track cached | 10 | in erase block sized buckets, and it uses a hybrid btree/log to track cached |
11 | extants (which can be anywhere from a single sector to the bucket size). It's | 11 | extents (which can be anywhere from a single sector to the bucket size). It's |
12 | designed to avoid random writes at all costs; it fills up an erase block | 12 | designed to avoid random writes at all costs; it fills up an erase block |
13 | sequentially, then issues a discard before reusing it. | 13 | sequentially, then issues a discard before reusing it. |
14 | 14 | ||
@@ -55,7 +55,10 @@ immediately. Without udev, you can manually register devices like this: | |||
55 | Registering the backing device makes the bcache device show up in /dev; you can | 55 | Registering the backing device makes the bcache device show up in /dev; you can |
56 | now format it and use it as normal. But the first time using a new bcache | 56 | now format it and use it as normal. But the first time using a new bcache |
57 | device, it'll be running in passthrough mode until you attach it to a cache. | 57 | device, it'll be running in passthrough mode until you attach it to a cache. |
58 | See the section on attaching. | 58 | If you are thinking about using bcache later, it is recommended to setup all your |
59 | slow devices as bcache backing devices without a cache, and you can choose to add | ||
60 | a caching device later. | ||
61 | See 'ATTACHING' section below. | ||
59 | 62 | ||
60 | The devices show up as: | 63 | The devices show up as: |
61 | 64 | ||
@@ -72,12 +75,14 @@ To get started: | |||
72 | mount /dev/bcache0 /mnt | 75 | mount /dev/bcache0 /mnt |
73 | 76 | ||
74 | You can control bcache devices through sysfs at /sys/block/bcache<N>/bcache . | 77 | You can control bcache devices through sysfs at /sys/block/bcache<N>/bcache . |
78 | You can also control them through /sys/fs//bcache/<cset-uuid>/ . | ||
75 | 79 | ||
76 | Cache devices are managed as sets; multiple caches per set isn't supported yet | 80 | Cache devices are managed as sets; multiple caches per set isn't supported yet |
77 | but will allow for mirroring of metadata and dirty data in the future. Your new | 81 | but will allow for mirroring of metadata and dirty data in the future. Your new |
78 | cache set shows up as /sys/fs/bcache/<UUID> | 82 | cache set shows up as /sys/fs/bcache/<UUID> |
79 | 83 | ||
80 | ATTACHING: | 84 | ATTACHING |
85 | --------- | ||
81 | 86 | ||
82 | After your cache device and backing device are registered, the backing device | 87 | After your cache device and backing device are registered, the backing device |
83 | must be attached to your cache set to enable caching. Attaching a backing | 88 | must be attached to your cache set to enable caching. Attaching a backing |
@@ -105,7 +110,8 @@ but all the cached data will be invalidated. If there was dirty data in the | |||
105 | cache, don't expect the filesystem to be recoverable - you will have massive | 110 | cache, don't expect the filesystem to be recoverable - you will have massive |
106 | filesystem corruption, though ext4's fsck does work miracles. | 111 | filesystem corruption, though ext4's fsck does work miracles. |
107 | 112 | ||
108 | ERROR HANDLING: | 113 | ERROR HANDLING |
114 | -------------- | ||
109 | 115 | ||
110 | Bcache tries to transparently handle IO errors to/from the cache device without | 116 | Bcache tries to transparently handle IO errors to/from the cache device without |
111 | affecting normal operation; if it sees too many errors (the threshold is | 117 | affecting normal operation; if it sees too many errors (the threshold is |
@@ -127,12 +133,181 @@ the backing devices to passthrough mode. | |||
127 | writeback mode). It currently doesn't do anything intelligent if it fails to | 133 | writeback mode). It currently doesn't do anything intelligent if it fails to |
128 | read some of the dirty data, though. | 134 | read some of the dirty data, though. |
129 | 135 | ||
130 | TROUBLESHOOTING PERFORMANCE: | 136 | |
137 | HOWTO/COOKBOOK | ||
138 | -------------- | ||
139 | |||
140 | A) Starting a bcache with a missing caching device | ||
141 | |||
142 | If registering the backing device doesn't help, it's already there, you just need | ||
143 | to force it to run without the cache: | ||
144 | host:~# echo /dev/sdb1 > /sys/fs/bcache/register | ||
145 | [ 119.844831] bcache: register_bcache() error opening /dev/sdb1: device already registered | ||
146 | |||
147 | Next, you try to register your caching device if it's present. However | ||
148 | if it's absent, or registration fails for some reason, you can still | ||
149 | start your bcache without its cache, like so: | ||
150 | host:/sys/block/sdb/sdb1/bcache# echo 1 > running | ||
151 | |||
152 | Note that this may cause data loss if you were running in writeback mode. | ||
153 | |||
154 | |||
155 | B) Bcache does not find its cache | ||
156 | |||
157 | host:/sys/block/md5/bcache# echo 0226553a-37cf-41d5-b3ce-8b1e944543a8 > attach | ||
158 | [ 1933.455082] bcache: bch_cached_dev_attach() Couldn't find uuid for md5 in set | ||
159 | [ 1933.478179] bcache: __cached_dev_store() Can't attach 0226553a-37cf-41d5-b3ce-8b1e944543a8 | ||
160 | [ 1933.478179] : cache set not found | ||
161 | |||
162 | In this case, the caching device was simply not registered at boot | ||
163 | or disappeared and came back, and needs to be (re-)registered: | ||
164 | host:/sys/block/md5/bcache# echo /dev/sdh2 > /sys/fs/bcache/register | ||
165 | |||
166 | |||
167 | C) Corrupt bcache crashes the kernel at device registration time: | ||
168 | |||
169 | This should never happen. If it does happen, then you have found a bug! | ||
170 | Please report it to the bcache development list: linux-bcache@vger.kernel.org | ||
171 | |||
172 | Be sure to provide as much information that you can including kernel dmesg | ||
173 | output if available so that we may assist. | ||
174 | |||
175 | |||
176 | D) Recovering data without bcache: | ||
177 | |||
178 | If bcache is not available in the kernel, a filesystem on the backing | ||
179 | device is still available at an 8KiB offset. So either via a loopdev | ||
180 | of the backing device created with --offset 8K, or any value defined by | ||
181 | --data-offset when you originally formatted bcache with `make-bcache`. | ||
182 | |||
183 | For example: | ||
184 | losetup -o 8192 /dev/loop0 /dev/your_bcache_backing_dev | ||
185 | |||
186 | This should present your unmodified backing device data in /dev/loop0 | ||
187 | |||
188 | If your cache is in writethrough mode, then you can safely discard the | ||
189 | cache device without loosing data. | ||
190 | |||
191 | |||
192 | E) Wiping a cache device | ||
193 | |||
194 | host:~# wipefs -a /dev/sdh2 | ||
195 | 16 bytes were erased at offset 0x1018 (bcache) | ||
196 | they were: c6 85 73 f6 4e 1a 45 ca 82 65 f5 7f 48 ba 6d 81 | ||
197 | |||
198 | After you boot back with bcache enabled, you recreate the cache and attach it: | ||
199 | host:~# make-bcache -C /dev/sdh2 | ||
200 | UUID: 7be7e175-8f4c-4f99-94b2-9c904d227045 | ||
201 | Set UUID: 5bc072a8-ab17-446d-9744-e247949913c1 | ||
202 | version: 0 | ||
203 | nbuckets: 106874 | ||
204 | block_size: 1 | ||
205 | bucket_size: 1024 | ||
206 | nr_in_set: 1 | ||
207 | nr_this_dev: 0 | ||
208 | first_bucket: 1 | ||
209 | [ 650.511912] bcache: run_cache_set() invalidating existing data | ||
210 | [ 650.549228] bcache: register_cache() registered cache device sdh2 | ||
211 | |||
212 | start backing device with missing cache: | ||
213 | host:/sys/block/md5/bcache# echo 1 > running | ||
214 | |||
215 | attach new cache: | ||
216 | host:/sys/block/md5/bcache# echo 5bc072a8-ab17-446d-9744-e247949913c1 > attach | ||
217 | [ 865.276616] bcache: bch_cached_dev_attach() Caching md5 as bcache0 on set 5bc072a8-ab17-446d-9744-e247949913c1 | ||
218 | |||
219 | |||
220 | F) Remove or replace a caching device | ||
221 | |||
222 | host:/sys/block/sda/sda7/bcache# echo 1 > detach | ||
223 | [ 695.872542] bcache: cached_dev_detach_finish() Caching disabled for sda7 | ||
224 | |||
225 | host:~# wipefs -a /dev/nvme0n1p4 | ||
226 | wipefs: error: /dev/nvme0n1p4: probing initialization failed: Device or resource busy | ||
227 | Ooops, it's disabled, but not unregistered, so it's still protected | ||
228 | |||
229 | We need to go and unregister it: | ||
230 | host:/sys/fs/bcache/b7ba27a1-2398-4649-8ae3-0959f57ba128# ls -l cache0 | ||
231 | lrwxrwxrwx 1 root root 0 Feb 25 18:33 cache0 -> ../../../devices/pci0000:00/0000:00:1d.0/0000:70:00.0/nvme/nvme0/nvme0n1/nvme0n1p4/bcache/ | ||
232 | host:/sys/fs/bcache/b7ba27a1-2398-4649-8ae3-0959f57ba128# echo 1 > stop | ||
233 | kernel: [ 917.041908] bcache: cache_set_free() Cache set b7ba27a1-2398-4649-8ae3-0959f57ba128 unregistered | ||
234 | |||
235 | Now we can wipe it: | ||
236 | host:~# wipefs -a /dev/nvme0n1p4 | ||
237 | /dev/nvme0n1p4: 16 bytes were erased at offset 0x00001018 (bcache): c6 85 73 f6 4e 1a 45 ca 82 65 f5 7f 48 ba 6d 81 | ||
238 | |||
239 | |||
240 | G) dm-crypt and bcache | ||
241 | |||
242 | First setup bcache unencrypted and then install dmcrypt on top of | ||
243 | /dev/bcache<N> This will work faster than if you dmcrypt both the backing | ||
244 | and caching devices and then install bcache on top. [benchmarks?] | ||
245 | |||
246 | |||
247 | H) Stop/free a registered bcache to wipe and/or recreate it | ||
248 | |||
249 | Suppose that you need to free up all bcache references so that you can | ||
250 | fdisk run and re-register a changed partition table, which won't work | ||
251 | if there are any active backing or caching devices left on it: | ||
252 | |||
253 | 1) Is it present in /dev/bcache* ? (there are times where it won't be) | ||
254 | |||
255 | If so, it's easy: | ||
256 | host:/sys/block/bcache0/bcache# echo 1 > stop | ||
257 | |||
258 | 2) But if your backing device is gone, this won't work: | ||
259 | host:/sys/block/bcache0# cd bcache | ||
260 | bash: cd: bcache: No such file or directory | ||
261 | |||
262 | In this case, you may have to unregister the dmcrypt block device that | ||
263 | references this bcache to free it up: | ||
264 | host:~# dmsetup remove oldds1 | ||
265 | bcache: bcache_device_free() bcache0 stopped | ||
266 | bcache: cache_set_free() Cache set 5bc072a8-ab17-446d-9744-e247949913c1 unregistered | ||
267 | |||
268 | This causes the backing bcache to be removed from /sys/fs/bcache and | ||
269 | then it can be reused. This would be true of any block device stacking | ||
270 | where bcache is a lower device. | ||
271 | |||
272 | 3) In other cases, you can also look in /sys/fs/bcache/: | ||
273 | |||
274 | host:/sys/fs/bcache# ls -l */{cache?,bdev?} | ||
275 | lrwxrwxrwx 1 root root 0 Mar 5 09:39 0226553a-37cf-41d5-b3ce-8b1e944543a8/bdev1 -> ../../../devices/virtual/block/dm-1/bcache/ | ||
276 | lrwxrwxrwx 1 root root 0 Mar 5 09:39 0226553a-37cf-41d5-b3ce-8b1e944543a8/cache0 -> ../../../devices/virtual/block/dm-4/bcache/ | ||
277 | lrwxrwxrwx 1 root root 0 Mar 5 09:39 5bc072a8-ab17-446d-9744-e247949913c1/cache0 -> ../../../devices/pci0000:00/0000:00:01.0/0000:01:00.0/ata10/host9/target9:0:0/9:0:0:0/block/sdl/sdl2/bcache/ | ||
278 | |||
279 | The device names will show which UUID is relevant, cd in that directory | ||
280 | and stop the cache: | ||
281 | host:/sys/fs/bcache/5bc072a8-ab17-446d-9744-e247949913c1# echo 1 > stop | ||
282 | |||
283 | This will free up bcache references and let you reuse the partition for | ||
284 | other purposes. | ||
285 | |||
286 | |||
287 | |||
288 | TROUBLESHOOTING PERFORMANCE | ||
289 | --------------------------- | ||
131 | 290 | ||
132 | Bcache has a bunch of config options and tunables. The defaults are intended to | 291 | Bcache has a bunch of config options and tunables. The defaults are intended to |
133 | be reasonable for typical desktop and server workloads, but they're not what you | 292 | be reasonable for typical desktop and server workloads, but they're not what you |
134 | want for getting the best possible numbers when benchmarking. | 293 | want for getting the best possible numbers when benchmarking. |
135 | 294 | ||
295 | - Backing device alignment | ||
296 | |||
297 | The default metadata size in bcache is 8k. If your backing device is | ||
298 | RAID based, then be sure to align this by a multiple of your stride | ||
299 | width using `make-bcache --data-offset`. If you intend to expand your | ||
300 | disk array in the future, then multiply a series of primes by your | ||
301 | raid stripe size to get the disk multiples that you would like. | ||
302 | |||
303 | For example: If you have a 64k stripe size, then the following offset | ||
304 | would provide alignment for many common RAID5 data spindle counts: | ||
305 | 64k * 2*2*2*3*3*5*7 bytes = 161280k | ||
306 | |||
307 | That space is wasted, but for only 157.5MB you can grow your RAID 5 | ||
308 | volume to the following data-spindle counts without re-aligning: | ||
309 | 3,4,5,6,7,8,9,10,12,14,15,18,20,21 ... | ||
310 | |||
136 | - Bad write performance | 311 | - Bad write performance |
137 | 312 | ||
138 | If write performance is not what you expected, you probably wanted to be | 313 | If write performance is not what you expected, you probably wanted to be |
@@ -140,7 +315,7 @@ want for getting the best possible numbers when benchmarking. | |||
140 | maturity, but simply because in writeback mode you'll lose data if something | 315 | maturity, but simply because in writeback mode you'll lose data if something |
141 | happens to your SSD) | 316 | happens to your SSD) |
142 | 317 | ||
143 | # echo writeback > /sys/block/bcache0/cache_mode | 318 | # echo writeback > /sys/block/bcache0/bcache/cache_mode |
144 | 319 | ||
145 | - Bad performance, or traffic not going to the SSD that you'd expect | 320 | - Bad performance, or traffic not going to the SSD that you'd expect |
146 | 321 | ||
@@ -193,7 +368,9 @@ want for getting the best possible numbers when benchmarking. | |||
193 | Solution: warm the cache by doing writes, or use the testing branch (there's | 368 | Solution: warm the cache by doing writes, or use the testing branch (there's |
194 | a fix for the issue there). | 369 | a fix for the issue there). |
195 | 370 | ||
196 | SYSFS - BACKING DEVICE: | 371 | |
372 | SYSFS - BACKING DEVICE | ||
373 | ---------------------- | ||
197 | 374 | ||
198 | Available at /sys/block/<bdev>/bcache, /sys/block/bcache*/bcache and | 375 | Available at /sys/block/<bdev>/bcache, /sys/block/bcache*/bcache and |
199 | (if attached) /sys/fs/bcache/<cset-uuid>/bdev* | 376 | (if attached) /sys/fs/bcache/<cset-uuid>/bdev* |
@@ -238,7 +415,7 @@ sequential_merge | |||
238 | against all new requests to determine which new requests are sequential | 415 | against all new requests to determine which new requests are sequential |
239 | continuations of previous requests for the purpose of determining sequential | 416 | continuations of previous requests for the purpose of determining sequential |
240 | cutoff. This is necessary if the sequential cutoff value is greater than the | 417 | cutoff. This is necessary if the sequential cutoff value is greater than the |
241 | maximum acceptable sequential size for any single request. | 418 | maximum acceptable sequential size for any single request. |
242 | 419 | ||
243 | state | 420 | state |
244 | The backing device can be in one of four different states: | 421 | The backing device can be in one of four different states: |
@@ -325,7 +502,7 @@ bucket_size | |||
325 | Size of buckets | 502 | Size of buckets |
326 | 503 | ||
327 | cache<0..n> | 504 | cache<0..n> |
328 | Symlink to each of the cache devices comprising this cache set. | 505 | Symlink to each of the cache devices comprising this cache set. |
329 | 506 | ||
330 | cache_available_percent | 507 | cache_available_percent |
331 | Percentage of cache device which doesn't contain dirty data, and could | 508 | Percentage of cache device which doesn't contain dirty data, and could |
diff --git a/Documentation/conf.py b/Documentation/conf.py new file mode 100644 index 000000000000..792b6338ef19 --- /dev/null +++ b/Documentation/conf.py | |||
@@ -0,0 +1,414 @@ | |||
1 | # -*- coding: utf-8 -*- | ||
2 | # | ||
3 | # The Linux Kernel documentation build configuration file, created by | ||
4 | # sphinx-quickstart on Fri Feb 12 13:51:46 2016. | ||
5 | # | ||
6 | # This file is execfile()d with the current directory set to its | ||
7 | # containing dir. | ||
8 | # | ||
9 | # Note that not all possible configuration values are present in this | ||
10 | # autogenerated file. | ||
11 | # | ||
12 | # All configuration values have a default; values that are commented out | ||
13 | # serve to show the default. | ||
14 | |||
15 | import sys | ||
16 | import os | ||
17 | |||
18 | # If extensions (or modules to document with autodoc) are in another directory, | ||
19 | # add these directories to sys.path here. If the directory is relative to the | ||
20 | # documentation root, use os.path.abspath to make it absolute, like shown here. | ||
21 | sys.path.insert(0, os.path.abspath('sphinx')) | ||
22 | |||
23 | # -- General configuration ------------------------------------------------ | ||
24 | |||
25 | # If your documentation needs a minimal Sphinx version, state it here. | ||
26 | #needs_sphinx = '1.0' | ||
27 | |||
28 | # Add any Sphinx extension module names here, as strings. They can be | ||
29 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom | ||
30 | # ones. | ||
31 | extensions = ['kernel-doc', 'rstFlatTable'] | ||
32 | |||
33 | # Gracefully handle missing rst2pdf. | ||
34 | try: | ||
35 | import rst2pdf | ||
36 | extensions += ['rst2pdf.pdfbuilder'] | ||
37 | except ImportError: | ||
38 | pass | ||
39 | |||
40 | # Add any paths that contain templates here, relative to this directory. | ||
41 | templates_path = ['_templates'] | ||
42 | |||
43 | # The suffix(es) of source filenames. | ||
44 | # You can specify multiple suffix as a list of string: | ||
45 | # source_suffix = ['.rst', '.md'] | ||
46 | source_suffix = '.rst' | ||
47 | |||
48 | # The encoding of source files. | ||
49 | #source_encoding = 'utf-8-sig' | ||
50 | |||
51 | # The master toctree document. | ||
52 | master_doc = 'index' | ||
53 | |||
54 | # General information about the project. | ||
55 | project = 'The Linux Kernel' | ||
56 | copyright = '2016, The kernel development community' | ||
57 | author = 'The kernel development community' | ||
58 | |||
59 | # The version info for the project you're documenting, acts as replacement for | ||
60 | # |version| and |release|, also used in various other places throughout the | ||
61 | # built documents. | ||
62 | # | ||
63 | # In a normal build, version and release are are set to KERNELVERSION and | ||
64 | # KERNELRELEASE, respectively, from the Makefile via Sphinx command line | ||
65 | # arguments. | ||
66 | # | ||
67 | # The following code tries to extract the information by reading the Makefile, | ||
68 | # when Sphinx is run directly (e.g. by Read the Docs). | ||
69 | try: | ||
70 | makefile_version = None | ||
71 | makefile_patchlevel = None | ||
72 | for line in open('../Makefile'): | ||
73 | key, val = [x.strip() for x in line.split('=', 2)] | ||
74 | if key == 'VERSION': | ||
75 | makefile_version = val | ||
76 | elif key == 'PATCHLEVEL': | ||
77 | makefile_patchlevel = val | ||
78 | if makefile_version and makefile_patchlevel: | ||
79 | break | ||
80 | except: | ||
81 | pass | ||
82 | finally: | ||
83 | if makefile_version and makefile_patchlevel: | ||
84 | version = release = makefile_version + '.' + makefile_patchlevel | ||
85 | else: | ||
86 | sys.stderr.write('Warning: Could not extract kernel version\n') | ||
87 | version = release = "unknown version" | ||
88 | |||
89 | # The language for content autogenerated by Sphinx. Refer to documentation | ||
90 | # for a list of supported languages. | ||
91 | # | ||
92 | # This is also used if you do content translation via gettext catalogs. | ||
93 | # Usually you set "language" from the command line for these cases. | ||
94 | language = None | ||
95 | |||
96 | # There are two options for replacing |today|: either, you set today to some | ||
97 | # non-false value, then it is used: | ||
98 | #today = '' | ||
99 | # Else, today_fmt is used as the format for a strftime call. | ||
100 | #today_fmt = '%B %d, %Y' | ||
101 | |||
102 | # List of patterns, relative to source directory, that match files and | ||
103 | # directories to ignore when looking for source files. | ||
104 | exclude_patterns = ['output'] | ||
105 | |||
106 | # The reST default role (used for this markup: `text`) to use for all | ||
107 | # documents. | ||
108 | #default_role = None | ||
109 | |||
110 | # If true, '()' will be appended to :func: etc. cross-reference text. | ||
111 | #add_function_parentheses = True | ||
112 | |||
113 | # If true, the current module name will be prepended to all description | ||
114 | # unit titles (such as .. function::). | ||
115 | #add_module_names = True | ||
116 | |||
117 | # If true, sectionauthor and moduleauthor directives will be shown in the | ||
118 | # output. They are ignored by default. | ||
119 | #show_authors = False | ||
120 | |||
121 | # The name of the Pygments (syntax highlighting) style to use. | ||
122 | pygments_style = 'sphinx' | ||
123 | |||
124 | # A list of ignored prefixes for module index sorting. | ||
125 | #modindex_common_prefix = [] | ||
126 | |||
127 | # If true, keep warnings as "system message" paragraphs in the built documents. | ||
128 | #keep_warnings = False | ||
129 | |||
130 | # If true, `todo` and `todoList` produce output, else they produce nothing. | ||
131 | todo_include_todos = False | ||
132 | |||
133 | primary_domain = 'C' | ||
134 | highlight_language = 'C' | ||
135 | |||
136 | # -- Options for HTML output ---------------------------------------------- | ||
137 | |||
138 | # The theme to use for HTML and HTML Help pages. See the documentation for | ||
139 | # a list of builtin themes. | ||
140 | |||
141 | # The Read the Docs theme is available from | ||
142 | # - https://github.com/snide/sphinx_rtd_theme | ||
143 | # - https://pypi.python.org/pypi/sphinx_rtd_theme | ||
144 | # - python-sphinx-rtd-theme package (on Debian) | ||
145 | try: | ||
146 | import sphinx_rtd_theme | ||
147 | html_theme = 'sphinx_rtd_theme' | ||
148 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] | ||
149 | except ImportError: | ||
150 | sys.stderr.write('Warning: The Sphinx \'sphinx_rtd_theme\' HTML theme was not found. Make sure you have the theme installed to produce pretty HTML output. Falling back to the default theme.\n') | ||
151 | |||
152 | # Theme options are theme-specific and customize the look and feel of a theme | ||
153 | # further. For a list of options available for each theme, see the | ||
154 | # documentation. | ||
155 | #html_theme_options = {} | ||
156 | |||
157 | # Add any paths that contain custom themes here, relative to this directory. | ||
158 | #html_theme_path = [] | ||
159 | |||
160 | # The name for this set of Sphinx documents. If None, it defaults to | ||
161 | # "<project> v<release> documentation". | ||
162 | #html_title = None | ||
163 | |||
164 | # A shorter title for the navigation bar. Default is the same as html_title. | ||
165 | #html_short_title = None | ||
166 | |||
167 | # The name of an image file (relative to this directory) to place at the top | ||
168 | # of the sidebar. | ||
169 | #html_logo = None | ||
170 | |||
171 | # The name of an image file (within the static path) to use as favicon of the | ||
172 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 | ||
173 | # pixels large. | ||
174 | #html_favicon = None | ||
175 | |||
176 | # Add any paths that contain custom static files (such as style sheets) here, | ||
177 | # relative to this directory. They are copied after the builtin static files, | ||
178 | # so a file named "default.css" will overwrite the builtin "default.css". | ||
179 | #html_static_path = ['_static'] | ||
180 | |||
181 | # Add any extra paths that contain custom files (such as robots.txt or | ||
182 | # .htaccess) here, relative to this directory. These files are copied | ||
183 | # directly to the root of the documentation. | ||
184 | #html_extra_path = [] | ||
185 | |||
186 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, | ||
187 | # using the given strftime format. | ||
188 | #html_last_updated_fmt = '%b %d, %Y' | ||
189 | |||
190 | # If true, SmartyPants will be used to convert quotes and dashes to | ||
191 | # typographically correct entities. | ||
192 | #html_use_smartypants = True | ||
193 | |||
194 | # Custom sidebar templates, maps document names to template names. | ||
195 | #html_sidebars = {} | ||
196 | |||
197 | # Additional templates that should be rendered to pages, maps page names to | ||
198 | # template names. | ||
199 | #html_additional_pages = {} | ||
200 | |||
201 | # If false, no module index is generated. | ||
202 | #html_domain_indices = True | ||
203 | |||
204 | # If false, no index is generated. | ||
205 | #html_use_index = True | ||
206 | |||
207 | # If true, the index is split into individual pages for each letter. | ||
208 | #html_split_index = False | ||
209 | |||
210 | # If true, links to the reST sources are added to the pages. | ||
211 | #html_show_sourcelink = True | ||
212 | |||
213 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. | ||
214 | #html_show_sphinx = True | ||
215 | |||
216 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. | ||
217 | #html_show_copyright = True | ||
218 | |||
219 | # If true, an OpenSearch description file will be output, and all pages will | ||
220 | # contain a <link> tag referring to it. The value of this option must be the | ||
221 | # base URL from which the finished HTML is served. | ||
222 | #html_use_opensearch = '' | ||
223 | |||
224 | # This is the file name suffix for HTML files (e.g. ".xhtml"). | ||
225 | #html_file_suffix = None | ||
226 | |||
227 | # Language to be used for generating the HTML full-text search index. | ||
228 | # Sphinx supports the following languages: | ||
229 | # 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja' | ||
230 | # 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr' | ||
231 | #html_search_language = 'en' | ||
232 | |||
233 | # A dictionary with options for the search language support, empty by default. | ||
234 | # Now only 'ja' uses this config value | ||
235 | #html_search_options = {'type': 'default'} | ||
236 | |||
237 | # The name of a javascript file (relative to the configuration directory) that | ||
238 | # implements a search results scorer. If empty, the default will be used. | ||
239 | #html_search_scorer = 'scorer.js' | ||
240 | |||
241 | # Output file base name for HTML help builder. | ||
242 | htmlhelp_basename = 'TheLinuxKerneldoc' | ||
243 | |||
244 | # -- Options for LaTeX output --------------------------------------------- | ||
245 | |||
246 | latex_elements = { | ||
247 | # The paper size ('letterpaper' or 'a4paper'). | ||
248 | #'papersize': 'letterpaper', | ||
249 | |||
250 | # The font size ('10pt', '11pt' or '12pt'). | ||
251 | #'pointsize': '10pt', | ||
252 | |||
253 | # Additional stuff for the LaTeX preamble. | ||
254 | #'preamble': '', | ||
255 | |||
256 | # Latex figure (float) alignment | ||
257 | #'figure_align': 'htbp', | ||
258 | } | ||
259 | |||
260 | # Grouping the document tree into LaTeX files. List of tuples | ||
261 | # (source start file, target name, title, | ||
262 | # author, documentclass [howto, manual, or own class]). | ||
263 | latex_documents = [ | ||
264 | (master_doc, 'TheLinuxKernel.tex', 'The Linux Kernel Documentation', | ||
265 | 'The kernel development community', 'manual'), | ||
266 | ] | ||
267 | |||
268 | # The name of an image file (relative to this directory) to place at the top of | ||
269 | # the title page. | ||
270 | #latex_logo = None | ||
271 | |||
272 | # For "manual" documents, if this is true, then toplevel headings are parts, | ||
273 | # not chapters. | ||
274 | #latex_use_parts = False | ||
275 | |||
276 | # If true, show page references after internal links. | ||
277 | #latex_show_pagerefs = False | ||
278 | |||
279 | # If true, show URL addresses after external links. | ||
280 | #latex_show_urls = False | ||
281 | |||
282 | # Documents to append as an appendix to all manuals. | ||
283 | #latex_appendices = [] | ||
284 | |||
285 | # If false, no module index is generated. | ||
286 | #latex_domain_indices = True | ||
287 | |||
288 | |||
289 | # -- Options for manual page output --------------------------------------- | ||
290 | |||
291 | # One entry per manual page. List of tuples | ||
292 | # (source start file, name, description, authors, manual section). | ||
293 | man_pages = [ | ||
294 | (master_doc, 'thelinuxkernel', 'The Linux Kernel Documentation', | ||
295 | [author], 1) | ||
296 | ] | ||
297 | |||
298 | # If true, show URL addresses after external links. | ||
299 | #man_show_urls = False | ||
300 | |||
301 | |||
302 | # -- Options for Texinfo output ------------------------------------------- | ||
303 | |||
304 | # Grouping the document tree into Texinfo files. List of tuples | ||
305 | # (source start file, target name, title, author, | ||
306 | # dir menu entry, description, category) | ||
307 | texinfo_documents = [ | ||
308 | (master_doc, 'TheLinuxKernel', 'The Linux Kernel Documentation', | ||
309 | author, 'TheLinuxKernel', 'One line description of project.', | ||
310 | 'Miscellaneous'), | ||
311 | ] | ||
312 | |||
313 | # Documents to append as an appendix to all manuals. | ||
314 | #texinfo_appendices = [] | ||
315 | |||
316 | # If false, no module index is generated. | ||
317 | #texinfo_domain_indices = True | ||
318 | |||
319 | # How to display URL addresses: 'footnote', 'no', or 'inline'. | ||
320 | #texinfo_show_urls = 'footnote' | ||
321 | |||
322 | # If true, do not generate a @detailmenu in the "Top" node's menu. | ||
323 | #texinfo_no_detailmenu = False | ||
324 | |||
325 | |||
326 | # -- Options for Epub output ---------------------------------------------- | ||
327 | |||
328 | # Bibliographic Dublin Core info. | ||
329 | epub_title = project | ||
330 | epub_author = author | ||
331 | epub_publisher = author | ||
332 | epub_copyright = copyright | ||
333 | |||
334 | # The basename for the epub file. It defaults to the project name. | ||
335 | #epub_basename = project | ||
336 | |||
337 | # The HTML theme for the epub output. Since the default themes are not | ||
338 | # optimized for small screen space, using the same theme for HTML and epub | ||
339 | # output is usually not wise. This defaults to 'epub', a theme designed to save | ||
340 | # visual space. | ||
341 | #epub_theme = 'epub' | ||
342 | |||
343 | # The language of the text. It defaults to the language option | ||
344 | # or 'en' if the language is not set. | ||
345 | #epub_language = '' | ||
346 | |||
347 | # The scheme of the identifier. Typical schemes are ISBN or URL. | ||
348 | #epub_scheme = '' | ||
349 | |||
350 | # The unique identifier of the text. This can be a ISBN number | ||
351 | # or the project homepage. | ||
352 | #epub_identifier = '' | ||
353 | |||
354 | # A unique identification for the text. | ||
355 | #epub_uid = '' | ||
356 | |||
357 | # A tuple containing the cover image and cover page html template filenames. | ||
358 | #epub_cover = () | ||
359 | |||
360 | # A sequence of (type, uri, title) tuples for the guide element of content.opf. | ||
361 | #epub_guide = () | ||
362 | |||
363 | # HTML files that should be inserted before the pages created by sphinx. | ||
364 | # The format is a list of tuples containing the path and title. | ||
365 | #epub_pre_files = [] | ||
366 | |||
367 | # HTML files that should be inserted after the pages created by sphinx. | ||
368 | # The format is a list of tuples containing the path and title. | ||
369 | #epub_post_files = [] | ||
370 | |||
371 | # A list of files that should not be packed into the epub file. | ||
372 | epub_exclude_files = ['search.html'] | ||
373 | |||
374 | # The depth of the table of contents in toc.ncx. | ||
375 | #epub_tocdepth = 3 | ||
376 | |||
377 | # Allow duplicate toc entries. | ||
378 | #epub_tocdup = True | ||
379 | |||
380 | # Choose between 'default' and 'includehidden'. | ||
381 | #epub_tocscope = 'default' | ||
382 | |||
383 | # Fix unsupported image types using the Pillow. | ||
384 | #epub_fix_images = False | ||
385 | |||
386 | # Scale large images. | ||
387 | #epub_max_image_width = 0 | ||
388 | |||
389 | # How to display URL addresses: 'footnote', 'no', or 'inline'. | ||
390 | #epub_show_urls = 'inline' | ||
391 | |||
392 | # If false, no index is generated. | ||
393 | #epub_use_index = True | ||
394 | |||
395 | #======= | ||
396 | # rst2pdf | ||
397 | # | ||
398 | # Grouping the document tree into PDF files. List of tuples | ||
399 | # (source start file, target name, title, author, options). | ||
400 | # | ||
401 | # See the Sphinx chapter of http://ralsina.me/static/manual.pdf | ||
402 | # | ||
403 | # FIXME: Do not add the index file here; the result will be too big. Adding | ||
404 | # multiple PDF files here actually tries to get the cross-referencing right | ||
405 | # *between* PDF files. | ||
406 | pdf_documents = [ | ||
407 | ('index', u'Kernel', u'Kernel', u'J. Random Bozo'), | ||
408 | ] | ||
409 | |||
410 | # kernel-doc extension configuration for running Sphinx directly (e.g. by Read | ||
411 | # the Docs). In a normal build, these are supplied from the Makefile via command | ||
412 | # line arguments. | ||
413 | kerneldoc_bin = '../scripts/kernel-doc' | ||
414 | kerneldoc_srctree = '..' | ||
diff --git a/Documentation/development-process/4.Coding b/Documentation/development-process/4.Coding index e3cb6a56653a..9a3ee77cefb1 100644 --- a/Documentation/development-process/4.Coding +++ b/Documentation/development-process/4.Coding | |||
@@ -346,7 +346,7 @@ which have not been so documented, there is no harm in adding kerneldoc | |||
346 | comments for the future; indeed, this can be a useful activity for | 346 | comments for the future; indeed, this can be a useful activity for |
347 | beginning kernel developers. The format of these comments, along with some | 347 | beginning kernel developers. The format of these comments, along with some |
348 | information on how to create kerneldoc templates can be found in the file | 348 | information on how to create kerneldoc templates can be found in the file |
349 | Documentation/kernel-doc-nano-HOWTO.txt. | 349 | Documentation/kernel-documentation.rst. |
350 | 350 | ||
351 | Anybody who reads through a significant amount of existing kernel code will | 351 | Anybody who reads through a significant amount of existing kernel code will |
352 | note that, often, comments are most notable by their absence. Once again, | 352 | note that, often, comments are most notable by their absence. Once again, |
diff --git a/Documentation/dmaengine/provider.txt b/Documentation/dmaengine/provider.txt index 122b7f4876bb..91ce82d5f0c4 100644 --- a/Documentation/dmaengine/provider.txt +++ b/Documentation/dmaengine/provider.txt | |||
@@ -323,7 +323,7 @@ supported. | |||
323 | * device_resume | 323 | * device_resume |
324 | - Resumes a transfer on the channel | 324 | - Resumes a transfer on the channel |
325 | - This command should operate synchronously on the channel, | 325 | - This command should operate synchronously on the channel, |
326 | pausing right away the work of the given channel | 326 | resuming right away the work of the given channel |
327 | 327 | ||
328 | * device_terminate_all | 328 | * device_terminate_all |
329 | - Aborts all the pending and ongoing transfers on the channel | 329 | - Aborts all the pending and ongoing transfers on the channel |
diff --git a/Documentation/filesystems/ocfs2-online-filecheck.txt b/Documentation/filesystems/ocfs2-online-filecheck.txt index 1ab07860430d..139fab175c8a 100644 --- a/Documentation/filesystems/ocfs2-online-filecheck.txt +++ b/Documentation/filesystems/ocfs2-online-filecheck.txt | |||
@@ -5,12 +5,12 @@ This document will describe OCFS2 online file check feature. | |||
5 | 5 | ||
6 | Introduction | 6 | Introduction |
7 | ============ | 7 | ============ |
8 | OCFS2 is often used in high-availaibility systems. However, OCFS2 usually | 8 | OCFS2 is often used in high-availability systems. However, OCFS2 usually |
9 | converts the filesystem to read-only when encounters an error. This may not be | 9 | converts the filesystem to read-only when encounters an error. This may not be |
10 | necessary, since turning the filesystem read-only would affect other running | 10 | necessary, since turning the filesystem read-only would affect other running |
11 | processes as well, decreasing availability. | 11 | processes as well, decreasing availability. |
12 | Then, a mount option (errors=continue) is introduced, which would return the | 12 | Then, a mount option (errors=continue) is introduced, which would return the |
13 | -EIO errno to the calling process and terminate furhter processing so that the | 13 | -EIO errno to the calling process and terminate further processing so that the |
14 | filesystem is not corrupted further. The filesystem is not converted to | 14 | filesystem is not corrupted further. The filesystem is not converted to |
15 | read-only, and the problematic file's inode number is reported in the kernel | 15 | read-only, and the problematic file's inode number is reported in the kernel |
16 | log. The user can try to check/fix this file via online filecheck feature. | 16 | log. The user can try to check/fix this file via online filecheck feature. |
@@ -44,7 +44,7 @@ There is a sysfs directory for each OCFS2 file system mounting: | |||
44 | 44 | ||
45 | /sys/fs/ocfs2/<devname>/filecheck | 45 | /sys/fs/ocfs2/<devname>/filecheck |
46 | 46 | ||
47 | Here, <devname> indicates the name of OCFS2 volumn device which has been already | 47 | Here, <devname> indicates the name of OCFS2 volume device which has been already |
48 | mounted. The file above would accept inode numbers. This could be used to | 48 | mounted. The file above would accept inode numbers. This could be used to |
49 | communicate with kernel space, tell which file(inode number) will be checked or | 49 | communicate with kernel space, tell which file(inode number) will be checked or |
50 | fixed. Currently, three operations are supported, which includes checking | 50 | fixed. Currently, three operations are supported, which includes checking |
@@ -76,14 +76,14 @@ The output is like this: | |||
76 | This time, the <ERROR> column indicates whether this fix is successful or not. | 76 | This time, the <ERROR> column indicates whether this fix is successful or not. |
77 | 77 | ||
78 | 3. The record cache is used to store the history of check/fix results. It's | 78 | 3. The record cache is used to store the history of check/fix results. It's |
79 | defalut size is 10, and can be adjust between the range of 10 ~ 100. You can | 79 | default size is 10, and can be adjust between the range of 10 ~ 100. You can |
80 | adjust the size like this: | 80 | adjust the size like this: |
81 | 81 | ||
82 | # echo "<size>" > /sys/fs/ocfs2/<devname>/filecheck/set | 82 | # echo "<size>" > /sys/fs/ocfs2/<devname>/filecheck/set |
83 | 83 | ||
84 | Fixing stuff | 84 | Fixing stuff |
85 | ============ | 85 | ============ |
86 | On receivng the inode, the filesystem would read the inode and the | 86 | On receiving the inode, the filesystem would read the inode and the |
87 | file metadata. In case of errors, the filesystem would fix the errors | 87 | file metadata. In case of errors, the filesystem would fix the errors |
88 | and report the problems it fixed in the kernel log. As a precautionary measure, | 88 | and report the problems it fixed in the kernel log. As a precautionary measure, |
89 | the inode must first be checked for errors before performing a final fix. | 89 | the inode must first be checked for errors before performing a final fix. |
diff --git a/Documentation/index.rst b/Documentation/index.rst new file mode 100644 index 000000000000..f92854f01773 --- /dev/null +++ b/Documentation/index.rst | |||
@@ -0,0 +1,22 @@ | |||
1 | .. The Linux Kernel documentation master file, created by | ||
2 | sphinx-quickstart on Fri Feb 12 13:51:46 2016. | ||
3 | You can adapt this file completely to your liking, but it should at least | ||
4 | contain the root `toctree` directive. | ||
5 | |||
6 | Welcome to The Linux Kernel's documentation! | ||
7 | ============================================ | ||
8 | |||
9 | Nothing for you to see here *yet*. Please move along. | ||
10 | |||
11 | Contents: | ||
12 | |||
13 | .. toctree:: | ||
14 | :maxdepth: 2 | ||
15 | |||
16 | kernel-documentation | ||
17 | |||
18 | Indices and tables | ||
19 | ================== | ||
20 | |||
21 | * :ref:`genindex` | ||
22 | * :ref:`search` | ||
diff --git a/Documentation/kernel-doc-nano-HOWTO.txt b/Documentation/kernel-doc-nano-HOWTO.txt index 78f69cdc9b3f..062e3af271b7 100644 --- a/Documentation/kernel-doc-nano-HOWTO.txt +++ b/Documentation/kernel-doc-nano-HOWTO.txt | |||
@@ -1,3 +1,6 @@ | |||
1 | NOTE: this document is outdated and will eventually be removed. See | ||
2 | Documentation/kernel-documentation.rst for current information. | ||
3 | |||
1 | kernel-doc nano-HOWTO | 4 | kernel-doc nano-HOWTO |
2 | ===================== | 5 | ===================== |
3 | 6 | ||
diff --git a/Documentation/kernel-documentation.rst b/Documentation/kernel-documentation.rst new file mode 100644 index 000000000000..c4eb5049da39 --- /dev/null +++ b/Documentation/kernel-documentation.rst | |||
@@ -0,0 +1,654 @@ | |||
1 | ========================== | ||
2 | Linux Kernel Documentation | ||
3 | ========================== | ||
4 | |||
5 | Introduction | ||
6 | ============ | ||
7 | |||
8 | The Linux kernel uses `Sphinx`_ to generate pretty documentation from | ||
9 | `reStructuredText`_ files under ``Documentation``. To build the documentation in | ||
10 | HTML or PDF formats, use ``make htmldocs`` or ``make pdfdocs``. The generated | ||
11 | documentation is placed in ``Documentation/output``. | ||
12 | |||
13 | .. _Sphinx: http://www.sphinx-doc.org/ | ||
14 | .. _reStructuredText: http://docutils.sourceforge.net/rst.html | ||
15 | |||
16 | The reStructuredText files may contain directives to include structured | ||
17 | documentation comments, or kernel-doc comments, from source files. Usually these | ||
18 | are used to describe the functions and types and design of the code. The | ||
19 | kernel-doc comments have some special structure and formatting, but beyond that | ||
20 | they are also treated as reStructuredText. | ||
21 | |||
22 | There is also the deprecated DocBook toolchain to generate documentation from | ||
23 | DocBook XML template files under ``Documentation/DocBook``. The DocBook files | ||
24 | are to be converted to reStructuredText, and the toolchain is slated to be | ||
25 | removed. | ||
26 | |||
27 | Finally, there are thousands of plain text documentation files scattered around | ||
28 | ``Documentation``. Some of these will likely be converted to reStructuredText | ||
29 | over time, but the bulk of them will remain in plain text. | ||
30 | |||
31 | Sphinx Build | ||
32 | ============ | ||
33 | |||
34 | The usual way to generate the documentation is to run ``make htmldocs`` or | ||
35 | ``make pdfdocs``. There are also other formats available, see the documentation | ||
36 | section of ``make help``. The generated documentation is placed in | ||
37 | format-specific subdirectories under ``Documentation/output``. | ||
38 | |||
39 | To generate documentation, Sphinx (``sphinx-build``) must obviously be | ||
40 | installed. For prettier HTML output, the Read the Docs Sphinx theme | ||
41 | (``sphinx_rtd_theme``) is used if available. For PDF output, ``rst2pdf`` is also | ||
42 | needed. All of these are widely available and packaged in distributions. | ||
43 | |||
44 | To pass extra options to Sphinx, you can use the ``SPHINXOPTS`` make | ||
45 | variable. For example, use ``make SPHINXOPTS=-v htmldocs`` to get more verbose | ||
46 | output. | ||
47 | |||
48 | To remove the generated documentation, run ``make cleandocs``. | ||
49 | |||
50 | Writing Documentation | ||
51 | ===================== | ||
52 | |||
53 | Adding new documentation can be as simple as: | ||
54 | |||
55 | 1. Add a new ``.rst`` file somewhere under ``Documentation``. | ||
56 | 2. Refer to it from the Sphinx main `TOC tree`_ in ``Documentation/index.rst``. | ||
57 | |||
58 | .. _TOC tree: http://www.sphinx-doc.org/en/stable/markup/toctree.html | ||
59 | |||
60 | This is usually good enough for simple documentation (like the one you're | ||
61 | reading right now), but for larger documents it may be advisable to create a | ||
62 | subdirectory (or use an existing one). For example, the graphics subsystem | ||
63 | documentation is under ``Documentation/gpu``, split to several ``.rst`` files, | ||
64 | and has a separate ``index.rst`` (with a ``toctree`` of its own) referenced from | ||
65 | the main index. | ||
66 | |||
67 | See the documentation for `Sphinx`_ and `reStructuredText`_ on what you can do | ||
68 | with them. In particular, the Sphinx `reStructuredText Primer`_ is a good place | ||
69 | to get started with reStructuredText. There are also some `Sphinx specific | ||
70 | markup constructs`_. | ||
71 | |||
72 | .. _reStructuredText Primer: http://www.sphinx-doc.org/en/stable/rest.html | ||
73 | .. _Sphinx specific markup constructs: http://www.sphinx-doc.org/en/stable/markup/index.html | ||
74 | |||
75 | Specific guidelines for the kernel documentation | ||
76 | ------------------------------------------------ | ||
77 | |||
78 | Here are some specific guidelines for the kernel documentation: | ||
79 | |||
80 | * Please don't go overboard with reStructuredText markup. Keep it simple. | ||
81 | |||
82 | * Please stick to this order of heading adornments: | ||
83 | |||
84 | 1. ``=`` with overline for document title:: | ||
85 | |||
86 | ============== | ||
87 | Document title | ||
88 | ============== | ||
89 | |||
90 | 2. ``=`` for chapters:: | ||
91 | |||
92 | Chapters | ||
93 | ======== | ||
94 | |||
95 | 3. ``-`` for sections:: | ||
96 | |||
97 | Section | ||
98 | ------- | ||
99 | |||
100 | 4. ``~`` for subsections:: | ||
101 | |||
102 | Subsection | ||
103 | ~~~~~~~~~~ | ||
104 | |||
105 | Although RST doesn't mandate a specific order ("Rather than imposing a fixed | ||
106 | number and order of section title adornment styles, the order enforced will be | ||
107 | the order as encountered."), having the higher levels the same overall makes | ||
108 | it easier to follow the documents. | ||
109 | |||
110 | list tables | ||
111 | ----------- | ||
112 | |||
113 | We recommend the use of *list table* formats. The *list table* formats are | ||
114 | double-stage lists. Compared to the ASCII-art they might not be as | ||
115 | comfortable for | ||
116 | readers of the text files. Their advantage is that they are easy to | ||
117 | create or modify and that the diff of a modification is much more meaningful, | ||
118 | because it is limited to the modified content. | ||
119 | |||
120 | The ``flat-table`` is a double-stage list similar to the ``list-table`` with | ||
121 | some additional features: | ||
122 | |||
123 | * column-span: with the role ``cspan`` a cell can be extended through | ||
124 | additional columns | ||
125 | |||
126 | * row-span: with the role ``rspan`` a cell can be extended through | ||
127 | additional rows | ||
128 | |||
129 | * auto span rightmost cell of a table row over the missing cells on the right | ||
130 | side of that table-row. With Option ``:fill-cells:`` this behavior can | ||
131 | changed from *auto span* to *auto fill*, which automatically inserts (empty) | ||
132 | cells instead of spanning the last cell. | ||
133 | |||
134 | options: | ||
135 | |||
136 | * ``:header-rows:`` [int] count of header rows | ||
137 | * ``:stub-columns:`` [int] count of stub columns | ||
138 | * ``:widths:`` [[int] [int] ... ] widths of columns | ||
139 | * ``:fill-cells:`` instead of auto-spanning missing cells, insert missing cells | ||
140 | |||
141 | roles: | ||
142 | |||
143 | * ``:cspan:`` [int] additional columns (*morecols*) | ||
144 | * ``:rspan:`` [int] additional rows (*morerows*) | ||
145 | |||
146 | The example below shows how to use this markup. The first level of the staged | ||
147 | list is the *table-row*. In the *table-row* there is only one markup allowed, | ||
148 | the list of the cells in this *table-row*. Exceptions are *comments* ( ``..`` ) | ||
149 | and *targets* (e.g. a ref to ``:ref:`last row <last row>``` / :ref:`last row | ||
150 | <last row>`). | ||
151 | |||
152 | .. code-block:: rst | ||
153 | |||
154 | .. flat-table:: table title | ||
155 | :widths: 2 1 1 3 | ||
156 | |||
157 | * - head col 1 | ||
158 | - head col 2 | ||
159 | - head col 3 | ||
160 | - head col 4 | ||
161 | |||
162 | * - column 1 | ||
163 | - field 1.1 | ||
164 | - field 1.2 with autospan | ||
165 | |||
166 | * - column 2 | ||
167 | - field 2.1 | ||
168 | - :rspan:`1` :cspan:`1` field 2.2 - 3.3 | ||
169 | |||
170 | * .. _`last row`: | ||
171 | |||
172 | - column 3 | ||
173 | |||
174 | Rendered as: | ||
175 | |||
176 | .. flat-table:: table title | ||
177 | :widths: 2 1 1 3 | ||
178 | |||
179 | * - head col 1 | ||
180 | - head col 2 | ||
181 | - head col 3 | ||
182 | - head col 4 | ||
183 | |||
184 | * - column 1 | ||
185 | - field 1.1 | ||
186 | - field 1.2 with autospan | ||
187 | |||
188 | * - column 2 | ||
189 | - field 2.1 | ||
190 | - :rspan:`1` :cspan:`1` field 2.2 - 3.3 | ||
191 | |||
192 | * .. _`last row`: | ||
193 | |||
194 | - column 3 | ||
195 | |||
196 | |||
197 | Including kernel-doc comments | ||
198 | ============================= | ||
199 | |||
200 | The Linux kernel source files may contain structured documentation comments, or | ||
201 | kernel-doc comments to describe the functions and types and design of the | ||
202 | code. The documentation comments may be included to any of the reStructuredText | ||
203 | documents using a dedicated kernel-doc Sphinx directive extension. | ||
204 | |||
205 | The kernel-doc directive is of the format:: | ||
206 | |||
207 | .. kernel-doc:: source | ||
208 | :option: | ||
209 | |||
210 | The *source* is the path to a source file, relative to the kernel source | ||
211 | tree. The following directive options are supported: | ||
212 | |||
213 | export: *[source-pattern ...]* | ||
214 | Include documentation for all functions in *source* that have been exported | ||
215 | using ``EXPORT_SYMBOL`` or ``EXPORT_SYMBOL_GPL`` either in *source* or in any | ||
216 | of the files specified by *source-pattern*. | ||
217 | |||
218 | The *source-pattern* is useful when the kernel-doc comments have been placed | ||
219 | in header files, while ``EXPORT_SYMBOL`` and ``EXPORT_SYMBOL_GPL`` are next to | ||
220 | the function definitions. | ||
221 | |||
222 | Examples:: | ||
223 | |||
224 | .. kernel-doc:: lib/bitmap.c | ||
225 | :export: | ||
226 | |||
227 | .. kernel-doc:: include/net/mac80211.h | ||
228 | :export: net/mac80211/*.c | ||
229 | |||
230 | internal: *[source-pattern ...]* | ||
231 | Include documentation for all functions and types in *source* that have | ||
232 | **not** been exported using ``EXPORT_SYMBOL`` or ``EXPORT_SYMBOL_GPL`` either | ||
233 | in *source* or in any of the files specified by *source-pattern*. | ||
234 | |||
235 | Example:: | ||
236 | |||
237 | .. kernel-doc:: drivers/gpu/drm/i915/intel_audio.c | ||
238 | :internal: | ||
239 | |||
240 | doc: *title* | ||
241 | Include documentation for the ``DOC:`` paragraph identified by *title* in | ||
242 | *source*. Spaces are allowed in *title*; do not quote the *title*. The *title* | ||
243 | is only used as an identifier for the paragraph, and is not included in the | ||
244 | output. Please make sure to have an appropriate heading in the enclosing | ||
245 | reStructuredText document. | ||
246 | |||
247 | Example:: | ||
248 | |||
249 | .. kernel-doc:: drivers/gpu/drm/i915/intel_audio.c | ||
250 | :doc: High Definition Audio over HDMI and Display Port | ||
251 | |||
252 | functions: *function* *[...]* | ||
253 | Include documentation for each *function* in *source*. | ||
254 | |||
255 | Example:: | ||
256 | |||
257 | .. kernel-doc:: lib/bitmap.c | ||
258 | :functions: bitmap_parselist bitmap_parselist_user | ||
259 | |||
260 | Without options, the kernel-doc directive includes all documentation comments | ||
261 | from the source file. | ||
262 | |||
263 | The kernel-doc extension is included in the kernel source tree, at | ||
264 | ``Documentation/sphinx/kernel-doc.py``. Internally, it uses the | ||
265 | ``scripts/kernel-doc`` script to extract the documentation comments from the | ||
266 | source. | ||
267 | |||
268 | Writing kernel-doc comments | ||
269 | =========================== | ||
270 | |||
271 | In order to provide embedded, "C" friendly, easy to maintain, but consistent and | ||
272 | extractable overview, function and type documentation, the Linux kernel has | ||
273 | adopted a consistent style for documentation comments. The format for this | ||
274 | documentation is called the kernel-doc format, described below. This style | ||
275 | embeds the documentation within the source files, using a few simple conventions | ||
276 | for adding documentation paragraphs and documenting functions and their | ||
277 | parameters, structures and unions and their members, enumerations, and typedefs. | ||
278 | |||
279 | .. note:: The kernel-doc format is deceptively similar to gtk-doc or Doxygen, | ||
280 | yet distinctively different, for historical reasons. The kernel source | ||
281 | contains tens of thousands of kernel-doc comments. Please stick to the style | ||
282 | described here. | ||
283 | |||
284 | The ``scripts/kernel-doc`` script is used by the Sphinx kernel-doc extension in | ||
285 | the documentation build to extract this embedded documentation into the various | ||
286 | HTML, PDF, and other format documents. | ||
287 | |||
288 | In order to provide good documentation of kernel functions and data structures, | ||
289 | please use the following conventions to format your kernel-doc comments in the | ||
290 | Linux kernel source. | ||
291 | |||
292 | How to format kernel-doc comments | ||
293 | --------------------------------- | ||
294 | |||
295 | The opening comment mark ``/**`` is reserved for kernel-doc comments. Only | ||
296 | comments so marked will be considered by the ``kernel-doc`` tool. Use it only | ||
297 | for comment blocks that contain kernel-doc formatted comments. The usual ``*/`` | ||
298 | should be used as the closing comment marker. The lines in between should be | ||
299 | prefixed by ``Â *Â `` (space star space). | ||
300 | |||
301 | The function and type kernel-doc comments should be placed just before the | ||
302 | function or type being described. The overview kernel-doc comments may be freely | ||
303 | placed at the top indentation level. | ||
304 | |||
305 | Example kernel-doc function comment:: | ||
306 | |||
307 | /** | ||
308 | * foobar() - Brief description of foobar. | ||
309 | * @arg: Description of argument of foobar. | ||
310 | * | ||
311 | * Longer description of foobar. | ||
312 | * | ||
313 | * Return: Description of return value of foobar. | ||
314 | */ | ||
315 | int foobar(int arg) | ||
316 | |||
317 | The format is similar for documentation for structures, enums, paragraphs, | ||
318 | etc. See the sections below for details. | ||
319 | |||
320 | The kernel-doc structure is extracted from the comments, and proper `Sphinx C | ||
321 | Domain`_ function and type descriptions with anchors are generated for them. The | ||
322 | descriptions are filtered for special kernel-doc highlights and | ||
323 | cross-references. See below for details. | ||
324 | |||
325 | .. _Sphinx C Domain: http://www.sphinx-doc.org/en/stable/domains.html | ||
326 | |||
327 | Highlights and cross-references | ||
328 | ------------------------------- | ||
329 | |||
330 | The following special patterns are recognized in the kernel-doc comment | ||
331 | descriptive text and converted to proper reStructuredText markup and `Sphinx C | ||
332 | Domain`_ references. | ||
333 | |||
334 | .. attention:: The below are **only** recognized within kernel-doc comments, | ||
335 | **not** within normal reStructuredText documents. | ||
336 | |||
337 | ``funcname()`` | ||
338 | Function reference. | ||
339 | |||
340 | ``@parameter`` | ||
341 | Name of a function parameter. (No cross-referencing, just formatting.) | ||
342 | |||
343 | ``%CONST`` | ||
344 | Name of a constant. (No cross-referencing, just formatting.) | ||
345 | |||
346 | ``$ENVVAR`` | ||
347 | Name of an environment variable. (No cross-referencing, just formatting.) | ||
348 | |||
349 | ``&struct name`` | ||
350 | Structure reference. | ||
351 | |||
352 | ``&enum name`` | ||
353 | Enum reference. | ||
354 | |||
355 | ``&typedef name`` | ||
356 | Typedef reference. | ||
357 | |||
358 | ``&struct_name->member`` or ``&struct_name.member`` | ||
359 | Structure or union member reference. The cross-reference will be to the struct | ||
360 | or union definition, not the member directly. | ||
361 | |||
362 | ``&name`` | ||
363 | A generic type reference. Prefer using the full reference described above | ||
364 | instead. This is mostly for legacy comments. | ||
365 | |||
366 | Cross-referencing from reStructuredText | ||
367 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
368 | |||
369 | .. highlight:: none | ||
370 | |||
371 | To cross-reference the functions and types defined in the kernel-doc comments | ||
372 | from reStructuredText documents, please use the `Sphinx C Domain`_ | ||
373 | references. For example:: | ||
374 | |||
375 | See function :c:func:`foo` and struct/union/enum/typedef :c:type:`bar`. | ||
376 | |||
377 | While the type reference works with just the type name, without the | ||
378 | struct/union/enum/typedef part in front, you may want to use:: | ||
379 | |||
380 | See :c:type:`struct foo <foo>`. | ||
381 | See :c:type:`union bar <bar>`. | ||
382 | See :c:type:`enum baz <baz>`. | ||
383 | See :c:type:`typedef meh <meh>`. | ||
384 | |||
385 | This will produce prettier links, and is in line with how kernel-doc does the | ||
386 | cross-references. | ||
387 | |||
388 | For further details, please refer to the `Sphinx C Domain`_ documentation. | ||
389 | |||
390 | Function documentation | ||
391 | ---------------------- | ||
392 | |||
393 | .. highlight:: c | ||
394 | |||
395 | The general format of a function and function-like macro kernel-doc comment is:: | ||
396 | |||
397 | /** | ||
398 | * function_name() - Brief description of function. | ||
399 | * @arg1: Describe the first argument. | ||
400 | * @arg2: Describe the second argument. | ||
401 | * One can provide multiple line descriptions | ||
402 | * for arguments. | ||
403 | * | ||
404 | * A longer description, with more discussion of the function function_name() | ||
405 | * that might be useful to those using or modifying it. Begins with an | ||
406 | * empty comment line, and may include additional embedded empty | ||
407 | * comment lines. | ||
408 | * | ||
409 | * The longer description may have multiple paragraphs. | ||
410 | * | ||
411 | * Return: Describe the return value of foobar. | ||
412 | * | ||
413 | * The return value description can also have multiple paragraphs, and should | ||
414 | * be placed at the end of the comment block. | ||
415 | */ | ||
416 | |||
417 | The brief description following the function name may span multiple lines, and | ||
418 | ends with an ``@argument:`` description, a blank comment line, or the end of the | ||
419 | comment block. | ||
420 | |||
421 | The kernel-doc function comments describe each parameter to the function, in | ||
422 | order, with the ``@argument:`` descriptions. The ``@argument:`` descriptions | ||
423 | must begin on the very next line following the opening brief function | ||
424 | description line, with no intervening blank comment lines. The ``@argument:`` | ||
425 | descriptions may span multiple lines. The continuation lines may contain | ||
426 | indentation. If a function parameter is ``...`` (varargs), it should be listed | ||
427 | in kernel-doc notation as: ``@...:``. | ||
428 | |||
429 | The return value, if any, should be described in a dedicated section at the end | ||
430 | of the comment starting with "Return:". | ||
431 | |||
432 | Structure, union, and enumeration documentation | ||
433 | ----------------------------------------------- | ||
434 | |||
435 | The general format of a struct, union, and enum kernel-doc comment is:: | ||
436 | |||
437 | /** | ||
438 | * struct struct_name - Brief description. | ||
439 | * @member_name: Description of member member_name. | ||
440 | * | ||
441 | * Description of the structure. | ||
442 | */ | ||
443 | |||
444 | Below, "struct" is used to mean structs, unions and enums, and "member" is used | ||
445 | to mean struct and union members as well as enumerations in an enum. | ||
446 | |||
447 | The brief description following the structure name may span multiple lines, and | ||
448 | ends with a ``@member:`` description, a blank comment line, or the end of the | ||
449 | comment block. | ||
450 | |||
451 | The kernel-doc data structure comments describe each member of the structure, in | ||
452 | order, with the ``@member:`` descriptions. The ``@member:`` descriptions must | ||
453 | begin on the very next line following the opening brief function description | ||
454 | line, with no intervening blank comment lines. The ``@member:`` descriptions may | ||
455 | span multiple lines. The continuation lines may contain indentation. | ||
456 | |||
457 | In-line member documentation comments | ||
458 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
459 | |||
460 | The structure members may also be documented in-line within the definition:: | ||
461 | |||
462 | /** | ||
463 | * struct foo - Brief description. | ||
464 | * @foo: The Foo member. | ||
465 | */ | ||
466 | struct foo { | ||
467 | int foo; | ||
468 | /** | ||
469 | * @bar: The Bar member. | ||
470 | */ | ||
471 | int bar; | ||
472 | /** | ||
473 | * @baz: The Baz member. | ||
474 | * | ||
475 | * Here, the member description may contain several paragraphs. | ||
476 | */ | ||
477 | int baz; | ||
478 | } | ||
479 | |||
480 | Private members | ||
481 | ~~~~~~~~~~~~~~~ | ||
482 | |||
483 | Inside a struct description, you can use the "private:" and "public:" comment | ||
484 | tags. Structure fields that are inside a "private:" area are not listed in the | ||
485 | generated output documentation. The "private:" and "public:" tags must begin | ||
486 | immediately following a ``/*`` comment marker. They may optionally include | ||
487 | comments between the ``:`` and the ending ``*/`` marker. | ||
488 | |||
489 | Example:: | ||
490 | |||
491 | /** | ||
492 | * struct my_struct - short description | ||
493 | * @a: first member | ||
494 | * @b: second member | ||
495 | * | ||
496 | * Longer description | ||
497 | */ | ||
498 | struct my_struct { | ||
499 | int a; | ||
500 | int b; | ||
501 | /* private: internal use only */ | ||
502 | int c; | ||
503 | }; | ||
504 | |||
505 | |||
506 | Typedef documentation | ||
507 | --------------------- | ||
508 | |||
509 | The general format of a typedef kernel-doc comment is:: | ||
510 | |||
511 | /** | ||
512 | * typedef type_name - Brief description. | ||
513 | * | ||
514 | * Description of the type. | ||
515 | */ | ||
516 | |||
517 | Overview documentation comments | ||
518 | ------------------------------- | ||
519 | |||
520 | To facilitate having source code and comments close together, you can include | ||
521 | kernel-doc documentation blocks that are free-form comments instead of being | ||
522 | kernel-doc for functions, structures, unions, enums, or typedefs. This could be | ||
523 | used for something like a theory of operation for a driver or library code, for | ||
524 | example. | ||
525 | |||
526 | This is done by using a ``DOC:`` section keyword with a section title. | ||
527 | |||
528 | The general format of an overview or high-level documentation comment is:: | ||
529 | |||
530 | /** | ||
531 | * DOC: Theory of Operation | ||
532 | * | ||
533 | * The whizbang foobar is a dilly of a gizmo. It can do whatever you | ||
534 | * want it to do, at any time. It reads your mind. Here's how it works. | ||
535 | * | ||
536 | * foo bar splat | ||
537 | * | ||
538 | * The only drawback to this gizmo is that is can sometimes damage | ||
539 | * hardware, software, or its subject(s). | ||
540 | */ | ||
541 | |||
542 | The title following ``DOC:`` acts as a heading within the source file, but also | ||
543 | as an identifier for extracting the documentation comment. Thus, the title must | ||
544 | be unique within the file. | ||
545 | |||
546 | Recommendations | ||
547 | --------------- | ||
548 | |||
549 | We definitely need kernel-doc formatted documentation for functions that are | ||
550 | exported to loadable modules using ``EXPORT_SYMBOL`` or ``EXPORT_SYMBOL_GPL``. | ||
551 | |||
552 | We also look to provide kernel-doc formatted documentation for functions | ||
553 | externally visible to other kernel files (not marked "static"). | ||
554 | |||
555 | We also recommend providing kernel-doc formatted documentation for private (file | ||
556 | "static") routines, for consistency of kernel source code layout. But this is | ||
557 | lower priority and at the discretion of the MAINTAINER of that kernel source | ||
558 | file. | ||
559 | |||
560 | Data structures visible in kernel include files should also be documented using | ||
561 | kernel-doc formatted comments. | ||
562 | |||
563 | DocBook XML [DEPRECATED] | ||
564 | ======================== | ||
565 | |||
566 | .. attention:: | ||
567 | |||
568 | This section describes the deprecated DocBook XML toolchain. Please do not | ||
569 | create new DocBook XML template files. Please consider converting existing | ||
570 | DocBook XML templates files to Sphinx/reStructuredText. | ||
571 | |||
572 | Converting DocBook to Sphinx | ||
573 | ---------------------------- | ||
574 | |||
575 | .. highlight:: none | ||
576 | |||
577 | Over time, we expect all of the documents under ``Documentation/DocBook`` to be | ||
578 | converted to Sphinx and reStructuredText. For most DocBook XML documents, a good | ||
579 | enough solution is to use the simple ``Documentation/sphinx/tmplcvt`` script, | ||
580 | which uses ``pandoc`` under the hood. For example:: | ||
581 | |||
582 | $ cd Documentation/sphinx | ||
583 | $ ./tmplcvt ../DocBook/in.tmpl ../out.rst | ||
584 | |||
585 | Then edit the resulting rst files to fix any remaining issues, and add the | ||
586 | document in the ``toctree`` in ``Documentation/index.rst``. | ||
587 | |||
588 | Components of the kernel-doc system | ||
589 | ----------------------------------- | ||
590 | |||
591 | Many places in the source tree have extractable documentation in the form of | ||
592 | block comments above functions. The components of this system are: | ||
593 | |||
594 | - ``scripts/kernel-doc`` | ||
595 | |||
596 | This is a perl script that hunts for the block comments and can mark them up | ||
597 | directly into reStructuredText, DocBook, man, text, and HTML. (No, not | ||
598 | texinfo.) | ||
599 | |||
600 | - ``Documentation/DocBook/*.tmpl`` | ||
601 | |||
602 | These are XML template files, which are normal XML files with special | ||
603 | place-holders for where the extracted documentation should go. | ||
604 | |||
605 | - ``scripts/docproc.c`` | ||
606 | |||
607 | This is a program for converting XML template files into XML files. When a | ||
608 | file is referenced it is searched for symbols exported (EXPORT_SYMBOL), to be | ||
609 | able to distinguish between internal and external functions. | ||
610 | |||
611 | It invokes kernel-doc, giving it the list of functions that are to be | ||
612 | documented. | ||
613 | |||
614 | Additionally it is used to scan the XML template files to locate all the files | ||
615 | referenced herein. This is used to generate dependency information as used by | ||
616 | make. | ||
617 | |||
618 | - ``Makefile`` | ||
619 | |||
620 | The targets 'xmldocs', 'psdocs', 'pdfdocs', and 'htmldocs' are used to build | ||
621 | DocBook XML files, PostScript files, PDF files, and html files in | ||
622 | Documentation/DocBook. The older target 'sgmldocs' is equivalent to 'xmldocs'. | ||
623 | |||
624 | - ``Documentation/DocBook/Makefile`` | ||
625 | |||
626 | This is where C files are associated with SGML templates. | ||
627 | |||
628 | How to use kernel-doc comments in DocBook XML template files | ||
629 | ------------------------------------------------------------ | ||
630 | |||
631 | DocBook XML template files (\*.tmpl) are like normal XML files, except that they | ||
632 | can contain escape sequences where extracted documentation should be inserted. | ||
633 | |||
634 | ``!E<filename>`` is replaced by the documentation, in ``<filename>``, for | ||
635 | functions that are exported using ``EXPORT_SYMBOL``: the function list is | ||
636 | collected from files listed in ``Documentation/DocBook/Makefile``. | ||
637 | |||
638 | ``!I<filename>`` is replaced by the documentation for functions that are **not** | ||
639 | exported using ``EXPORT_SYMBOL``. | ||
640 | |||
641 | ``!D<filename>`` is used to name additional files to search for functions | ||
642 | exported using ``EXPORT_SYMBOL``. | ||
643 | |||
644 | ``!F<filename> <function [functions...]>`` is replaced by the documentation, in | ||
645 | ``<filename>``, for the functions listed. | ||
646 | |||
647 | ``!P<filename> <section title>`` is replaced by the contents of the ``DOC:`` | ||
648 | section titled ``<section title>`` from ``<filename>``. Spaces are allowed in | ||
649 | ``<section title>``; do not quote the ``<section title>``. | ||
650 | |||
651 | ``!C<filename>`` is replaced by nothing, but makes the tools check that all DOC: | ||
652 | sections and documented functions, symbols, etc. are used. This makes sense to | ||
653 | use when you use ``!F`` or ``!P`` only and want to verify that all documentation | ||
654 | is included. | ||
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index f1fac4d3dc51..724970a25666 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -3996,8 +3996,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
3996 | 3996 | ||
3997 | trace_event=[event-list] | 3997 | trace_event=[event-list] |
3998 | [FTRACE] Set and start specified trace events in order | 3998 | [FTRACE] Set and start specified trace events in order |
3999 | to facilitate early boot debugging. | 3999 | to facilitate early boot debugging. The event-list is a |
4000 | See also Documentation/trace/events.txt | 4000 | comma separated list of trace events to enable. See |
4001 | also Documentation/trace/events.txt | ||
4001 | 4002 | ||
4002 | trace_options=[option-list] | 4003 | trace_options=[option-list] |
4003 | [FTRACE] Enable or disable tracer options at boot. | 4004 | [FTRACE] Enable or disable tracer options at boot. |
diff --git a/Documentation/md.txt b/Documentation/md.txt index 1a2ada46aaed..d6e2fcf27337 100644 --- a/Documentation/md.txt +++ b/Documentation/md.txt | |||
@@ -602,7 +602,7 @@ These currently include | |||
602 | 602 | ||
603 | stripe_cache_size (currently raid5 only) | 603 | stripe_cache_size (currently raid5 only) |
604 | number of entries in the stripe cache. This is writable, but | 604 | number of entries in the stripe cache. This is writable, but |
605 | there are upper and lower limits (32768, 16). Default is 128. | 605 | there are upper and lower limits (32768, 17). Default is 256. |
606 | strip_cache_active (currently raid5 only) | 606 | strip_cache_active (currently raid5 only) |
607 | number of active entries in the stripe cache | 607 | number of active entries in the stripe cache |
608 | preread_bypass_threshold (currently raid5 only) | 608 | preread_bypass_threshold (currently raid5 only) |
diff --git a/Documentation/mic/mpssd/mpssd.c b/Documentation/mic/mpssd/mpssd.c index 30fb842a976d..49db1def1721 100644 --- a/Documentation/mic/mpssd/mpssd.c +++ b/Documentation/mic/mpssd/mpssd.c | |||
@@ -1538,9 +1538,9 @@ set_cmdline(struct mic_info *mic) | |||
1538 | 1538 | ||
1539 | len = snprintf(buffer, PATH_MAX, | 1539 | len = snprintf(buffer, PATH_MAX, |
1540 | "clocksource=tsc highres=off nohz=off "); | 1540 | "clocksource=tsc highres=off nohz=off "); |
1541 | len += snprintf(buffer + len, PATH_MAX, | 1541 | len += snprintf(buffer + len, PATH_MAX - len, |
1542 | "cpufreq_on;corec6_off;pc3_off;pc6_off "); | 1542 | "cpufreq_on;corec6_off;pc3_off;pc6_off "); |
1543 | len += snprintf(buffer + len, PATH_MAX, | 1543 | len += snprintf(buffer + len, PATH_MAX - len, |
1544 | "ifcfg=static;address,172.31.%d.1;netmask,255.255.255.0", | 1544 | "ifcfg=static;address,172.31.%d.1;netmask,255.255.255.0", |
1545 | mic->id + 1); | 1545 | mic->id + 1); |
1546 | 1546 | ||
diff --git a/Documentation/security/self-protection.txt b/Documentation/security/self-protection.txt index babd6378ec05..3010576c9fca 100644 --- a/Documentation/security/self-protection.txt +++ b/Documentation/security/self-protection.txt | |||
@@ -183,8 +183,9 @@ provide meaningful defenses. | |||
183 | ### Canaries, blinding, and other secrets | 183 | ### Canaries, blinding, and other secrets |
184 | 184 | ||
185 | It should be noted that things like the stack canary discussed earlier | 185 | It should be noted that things like the stack canary discussed earlier |
186 | are technically statistical defenses, since they rely on a (leakable) | 186 | are technically statistical defenses, since they rely on a secret value, |
187 | secret value. | 187 | and such values may become discoverable through an information exposure |
188 | flaw. | ||
188 | 189 | ||
189 | Blinding literal values for things like JITs, where the executable | 190 | Blinding literal values for things like JITs, where the executable |
190 | contents may be partially under the control of userspace, need a similar | 191 | contents may be partially under the control of userspace, need a similar |
@@ -199,8 +200,8 @@ working?) in order to maximize their success. | |||
199 | Since the location of kernel memory is almost always instrumental in | 200 | Since the location of kernel memory is almost always instrumental in |
200 | mounting a successful attack, making the location non-deterministic | 201 | mounting a successful attack, making the location non-deterministic |
201 | raises the difficulty of an exploit. (Note that this in turn makes | 202 | raises the difficulty of an exploit. (Note that this in turn makes |
202 | the value of leaks higher, since they may be used to discover desired | 203 | the value of information exposures higher, since they may be used to |
203 | memory locations.) | 204 | discover desired memory locations.) |
204 | 205 | ||
205 | #### Text and module base | 206 | #### Text and module base |
206 | 207 | ||
@@ -222,14 +223,21 @@ become more difficult to locate. | |||
222 | Much of the kernel's dynamic memory (e.g. kmalloc, vmalloc, etc) ends up | 223 | Much of the kernel's dynamic memory (e.g. kmalloc, vmalloc, etc) ends up |
223 | being relatively deterministic in layout due to the order of early-boot | 224 | being relatively deterministic in layout due to the order of early-boot |
224 | initializations. If the base address of these areas is not the same | 225 | initializations. If the base address of these areas is not the same |
225 | between boots, targeting them is frustrated, requiring a leak specific | 226 | between boots, targeting them is frustrated, requiring an information |
226 | to the region. | 227 | exposure specific to the region. |
228 | |||
229 | #### Structure layout | ||
230 | |||
231 | By performing a per-build randomization of the layout of sensitive | ||
232 | structures, attacks must either be tuned to known kernel builds or expose | ||
233 | enough kernel memory to determine structure layouts before manipulating | ||
234 | them. | ||
227 | 235 | ||
228 | 236 | ||
229 | ## Preventing Leaks | 237 | ## Preventing Information Exposures |
230 | 238 | ||
231 | Since the locations of sensitive structures are the primary target for | 239 | Since the locations of sensitive structures are the primary target for |
232 | attacks, it is important to defend against leaks of both kernel memory | 240 | attacks, it is important to defend against exposure of both kernel memory |
233 | addresses and kernel memory contents (since they may contain kernel | 241 | addresses and kernel memory contents (since they may contain kernel |
234 | addresses or other sensitive things like canary values). | 242 | addresses or other sensitive things like canary values). |
235 | 243 | ||
@@ -250,8 +258,8 @@ sure structure holes are cleared. | |||
250 | When releasing memory, it is best to poison the contents (clear stack on | 258 | When releasing memory, it is best to poison the contents (clear stack on |
251 | syscall return, wipe heap memory on a free), to avoid reuse attacks that | 259 | syscall return, wipe heap memory on a free), to avoid reuse attacks that |
252 | rely on the old contents of memory. This frustrates many uninitialized | 260 | rely on the old contents of memory. This frustrates many uninitialized |
253 | variable attacks, stack info leaks, heap info leaks, and use-after-free | 261 | variable attacks, stack content exposures, heap content exposures, and |
254 | attacks. | 262 | use-after-free attacks. |
255 | 263 | ||
256 | ### Destination tracking | 264 | ### Destination tracking |
257 | 265 | ||
diff --git a/Documentation/sphinx/convert_template.sed b/Documentation/sphinx/convert_template.sed new file mode 100644 index 000000000000..c1503fcca4ec --- /dev/null +++ b/Documentation/sphinx/convert_template.sed | |||
@@ -0,0 +1,18 @@ | |||
1 | # | ||
2 | # Pandoc doesn't grok <function> or <structname>, so convert them | ||
3 | # ahead of time. | ||
4 | # | ||
5 | # Use the following escapes to pass through pandoc: | ||
6 | # $bq = "`" | ||
7 | # $lt = "<" | ||
8 | # $gt = ">" | ||
9 | # | ||
10 | s%<function>\([^<(]\+\)()</function>%:c:func:$bq\1()$bq%g | ||
11 | s%<function>\([^<(]\+\)</function>%:c:func:$bq\1()$bq%g | ||
12 | s%<structname>struct *\([^<]\+\)</structname>%:c:type:$bqstruct \1 $lt\1$gt$bq%g | ||
13 | s%struct <structname>\([^<]\+\)</structname>%:c:type:$bqstruct \1 $lt\1$gt$bq%g | ||
14 | s%<structname>\([^<]\+\)</structname>%:c:type:$bqstruct \1 $lt\1$gt$bq%g | ||
15 | # | ||
16 | # Wrap docproc directives in para and code blocks. | ||
17 | # | ||
18 | s%^\(!.*\)$%<para><code>DOCPROC: \1</code></para>% | ||
diff --git a/Documentation/sphinx/kernel-doc.py b/Documentation/sphinx/kernel-doc.py new file mode 100644 index 000000000000..f6920c0af6ee --- /dev/null +++ b/Documentation/sphinx/kernel-doc.py | |||
@@ -0,0 +1,141 @@ | |||
1 | # coding=utf-8 | ||
2 | # | ||
3 | # Copyright © 2016 Intel Corporation | ||
4 | # | ||
5 | # Permission is hereby granted, free of charge, to any person obtaining a | ||
6 | # copy of this software and associated documentation files (the "Software"), | ||
7 | # to deal in the Software without restriction, including without limitation | ||
8 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
9 | # and/or sell copies of the Software, and to permit persons to whom the | ||
10 | # Software is furnished to do so, subject to the following conditions: | ||
11 | # | ||
12 | # The above copyright notice and this permission notice (including the next | ||
13 | # paragraph) shall be included in all copies or substantial portions of the | ||
14 | # Software. | ||
15 | # | ||
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
19 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
22 | # IN THE SOFTWARE. | ||
23 | # | ||
24 | # Authors: | ||
25 | # Jani Nikula <jani.nikula@intel.com> | ||
26 | # | ||
27 | # Please make sure this works on both python2 and python3. | ||
28 | # | ||
29 | |||
30 | import os | ||
31 | import subprocess | ||
32 | import sys | ||
33 | import re | ||
34 | import glob | ||
35 | |||
36 | from docutils import nodes, statemachine | ||
37 | from docutils.statemachine import ViewList | ||
38 | from docutils.parsers.rst import directives | ||
39 | from sphinx.util.compat import Directive | ||
40 | from sphinx.ext.autodoc import AutodocReporter | ||
41 | |||
42 | class KernelDocDirective(Directive): | ||
43 | """Extract kernel-doc comments from the specified file""" | ||
44 | required_argument = 1 | ||
45 | optional_arguments = 4 | ||
46 | option_spec = { | ||
47 | 'doc': directives.unchanged_required, | ||
48 | 'functions': directives.unchanged_required, | ||
49 | 'export': directives.unchanged, | ||
50 | 'internal': directives.unchanged, | ||
51 | } | ||
52 | has_content = False | ||
53 | |||
54 | def run(self): | ||
55 | env = self.state.document.settings.env | ||
56 | cmd = [env.config.kerneldoc_bin, '-rst', '-enable-lineno'] | ||
57 | |||
58 | filename = env.config.kerneldoc_srctree + '/' + self.arguments[0] | ||
59 | export_file_patterns = [] | ||
60 | |||
61 | # Tell sphinx of the dependency | ||
62 | env.note_dependency(os.path.abspath(filename)) | ||
63 | |||
64 | tab_width = self.options.get('tab-width', self.state.document.settings.tab_width) | ||
65 | |||
66 | # FIXME: make this nicer and more robust against errors | ||
67 | if 'export' in self.options: | ||
68 | cmd += ['-export'] | ||
69 | export_file_patterns = str(self.options.get('export')).split() | ||
70 | elif 'internal' in self.options: | ||
71 | cmd += ['-internal'] | ||
72 | export_file_patterns = str(self.options.get('internal')).split() | ||
73 | elif 'doc' in self.options: | ||
74 | cmd += ['-function', str(self.options.get('doc'))] | ||
75 | elif 'functions' in self.options: | ||
76 | for f in str(self.options.get('functions')).split(): | ||
77 | cmd += ['-function', f] | ||
78 | |||
79 | for pattern in export_file_patterns: | ||
80 | for f in glob.glob(env.config.kerneldoc_srctree + '/' + pattern): | ||
81 | env.note_dependency(os.path.abspath(f)) | ||
82 | cmd += ['-export-file', f] | ||
83 | |||
84 | cmd += [filename] | ||
85 | |||
86 | try: | ||
87 | env.app.verbose('calling kernel-doc \'%s\'' % (" ".join(cmd))) | ||
88 | |||
89 | p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) | ||
90 | out, err = p.communicate() | ||
91 | |||
92 | # python2 needs conversion to unicode. | ||
93 | # python3 with universal_newlines=True returns strings. | ||
94 | if sys.version_info.major < 3: | ||
95 | out, err = unicode(out, 'utf-8'), unicode(err, 'utf-8') | ||
96 | |||
97 | if p.returncode != 0: | ||
98 | sys.stderr.write(err) | ||
99 | |||
100 | env.app.warn('kernel-doc \'%s\' failed with return code %d' % (" ".join(cmd), p.returncode)) | ||
101 | return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))] | ||
102 | elif env.config.kerneldoc_verbosity > 0: | ||
103 | sys.stderr.write(err) | ||
104 | |||
105 | lines = statemachine.string2lines(out, tab_width, convert_whitespace=True) | ||
106 | result = ViewList() | ||
107 | |||
108 | lineoffset = 0; | ||
109 | line_regex = re.compile("^#define LINENO ([0-9]+)$") | ||
110 | for line in lines: | ||
111 | match = line_regex.search(line) | ||
112 | if match: | ||
113 | # sphinx counts lines from 0 | ||
114 | lineoffset = int(match.group(1)) - 1 | ||
115 | # we must eat our comments since the upset the markup | ||
116 | else: | ||
117 | result.append(line, filename, lineoffset) | ||
118 | lineoffset += 1 | ||
119 | |||
120 | node = nodes.section() | ||
121 | buf = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter | ||
122 | self.state.memo.reporter = AutodocReporter(result, self.state.memo.reporter) | ||
123 | self.state.memo.title_styles, self.state.memo.section_level = [], 0 | ||
124 | try: | ||
125 | self.state.nested_parse(result, 0, node, match_titles=1) | ||
126 | finally: | ||
127 | self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter = buf | ||
128 | |||
129 | return node.children | ||
130 | |||
131 | except Exception as e: # pylint: disable=W0703 | ||
132 | env.app.warn('kernel-doc \'%s\' processing failed with: %s' % | ||
133 | (" ".join(cmd), str(e))) | ||
134 | return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))] | ||
135 | |||
136 | def setup(app): | ||
137 | app.add_config_value('kerneldoc_bin', None, 'env') | ||
138 | app.add_config_value('kerneldoc_srctree', None, 'env') | ||
139 | app.add_config_value('kerneldoc_verbosity', 1, 'env') | ||
140 | |||
141 | app.add_directive('kernel-doc', KernelDocDirective) | ||
diff --git a/Documentation/sphinx/post_convert.sed b/Documentation/sphinx/post_convert.sed new file mode 100644 index 000000000000..392770bac53b --- /dev/null +++ b/Documentation/sphinx/post_convert.sed | |||
@@ -0,0 +1,23 @@ | |||
1 | # | ||
2 | # Unescape. | ||
3 | # | ||
4 | s/$bq/`/g | ||
5 | s/$lt/</g | ||
6 | s/$gt/>/g | ||
7 | # | ||
8 | # pandoc thinks that both "_" needs to be escaped. Remove the extra | ||
9 | # backslashes. | ||
10 | # | ||
11 | s/\\_/_/g | ||
12 | # | ||
13 | # Unwrap docproc directives. | ||
14 | # | ||
15 | s/^``DOCPROC: !E\(.*\)``$/.. kernel-doc:: \1\n :export:/ | ||
16 | s/^``DOCPROC: !I\(.*\)``$/.. kernel-doc:: \1\n :internal:/ | ||
17 | s/^``DOCPROC: !F\([^ ]*\) \(.*\)``$/.. kernel-doc:: \1\n :functions: \2/ | ||
18 | s/^``DOCPROC: !P\([^ ]*\) \(.*\)``$/.. kernel-doc:: \1\n :doc: \2/ | ||
19 | s/^``DOCPROC: \(!.*\)``$/.. WARNING: DOCPROC directive not supported: \1/ | ||
20 | # | ||
21 | # Trim trailing whitespace. | ||
22 | # | ||
23 | s/[[:space:]]*$// | ||
diff --git a/Documentation/sphinx/rstFlatTable.py b/Documentation/sphinx/rstFlatTable.py new file mode 100644 index 000000000000..26db852e3c74 --- /dev/null +++ b/Documentation/sphinx/rstFlatTable.py | |||
@@ -0,0 +1,365 @@ | |||
1 | #!/usr/bin/env python3 | ||
2 | # -*- coding: utf-8; mode: python -*- | ||
3 | # pylint: disable=C0330, R0903, R0912 | ||
4 | |||
5 | u""" | ||
6 | flat-table | ||
7 | ~~~~~~~~~~ | ||
8 | |||
9 | Implementation of the ``flat-table`` reST-directive. | ||
10 | |||
11 | :copyright: Copyright (C) 2016 Markus Heiser | ||
12 | :license: GPL Version 2, June 1991 see linux/COPYING for details. | ||
13 | |||
14 | The ``flat-table`` (:py:class:`FlatTable`) is a double-stage list similar to | ||
15 | the ``list-table`` with some additional features: | ||
16 | |||
17 | * *column-span*: with the role ``cspan`` a cell can be extended through | ||
18 | additional columns | ||
19 | |||
20 | * *row-span*: with the role ``rspan`` a cell can be extended through | ||
21 | additional rows | ||
22 | |||
23 | * *auto span* rightmost cell of a table row over the missing cells on the | ||
24 | right side of that table-row. With Option ``:fill-cells:`` this behavior | ||
25 | can changed from *auto span* to *auto fill*, which automaticly inserts | ||
26 | (empty) cells instead of spanning the last cell. | ||
27 | |||
28 | Options: | ||
29 | |||
30 | * header-rows: [int] count of header rows | ||
31 | * stub-columns: [int] count of stub columns | ||
32 | * widths: [[int] [int] ... ] widths of columns | ||
33 | * fill-cells: instead of autospann missing cells, insert missing cells | ||
34 | |||
35 | roles: | ||
36 | |||
37 | * cspan: [int] additionale columns (*morecols*) | ||
38 | * rspan: [int] additionale rows (*morerows*) | ||
39 | """ | ||
40 | |||
41 | # ============================================================================== | ||
42 | # imports | ||
43 | # ============================================================================== | ||
44 | |||
45 | import sys | ||
46 | |||
47 | from docutils import nodes | ||
48 | from docutils.parsers.rst import directives, roles | ||
49 | from docutils.parsers.rst.directives.tables import Table | ||
50 | from docutils.utils import SystemMessagePropagation | ||
51 | |||
52 | # ============================================================================== | ||
53 | # common globals | ||
54 | # ============================================================================== | ||
55 | |||
56 | # The version numbering follows numbering of the specification | ||
57 | # (Documentation/books/kernel-doc-HOWTO). | ||
58 | __version__ = '1.0' | ||
59 | |||
60 | PY3 = sys.version_info[0] == 3 | ||
61 | PY2 = sys.version_info[0] == 2 | ||
62 | |||
63 | if PY3: | ||
64 | # pylint: disable=C0103, W0622 | ||
65 | unicode = str | ||
66 | basestring = str | ||
67 | |||
68 | # ============================================================================== | ||
69 | def setup(app): | ||
70 | # ============================================================================== | ||
71 | |||
72 | app.add_directive("flat-table", FlatTable) | ||
73 | roles.register_local_role('cspan', c_span) | ||
74 | roles.register_local_role('rspan', r_span) | ||
75 | |||
76 | # ============================================================================== | ||
77 | def c_span(name, rawtext, text, lineno, inliner, options=None, content=None): | ||
78 | # ============================================================================== | ||
79 | # pylint: disable=W0613 | ||
80 | |||
81 | options = options if options is not None else {} | ||
82 | content = content if content is not None else [] | ||
83 | nodelist = [colSpan(span=int(text))] | ||
84 | msglist = [] | ||
85 | return nodelist, msglist | ||
86 | |||
87 | # ============================================================================== | ||
88 | def r_span(name, rawtext, text, lineno, inliner, options=None, content=None): | ||
89 | # ============================================================================== | ||
90 | # pylint: disable=W0613 | ||
91 | |||
92 | options = options if options is not None else {} | ||
93 | content = content if content is not None else [] | ||
94 | nodelist = [rowSpan(span=int(text))] | ||
95 | msglist = [] | ||
96 | return nodelist, msglist | ||
97 | |||
98 | |||
99 | # ============================================================================== | ||
100 | class rowSpan(nodes.General, nodes.Element): pass # pylint: disable=C0103,C0321 | ||
101 | class colSpan(nodes.General, nodes.Element): pass # pylint: disable=C0103,C0321 | ||
102 | # ============================================================================== | ||
103 | |||
104 | # ============================================================================== | ||
105 | class FlatTable(Table): | ||
106 | # ============================================================================== | ||
107 | |||
108 | u"""FlatTable (``flat-table``) directive""" | ||
109 | |||
110 | option_spec = { | ||
111 | 'name': directives.unchanged | ||
112 | , 'class': directives.class_option | ||
113 | , 'header-rows': directives.nonnegative_int | ||
114 | , 'stub-columns': directives.nonnegative_int | ||
115 | , 'widths': directives.positive_int_list | ||
116 | , 'fill-cells' : directives.flag } | ||
117 | |||
118 | def run(self): | ||
119 | |||
120 | if not self.content: | ||
121 | error = self.state_machine.reporter.error( | ||
122 | 'The "%s" directive is empty; content required.' % self.name, | ||
123 | nodes.literal_block(self.block_text, self.block_text), | ||
124 | line=self.lineno) | ||
125 | return [error] | ||
126 | |||
127 | title, messages = self.make_title() | ||
128 | node = nodes.Element() # anonymous container for parsing | ||
129 | self.state.nested_parse(self.content, self.content_offset, node) | ||
130 | |||
131 | tableBuilder = ListTableBuilder(self) | ||
132 | tableBuilder.parseFlatTableNode(node) | ||
133 | tableNode = tableBuilder.buildTableNode() | ||
134 | # SDK.CONSOLE() # print --> tableNode.asdom().toprettyxml() | ||
135 | if title: | ||
136 | tableNode.insert(0, title) | ||
137 | return [tableNode] + messages | ||
138 | |||
139 | |||
140 | # ============================================================================== | ||
141 | class ListTableBuilder(object): | ||
142 | # ============================================================================== | ||
143 | |||
144 | u"""Builds a table from a double-stage list""" | ||
145 | |||
146 | def __init__(self, directive): | ||
147 | self.directive = directive | ||
148 | self.rows = [] | ||
149 | self.max_cols = 0 | ||
150 | |||
151 | def buildTableNode(self): | ||
152 | |||
153 | colwidths = self.directive.get_column_widths(self.max_cols) | ||
154 | stub_columns = self.directive.options.get('stub-columns', 0) | ||
155 | header_rows = self.directive.options.get('header-rows', 0) | ||
156 | |||
157 | table = nodes.table() | ||
158 | tgroup = nodes.tgroup(cols=len(colwidths)) | ||
159 | table += tgroup | ||
160 | |||
161 | |||
162 | for colwidth in colwidths: | ||
163 | colspec = nodes.colspec(colwidth=colwidth) | ||
164 | # FIXME: It seems, that the stub method only works well in the | ||
165 | # absence of rowspan (observed by the html buidler, the docutils-xml | ||
166 | # build seems OK). This is not extraordinary, because there exists | ||
167 | # no table directive (except *this* flat-table) which allows to | ||
168 | # define coexistent of rowspan and stubs (there was no use-case | ||
169 | # before flat-table). This should be reviewed (later). | ||
170 | if stub_columns: | ||
171 | colspec.attributes['stub'] = 1 | ||
172 | stub_columns -= 1 | ||
173 | tgroup += colspec | ||
174 | stub_columns = self.directive.options.get('stub-columns', 0) | ||
175 | |||
176 | if header_rows: | ||
177 | thead = nodes.thead() | ||
178 | tgroup += thead | ||
179 | for row in self.rows[:header_rows]: | ||
180 | thead += self.buildTableRowNode(row) | ||
181 | |||
182 | tbody = nodes.tbody() | ||
183 | tgroup += tbody | ||
184 | |||
185 | for row in self.rows[header_rows:]: | ||
186 | tbody += self.buildTableRowNode(row) | ||
187 | return table | ||
188 | |||
189 | def buildTableRowNode(self, row_data, classes=None): | ||
190 | classes = [] if classes is None else classes | ||
191 | row = nodes.row() | ||
192 | for cell in row_data: | ||
193 | if cell is None: | ||
194 | continue | ||
195 | cspan, rspan, cellElements = cell | ||
196 | |||
197 | attributes = {"classes" : classes} | ||
198 | if rspan: | ||
199 | attributes['morerows'] = rspan | ||
200 | if cspan: | ||
201 | attributes['morecols'] = cspan | ||
202 | entry = nodes.entry(**attributes) | ||
203 | entry.extend(cellElements) | ||
204 | row += entry | ||
205 | return row | ||
206 | |||
207 | def raiseError(self, msg): | ||
208 | error = self.directive.state_machine.reporter.error( | ||
209 | msg | ||
210 | , nodes.literal_block(self.directive.block_text | ||
211 | , self.directive.block_text) | ||
212 | , line = self.directive.lineno ) | ||
213 | raise SystemMessagePropagation(error) | ||
214 | |||
215 | def parseFlatTableNode(self, node): | ||
216 | u"""parses the node from a :py:class:`FlatTable` directive's body""" | ||
217 | |||
218 | if len(node) != 1 or not isinstance(node[0], nodes.bullet_list): | ||
219 | self.raiseError( | ||
220 | 'Error parsing content block for the "%s" directive: ' | ||
221 | 'exactly one bullet list expected.' % self.directive.name ) | ||
222 | |||
223 | for rowNum, rowItem in enumerate(node[0]): | ||
224 | row = self.parseRowItem(rowItem, rowNum) | ||
225 | self.rows.append(row) | ||
226 | self.roundOffTableDefinition() | ||
227 | |||
228 | def roundOffTableDefinition(self): | ||
229 | u"""Round off the table definition. | ||
230 | |||
231 | This method rounds off the table definition in :py:member:`rows`. | ||
232 | |||
233 | * This method inserts the needed ``None`` values for the missing cells | ||
234 | arising from spanning cells over rows and/or columns. | ||
235 | |||
236 | * recount the :py:member:`max_cols` | ||
237 | |||
238 | * Autospan or fill (option ``fill-cells``) missing cells on the right | ||
239 | side of the table-row | ||
240 | """ | ||
241 | |||
242 | y = 0 | ||
243 | while y < len(self.rows): | ||
244 | x = 0 | ||
245 | |||
246 | while x < len(self.rows[y]): | ||
247 | cell = self.rows[y][x] | ||
248 | if cell is None: | ||
249 | x += 1 | ||
250 | continue | ||
251 | cspan, rspan = cell[:2] | ||
252 | # handle colspan in current row | ||
253 | for c in range(cspan): | ||
254 | try: | ||
255 | self.rows[y].insert(x+c+1, None) | ||
256 | except: # pylint: disable=W0702 | ||
257 | # the user sets ambiguous rowspans | ||
258 | pass # SDK.CONSOLE() | ||
259 | # handle colspan in spanned rows | ||
260 | for r in range(rspan): | ||
261 | for c in range(cspan + 1): | ||
262 | try: | ||
263 | self.rows[y+r+1].insert(x+c, None) | ||
264 | except: # pylint: disable=W0702 | ||
265 | # the user sets ambiguous rowspans | ||
266 | pass # SDK.CONSOLE() | ||
267 | x += 1 | ||
268 | y += 1 | ||
269 | |||
270 | # Insert the missing cells on the right side. For this, first | ||
271 | # re-calculate the max columns. | ||
272 | |||
273 | for row in self.rows: | ||
274 | if self.max_cols < len(row): | ||
275 | self.max_cols = len(row) | ||
276 | |||
277 | # fill with empty cells or cellspan? | ||
278 | |||
279 | fill_cells = False | ||
280 | if 'fill-cells' in self.directive.options: | ||
281 | fill_cells = True | ||
282 | |||
283 | for row in self.rows: | ||
284 | x = self.max_cols - len(row) | ||
285 | if x and not fill_cells: | ||
286 | if row[-1] is None: | ||
287 | row.append( ( x - 1, 0, []) ) | ||
288 | else: | ||
289 | cspan, rspan, content = row[-1] | ||
290 | row[-1] = (cspan + x, rspan, content) | ||
291 | elif x and fill_cells: | ||
292 | for i in range(x): | ||
293 | row.append( (0, 0, nodes.comment()) ) | ||
294 | |||
295 | def pprint(self): | ||
296 | # for debugging | ||
297 | retVal = "[ " | ||
298 | for row in self.rows: | ||
299 | retVal += "[ " | ||
300 | for col in row: | ||
301 | if col is None: | ||
302 | retVal += ('%r' % col) | ||
303 | retVal += "\n , " | ||
304 | else: | ||
305 | content = col[2][0].astext() | ||
306 | if len (content) > 30: | ||
307 | content = content[:30] + "..." | ||
308 | retVal += ('(cspan=%s, rspan=%s, %r)' | ||
309 | % (col[0], col[1], content)) | ||
310 | retVal += "]\n , " | ||
311 | retVal = retVal[:-2] | ||
312 | retVal += "]\n , " | ||
313 | retVal = retVal[:-2] | ||
314 | return retVal + "]" | ||
315 | |||
316 | def parseRowItem(self, rowItem, rowNum): | ||
317 | row = [] | ||
318 | childNo = 0 | ||
319 | error = False | ||
320 | cell = None | ||
321 | target = None | ||
322 | |||
323 | for child in rowItem: | ||
324 | if (isinstance(child , nodes.comment) | ||
325 | or isinstance(child, nodes.system_message)): | ||
326 | pass | ||
327 | elif isinstance(child , nodes.target): | ||
328 | target = child | ||
329 | elif isinstance(child, nodes.bullet_list): | ||
330 | childNo += 1 | ||
331 | cell = child | ||
332 | else: | ||
333 | error = True | ||
334 | break | ||
335 | |||
336 | if childNo != 1 or error: | ||
337 | self.raiseError( | ||
338 | 'Error parsing content block for the "%s" directive: ' | ||
339 | 'two-level bullet list expected, but row %s does not ' | ||
340 | 'contain a second-level bullet list.' | ||
341 | % (self.directive.name, rowNum + 1)) | ||
342 | |||
343 | for cellItem in cell: | ||
344 | cspan, rspan, cellElements = self.parseCellItem(cellItem) | ||
345 | if target is not None: | ||
346 | cellElements.insert(0, target) | ||
347 | row.append( (cspan, rspan, cellElements) ) | ||
348 | return row | ||
349 | |||
350 | def parseCellItem(self, cellItem): | ||
351 | # search and remove cspan, rspan colspec from the first element in | ||
352 | # this listItem (field). | ||
353 | cspan = rspan = 0 | ||
354 | if not len(cellItem): | ||
355 | return cspan, rspan, [] | ||
356 | for elem in cellItem[0]: | ||
357 | if isinstance(elem, colSpan): | ||
358 | cspan = elem.get("span") | ||
359 | elem.parent.remove(elem) | ||
360 | continue | ||
361 | if isinstance(elem, rowSpan): | ||
362 | rspan = elem.get("span") | ||
363 | elem.parent.remove(elem) | ||
364 | continue | ||
365 | return cspan, rspan, cellItem[:] | ||
diff --git a/Documentation/sphinx/tmplcvt b/Documentation/sphinx/tmplcvt new file mode 100755 index 000000000000..909a73065e0a --- /dev/null +++ b/Documentation/sphinx/tmplcvt | |||
@@ -0,0 +1,19 @@ | |||
1 | #!/bin/bash | ||
2 | # | ||
3 | # Convert a template file into something like RST | ||
4 | # | ||
5 | # fix <function> | ||
6 | # feed to pandoc | ||
7 | # fix \_ | ||
8 | # title line? | ||
9 | # | ||
10 | |||
11 | in=$1 | ||
12 | rst=$2 | ||
13 | tmp=$rst.tmp | ||
14 | |||
15 | cp $in $tmp | ||
16 | sed --in-place -f convert_template.sed $tmp | ||
17 | pandoc -s -S -f docbook -t rst -o $rst $tmp | ||
18 | sed --in-place -f post_convert.sed $rst | ||
19 | rm $tmp | ||
diff --git a/Documentation/sync_file.txt b/Documentation/sync_file.txt index eaf8297dbca2..e8e2ebafe5fa 100644 --- a/Documentation/sync_file.txt +++ b/Documentation/sync_file.txt | |||
@@ -6,8 +6,8 @@ | |||
6 | 6 | ||
7 | This document serves as a guide for device drivers writers on what the | 7 | This document serves as a guide for device drivers writers on what the |
8 | sync_file API is, and how drivers can support it. Sync file is the carrier of | 8 | sync_file API is, and how drivers can support it. Sync file is the carrier of |
9 | the fences(struct fence) that needs to synchronized between drivers or across | 9 | the fences(struct fence) that are needed to synchronize between drivers or |
10 | process boundaries. | 10 | across process boundaries. |
11 | 11 | ||
12 | The sync_file API is meant to be used to send and receive fence information | 12 | The sync_file API is meant to be used to send and receive fence information |
13 | to/from userspace. It enables userspace to do explicit fencing, where instead | 13 | to/from userspace. It enables userspace to do explicit fencing, where instead |
@@ -32,7 +32,7 @@ in-fences and out-fences | |||
32 | Sync files can go either to or from userspace. When a sync_file is sent from | 32 | Sync files can go either to or from userspace. When a sync_file is sent from |
33 | the driver to userspace we call the fences it contains 'out-fences'. They are | 33 | the driver to userspace we call the fences it contains 'out-fences'. They are |
34 | related to a buffer that the driver is processing or is going to process, so | 34 | related to a buffer that the driver is processing or is going to process, so |
35 | the driver an create out-fence to be able to notify, through fence_signal(), | 35 | the driver creates an out-fence to be able to notify, through fence_signal(), |
36 | when it has finished using (or processing) that buffer. Out-fences are fences | 36 | when it has finished using (or processing) that buffer. Out-fences are fences |
37 | that the driver creates. | 37 | that the driver creates. |
38 | 38 | ||
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt index 720355cbdf45..95ccbe6d79ce 100644 --- a/Documentation/sysctl/vm.txt +++ b/Documentation/sysctl/vm.txt | |||
@@ -61,6 +61,7 @@ Currently, these files are in /proc/sys/vm: | |||
61 | - swappiness | 61 | - swappiness |
62 | - user_reserve_kbytes | 62 | - user_reserve_kbytes |
63 | - vfs_cache_pressure | 63 | - vfs_cache_pressure |
64 | - watermark_scale_factor | ||
64 | - zone_reclaim_mode | 65 | - zone_reclaim_mode |
65 | 66 | ||
66 | ============================================================== | 67 | ============================================================== |
diff --git a/Documentation/thermal/intel_powerclamp.txt b/Documentation/thermal/intel_powerclamp.txt index 332de4a39b5a..60073dc9f748 100644 --- a/Documentation/thermal/intel_powerclamp.txt +++ b/Documentation/thermal/intel_powerclamp.txt | |||
@@ -121,7 +121,7 @@ time is considered largely as a non-causal system where its behavior | |||
121 | cannot be based on the past or current input. Therefore, the | 121 | cannot be based on the past or current input. Therefore, the |
122 | intel_powerclamp driver attempts to enforce the desired idle time | 122 | intel_powerclamp driver attempts to enforce the desired idle time |
123 | instantly as given input (target idle ratio). After injection, | 123 | instantly as given input (target idle ratio). After injection, |
124 | powerclamp moniors the actual idle for a given time window and adjust | 124 | powerclamp monitors the actual idle for a given time window and adjust |
125 | the next injection accordingly to avoid over/under correction. | 125 | the next injection accordingly to avoid over/under correction. |
126 | 126 | ||
127 | When used in a causal control system, such as a temperature control, | 127 | When used in a causal control system, such as a temperature control, |
diff --git a/Documentation/usb/gadget_multi.txt b/Documentation/usb/gadget_multi.txt index 5faf514047e9..b3146dd7aa43 100644 --- a/Documentation/usb/gadget_multi.txt +++ b/Documentation/usb/gadget_multi.txt | |||
@@ -36,7 +36,7 @@ configuration with CDC ECM which should work better under Linux. | |||
36 | 36 | ||
37 | ** Windows host drivers | 37 | ** Windows host drivers |
38 | 38 | ||
39 | For the gadget two work under Windows two conditions have to be met: | 39 | For the gadget to work under Windows two conditions have to be met: |
40 | 40 | ||
41 | *** Detecting as composite gadget | 41 | *** Detecting as composite gadget |
42 | 42 | ||
diff --git a/Documentation/workqueue.txt b/Documentation/workqueue.txt index 5e0e05c5183e..c49e3178178d 100644 --- a/Documentation/workqueue.txt +++ b/Documentation/workqueue.txt | |||
@@ -169,7 +169,7 @@ resources, scheduled and executed. | |||
169 | WQ_UNBOUND | 169 | WQ_UNBOUND |
170 | 170 | ||
171 | Work items queued to an unbound wq are served by the special | 171 | Work items queued to an unbound wq are served by the special |
172 | woker-pools which host workers which are not bound to any | 172 | worker-pools which host workers which are not bound to any |
173 | specific CPU. This makes the wq behave as a simple execution | 173 | specific CPU. This makes the wq behave as a simple execution |
174 | context provider without concurrency management. The unbound | 174 | context provider without concurrency management. The unbound |
175 | worker-pools try to start execution of work items as soon as | 175 | worker-pools try to start execution of work items as soon as |
diff --git a/Documentation/zh_CN/CodingStyle b/Documentation/zh_CN/CodingStyle index 654afd72eb24..12717791baac 100644 --- a/Documentation/zh_CN/CodingStyle +++ b/Documentation/zh_CN/CodingStyle | |||
@@ -24,34 +24,33 @@ Documentation/CodingStyleçš„ä¸æ–‡ç¿»è¯‘ | |||
24 | 24 | ||
25 | Linuxå†…æ ¸ä»£ç é£Žæ ¼ | 25 | Linuxå†…æ ¸ä»£ç é£Žæ ¼ |
26 | 26 | ||
27 | 这是一个简çŸçš„æ–‡æ¡£ï¼Œæè¿°äº†linuxå†…æ ¸çš„é¦–é€‰ä»£ç é£Žæ ¼ã€‚ä»£ç é£Žæ ¼æ˜¯å› äººè€Œå¼‚çš„ï¼Œè€Œä¸”æˆ‘ | 27 | 这是一个简çŸçš„æ–‡æ¡£ï¼Œæè¿°äº† linux å†…æ ¸çš„é¦–é€‰ä»£ç é£Žæ ¼ã€‚ä»£ç é£Žæ ¼æ˜¯å› äººè€Œå¼‚çš„ï¼Œè€Œä¸”æˆ‘ |
28 | 䏿„¿æ„æŠŠæˆ‘çš„è§‚ç‚¹å¼ºåŠ ç»™ä»»ä½•äººï¼Œä¸è¿‡è¿™é‡Œæ‰€è®²è¿°çš„æ˜¯æˆ‘å¿…é¡»è¦ç»´æŠ¤çš„ä»£ç æ‰€éµå®ˆçš„é£Žæ ¼ï¼Œ | 28 | 䏿„¿æ„æŠŠè‡ªå·±çš„è§‚ç‚¹å¼ºåŠ ç»™ä»»ä½•äººï¼Œä½†è¿™å°±åƒæˆ‘去åšä»»ä½•事情都必须éµå¾ªçš„åŽŸåˆ™é‚£æ ·ï¼Œæˆ‘ä¹Ÿ |
29 | 并且我也希望ç»å¤§å¤šæ•°å…¶ä»–代ç 也能éµå®ˆè¿™ä¸ªé£Žæ ¼ã€‚è¯·åœ¨å†™ä»£ç æ—¶è‡³å°‘考虑一下本文所述的 | 29 | 希望在ç»å¤§å¤šæ•°äº‹ä¸Šä¿æŒè¿™ç§çš„æ€åº¦ã€‚è¯·ï¼ˆåœ¨å†™ä»£ç æ—¶ï¼‰è‡³å°‘考虑一下这里的代ç é£Žæ ¼ã€‚ |
30 | é£Žæ ¼ã€‚ | ||
31 | 30 | ||
32 | é¦–å…ˆï¼Œæˆ‘å»ºè®®ä½ æ‰“å°ä¸€ä»½GNU代ç 规范,然åŽä¸è¦è¯»å®ƒã€‚烧了它,这是一个具有é‡å¤§è±¡å¾æ€§ | 31 | é¦–å…ˆï¼Œæˆ‘å»ºè®®ä½ æ‰“å°ä¸€ä»½ GNU 代ç 规范,然åŽä¸è¦è¯»ã€‚烧了它,这是一个具有é‡å¤§è±¡å¾æ€§æ„义 |
33 | æ„义的动作。 | 32 | 的动作。 |
34 | 33 | ||
35 | ä¸ç®¡æ€Žæ ·ï¼ŒçŽ°åœ¨æˆ‘ä»¬å¼€å§‹ï¼š | 34 | ä¸ç®¡æ€Žæ ·ï¼ŒçŽ°åœ¨æˆ‘ä»¬å¼€å§‹ï¼š |
36 | 35 | ||
37 | 36 | ||
38 | ç¬¬ä¸€ç« ï¼šç¼©è¿› | 37 | ç¬¬ä¸€ç« ï¼šç¼©è¿› |
39 | 38 | ||
40 | 制表符是8个å—符,所以缩进也是8个å—符。有些异端è¿åŠ¨è¯•å›¾å°†ç¼©è¿›å˜ä¸º4(乃至2)个å—符 | 39 | 制表符是 8 个å—符,所以缩进也是 8 个å—符。有些异端è¿åŠ¨è¯•å›¾å°†ç¼©è¿›å˜ä¸º 4(甚至 2ï¼ï¼‰ |
41 | æ·±ï¼Œè¿™å‡ ä¹Žç›¸å½“äºŽå°è¯•将圆周率的值定义为3。 | 40 | 个å—ç¬¦æ·±ï¼Œè¿™å‡ ä¹Žç›¸å½“äºŽå°è¯•将圆周率的值定义为 3。 |
42 | 41 | ||
43 | ç†ç”±ï¼šç¼©è¿›çš„全部æ„义就在于清楚的定义一个控制å—èµ·æ¢äºŽä½•å¤„ã€‚å°¤å…¶æ˜¯å½“ä½ ç›¯ç€ä½ çš„å±å¹• | 42 | ç†ç”±ï¼šç¼©è¿›çš„全部æ„义就在于清楚的定义一个控制å—èµ·æ¢äºŽä½•å¤„ã€‚å°¤å…¶æ˜¯å½“ä½ ç›¯ç€ä½ çš„å±å¹• |
44 | 连ç»çœ‹äº†20å°æ—¶ä¹‹åŽï¼Œä½ 将会å‘çŽ°å¤§ä¸€ç‚¹çš„ç¼©è¿›ä¼šä½¿ä½ æ›´å®¹æ˜“åˆ†è¾¨ç¼©è¿›ã€‚ | 43 | 连ç»çœ‹äº† 20 å°æ—¶ä¹‹åŽï¼Œä½ 将会å‘çŽ°å¤§ä¸€ç‚¹çš„ç¼©è¿›ä¼šä½¿ä½ æ›´å®¹æ˜“åˆ†è¾¨ç¼©è¿›ã€‚ |
45 | 44 | ||
46 | 现在,有些人会抱怨8个å—符的缩进会使代ç å‘å³è¾¹ç§»åŠ¨çš„å¤ªè¿œï¼Œåœ¨80个å—符的终端å±å¹•上 | 45 | 现在,有些人会抱怨 8 个å—符的缩进会使代ç å‘å³è¾¹ç§»åŠ¨çš„å¤ªè¿œï¼Œåœ¨ 80 个å—符的终端å±å¹•上 |
47 | å°±å¾ˆéš¾è¯»è¿™æ ·çš„ä»£ç ã€‚è¿™ä¸ªé—®é¢˜çš„ç”æ¡ˆæ˜¯ï¼Œå¦‚æžœä½ éœ€è¦3级以上的缩进,ä¸ç®¡ç”¨ä½•ç§æ–¹å¼ä½ | 46 | å°±å¾ˆéš¾è¯»è¿™æ ·çš„ä»£ç ã€‚è¿™ä¸ªé—®é¢˜çš„ç”æ¡ˆæ˜¯ï¼Œå¦‚æžœä½ éœ€è¦ 3 级以上的缩进,ä¸ç®¡ç”¨ä½•ç§æ–¹å¼ä½ |
48 | 的代ç å·²ç»æœ‰é—®é¢˜äº†ï¼Œåº”该修æ£ä½ 的程åºã€‚ | 47 | 的代ç å·²ç»æœ‰é—®é¢˜äº†ï¼Œåº”该修æ£ä½ 的程åºã€‚ |
49 | 48 | ||
50 | 简而言之,8个å—符的缩进å¯ä»¥è®©ä»£ç æ›´å®¹æ˜“é˜…è¯»ï¼Œè¿˜æœ‰ä¸€ä¸ªå¥½å¤„æ˜¯å½“ä½ çš„å‡½æ•°åµŒå¥—å¤ªæ·±çš„ | 49 | 简而言之,8 个å—符的缩进å¯ä»¥è®©ä»£ç æ›´å®¹æ˜“é˜…è¯»ï¼Œè¿˜æœ‰ä¸€ä¸ªå¥½å¤„æ˜¯å½“ä½ çš„å‡½æ•°åµŒå¥—å¤ªæ·±çš„ |
51 | 时候å¯ä»¥ç»™ä½ è¦å‘Šã€‚留心这个è¦å‘Šã€‚ | 50 | 时候å¯ä»¥ç»™ä½ è¦å‘Šã€‚留心这个è¦å‘Šã€‚ |
52 | 51 | ||
53 | 在switchè¯å¥ä¸æ¶ˆé™¤å¤šçº§ç¼©è¿›çš„é¦–é€‰çš„æ–¹å¼æ˜¯è®©â€œswitchâ€å’Œä»Žå±žäºŽå®ƒçš„“caseâ€æ ‡ç¾å¯¹é½äºŽåŒ | 52 | 在 switch è¯å¥ä¸æ¶ˆé™¤å¤šçº§ç¼©è¿›çš„é¦–é€‰çš„æ–¹å¼æ˜¯è®© “switch†和从属于它的 “caseâ€ æ ‡ç¾ |
54 | 一列,而ä¸è¦â€œä¸¤æ¬¡ç¼©è¿›â€â€œcaseâ€æ ‡ç¾ã€‚比如: | 53 | 对é½äºŽåŒä¸€åˆ—,而ä¸è¦ “两次缩进†“caseâ€ æ ‡ç¾ã€‚比如: |
55 | 54 | ||
56 | switch (suffix) { | 55 | switch (suffix) { |
57 | case 'G': | 56 | case 'G': |
@@ -70,7 +69,6 @@ Documentation/CodingStyleçš„ä¸æ–‡ç¿»è¯‘ | |||
70 | break; | 69 | break; |
71 | } | 70 | } |
72 | 71 | ||
73 | |||
74 | ä¸è¦æŠŠå¤šä¸ªè¯å¥æ”¾åœ¨ä¸€è¡Œé‡Œï¼Œé™¤éžä½ 有什么东西è¦éšè—: | 72 | ä¸è¦æŠŠå¤šä¸ªè¯å¥æ”¾åœ¨ä¸€è¡Œé‡Œï¼Œé™¤éžä½ 有什么东西è¦éšè—: |
75 | 73 | ||
76 | if (condition) do_this; | 74 | if (condition) do_this; |
@@ -79,7 +77,7 @@ Documentation/CodingStyleçš„ä¸æ–‡ç¿»è¯‘ | |||
79 | 也ä¸è¦åœ¨ä¸€è¡Œé‡Œæ”¾å¤šä¸ªèµ‹å€¼è¯å¥ã€‚å†…æ ¸ä»£ç é£Žæ ¼è¶…çº§ç®€å•。就是é¿å…å¯èƒ½å¯¼è‡´åˆ«äººè¯¯è¯»çš„表 | 77 | 也ä¸è¦åœ¨ä¸€è¡Œé‡Œæ”¾å¤šä¸ªèµ‹å€¼è¯å¥ã€‚å†…æ ¸ä»£ç é£Žæ ¼è¶…çº§ç®€å•。就是é¿å…å¯èƒ½å¯¼è‡´åˆ«äººè¯¯è¯»çš„表 |
80 | è¾¾å¼ã€‚ | 78 | è¾¾å¼ã€‚ |
81 | 79 | ||
82 | é™¤äº†æ³¨é‡Šã€æ–‡æ¡£å’ŒKconfig之外,ä¸è¦ä½¿ç”¨ç©ºæ ¼æ¥ç¼©è¿›ï¼Œå‰é¢çš„ä¾‹åæ˜¯ä¾‹å¤–,是有æ„为之。 | 80 | é™¤äº†æ³¨é‡Šã€æ–‡æ¡£å’Œ Kconfig 之外,ä¸è¦ä½¿ç”¨ç©ºæ ¼æ¥ç¼©è¿›ï¼Œå‰é¢çš„ä¾‹åæ˜¯ä¾‹å¤–,是有æ„为之。 |
83 | 81 | ||
84 | 选用一个好的编辑器,ä¸è¦åœ¨è¡Œå°¾ç•™ç©ºæ ¼ã€‚ | 82 | 选用一个好的编辑器,ä¸è¦åœ¨è¡Œå°¾ç•™ç©ºæ ¼ã€‚ |
85 | 83 | ||
@@ -88,27 +86,18 @@ Documentation/CodingStyleçš„ä¸æ–‡ç¿»è¯‘ | |||
88 | 86 | ||
89 | 代ç é£Žæ ¼çš„æ„义就在于使用平常使用的工具æ¥ç»´æŒä»£ç çš„å¯è¯»æ€§å’Œå¯ç»´æŠ¤æ€§ã€‚ | 87 | 代ç é£Žæ ¼çš„æ„义就在于使用平常使用的工具æ¥ç»´æŒä»£ç çš„å¯è¯»æ€§å’Œå¯ç»´æŠ¤æ€§ã€‚ |
90 | 88 | ||
91 | æ¯ä¸€è¡Œçš„长度的é™åˆ¶æ˜¯80列,我们强烈建议您éµå®ˆè¿™ä¸ªæƒ¯ä¾‹ã€‚ | 89 | æ¯ä¸€è¡Œçš„长度的é™åˆ¶æ˜¯ 80 列,我们强烈建议您éµå®ˆè¿™ä¸ªæƒ¯ä¾‹ã€‚ |
92 | 90 | ||
93 | 长于80列的è¯å¥è¦æ‰“æ•£æˆæœ‰æ„义的片段。æ¯ä¸ªç‰‡æ®µè¦æ˜Žæ˜¾çŸäºŽåŽŸæ¥çš„è¯å¥ï¼Œè€Œä¸”放置的ä½ç½® | 91 | 长于 80 列的è¯å¥è¦æ‰“æ•£æˆæœ‰æ„义的片段。除éžè¶…过 80 åˆ—èƒ½æ˜¾è‘—å¢žåŠ å¯è¯»æ€§ï¼Œå¹¶ä¸”ä¸ä¼šéšè— |
94 | 也明显的é å³ã€‚åŒæ ·çš„è§„åˆ™ä¹Ÿé€‚ç”¨äºŽæœ‰å¾ˆé•¿å‚æ•°åˆ—表的函数头。长å—ç¬¦ä¸²ä¹Ÿè¦æ‰“æ•£æˆè¾ƒçŸçš„ | 92 | ä¿¡æ¯ã€‚åç‰‡æ®µè¦æ˜Žæ˜¾çŸäºŽæ¯ç‰‡æ®µï¼Œå¹¶æ˜Žæ˜¾é å³ã€‚è¿™åŒæ ·é€‚用于有ç€å¾ˆé•¿å‚数列表的函数头。 |
95 | å—符串。唯一的例外是超过80列å¯ä»¥å¤§å¹…度æé«˜å¯è¯»æ€§å¹¶ä¸”ä¸ä¼šéšè—ä¿¡æ¯çš„æƒ…况。 | 93 | 然而,ç»å¯¹ä¸è¦æ‰“散对用户å¯è§çš„å—符串,例如 printk ä¿¡æ¯ï¼Œå› ä¸ºè¿™å°†å¯¼è‡´æ— æ³• grep 这些 |
96 | 94 | ä¿¡æ¯ã€‚ | |
97 | void fun(int a, int b, int c) | ||
98 | { | ||
99 | if (condition) | ||
100 | printk(KERN_WARNING "Warning this is a long printk with " | ||
101 | "3 parameters a: %u b: %u " | ||
102 | "c: %u \n", a, b, c); | ||
103 | else | ||
104 | next_statement; | ||
105 | } | ||
106 | 95 | ||
107 | ç¬¬ä¸‰ç« ï¼šå¤§æ‹¬å·å’Œç©ºæ ¼çš„æ”¾ç½® | 96 | ç¬¬ä¸‰ç« ï¼šå¤§æ‹¬å·å’Œç©ºæ ¼çš„æ”¾ç½® |
108 | 97 | ||
109 | Cè¯è¨€é£Žæ ¼ä¸å¦å¤–一个常è§é—®é¢˜æ˜¯å¤§æ‹¬å·çš„æ”¾ç½®ã€‚和缩进大å°ä¸åŒï¼Œé€‰æ‹©æˆ–弃用æŸç§æ”¾ç½®ç– | 98 | Cè¯è¨€é£Žæ ¼ä¸å¦å¤–一个常è§é—®é¢˜æ˜¯å¤§æ‹¬å·çš„æ”¾ç½®ã€‚和缩进大å°ä¸åŒï¼Œé€‰æ‹©æˆ–弃用æŸç§æ”¾ç½®ç– |
110 | ç•¥å¹¶æ²¡æœ‰å¤šå°‘æŠ€æœ¯ä¸Šçš„åŽŸå› ï¼Œä¸è¿‡é¦–选的方å¼ï¼Œå°±åƒKernighanå’ŒRitchie展示给我们的,是 | 99 | ç•¥å¹¶æ²¡æœ‰å¤šå°‘æŠ€æœ¯ä¸Šçš„åŽŸå› ï¼Œä¸è¿‡é¦–选的方å¼ï¼Œå°±åƒ Kernighan å’Œ Ritchie 展示给我们的, |
111 | æŠŠèµ·å§‹å¤§æ‹¬å·æ”¾åœ¨è¡Œå°¾ï¼Œè€ŒæŠŠç»“æŸå¤§æ‹¬å·æ”¾åœ¨è¡Œé¦–,所以: | 100 | æ˜¯æŠŠèµ·å§‹å¤§æ‹¬å·æ”¾åœ¨è¡Œå°¾ï¼Œè€ŒæŠŠç»“æŸå¤§æ‹¬å·æ”¾åœ¨è¡Œé¦–,所以: |
112 | 101 | ||
113 | if (x is true) { | 102 | if (x is true) { |
114 | we do y | 103 | we do y |
@@ -134,12 +123,12 @@ Cè¯è¨€é£Žæ ¼ä¸å¦å¤–一个常è§é—®é¢˜æ˜¯å¤§æ‹¬å·çš„æ”¾ç½®ã€‚和缩进大å°ä | |||
134 | body of function | 123 | body of function |
135 | } | 124 | } |
136 | 125 | ||
137 | 全世界的异端å¯èƒ½ä¼šæŠ±æ€¨è¿™ä¸ªä¸ä¸€è‡´æ€§æ˜¯â€¦â€¦å‘ƒâ€¦â€¦ä¸ä¸€è‡´çš„,ä¸è¿‡æ‰€æœ‰æ€ç»´å¥å…¨çš„人都知é“( | 126 | 全世界的异端å¯èƒ½ä¼šæŠ±æ€¨è¿™ä¸ªä¸ä¸€è‡´æ€§æ˜¯â€¦â€¦å‘ƒâ€¦â€¦ä¸ä¸€è‡´çš„,ä¸è¿‡æ‰€æœ‰æ€ç»´å¥å…¨çš„äººéƒ½çŸ¥é“ |
138 | a)K&R是_æ£ç¡®çš„_,并且(b)K&R是æ£ç¡®çš„。æ¤å¤–,ä¸ç®¡æ€Žæ ·å‡½æ•°éƒ½æ˜¯ç‰¹æ®Šçš„(在Cè¯è¨€ä¸ | 127 | (a) K&R 是 _æ£ç¡®çš„_,并且 (b) K&R 是æ£ç¡®çš„。æ¤å¤–,ä¸ç®¡æ€Žæ ·å‡½æ•°éƒ½æ˜¯ç‰¹æ®Šçš„(C |
139 | ,函数是ä¸èƒ½åµŒå¥—的)。 | 128 | 函数是ä¸èƒ½åµŒå¥—的)。 |
140 | 129 | ||
141 | 注æ„结æŸå¤§æ‹¬å·ç‹¬è‡ªå æ®ä¸€è¡Œï¼Œé™¤éžå®ƒåŽé¢è·Ÿç€åŒä¸€ä¸ªè¯å¥çš„剩余部分,也就是doè¯å¥ä¸çš„ | 130 | 注æ„结æŸå¤§æ‹¬å·ç‹¬è‡ªå æ®ä¸€è¡Œï¼Œé™¤éžå®ƒåŽé¢è·Ÿç€åŒä¸€ä¸ªè¯å¥çš„剩余部分,也就是 do è¯å¥ä¸çš„ |
142 | “whileâ€æˆ–者ifè¯å¥ä¸çš„“elseâ€ï¼Œåƒè¿™æ ·ï¼š | 131 | “while†或者 if è¯å¥ä¸çš„ “elseâ€ï¼Œåƒè¿™æ ·ï¼š |
143 | 132 | ||
144 | do { | 133 | do { |
145 | body of do-loop | 134 | body of do-loop |
@@ -158,41 +147,50 @@ a)K&R是_æ£ç¡®çš„_,并且(b)K&R是æ£ç¡®çš„。æ¤å¤–,ä¸ç®¡æ€Žæ ·å‡½æ | |||
158 | ç†ç”±ï¼šK&R。 | 147 | ç†ç”±ï¼šK&R。 |
159 | 148 | ||
160 | 也请注æ„è¿™ç§å¤§æ‹¬å·çš„æ”¾ç½®æ–¹å¼ä¹Ÿèƒ½ä½¿ç©ºï¼ˆæˆ–者差ä¸å¤šç©ºçš„ï¼‰è¡Œçš„æ•°é‡æœ€å°åŒ–ï¼ŒåŒæ—¶ä¸å¤±å¯ | 149 | 也请注æ„è¿™ç§å¤§æ‹¬å·çš„æ”¾ç½®æ–¹å¼ä¹Ÿèƒ½ä½¿ç©ºï¼ˆæˆ–者差ä¸å¤šç©ºçš„ï¼‰è¡Œçš„æ•°é‡æœ€å°åŒ–ï¼ŒåŒæ—¶ä¸å¤±å¯ |
161 | è¯»æ€§ã€‚å› æ¤ï¼Œç”±äºŽä½ çš„å±å¹•上的新行是ä¸å¯å†ç”Ÿèµ„æºï¼ˆæƒ³æƒ³25行的终端å±å¹•ï¼‰ï¼Œä½ å°†ä¼šæœ‰æ›´ | 150 | è¯»æ€§ã€‚å› æ¤ï¼Œç”±äºŽä½ çš„å±å¹•上的新行是ä¸å¯å†ç”Ÿèµ„æºï¼ˆæƒ³æƒ³ 25 行的终端å±å¹•ï¼‰ï¼Œä½ å°†ä¼šæœ‰æ›´ |
162 | å¤šçš„ç©ºè¡Œæ¥æ”¾ç½®æ³¨é‡Šã€‚ | 151 | å¤šçš„ç©ºè¡Œæ¥æ”¾ç½®æ³¨é‡Šã€‚ |
163 | 152 | ||
164 | å½“åªæœ‰ä¸€ä¸ªå•独的è¯å¥çš„æ—¶å€™ï¼Œä¸ç”¨åŠ ä¸å¿…è¦çš„大括å·ã€‚ | 153 | å½“åªæœ‰ä¸€ä¸ªå•独的è¯å¥çš„æ—¶å€™ï¼Œä¸ç”¨åŠ ä¸å¿…è¦çš„大括å·ã€‚ |
165 | 154 | ||
166 | if (condition) | 155 | if (condition) |
167 | action(); | 156 | action(); |
157 | |||
158 | 和 | ||
159 | |||
160 | if (condition) | ||
161 | do_this(); | ||
162 | else | ||
163 | do_that(); | ||
168 | 164 | ||
169 | 这点ä¸é€‚用于本身为æŸä¸ªæ¡ä»¶è¯å¥çš„一个分支的å•独è¯å¥ã€‚这时需è¦åœ¨ä¸¤ä¸ªåˆ†æ”¯é‡Œéƒ½ä½¿ç”¨å¤§ | 165 | 这并ä¸é€‚ç”¨äºŽåªæœ‰ä¸€ä¸ªæ¡ä»¶åˆ†æ”¯æ˜¯å•è¯å¥çš„æƒ…况;这时所有分支都è¦ä½¿ç”¨å¤§æ‹¬å·ï¼š |
170 | 括å·ã€‚ | ||
171 | 166 | ||
172 | if (condition) { | 167 | if (condition) { |
173 | do_this(); | 168 | do_this(); |
174 | do_that(); | 169 | do_that(); |
175 | } else { | 170 | } else { |
176 | otherwise(); | 171 | otherwise(); |
177 | } | 172 | } |
178 | 173 | ||
179 | 3.1ï¼šç©ºæ ¼ | 174 | 3.1ï¼šç©ºæ ¼ |
180 | 175 | ||
181 | Linuxå†…æ ¸çš„ç©ºæ ¼ä½¿ç”¨æ–¹å¼ï¼ˆä¸»è¦ï¼‰å–决于它是用于函数还是关键å—。(大多数)关键å—åŽ | 176 | Linux å†…æ ¸çš„ç©ºæ ¼ä½¿ç”¨æ–¹å¼ï¼ˆä¸»è¦ï¼‰å–决于它是用于函数还是关键å—。(大多数)关键å—åŽ |
182 | è¦åŠ ä¸€ä¸ªç©ºæ ¼ã€‚å€¼å¾—æ³¨æ„的例外是sizeofã€typeofã€alignofå’Œ__attribute__ï¼Œè¿™äº›å…³é”®å— | 177 | è¦åŠ ä¸€ä¸ªç©ºæ ¼ã€‚å€¼å¾—æ³¨æ„的例外是 sizeofã€typeofã€alignof å’Œ __attribute__,这些 |
183 | æŸäº›ç¨‹åº¦ä¸Šçœ‹èµ·æ¥æ›´åƒå‡½æ•°ï¼ˆå®ƒä»¬åœ¨Linux里也常常伴éšå°æ‹¬å·è€Œä½¿ç”¨ï¼Œå°½ç®¡åœ¨Cè¯è¨€é‡Œè¿™æ · | 178 | 关键嗿Ÿäº›ç¨‹åº¦ä¸Šçœ‹èµ·æ¥æ›´åƒå‡½æ•°ï¼ˆå®ƒä»¬åœ¨ Linux 里也常常伴éšå°æ‹¬å·è€Œä½¿ç”¨ï¼Œå°½ç®¡åœ¨ C 里 |
184 | çš„å°æ‹¬å·ä¸æ˜¯å¿…需的,就åƒâ€œstruct fileinfo infoâ€å£°æ˜Žè¿‡åŽçš„“sizeof infoâ€ï¼‰ã€‚ | 179 | è¿™æ ·çš„å°æ‹¬å·ä¸æ˜¯å¿…éœ€çš„ï¼Œå°±åƒ â€œstruct fileinfo info†声明过åŽçš„ “sizeof infoâ€ï¼‰ã€‚ |
185 | 180 | ||
186 | 所以在这些关键å—ä¹‹åŽæ”¾ä¸€ä¸ªç©ºæ ¼ï¼š | 181 | 所以在这些关键å—ä¹‹åŽæ”¾ä¸€ä¸ªç©ºæ ¼ï¼š |
182 | |||
187 | if, switch, case, for, do, while | 183 | if, switch, case, for, do, while |
188 | 但是ä¸è¦åœ¨sizeofã€typeofã€alignof或者__attribute__这些关键å—ä¹‹åŽæ”¾ç©ºæ ¼ã€‚例如, | 184 | |
185 | 但是ä¸è¦åœ¨ sizeofã€typeofã€alignof 或者 __attribute__ 这些关键å—ä¹‹åŽæ”¾ç©ºæ ¼ã€‚例如, | ||
186 | |||
189 | s = sizeof(struct file); | 187 | s = sizeof(struct file); |
190 | 188 | ||
191 | ä¸è¦åœ¨å°æ‹¬å·é‡Œçš„表达å¼ä¸¤ä¾§åŠ ç©ºæ ¼ã€‚è¿™æ˜¯ä¸€ä¸ªå例: | 189 | ä¸è¦åœ¨å°æ‹¬å·é‡Œçš„表达å¼ä¸¤ä¾§åŠ ç©ºæ ¼ã€‚è¿™æ˜¯ä¸€ä¸ªå例: |
192 | 190 | ||
193 | s = sizeof( struct file ); | 191 | s = sizeof( struct file ); |
194 | 192 | ||
195 | 当声明指针类型或者返回指针类型的函数时,“*â€çš„é¦–é€‰ä½¿ç”¨æ–¹å¼æ˜¯ä½¿ä¹‹é è¿‘å˜é‡å或者函 | 193 | 当声明指针类型或者返回指针类型的函数时,“*â€ çš„é¦–é€‰ä½¿ç”¨æ–¹å¼æ˜¯ä½¿ä¹‹é è¿‘å˜é‡å或者函 |
196 | æ•°åï¼Œè€Œä¸æ˜¯é 近类型å。例å: | 194 | æ•°åï¼Œè€Œä¸æ˜¯é 近类型å。例å: |
197 | 195 | ||
198 | char *linux_banner; | 196 | char *linux_banner; |
@@ -204,15 +202,18 @@ Linuxå†…æ ¸çš„ç©ºæ ¼ä½¿ç”¨æ–¹å¼ï¼ˆä¸»è¦ï¼‰å–决于它是用于函数还是关 | |||
204 | = + - < > * / % | & ^ <= >= == != ? : | 202 | = + - < > * / % | & ^ <= >= == != ? : |
205 | 203 | ||
206 | 但是一元æ“作符åŽä¸è¦åŠ ç©ºæ ¼ï¼š | 204 | 但是一元æ“作符åŽä¸è¦åŠ ç©ºæ ¼ï¼š |
205 | |||
207 | & * + - ~ ! sizeof typeof alignof __attribute__ defined | 206 | & * + - ~ ! sizeof typeof alignof __attribute__ defined |
208 | 207 | ||
209 | åŽç¼€è‡ªåŠ å’Œè‡ªå‡ä¸€å…ƒæ“作符å‰ä¸åŠ ç©ºæ ¼ï¼š | 208 | åŽç¼€è‡ªåŠ å’Œè‡ªå‡ä¸€å…ƒæ“作符å‰ä¸åŠ ç©ºæ ¼ï¼š |
209 | |||
210 | ++ -- | 210 | ++ -- |
211 | 211 | ||
212 | å‰ç¼€è‡ªåŠ å’Œè‡ªå‡ä¸€å…ƒæ“作符åŽä¸åŠ ç©ºæ ¼ï¼š | 212 | å‰ç¼€è‡ªåŠ å’Œè‡ªå‡ä¸€å…ƒæ“作符åŽä¸åŠ ç©ºæ ¼ï¼š |
213 | |||
213 | ++ -- | 214 | ++ -- |
214 | 215 | ||
215 | “.â€å’Œâ€œ->â€ç»“构体æˆå‘˜æ“作符å‰åŽä¸åŠ ç©ºæ ¼ã€‚ | 216 | ‘.’ å’Œ “->†结构体æˆå‘˜æ“作符å‰åŽä¸åŠ ç©ºæ ¼ã€‚ |
216 | 217 | ||
217 | ä¸è¦åœ¨è¡Œå°¾ç•™ç©ºç™½ã€‚有些å¯ä»¥è‡ªåŠ¨ç¼©è¿›çš„ç¼–è¾‘å™¨ä¼šåœ¨æ–°è¡Œçš„è¡Œé¦–åŠ å…¥é€‚é‡çš„空白,然åŽä½ | 218 | ä¸è¦åœ¨è¡Œå°¾ç•™ç©ºç™½ã€‚有些å¯ä»¥è‡ªåŠ¨ç¼©è¿›çš„ç¼–è¾‘å™¨ä¼šåœ¨æ–°è¡Œçš„è¡Œé¦–åŠ å…¥é€‚é‡çš„空白,然åŽä½ |
218 | å°±å¯ä»¥ç›´æŽ¥åœ¨é‚£ä¸€è¡Œè¾“入代ç 。ä¸è¿‡å‡å¦‚ä½ æœ€åŽæ²¡æœ‰åœ¨é‚£ä¸€è¡Œè¾“入代ç ï¼Œæœ‰äº›ç¼–è¾‘å™¨å°±ä¸ | 219 | å°±å¯ä»¥ç›´æŽ¥åœ¨é‚£ä¸€è¡Œè¾“入代ç 。ä¸è¿‡å‡å¦‚ä½ æœ€åŽæ²¡æœ‰åœ¨é‚£ä¸€è¡Œè¾“入代ç ï¼Œæœ‰äº›ç¼–è¾‘å™¨å°±ä¸ |
@@ -225,23 +226,23 @@ Linuxå†…æ ¸çš„ç©ºæ ¼ä½¿ç”¨æ–¹å¼ï¼ˆä¸»è¦ï¼‰å–决于它是用于函数还是关 | |||
225 | 226 | ||
226 | ç¬¬å››ç« ï¼šå‘½å | 227 | ç¬¬å››ç« ï¼šå‘½å |
227 | 228 | ||
228 | C是一个简朴的è¯è¨€ï¼Œä½ 的命åä¹Ÿåº”è¯¥è¿™æ ·ã€‚å’ŒModula-2å’ŒPascal程åºå‘˜ä¸åŒï¼ŒC程åºå‘˜ä¸ä½¿ | 229 | C是一个简朴的è¯è¨€ï¼Œä½ 的命åä¹Ÿåº”è¯¥è¿™æ ·ã€‚å’Œ Modula-2 å’Œ Pascal 程åºå‘˜ä¸åŒï¼ŒC 程åºå‘˜ |
229 | 用类似ThisVariableIsATemporaryCounterè¿™æ ·åŽä¸½çš„åå—。C程åºå‘˜ä¼šç§°é‚£ä¸ªå˜é‡ä¸ºâ€œtmp†| 230 | ä¸ä½¿ç”¨ç±»ä¼¼ ThisVariableIsATemporaryCounter è¿™æ ·åŽä¸½çš„åå—。C 程åºå‘˜ä¼šç§°é‚£ä¸ªå˜é‡ |
230 | ï¼Œè¿™æ ·å†™èµ·æ¥ä¼šæ›´å®¹æ˜“,而且至少ä¸ä¼šä»¤å…¶éš¾äºŽç†è§£ã€‚ | 231 | 为 “tmpâ€ï¼Œè¿™æ ·å†™èµ·æ¥ä¼šæ›´å®¹æ˜“,而且至少ä¸ä¼šä»¤å…¶éš¾äºŽç†è§£ã€‚ |
231 | 232 | ||
232 | ä¸è¿‡ï¼Œè™½ç„¶æ··ç”¨å¤§å°å†™çš„åå—æ˜¯ä¸æå€¡ä½¿ç”¨çš„,但是全局å˜é‡è¿˜æ˜¯éœ€è¦ä¸€ä¸ªå…·æè¿°æ€§çš„åå— | 233 | ä¸è¿‡ï¼Œè™½ç„¶æ··ç”¨å¤§å°å†™çš„åå—æ˜¯ä¸æå€¡ä½¿ç”¨çš„,但是全局å˜é‡è¿˜æ˜¯éœ€è¦ä¸€ä¸ªå…·æè¿°æ€§çš„åå— |
233 | 。称一个全局函数为“fooâ€æ˜¯ä¸€ä¸ªéš¾ä»¥é¥¶æ•的错误。 | 234 | 。称一个全局函数为 “foo†是一个难以饶æ•的错误。 |
234 | 235 | ||
235 | 全局å˜é‡ï¼ˆåªæœ‰å½“ä½ çœŸæ£éœ€è¦å®ƒä»¬çš„æ—¶å€™å†ç”¨å®ƒï¼‰éœ€è¦æœ‰ä¸€ä¸ªå…·æè¿°æ€§çš„åå—,就åƒå…¨å±€å‡½ | 236 | 全局å˜é‡ï¼ˆåªæœ‰å½“ä½ çœŸæ£éœ€è¦å®ƒä»¬çš„æ—¶å€™å†ç”¨å®ƒï¼‰éœ€è¦æœ‰ä¸€ä¸ªå…·æè¿°æ€§çš„åå—,就åƒå…¨å±€å‡½ |
236 | æ•°ã€‚å¦‚æžœä½ æœ‰ä¸€ä¸ªå¯ä»¥è®¡ç®—活动用户数é‡çš„å‡½æ•°ï¼Œä½ åº”è¯¥å«å®ƒâ€œcount_active_users()â€æˆ–者 | 237 | æ•°ã€‚å¦‚æžœä½ æœ‰ä¸€ä¸ªå¯ä»¥è®¡ç®—活动用户数é‡çš„å‡½æ•°ï¼Œä½ åº”è¯¥å«å®ƒ “count_active_users()†|
237 | 类似的åå—ï¼Œä½ ä¸åº”该å«å®ƒâ€œcntuser()â€ã€‚ | 238 | 或者类似的åå—ï¼Œä½ ä¸åº”该å«å®ƒ “cntuser()â€ã€‚ |
238 | 239 | ||
239 | 在函数åä¸åŒ…å«å‡½æ•°ç±»åž‹ï¼ˆæ‰€è°“çš„åŒˆç‰™åˆ©å‘½åæ³•)是脑å出了问题——编译器知é“那些类型而 | 240 | 在函数åä¸åŒ…å«å‡½æ•°ç±»åž‹ï¼ˆæ‰€è°“çš„åŒˆç‰™åˆ©å‘½åæ³•)是脑å出了问题——编译器知é“那些类型而 |
240 | ä¸”èƒ½å¤Ÿæ£€æŸ¥é‚£äº›ç±»åž‹ï¼Œè¿™æ ·åšåªèƒ½æŠŠç¨‹åºå‘˜å¼„ç³Šæ¶‚äº†ã€‚éš¾æ€ªå¾®è½¯æ€»æ˜¯åˆ¶é€ å‡ºæœ‰é—®é¢˜çš„ç¨‹åºã€‚ | 241 | ä¸”èƒ½å¤Ÿæ£€æŸ¥é‚£äº›ç±»åž‹ï¼Œè¿™æ ·åšåªèƒ½æŠŠç¨‹åºå‘˜å¼„ç³Šæ¶‚äº†ã€‚éš¾æ€ªå¾®è½¯æ€»æ˜¯åˆ¶é€ å‡ºæœ‰é—®é¢˜çš„ç¨‹åºã€‚ |
241 | 242 | ||
242 | 本地å˜é‡å应该简çŸï¼Œè€Œä¸”能够表达相关的å«ä¹‰ã€‚å¦‚æžœä½ æœ‰ä¸€äº›éšæœºçš„æ•´æ•°åž‹çš„循环计数器 | 243 | 本地å˜é‡å应该简çŸï¼Œè€Œä¸”能够表达相关的å«ä¹‰ã€‚å¦‚æžœä½ æœ‰ä¸€äº›éšæœºçš„æ•´æ•°åž‹çš„循环计数器 |
243 | ,它应该被称为“iâ€ã€‚å«å®ƒâ€œloop_counterâ€å¹¶æ— 益处,如果它没有被误解的å¯èƒ½çš„è¯ã€‚类似 | 244 | ,它应该被称为 “iâ€ã€‚å«å®ƒ “loop_counterâ€ å¹¶æ— ç›Šå¤„ï¼Œå¦‚æžœå®ƒæ²¡æœ‰è¢«è¯¯è§£çš„å¯èƒ½çš„è¯ã€‚ |
244 | 的,“tmpâ€å¯ä»¥ç”¨æ¥ç§°å‘¼ä»»æ„类型的临时å˜é‡ã€‚ | 245 | 类似的,“tmp†å¯ä»¥ç”¨æ¥ç§°å‘¼ä»»æ„类型的临时å˜é‡ã€‚ |
245 | 246 | ||
246 | å¦‚æžœä½ æ€•æ··æ·†äº†ä½ çš„æœ¬åœ°å˜é‡åï¼Œä½ å°±é‡åˆ°å¦ä¸€ä¸ªé—®é¢˜äº†ï¼Œå«åšå‡½æ•°å¢žé•¿è·å°”蒙失衡综åˆç—‡ | 247 | å¦‚æžœä½ æ€•æ··æ·†äº†ä½ çš„æœ¬åœ°å˜é‡åï¼Œä½ å°±é‡åˆ°å¦ä¸€ä¸ªé—®é¢˜äº†ï¼Œå«åšå‡½æ•°å¢žé•¿è·å°”蒙失衡综åˆç—‡ |
247 | 。请看第å…ç« ï¼ˆå‡½æ•°ï¼‰ã€‚ | 248 | 。请看第å…ç« ï¼ˆå‡½æ•°ï¼‰ã€‚ |
@@ -249,9 +250,9 @@ C是一个简朴的è¯è¨€ï¼Œä½ 的命åä¹Ÿåº”è¯¥è¿™æ ·ã€‚å’ŒModula-2å’ŒPascalç¨ | |||
249 | 250 | ||
250 | ç¬¬äº”ç« ï¼šTypedef | 251 | ç¬¬äº”ç« ï¼šTypedef |
251 | 252 | ||
252 | ä¸è¦ä½¿ç”¨ç±»ä¼¼â€œvps_tâ€ä¹‹ç±»çš„东西。 | 253 | ä¸è¦ä½¿ç”¨ç±»ä¼¼ “vps_t†之类的东西。 |
253 | 254 | ||
254 | 对结构体和指针使用typedefæ˜¯ä¸€ä¸ªé”™è¯¯ã€‚å½“ä½ åœ¨ä»£ç 里看到: | 255 | 对结构体和指针使用 typedef æ˜¯ä¸€ä¸ªé”™è¯¯ã€‚å½“ä½ åœ¨ä»£ç 里看到: |
255 | 256 | ||
256 | vps_t a; | 257 | vps_t a; |
257 | 258 | ||
@@ -261,91 +262,91 @@ C是一个简朴的è¯è¨€ï¼Œä½ 的命åä¹Ÿåº”è¯¥è¿™æ ·ã€‚å’ŒModula-2å’ŒPascalç¨ | |||
261 | 262 | ||
262 | struct virtual_container *a; | 263 | struct virtual_container *a; |
263 | 264 | ||
264 | ä½ å°±çŸ¥é““aâ€æ˜¯ä»€ä¹ˆäº†ã€‚ | 265 | ä½ å°±çŸ¥é“ â€œa†是什么了。 |
265 | 266 | ||
266 | 很多人认为typedef“能æé«˜å¯è¯»æ€§â€ã€‚å®žé™…ä¸æ˜¯è¿™æ ·çš„。它们åªåœ¨ä¸‹åˆ—情况下有用: | 267 | 很多人认为 typedef “能æé«˜å¯è¯»æ€§â€ã€‚å®žé™…ä¸æ˜¯è¿™æ ·çš„。它们åªåœ¨ä¸‹åˆ—情况下有用: |
267 | 268 | ||
268 | (a) 完全ä¸é€æ˜Žçš„å¯¹è±¡ï¼ˆè¿™ç§æƒ…况下è¦ä¸»åŠ¨ä½¿ç”¨typedefæ¥éšè—这个对象实际上是什么)。 | 269 | (a) 完全ä¸é€æ˜Žçš„å¯¹è±¡ï¼ˆè¿™ç§æƒ…况下è¦ä¸»åŠ¨ä½¿ç”¨ typedef æ¥éšè—这个对象实际上是什么)。 |
269 | 270 | ||
270 | 例如:“pte_tâ€ç‰ä¸é€æ˜Žå¯¹è±¡ï¼Œä½ åªèƒ½ç”¨åˆé€‚的访问函数æ¥è®¿é—®å®ƒä»¬ã€‚ | 271 | 例如:“pte_t†ç‰ä¸é€æ˜Žå¯¹è±¡ï¼Œä½ åªèƒ½ç”¨åˆé€‚的访问函数æ¥è®¿é—®å®ƒä»¬ã€‚ |
271 | 272 | ||
272 | 注æ„ï¼ä¸é€æ˜Žæ€§å’Œâ€œè®¿é—®å‡½æ•°â€æœ¬èº«æ˜¯ä¸å¥½çš„。我们使用pte_tç‰ç±»åž‹çš„åŽŸå› åœ¨äºŽçœŸçš„æ˜¯ | 273 | 注æ„ï¼ä¸é€æ˜Žæ€§å’Œâ€œè®¿é—®å‡½æ•°â€æœ¬èº«æ˜¯ä¸å¥½çš„。我们使用 pte_t ç‰ç±»åž‹çš„åŽŸå› åœ¨äºŽçœŸçš„æ˜¯ |
273 | 完全没有任何共用的å¯è®¿é—®ä¿¡æ¯ã€‚ | 274 | 完全没有任何共用的å¯è®¿é—®ä¿¡æ¯ã€‚ |
274 | 275 | ||
275 | (b) 清楚的整数类型,如æ¤ï¼Œè¿™å±‚抽象就å¯ä»¥å¸®åŠ©æ¶ˆé™¤åˆ°åº•æ˜¯â€œintâ€è¿˜æ˜¯â€œlongâ€çš„æ··æ·†ã€‚ | 276 | (b) 清楚的整数类型,如æ¤ï¼Œè¿™å±‚抽象就å¯ä»¥å¸®åŠ©æ¶ˆé™¤åˆ°åº•æ˜¯ “int†还是 “long†的混淆。 |
276 | 277 | ||
277 | u8/u16/u32是完全没有问题的typedef,ä¸è¿‡å®ƒä»¬æ›´ç¬¦åˆç±»åˆ«(d)è€Œä¸æ˜¯è¿™é‡Œã€‚ | 278 | u8/u16/u32 是完全没有问题的 typedef,ä¸è¿‡å®ƒä»¬æ›´ç¬¦åˆç±»åˆ« (d) è€Œä¸æ˜¯è¿™é‡Œã€‚ |
278 | 279 | ||
279 | 冿¬¡æ³¨æ„ï¼è¦è¿™æ ·åšï¼Œå¿…é¡»äº‹å‡ºæœ‰å› ã€‚å¦‚æžœæŸä¸ªå˜é‡æ˜¯â€œunsigned longâ€œï¼Œé‚£ä¹ˆæ²¡æœ‰å¿…è¦ | 280 | 冿¬¡æ³¨æ„ï¼è¦è¿™æ ·åšï¼Œå¿…é¡»äº‹å‡ºæœ‰å› ã€‚å¦‚æžœæŸä¸ªå˜é‡æ˜¯ “unsigned longâ€œï¼Œé‚£ä¹ˆæ²¡æœ‰å¿…è¦ |
280 | 281 | ||
281 | typedef unsigned long myflags_t; | 282 | typedef unsigned long myflags_t; |
282 | 283 | ||
283 | ä¸è¿‡å¦‚æžœæœ‰ä¸€ä¸ªæ˜Žç¡®çš„åŽŸå› ï¼Œæ¯”å¦‚å®ƒåœ¨æŸç§æƒ…况下å¯èƒ½ä¼šæ˜¯ä¸€ä¸ªâ€œunsigned intâ€è€Œåœ¨ | 284 | ä¸è¿‡å¦‚æžœæœ‰ä¸€ä¸ªæ˜Žç¡®çš„åŽŸå› ï¼Œæ¯”å¦‚å®ƒåœ¨æŸç§æƒ…况下å¯èƒ½ä¼šæ˜¯ä¸€ä¸ª “unsigned int†而在 |
284 | 其他情况下å¯èƒ½ä¸ºâ€œunsigned longâ€ï¼Œé‚£ä¹ˆå°±ä¸è¦çŠ¹è±«ï¼Œè¯·åŠ¡å¿…ä½¿ç”¨typedef。 | 285 | 其他情况下å¯èƒ½ä¸º “unsigned longâ€ï¼Œé‚£ä¹ˆå°±ä¸è¦çŠ¹è±«ï¼Œè¯·åŠ¡å¿…ä½¿ç”¨ typedef。 |
285 | 286 | ||
286 | (c) å½“ä½ ä½¿ç”¨sparse按å—é¢çš„创建一个新类型æ¥åšç±»åž‹æ£€æŸ¥çš„æ—¶å€™ã€‚ | 287 | (c) å½“ä½ ä½¿ç”¨sparse按å—é¢çš„创建一个新类型æ¥åšç±»åž‹æ£€æŸ¥çš„æ—¶å€™ã€‚ |
287 | 288 | ||
288 | (d) å’Œæ ‡å‡†C99类型相åŒçš„类型,在æŸäº›ä¾‹å¤–的情况下。 | 289 | (d) å’Œæ ‡å‡†C99类型相åŒçš„类型,在æŸäº›ä¾‹å¤–的情况下。 |
289 | 290 | ||
290 | 虽然让眼ç›å’Œè„‘ç‹æ¥é€‚åº”æ–°çš„æ ‡å‡†ç±»åž‹æ¯”å¦‚â€œuint32_tâ€ä¸éœ€è¦èŠ±å¾ˆå¤šæ—¶é—´ï¼Œå¯æ˜¯æœ‰äº› | 291 | 虽然让眼ç›å’Œè„‘ç‹æ¥é€‚åº”æ–°çš„æ ‡å‡†ç±»åž‹æ¯”å¦‚ “uint32_t†ä¸éœ€è¦èŠ±å¾ˆå¤šæ—¶é—´ï¼Œå¯æ˜¯æœ‰äº› |
291 | 人ä»ç„¶æ‹’ç»ä½¿ç”¨å®ƒä»¬ã€‚ | 292 | 人ä»ç„¶æ‹’ç»ä½¿ç”¨å®ƒä»¬ã€‚ |
292 | 293 | ||
293 | å› æ¤ï¼ŒLinux特有的ç‰åŒäºŽæ ‡å‡†ç±»åž‹çš„“u8/u16/u32/u64â€ç±»åž‹å’Œå®ƒä»¬çš„æœ‰ç¬¦å·ç±»åž‹æ˜¯è¢« | 294 | å› æ¤ï¼ŒLinux 特有的ç‰åŒäºŽæ ‡å‡†ç±»åž‹çš„ “u8/u16/u32/u64†类型和它们的有符å·ç±»åž‹æ˜¯è¢« |
294 | å…è®¸çš„â€”â€”å°½ç®¡åœ¨ä½ è‡ªå·±çš„æ–°ä»£ç ä¸ï¼Œå®ƒä»¬ä¸æ˜¯å¼ºåˆ¶è¦æ±‚è¦ä½¿ç”¨çš„。 | 295 | å…è®¸çš„â€”â€”å°½ç®¡åœ¨ä½ è‡ªå·±çš„æ–°ä»£ç ä¸ï¼Œå®ƒä»¬ä¸æ˜¯å¼ºåˆ¶è¦æ±‚è¦ä½¿ç”¨çš„。 |
295 | 296 | ||
296 | 当编辑已ç»ä½¿ç”¨äº†æŸä¸ªç±»åž‹é›†çš„å·²æœ‰ä»£ç æ—¶ï¼Œä½ 应该éµå¾ªé‚£äº›ä»£ç ä¸å·²ç»åšå‡ºçš„选择。 | 297 | 当编辑已ç»ä½¿ç”¨äº†æŸä¸ªç±»åž‹é›†çš„å·²æœ‰ä»£ç æ—¶ï¼Œä½ 应该éµå¾ªé‚£äº›ä»£ç ä¸å·²ç»åšå‡ºçš„选择。 |
297 | 298 | ||
298 | (e) å¯ä»¥åœ¨ç”¨æˆ·ç©ºé—´å®‰å…¨ä½¿ç”¨çš„类型。 | 299 | (e) å¯ä»¥åœ¨ç”¨æˆ·ç©ºé—´å®‰å…¨ä½¿ç”¨çš„类型。 |
299 | 300 | ||
300 | 在æŸäº›ç”¨æˆ·ç©ºé—´å¯è§çš„结构体里,我们ä¸èƒ½è¦æ±‚C99类型而且ä¸èƒ½ç”¨ä¸Šé¢æåˆ°çš„“u32†| 301 | 在æŸäº›ç”¨æˆ·ç©ºé—´å¯è§çš„结构体里,我们ä¸èƒ½è¦æ±‚C99类型而且ä¸èƒ½ç”¨ä¸Šé¢æåˆ°çš„ “u32†|
301 | ç±»åž‹ã€‚å› æ¤ï¼Œæˆ‘们在与用户空间共享的所有结构体ä¸ä½¿ç”¨__u32和类似的类型。 | 302 | ç±»åž‹ã€‚å› æ¤ï¼Œæˆ‘们在与用户空间共享的所有结构体ä¸ä½¿ç”¨ __u32 和类似的类型。 |
302 | 303 | ||
303 | å¯èƒ½è¿˜æœ‰å…¶ä»–的情况,ä¸è¿‡åŸºæœ¬çš„规则是永远ä¸è¦ä½¿ç”¨typedef,除éžä½ å¯ä»¥æ˜Žç¡®çš„应用上 | 304 | å¯èƒ½è¿˜æœ‰å…¶ä»–的情况,ä¸è¿‡åŸºæœ¬çš„规则是永远ä¸è¦ä½¿ç”¨ typedef,除éžä½ å¯ä»¥æ˜Žç¡®çš„应用上 |
304 | è¿°æŸä¸ªè§„则ä¸çš„一个。 | 305 | è¿°æŸä¸ªè§„则ä¸çš„一个。 |
305 | 306 | ||
306 | 总的æ¥è¯´ï¼Œå¦‚æžœä¸€ä¸ªæŒ‡é’ˆæˆ–è€…ä¸€ä¸ªç»“æž„ä½“é‡Œçš„å…ƒç´ å¯ä»¥åˆç†çš„è¢«ç›´æŽ¥è®¿é—®åˆ°ï¼Œé‚£ä¹ˆå®ƒä»¬å°±ä¸ | 307 | 总的æ¥è¯´ï¼Œå¦‚æžœä¸€ä¸ªæŒ‡é’ˆæˆ–è€…ä¸€ä¸ªç»“æž„ä½“é‡Œçš„å…ƒç´ å¯ä»¥åˆç†çš„è¢«ç›´æŽ¥è®¿é—®åˆ°ï¼Œé‚£ä¹ˆå®ƒä»¬å°±ä¸ |
307 | 应该是一个typedef。 | 308 | 应该是一个 typedef。 |
308 | 309 | ||
309 | 310 | ||
310 | 第å…ç« ï¼šå‡½æ•° | 311 | 第å…ç« ï¼šå‡½æ•° |
311 | 312 | ||
312 | 函数应该简çŸè€Œæ¼‚亮,并且åªå®Œæˆä¸€ä»¶äº‹æƒ…。函数应该å¯ä»¥ä¸€å±æˆ–è€…ä¸¤å±æ˜¾ç¤ºå®Œï¼ˆæˆ‘们都知 | 313 | 函数应该简çŸè€Œæ¼‚亮,并且åªå®Œæˆä¸€ä»¶äº‹æƒ…。函数应该å¯ä»¥ä¸€å±æˆ–è€…ä¸¤å±æ˜¾ç¤ºå®Œï¼ˆæˆ‘们都知 |
313 | é“ISO/ANSIå±å¹•大尿˜¯80x24),åªåšä¸€ä»¶äº‹æƒ…,而且把它åšå¥½ã€‚ | 314 | é“ ISO/ANSI å±å¹•大尿˜¯ 80x24),åªåšä¸€ä»¶äº‹æƒ…,而且把它åšå¥½ã€‚ |
314 | 315 | ||
315 | ä¸€ä¸ªå‡½æ•°çš„æœ€å¤§é•¿åº¦æ˜¯å’Œè¯¥å‡½æ•°çš„å¤æ‚度和缩进级数æˆåæ¯”çš„ã€‚æ‰€ä»¥ï¼Œå¦‚æžœä½ æœ‰ä¸€ä¸ªç†è®ºä¸Š | 316 | ä¸€ä¸ªå‡½æ•°çš„æœ€å¤§é•¿åº¦æ˜¯å’Œè¯¥å‡½æ•°çš„å¤æ‚度和缩进级数æˆåæ¯”çš„ã€‚æ‰€ä»¥ï¼Œå¦‚æžœä½ æœ‰ä¸€ä¸ªç†è®ºä¸Š |
316 | 很简å•çš„åªæœ‰ä¸€ä¸ªå¾ˆé•¿ï¼ˆä½†æ˜¯ç®€å•)的caseè¯å¥çš„å‡½æ•°ï¼Œè€Œä¸”ä½ éœ€è¦åœ¨æ¯ä¸ªcase里åšå¾ˆå¤šå¾ˆ | 317 | 很简å•çš„åªæœ‰ä¸€ä¸ªå¾ˆé•¿ï¼ˆä½†æ˜¯ç®€å•)的 case è¯å¥çš„å‡½æ•°ï¼Œè€Œä¸”ä½ éœ€è¦åœ¨æ¯ä¸ª case é‡Œåš |
317 | å°çš„äº‹æƒ…ï¼Œè¿™æ ·çš„å‡½æ•°å°½ç®¡å¾ˆé•¿ï¼Œä½†ä¹Ÿæ˜¯å¯ä»¥çš„。 | 318 | 很多很å°çš„äº‹æƒ…ï¼Œè¿™æ ·çš„å‡½æ•°å°½ç®¡å¾ˆé•¿ï¼Œä½†ä¹Ÿæ˜¯å¯ä»¥çš„。 |
318 | 319 | ||
319 | ä¸è¿‡ï¼Œå¦‚æžœä½ æœ‰ä¸€ä¸ªå¤æ‚çš„å‡½æ•°ï¼Œè€Œä¸”ä½ æ€€ç–‘ä¸€ä¸ªå¤©åˆ†ä¸æ˜¯å¾ˆé«˜çš„高ä¸ä¸€å¹´çº§å¦ç”Ÿå¯èƒ½ç”šè‡³ | 320 | ä¸è¿‡ï¼Œå¦‚æžœä½ æœ‰ä¸€ä¸ªå¤æ‚çš„å‡½æ•°ï¼Œè€Œä¸”ä½ æ€€ç–‘ä¸€ä¸ªå¤©åˆ†ä¸æ˜¯å¾ˆé«˜çš„高ä¸ä¸€å¹´çº§å¦ç”Ÿå¯èƒ½ç”šè‡³ |
320 | æžä¸æ¸…æ¥šè¿™ä¸ªå‡½æ•°çš„ç›®çš„ï¼Œä½ åº”è¯¥ä¸¥æ ¼çš„éµå®ˆå‰é¢æåˆ°çš„长度é™åˆ¶ã€‚使用辅助函数,并为之 | 321 | æžä¸æ¸…æ¥šè¿™ä¸ªå‡½æ•°çš„ç›®çš„ï¼Œä½ åº”è¯¥ä¸¥æ ¼çš„éµå®ˆå‰é¢æåˆ°çš„长度é™åˆ¶ã€‚使用辅助函数,并为之 |
321 | å–个具æè¿°æ€§çš„åå—ï¼ˆå¦‚æžœä½ è§‰å¾—å®ƒä»¬çš„æ€§èƒ½å¾ˆé‡è¦çš„è¯ï¼Œå¯ä»¥è®©ç¼–译器内è”å®ƒä»¬ï¼Œè¿™æ ·çš„ | 322 | å–个具æè¿°æ€§çš„åå—ï¼ˆå¦‚æžœä½ è§‰å¾—å®ƒä»¬çš„æ€§èƒ½å¾ˆé‡è¦çš„è¯ï¼Œå¯ä»¥è®©ç¼–译器内è”å®ƒä»¬ï¼Œè¿™æ ·çš„ |
322 | æ•ˆæžœå¾€å¾€ä¼šæ¯”ä½ å†™ä¸€ä¸ªå¤æ‚函数的效果è¦å¥½ã€‚) | 323 | æ•ˆæžœå¾€å¾€ä¼šæ¯”ä½ å†™ä¸€ä¸ªå¤æ‚函数的效果è¦å¥½ã€‚) |
323 | 324 | ||
324 | 函数的å¦å¤–ä¸€ä¸ªè¡¡é‡æ ‡å‡†æ˜¯æœ¬åœ°å˜é‡çš„æ•°é‡ã€‚æ¤æ•°é‡ä¸åº”超过5ï¼10个,å¦åˆ™ä½ 的函数就有 | 325 | 函数的å¦å¤–ä¸€ä¸ªè¡¡é‡æ ‡å‡†æ˜¯æœ¬åœ°å˜é‡çš„æ•°é‡ã€‚æ¤æ•°é‡ä¸åº”超过 5ï¼10 个,å¦åˆ™ä½ 的函数就有 |
325 | é—®é¢˜äº†ã€‚é‡æ–°è€ƒè™‘ä¸€ä¸‹ä½ çš„å‡½æ•°ï¼ŒæŠŠå®ƒåˆ†æ‹†æˆæ›´å°çš„函数。人的大脑一般å¯ä»¥è½»æ¾çš„åŒæ—¶è·Ÿ | 326 | é—®é¢˜äº†ã€‚é‡æ–°è€ƒè™‘ä¸€ä¸‹ä½ çš„å‡½æ•°ï¼ŒæŠŠå®ƒåˆ†æ‹†æˆæ›´å°çš„函数。人的大脑一般å¯ä»¥è½»æ¾çš„åŒæ—¶è·Ÿ |
326 | 踪7个ä¸åŒçš„事物,如果å†å¢žå¤šçš„è¯ï¼Œå°±ä¼šç³Šæ¶‚了。å³ä¾¿ä½ èªé¢–è¿‡äººï¼Œä½ ä¹Ÿå¯èƒ½ä¼šè®°ä¸æ¸…ä½ 2 | 327 | 踪 7 个ä¸åŒçš„事物,如果å†å¢žå¤šçš„è¯ï¼Œå°±ä¼šç³Šæ¶‚了。å³ä¾¿ä½ èªé¢–è¿‡äººï¼Œä½ ä¹Ÿå¯èƒ½ä¼šè®°ä¸æ¸…ä½ |
327 | 个星期å‰åšè¿‡çš„事情。 | 328 | 2 个星期å‰åšè¿‡çš„事情。 |
328 | 329 | ||
329 | åœ¨æºæ–‡ä»¶é‡Œï¼Œä½¿ç”¨ç©ºè¡Œéš”å¼€ä¸åŒçš„函数。如果该函数需è¦è¢«å¯¼å‡ºï¼Œå®ƒçš„EXPORT*å®åº”该紧贴 | 330 | åœ¨æºæ–‡ä»¶é‡Œï¼Œä½¿ç”¨ç©ºè¡Œéš”å¼€ä¸åŒçš„函数。如果该函数需è¦è¢«å¯¼å‡ºï¼Œå®ƒçš„ EXPORT* å®åº”该紧贴 |
330 | 在它的结æŸå¤§æ‹¬å·ä¹‹ä¸‹ã€‚比如: | 331 | 在它的结æŸå¤§æ‹¬å·ä¹‹ä¸‹ã€‚比如: |
331 | 332 | ||
332 | int system_is_up(void) | 333 | int system_is_up(void) |
333 | { | 334 | { |
334 | return system_state == SYSTEM_RUNNING; | 335 | return system_state == SYSTEM_RUNNING; |
335 | } | 336 | } |
336 | EXPORT_SYMBOL(system_is_up); | 337 | EXPORT_SYMBOL(system_is_up); |
337 | 338 | ||
338 | 在函数原型ä¸ï¼ŒåŒ…å«å‡½æ•°å和它们的数æ®ç±»åž‹ã€‚虽然Cè¯è¨€é‡Œæ²¡æœ‰è¿™æ ·çš„è¦æ±‚,在Linux里这 | 339 | 在函数原型ä¸ï¼ŒåŒ…å«å‡½æ•°å和它们的数æ®ç±»åž‹ã€‚虽然Cè¯è¨€é‡Œæ²¡æœ‰è¿™æ ·çš„è¦æ±‚,在 Linux 里这 |
339 | 是æå€¡çš„åšæ³•ï¼Œå› ä¸ºè¿™æ ·å¯ä»¥å¾ˆç®€å•的给读者æä¾›æ›´å¤šçš„æœ‰ä»·å€¼çš„ä¿¡æ¯ã€‚ | 340 | 是æå€¡çš„åšæ³•ï¼Œå› ä¸ºè¿™æ ·å¯ä»¥å¾ˆç®€å•的给读者æä¾›æ›´å¤šçš„æœ‰ä»·å€¼çš„ä¿¡æ¯ã€‚ |
340 | 341 | ||
341 | 342 | ||
342 | ç¬¬ä¸ƒç« ï¼šé›†ä¸çš„函数退出途径 | 343 | ç¬¬ä¸ƒç« ï¼šé›†ä¸çš„函数退出途径 |
343 | 344 | ||
344 | 虽然被æŸäº›äººå£°ç§°å·²ç»è¿‡æ—¶ï¼Œä½†æ˜¯gotoè¯å¥çš„ç‰ä»·ç‰©è¿˜æ˜¯ç»å¸¸è¢«ç¼–è¯‘å™¨æ‰€ä½¿ç”¨ï¼Œå…·ä½“å½¢å¼æ˜¯ | 345 | 虽然被æŸäº›äººå£°ç§°å·²ç»è¿‡æ—¶ï¼Œä½†æ˜¯ goto è¯å¥çš„ç‰ä»·ç‰©è¿˜æ˜¯ç»å¸¸è¢«ç¼–è¯‘å™¨æ‰€ä½¿ç”¨ï¼Œå…·ä½“å½¢å¼æ˜¯ |
345 | æ— æ¡ä»¶è·³è½¬æŒ‡ä»¤ã€‚ | 346 | æ— æ¡ä»¶è·³è½¬æŒ‡ä»¤ã€‚ |
346 | 347 | ||
347 | 当一个函数从多个ä½ç½®é€€å‡ºå¹¶ä¸”需è¦åšä¸€äº›é€šç”¨çš„æ¸…ç†å·¥ä½œçš„æ—¶å€™ï¼Œgotoçš„å¥½å¤„å°±æ˜¾çŽ°å‡ºæ¥ | 348 | 当一个函数从多个ä½ç½®é€€å‡ºï¼Œå¹¶ä¸”需è¦åšä¸€äº›ç±»ä¼¼æ¸…ç†çš„å¸¸è§æ“作时,goto è¯å¥å°±å¾ˆæ–¹ä¾¿äº†ã€‚ |
348 | 了。 | 349 | 如果并ä¸éœ€è¦æ¸…ç†æ“作,那么直接 return å³å¯ã€‚ |
349 | 350 | ||
350 | ç†ç”±æ˜¯ï¼š | 351 | ç†ç”±æ˜¯ï¼š |
351 | 352 | ||
@@ -354,26 +355,37 @@ EXPORT_SYMBOL(system_is_up); | |||
354 | - å¯ä»¥é¿å…由于修改时忘记更新æŸä¸ªå•独的退出点而导致的错误 | 355 | - å¯ä»¥é¿å…由于修改时忘记更新æŸä¸ªå•独的退出点而导致的错误 |
355 | - å‡è½»äº†ç¼–è¯‘å™¨çš„å·¥ä½œï¼Œæ— éœ€åˆ é™¤å†—ä½™ä»£ç ;) | 356 | - å‡è½»äº†ç¼–è¯‘å™¨çš„å·¥ä½œï¼Œæ— éœ€åˆ é™¤å†—ä½™ä»£ç ;) |
356 | 357 | ||
357 | int fun(int a) | 358 | int fun(int a) |
358 | { | 359 | { |
359 | int result = 0; | 360 | int result = 0; |
360 | char *buffer = kmalloc(SIZE); | 361 | char *buffer; |
361 | 362 | ||
362 | if (buffer == NULL) | 363 | buffer = kmalloc(SIZE, GFP_KERNEL); |
363 | return -ENOMEM; | 364 | if (!buffer) |
364 | 365 | return -ENOMEM; | |
365 | if (condition1) { | 366 | |
366 | while (loop1) { | 367 | if (condition1) { |
367 | ... | 368 | while (loop1) { |
369 | ... | ||
370 | } | ||
371 | result = 1; | ||
372 | goto out_buffer; | ||
368 | } | 373 | } |
369 | result = 1; | 374 | ... |
370 | goto out; | 375 | out_buffer: |
376 | kfree(buffer); | ||
377 | return result; | ||
371 | } | 378 | } |
372 | ... | 379 | |
373 | out: | 380 | ä¸€ä¸ªéœ€è¦æ³¨æ„的常è§é”™è¯¯æ˜¯â€œä¸€ä¸ª err 错误â€ï¼Œå°±åƒè¿™æ ·ï¼š |
374 | kfree(buffer); | 381 | |
375 | return result; | 382 | err: |
376 | } | 383 | kfree(foo->bar); |
384 | kfree(foo); | ||
385 | return ret; | ||
386 | |||
387 | 这段代ç 的错误是,在æŸäº›é€€å‡ºè·¯å¾„上 “foo†是 NULL。通常情况下,通过把它分离æˆä¸¤ä¸ª | ||
388 | é”™è¯¯æ ‡ç¾ â€œerr_bar:†和 “err_foo:†æ¥ä¿®å¤è¿™ä¸ªé”™è¯¯ã€‚ | ||
377 | 389 | ||
378 | ç¬¬å…«ç« ï¼šæ³¨é‡Š | 390 | ç¬¬å…«ç« ï¼šæ³¨é‡Š |
379 | 391 | ||
@@ -386,10 +398,10 @@ out: | |||
386 | åŠ å¤ªå¤šã€‚ä½ åº”è¯¥åšçš„,是把注释放在函数的头部,告诉人们它åšäº†ä»€ä¹ˆï¼Œä¹Ÿå¯ä»¥åŠ ä¸Šå®ƒåšè¿™ | 398 | åŠ å¤ªå¤šã€‚ä½ åº”è¯¥åšçš„,是把注释放在函数的头部,告诉人们它åšäº†ä»€ä¹ˆï¼Œä¹Ÿå¯ä»¥åŠ ä¸Šå®ƒåšè¿™ |
387 | äº›äº‹æƒ…çš„åŽŸå› ã€‚ | 399 | äº›äº‹æƒ…çš„åŽŸå› ã€‚ |
388 | 400 | ||
389 | å½“æ³¨é‡Šå†…æ ¸API函数时,请使用kernel-docæ ¼å¼ã€‚请看 | 401 | å½“æ³¨é‡Šå†…æ ¸API函数时,请使用 kernel-doc æ ¼å¼ã€‚请看 |
390 | Documentation/kernel-doc-nano-HOWTO.txtå’Œscripts/kernel-doc以获得详细信æ¯ã€‚ | 402 | Documentation/kernel-documentation.rstå’Œscripts/kernel-doc 以获得详细信æ¯ã€‚ |
391 | 403 | ||
392 | Linuxçš„æ³¨é‡Šé£Žæ ¼æ˜¯C89“/* ... */â€é£Žæ ¼ã€‚ä¸è¦ä½¿ç”¨C99é£Žæ ¼â€œ// ...â€æ³¨é‡Šã€‚ | 404 | Linuxçš„æ³¨é‡Šé£Žæ ¼æ˜¯ C89 “/* ... */â€ é£Žæ ¼ã€‚ä¸è¦ä½¿ç”¨ C99 é£Žæ ¼ “// ...†注释。 |
393 | 405 | ||
394 | é•¿ï¼ˆå¤šè¡Œï¼‰çš„é¦–é€‰æ³¨é‡Šé£Žæ ¼æ˜¯ï¼š | 406 | é•¿ï¼ˆå¤šè¡Œï¼‰çš„é¦–é€‰æ³¨é‡Šé£Žæ ¼æ˜¯ï¼š |
395 | 407 | ||
@@ -402,6 +414,15 @@ Linuxçš„æ³¨é‡Šé£Žæ ¼æ˜¯C89“/* ... */â€é£Žæ ¼ã€‚ä¸è¦ä½¿ç”¨C99é£Žæ ¼â€œ// ... | |||
402 | * with beginning and ending almost-blank lines. | 414 | * with beginning and ending almost-blank lines. |
403 | */ | 415 | */ |
404 | 416 | ||
417 | 对于在 net/ å’Œ drivers/net/ çš„æ–‡ä»¶ï¼Œé¦–é€‰çš„é•¿ï¼ˆå¤šè¡Œï¼‰æ³¨é‡Šé£Žæ ¼æœ‰äº›ä¸åŒã€‚ | ||
418 | |||
419 | /* The preferred comment style for files in net/ and drivers/net | ||
420 | * looks like this. | ||
421 | * | ||
422 | * It is nearly the same as the generally preferred comment style, | ||
423 | * but there is no initial almost-blank line. | ||
424 | */ | ||
425 | |||
405 | 注释数æ®ä¹Ÿæ˜¯å¾ˆé‡è¦çš„,ä¸ç®¡æ˜¯åŸºæœ¬ç±»åž‹è¿˜æ˜¯è¡ç”Ÿç±»åž‹ã€‚为了方便实现这一点,æ¯ä¸€è¡Œåº”åª | 426 | 注释数æ®ä¹Ÿæ˜¯å¾ˆé‡è¦çš„,ä¸ç®¡æ˜¯åŸºæœ¬ç±»åž‹è¿˜æ˜¯è¡ç”Ÿç±»åž‹ã€‚为了方便实现这一点,æ¯ä¸€è¡Œåº”åª |
406 | 声明一个数æ®ï¼ˆä¸è¦ä½¿ç”¨é€—å·æ¥ä¸€æ¬¡å£°æ˜Žå¤šä¸ªæ•°æ®ï¼‰ã€‚è¿™æ ·ä½ å°±æœ‰ç©ºé—´æ¥ä¸ºæ¯ä¸ªæ•°æ®å†™ä¸€æ®µ | 427 | 声明一个数æ®ï¼ˆä¸è¦ä½¿ç”¨é€—å·æ¥ä¸€æ¬¡å£°æ˜Žå¤šä¸ªæ•°æ®ï¼‰ã€‚è¿™æ ·ä½ å°±æœ‰ç©ºé—´æ¥ä¸ºæ¯ä¸ªæ•°æ®å†™ä¸€æ®µ |
407 | å°æ³¨é‡Šæ¥è§£é‡Šå®ƒä»¬çš„用途了。 | 428 | å°æ³¨é‡Šæ¥è§£é‡Šå®ƒä»¬çš„用途了。 |
@@ -409,49 +430,63 @@ Linuxçš„æ³¨é‡Šé£Žæ ¼æ˜¯C89“/* ... */â€é£Žæ ¼ã€‚ä¸è¦ä½¿ç”¨C99é£Žæ ¼â€œ// ... | |||
409 | 430 | ||
410 | 第ä¹ç« ï¼šä½ å·²ç»æŠŠäº‹æƒ…å¼„ç³Ÿäº† | 431 | 第ä¹ç« ï¼šä½ å·²ç»æŠŠäº‹æƒ…å¼„ç³Ÿäº† |
411 | 432 | ||
412 | è¿™æ²¡ä»€ä¹ˆï¼Œæˆ‘ä»¬éƒ½æ˜¯è¿™æ ·ã€‚å¯èƒ½ä½ 的使用了很长时间Unix的朋å‹å·²ç»å‘Šè¯‰ä½ “GNU emacsâ€èƒ½ | 433 | è¿™æ²¡ä»€ä¹ˆï¼Œæˆ‘ä»¬éƒ½æ˜¯è¿™æ ·ã€‚å¯èƒ½ä½ 的使用了很长时间 Unix 的朋å‹å·²ç»å‘Šè¯‰ä½ “GNU emacs†能 |
413 | è‡ªåŠ¨å¸®ä½ æ ¼å¼åŒ–Cæºä»£ç ï¼Œè€Œä¸”ä½ ä¹Ÿæ³¨æ„åˆ°äº†ï¼Œç¡®å®žæ˜¯è¿™æ ·ï¼Œä¸è¿‡å®ƒæ‰€ä½¿ç”¨çš„默认值和我们 | 434 | è‡ªåŠ¨å¸®ä½ æ ¼å¼åŒ– C æºä»£ç ï¼Œè€Œä¸”ä½ ä¹Ÿæ³¨æ„åˆ°äº†ï¼Œç¡®å®žæ˜¯è¿™æ ·ï¼Œä¸è¿‡å®ƒæ‰€ä½¿ç”¨çš„默认值和我们 |
414 | 想è¦çš„ç›¸åŽ»ç”šè¿œï¼ˆå®žé™…ä¸Šï¼Œç”šè‡³æ¯”éšæœºæ‰“的还è¦å·®â€”â€”æ— æ•°ä¸ªçŒ´å在GNU emacsé‡Œæ‰“å—æ°¸è¿œä¸ | 435 | 想è¦çš„ç›¸åŽ»ç”šè¿œï¼ˆå®žé™…ä¸Šï¼Œç”šè‡³æ¯”éšæœºæ‰“的还è¦å·®â€”â€”æ— æ•°ä¸ªçŒ´å在 GNU emacs é‡Œæ‰“å—æ°¸è¿œä¸ |
415 | ä¼šåˆ›é€ å‡ºä¸€ä¸ªå¥½ç¨‹åºï¼‰ï¼ˆè¯‘注:请å‚考Infinite Monkey Theorem) | 436 | ä¼šåˆ›é€ å‡ºä¸€ä¸ªå¥½ç¨‹åºï¼‰ï¼ˆè¯‘注:请å‚考 Infinite Monkey Theorem) |
416 | 437 | ||
417 | æ‰€ä»¥ä½ è¦ä¹ˆæ”¾å¼ƒGNU emacs,è¦ä¹ˆæ”¹å˜å®ƒè®©å®ƒä½¿ç”¨æ›´åˆç†çš„设定。è¦é‡‡ç”¨åŽä¸€ä¸ªæ–¹æ¡ˆï¼Œä½ å¯ | 438 | æ‰€ä»¥ä½ è¦ä¹ˆæ”¾å¼ƒ GNU emacs,è¦ä¹ˆæ”¹å˜å®ƒè®©å®ƒä½¿ç”¨æ›´åˆç†çš„设定。è¦é‡‡ç”¨åŽä¸€ä¸ªæ–¹æ¡ˆï¼Œä½ å¯ |
418 | 以把下é¢è¿™æ®µç²˜è´´åˆ°ä½ çš„.emacs文件里。 | 439 | 以把下é¢è¿™æ®µç²˜è´´åˆ°ä½ çš„ .emacs 文件里。 |
419 | 440 | ||
420 | (defun linux-c-mode () | 441 | (defun c-lineup-arglist-tabs-only (ignored) |
421 | "C mode with adjusted defaults for use with the Linux kernel." | 442 | "Line up argument lists by tabs, not spaces" |
422 | (interactive) | 443 | (let* ((anchor (c-langelem-pos c-syntactic-element)) |
423 | (c-mode) | 444 | (column (c-langelem-2nd-pos c-syntactic-element)) |
424 | (c-set-style "K&R") | 445 | (offset (- (1+ column) anchor)) |
425 | (setq tab-width 8) | 446 | (steps (floor offset c-basic-offset))) |
426 | (setq indent-tabs-mode t) | 447 | (* (max steps 1) |
427 | (setq c-basic-offset 8)) | 448 | c-basic-offset))) |
428 | 449 | ||
429 | è¿™æ ·å°±å®šä¹‰äº†M-x linux-c-modeå‘½ä»¤ã€‚å½“ä½ hack一个模å—çš„æ—¶å€™ï¼Œå¦‚æžœä½ æŠŠå—符串 | 450 | (add-hook 'c-mode-common-hook |
430 | -*- linux-c -*-放在头两行的æŸä¸ªä½ç½®ï¼Œè¿™ä¸ªæ¨¡å¼å°†ä¼šè¢«è‡ªåŠ¨è°ƒç”¨ã€‚å¦‚æžœä½ å¸Œæœ›åœ¨ä½ ä¿®æ”¹ | 451 | (lambda () |
431 | /usr/src/linuxé‡Œçš„æ–‡ä»¶æ—¶é”æœ¯èˆ¬è‡ªåŠ¨æ‰“å¼€linux-c-modeçš„è¯ï¼Œä½ 也å¯èƒ½éœ€è¦æ·»åŠ | 452 | ;; Add kernel style |
432 | 453 | (c-add-style | |
433 | (setq auto-mode-alist (cons '("/usr/src/linux.*/.*\\.[ch]$" . linux-c-mode) | 454 | "linux-tabs-only" |
434 | auto-mode-alist)) | 455 | '("linux" (c-offsets-alist |
435 | 456 | (arglist-cont-nonempty | |
436 | åˆ°ä½ çš„.emacs文件里。 | 457 | c-lineup-gcc-asm-reg |
437 | 458 | c-lineup-arglist-tabs-only)))))) | |
438 | ä¸è¿‡å°±ç®—ä½ å°è¯•让emacsæ£ç¡®çš„æ ¼å¼åŒ–代ç å¤±è´¥äº†ï¼Œä¹Ÿå¹¶ä¸æ„味ç€ä½ 失去了一切:还å¯ä»¥ç”¨â€œ | 459 | |
439 | indentâ€ã€‚ | 460 | (add-hook 'c-mode-hook |
440 | 461 | (lambda () | |
441 | ä¸è¿‡ï¼ŒGNU indent也有和GNU emacsä¸€æ ·æœ‰é—®é¢˜çš„è®¾å®šï¼Œæ‰€ä»¥ä½ éœ€è¦ç»™å®ƒä¸€äº›å‘½ä»¤é€‰é¡¹ã€‚ä¸ | 462 | (let ((filename (buffer-file-name))) |
442 | 过,这还ä¸ç®—å¤ªç³Ÿç³•ï¼Œå› ä¸ºå°±ç®—æ˜¯GNU indent的作者也认åŒK&Rçš„æƒå¨æ€§ï¼ˆGNUçš„äººå¹¶ä¸æ˜¯å | 463 | ;; Enable kernel mode for the appropriate files |
443 | äººï¼Œä»–ä»¬åªæ˜¯åœ¨è¿™ä¸ªé—®é¢˜ä¸Šè¢«ä¸¥é‡çš„è¯¯å¯¼äº†ï¼‰ï¼Œæ‰€ä»¥ä½ åªè¦ç»™indent指定选项“-kr -i8†| 464 | (when (and filename |
444 | (代表“K&R,8个å—符缩进â€ï¼‰ï¼Œæˆ–者使用“scripts/Lindentâ€ï¼Œè¿™æ ·å°±å¯ä»¥ä»¥æœ€æ—¶é«¦çš„æ–¹å¼ | 465 | (string-match (expand-file-name "~/src/linux-trees") |
466 | filename)) | ||
467 | (setq indent-tabs-mode t) | ||
468 | (setq show-trailing-whitespace t) | ||
469 | (c-set-style "linux-tabs-only"))))) | ||
470 | |||
471 | 这会让 emacs 在 ~/src/linux-trees 目录下的 C æºæ–‡ä»¶èŽ·å¾—æ›´å¥½çš„å†…æ ¸ä»£ç é£Žæ ¼ã€‚ | ||
472 | |||
473 | ä¸è¿‡å°±ç®—ä½ å°è¯•让 emacs æ£ç¡®çš„æ ¼å¼åŒ–代ç å¤±è´¥äº†ï¼Œä¹Ÿå¹¶ä¸æ„味ç€ä½ 失去了一切:还å¯ä»¥ç”¨ | ||
474 | “indentâ€ã€‚ | ||
475 | |||
476 | ä¸è¿‡ï¼ŒGNU indent 也有和 GNU emacs ä¸€æ ·æœ‰é—®é¢˜çš„è®¾å®šï¼Œæ‰€ä»¥ä½ éœ€è¦ç»™å®ƒä¸€äº›å‘½ä»¤é€‰é¡¹ã€‚ä¸ | ||
477 | 过,这还ä¸ç®—å¤ªç³Ÿç³•ï¼Œå› ä¸ºå°±ç®—æ˜¯ GNU indent çš„ä½œè€…ä¹Ÿè®¤åŒ K&R çš„æƒå¨æ€§ï¼ˆGNU çš„äººå¹¶ä¸æ˜¯ | ||
478 | åäººï¼Œä»–ä»¬åªæ˜¯åœ¨è¿™ä¸ªé—®é¢˜ä¸Šè¢«ä¸¥é‡çš„è¯¯å¯¼äº†ï¼‰ï¼Œæ‰€ä»¥ä½ åªè¦ç»™ indent 指定选项 “-kr -i8†| ||
479 | (代表 “K&R,8 个å—符缩进â€ï¼‰ï¼Œæˆ–者使用 “scripts/Lindentâ€ï¼Œè¿™æ ·å°±å¯ä»¥ä»¥æœ€æ—¶é«¦çš„æ–¹å¼ | ||
445 | 缩进æºä»£ç 。 | 480 | 缩进æºä»£ç 。 |
446 | 481 | ||
447 | “indentâ€æœ‰å¾ˆå¤šé€‰é¡¹ï¼Œç‰¹åˆ«æ˜¯é‡æ–°æ ¼å¼åŒ–æ³¨é‡Šçš„æ—¶å€™ï¼Œä½ å¯èƒ½éœ€è¦çœ‹ä¸€ä¸‹å®ƒçš„æ‰‹å†Œé¡µã€‚ä¸è¿‡ | 482 | “indentâ€ æœ‰å¾ˆå¤šé€‰é¡¹ï¼Œç‰¹åˆ«æ˜¯é‡æ–°æ ¼å¼åŒ–æ³¨é‡Šçš„æ—¶å€™ï¼Œä½ å¯èƒ½éœ€è¦çœ‹ä¸€ä¸‹å®ƒçš„æ‰‹å†Œé¡µã€‚ä¸è¿‡ |
448 | è®°ä½ï¼šâ€œindentâ€ä¸èƒ½ä¿®æ£åçš„ç¼–ç¨‹ä¹ æƒ¯ã€‚ | 483 | è®°ä½ï¼šâ€œindent†ä¸èƒ½ä¿®æ£åçš„ç¼–ç¨‹ä¹ æƒ¯ã€‚ |
449 | 484 | ||
450 | 485 | ||
451 | 第åç« ï¼šKconfigé…置文件 | 486 | 第åç« ï¼šKconfig é…置文件 |
452 | 487 | ||
453 | 对于é布æºç æ ‘çš„æ‰€æœ‰Kconfig*é…置文件æ¥è¯´ï¼Œå®ƒä»¬ç¼©è¿›æ–¹å¼ä¸ŽC代ç 相比有所ä¸åŒã€‚紧挨 | 488 | 对于é布æºç æ ‘çš„æ‰€æœ‰ Kconfig* é…置文件æ¥è¯´ï¼Œå®ƒä»¬ç¼©è¿›æ–¹å¼ä¸Ž C 代ç 相比有所ä¸åŒã€‚紧挨 |
454 | 在“configâ€å®šä¹‰ä¸‹é¢çš„行缩进一个制表符,帮助信æ¯åˆ™å†å¤šç¼©è¿›2ä¸ªç©ºæ ¼ã€‚æ¯”å¦‚ï¼š | 489 | 在 “config†定义下é¢çš„行缩进一个制表符,帮助信æ¯åˆ™å†å¤šç¼©è¿› 2 ä¸ªç©ºæ ¼ã€‚æ¯”å¦‚ï¼š |
455 | 490 | ||
456 | config AUDIT | 491 | config AUDIT |
457 | bool "Auditing support" | 492 | bool "Auditing support" |
@@ -470,7 +505,7 @@ config ADFS_FS_RW | |||
470 | depends on ADFS_FS | 505 | depends on ADFS_FS |
471 | ... | 506 | ... |
472 | 507 | ||
473 | è¦æŸ¥çœ‹é…置文件的完整文档,请看Documentation/kbuild/kconfig-language.txt。 | 508 | è¦æŸ¥çœ‹é…置文件的完整文档,请看 Documentation/kbuild/kconfig-language.txt。 |
474 | 509 | ||
475 | 510 | ||
476 | 第åä¸€ç« ï¼šæ•°æ®ç»“æž„ | 511 | 第åä¸€ç« ï¼šæ•°æ®ç»“æž„ |
@@ -489,11 +524,11 @@ config ADFS_FS_RW | |||
489 | 很多数æ®ç»“构实际上有2级引用计数,它们通常有ä¸åŒâ€œç±»â€çš„用户。å类计数器统计å类用 | 524 | 很多数æ®ç»“构实际上有2级引用计数,它们通常有ä¸åŒâ€œç±»â€çš„用户。å类计数器统计å类用 |
490 | 户的数é‡ï¼Œæ¯å½“å类计数器å‡è‡³é›¶æ—¶ï¼Œå…¨å±€è®¡æ•°å™¨å‡ä¸€ã€‚ | 525 | 户的数é‡ï¼Œæ¯å½“å类计数器å‡è‡³é›¶æ—¶ï¼Œå…¨å±€è®¡æ•°å™¨å‡ä¸€ã€‚ |
491 | 526 | ||
492 | è¿™ç§â€œå¤šçº§å¼•用计数â€çš„例åå¯ä»¥åœ¨å†…å˜ç®¡ç†ï¼ˆâ€œstruct mm_structâ€ï¼šmm_userså’Œmm_count) | 527 | è¿™ç§â€œå¤šçº§å¼•用计数â€çš„例åå¯ä»¥åœ¨å†…å˜ç®¡ç†ï¼ˆâ€œstruct mm_structâ€ï¼šmm_users å’Œ mm_count) |
493 | 和文件系统(“struct super_blockâ€ï¼šs_countå’Œs_activeï¼‰ä¸æ‰¾åˆ°ã€‚ | 528 | 和文件系统(“struct super_blockâ€ï¼šs_countå’Œs_activeï¼‰ä¸æ‰¾åˆ°ã€‚ |
494 | 529 | ||
495 | è®°ä½ï¼šå¦‚æžœå¦ä¸€ä¸ªæ‰§è¡Œçº¿ç´¢å¯ä»¥æ‰¾åˆ°ä½ 的数æ®ç»“构,但是这个数æ®ç»“构没有引用计数器,这 | 530 | è®°ä½ï¼šå¦‚æžœå¦ä¸€ä¸ªæ‰§è¡Œçº¿ç´¢å¯ä»¥æ‰¾åˆ°ä½ 的数æ®ç»“构,但是这个数æ®ç»“构没有引用计数器,这 |
496 | é‡Œå‡ ä¹Žè‚¯å®šæ˜¯ä¸€ä¸ªbug。 | 531 | é‡Œå‡ ä¹Žè‚¯å®šæ˜¯ä¸€ä¸ª bug。 |
497 | 532 | ||
498 | 533 | ||
499 | 第åäºŒç« ï¼šå®ï¼Œæžšä¸¾å’ŒRTL | 534 | 第åäºŒç« ï¼šå®ï¼Œæžšä¸¾å’ŒRTL |
@@ -508,102 +543,128 @@ config ADFS_FS_RW | |||
508 | 543 | ||
509 | 一般的,如果能写æˆå†…è”函数就ä¸è¦å†™æˆåƒå‡½æ•°çš„å®ã€‚ | 544 | 一般的,如果能写æˆå†…è”函数就ä¸è¦å†™æˆåƒå‡½æ•°çš„å®ã€‚ |
510 | 545 | ||
511 | 嫿œ‰å¤šä¸ªè¯å¥çš„å®åº”该被包å«åœ¨ä¸€ä¸ªdo-while代ç å—里: | 546 | 嫿œ‰å¤šä¸ªè¯å¥çš„å®åº”该被包å«åœ¨ä¸€ä¸ª do-while 代ç å—里: |
512 | 547 | ||
513 | #define macrofun(a, b, c) \ | 548 | #define macrofun(a, b, c) \ |
514 | do { \ | 549 | do { \ |
515 | if (a == 5) \ | 550 | if (a == 5) \ |
516 | do_this(b, c); \ | 551 | do_this(b, c); \ |
517 | } while (0) | 552 | } while (0) |
518 | 553 | ||
519 | 使用å®çš„æ—¶å€™åº”é¿å…的事情: | 554 | 使用å®çš„æ—¶å€™åº”é¿å…的事情: |
520 | 555 | ||
521 | 1) å½±å“æŽ§åˆ¶æµç¨‹çš„å®ï¼š | 556 | 1) å½±å“æŽ§åˆ¶æµç¨‹çš„å®ï¼š |
522 | 557 | ||
523 | #define FOO(x) \ | 558 | #define FOO(x) \ |
524 | do { \ | 559 | do { \ |
525 | if (blah(x) < 0) \ | 560 | if (blah(x) < 0) \ |
526 | return -EBUGGERED; \ | 561 | return -EBUGGERED; \ |
527 | } while(0) | 562 | } while (0) |
528 | 563 | ||
529 | éžå¸¸ä¸å¥½ã€‚它看起æ¥åƒä¸€ä¸ªå‡½æ•°ï¼Œä¸è¿‡å´èƒ½å¯¼è‡´â€œè°ƒç”¨â€å®ƒçš„函数退出;ä¸è¦æ‰“乱读者大脑里 | 564 | éžå¸¸ä¸å¥½ã€‚它看起æ¥åƒä¸€ä¸ªå‡½æ•°ï¼Œä¸è¿‡å´èƒ½å¯¼è‡´â€œè°ƒç”¨â€å®ƒçš„函数退出;ä¸è¦æ‰“乱读者大脑里 |
530 | çš„è¯æ³•分æžå™¨ã€‚ | 565 | çš„è¯æ³•分æžå™¨ã€‚ |
531 | 566 | ||
532 | 2) ä¾èµ–于一个固定åå—的本地å˜é‡çš„å®ï¼š | 567 | 2) ä¾èµ–于一个固定åå—的本地å˜é‡çš„å®ï¼š |
533 | 568 | ||
534 | #define FOO(val) bar(index, val) | 569 | #define FOO(val) bar(index, val) |
535 | 570 | ||
536 | å¯èƒ½çœ‹èµ·æ¥åƒæ˜¯ä¸ªä¸é”™çš„东西,ä¸è¿‡å®ƒéžå¸¸å®¹æ˜“把读代ç 的人æžç³Šæ¶‚ï¼Œè€Œä¸”å®¹æ˜“å¯¼è‡´çœ‹èµ·æ¥ | 571 | å¯èƒ½çœ‹èµ·æ¥åƒæ˜¯ä¸ªä¸é”™çš„东西,ä¸è¿‡å®ƒéžå¸¸å®¹æ˜“把读代ç 的人æžç³Šæ¶‚ï¼Œè€Œä¸”å®¹æ˜“å¯¼è‡´çœ‹èµ·æ¥ |
537 | ä¸ç›¸å…³çš„æ”¹åЍ另æ¥é”™è¯¯ã€‚ | 572 | ä¸ç›¸å…³çš„æ”¹åЍ另æ¥é”™è¯¯ã€‚ |
538 | 573 | ||
539 | 3) ä½œä¸ºå·¦å€¼çš„å¸¦å‚æ•°çš„å®ï¼š FOO(x) = y;如果有人把FOOå˜æˆä¸€ä¸ªå†…è”函数的è¯ï¼Œè¿™ç§ç”¨ | 574 | 3) ä½œä¸ºå·¦å€¼çš„å¸¦å‚æ•°çš„å®ï¼š FOO(x) = y;如果有人把 FOO å˜æˆä¸€ä¸ªå†…è”函数的è¯ï¼Œè¿™ç§ç”¨ |
540 | 法就会出错了。 | 575 | 法就会出错了。 |
541 | 576 | ||
542 | 4) 忘记了优先级:使用表达å¼å®šä¹‰å¸¸é‡çš„å®å¿…须将表达å¼ç½®äºŽä¸€å¯¹å°æ‹¬å·ä¹‹å†…ã€‚å¸¦å‚æ•°çš„ | 577 | 4) 忘记了优先级:使用表达å¼å®šä¹‰å¸¸é‡çš„å®å¿…须将表达å¼ç½®äºŽä¸€å¯¹å°æ‹¬å·ä¹‹å†…ã€‚å¸¦å‚æ•°çš„ |
543 | å®ä¹Ÿè¦æ³¨æ„æ¤ç±»é—®é¢˜ã€‚ | 578 | å®ä¹Ÿè¦æ³¨æ„æ¤ç±»é—®é¢˜ã€‚ |
544 | 579 | ||
545 | #define CONSTANT 0x4000 | 580 | #define CONSTANT 0x4000 |
546 | #define CONSTEXP (CONSTANT | 3) | 581 | #define CONSTEXP (CONSTANT | 3) |
582 | |||
583 | 5) 在å®é‡Œå®šä¹‰ç±»ä¼¼å‡½æ•°çš„æœ¬åœ°å˜é‡æ—¶å‘½å冲çªï¼š | ||
547 | 584 | ||
548 | cpp手册对å®çš„讲解很详细。Gcc internals手册也详细讲解了RTL(译注:register | 585 | #define FOO(x) \ |
586 | ({ \ | ||
587 | typeof(x) ret; \ | ||
588 | ret = calc_ret(x); \ | ||
589 | (ret); \ | ||
590 | }) | ||
591 | |||
592 | ret 是本地å˜é‡çš„通用åå— - __foo_ret æ›´ä¸å®¹æ˜“与一个已å˜åœ¨çš„å˜é‡å†²çªã€‚ | ||
593 | |||
594 | cpp 手册对å®çš„讲解很详细。gcc internals 手册也详细讲解了 RTL(译注:register | ||
549 | transfer languageï¼‰ï¼Œå†…æ ¸é‡Œçš„æ±‡ç¼–è¯è¨€ç»å¸¸ç”¨åˆ°å®ƒã€‚ | 595 | transfer languageï¼‰ï¼Œå†…æ ¸é‡Œçš„æ±‡ç¼–è¯è¨€ç»å¸¸ç”¨åˆ°å®ƒã€‚ |
550 | 596 | ||
551 | 597 | ||
552 | 第åä¸‰ç« ï¼šæ‰“å°å†…æ ¸æ¶ˆæ¯ | 598 | 第åä¸‰ç« ï¼šæ‰“å°å†…æ ¸æ¶ˆæ¯ |
553 | 599 | ||
554 | å†…æ ¸å¼€å‘者应该是å—过良好教育的。请一定注æ„å†…æ ¸ä¿¡æ¯çš„æ‹¼å†™ï¼Œä»¥ç»™äººä»¥å¥½çš„å°è±¡ã€‚ä¸è¦ | 600 | å†…æ ¸å¼€å‘者应该是å—过良好教育的。请一定注æ„å†…æ ¸ä¿¡æ¯çš„æ‹¼å†™ï¼Œä»¥ç»™äººä»¥å¥½çš„å°è±¡ã€‚ä¸è¦ |
555 | 用ä¸è§„范的å•è¯æ¯”如“dontâ€ï¼Œè€Œè¦ç”¨â€œdo notâ€æˆ–者“don'tâ€ã€‚ä¿è¯è¿™äº›ä¿¡æ¯ç®€å•ã€æ˜Žäº†ã€æ— | 601 | 用ä¸è§„范的å•è¯æ¯”如 “dontâ€ï¼Œè€Œè¦ç”¨ “do notâ€æˆ–者 “don'tâ€ã€‚ä¿è¯è¿™äº›ä¿¡æ¯ç®€å•ã€æ˜Žäº†ã€ |
556 | æ§ä¹‰ã€‚ | 602 | æ— æ§ä¹‰ã€‚ |
557 | 603 | ||
558 | å†…æ ¸ä¿¡æ¯ä¸å¿…以å¥å·ï¼ˆè¯‘注:英文å¥å·ï¼Œå³ç‚¹ï¼‰ç»“æŸã€‚ | 604 | å†…æ ¸ä¿¡æ¯ä¸å¿…以å¥å·ï¼ˆè¯‘注:英文å¥å·ï¼Œå³ç‚¹ï¼‰ç»“æŸã€‚ |
559 | 605 | ||
560 | åœ¨å°æ‹¬å·é‡Œæ‰“å°æ•°å—(%d)没有任何价值,应该é¿å…è¿™æ ·åšã€‚ | 606 | åœ¨å°æ‹¬å·é‡Œæ‰“å°æ•°å— (%d) 没有任何价值,应该é¿å…è¿™æ ·åšã€‚ |
561 | 607 | ||
562 | <linux/device.h>里有一些驱动模型诊æ–å®ï¼Œä½ 应该使用它们,以确ä¿ä¿¡æ¯å¯¹åº”于æ£ç¡®çš„ | 608 | <linux/device.h> 里有一些驱动模型诊æ–å®ï¼Œä½ 应该使用它们,以确ä¿ä¿¡æ¯å¯¹åº”于æ£ç¡®çš„ |
563 | è®¾å¤‡å’Œé©±åŠ¨ï¼Œå¹¶ä¸”è¢«æ ‡è®°äº†æ£ç¡®çš„æ¶ˆæ¯çº§åˆ«ã€‚è¿™äº›å®æœ‰ï¼šdev_err(), dev_warn(), | 609 | è®¾å¤‡å’Œé©±åŠ¨ï¼Œå¹¶ä¸”è¢«æ ‡è®°äº†æ£ç¡®çš„æ¶ˆæ¯çº§åˆ«ã€‚è¿™äº›å®æœ‰ï¼šdev_err(),dev_warn(), |
564 | dev_info()ç‰ç‰ã€‚对于那些ä¸å’ŒæŸä¸ªç‰¹å®šè®¾å¤‡ç›¸å…³è¿žçš„ä¿¡æ¯ï¼Œ<linux/kernel.h>定义了 | 610 | dev_info() ç‰ç‰ã€‚对于那些ä¸å’ŒæŸä¸ªç‰¹å®šè®¾å¤‡ç›¸å…³è¿žçš„ä¿¡æ¯ï¼Œ<linux/printk.h> 定义了 |
565 | pr_debug()和pr_info()。 | 611 | pr_notice(),pr_info(),pr_warn(),pr_err() 和其他。 |
566 | 612 | ||
567 | 写出好的调试信æ¯å¯ä»¥æ˜¯ä¸€ä¸ªå¾ˆå¤§çš„æŒ‘æˆ˜ï¼›å½“ä½ å†™å‡ºæ¥ä¹‹åŽï¼Œè¿™äº›ä¿¡æ¯åœ¨è¿œç¨‹é™¤é”™çš„æ—¶å€™ | 613 | 写出好的调试信æ¯å¯ä»¥æ˜¯ä¸€ä¸ªå¾ˆå¤§çš„æŒ‘æˆ˜ï¼›ä¸€æ—¦ä½ å†™å‡ºåŽï¼Œè¿™äº›ä¿¡æ¯åœ¨è¿œç¨‹é™¤é”™æ—¶èƒ½æä¾›æžå¤§ |
568 | 就会æˆä¸ºæžå¤§çš„帮助。当DEBUGç¬¦å·æ²¡æœ‰è¢«å®šä¹‰çš„æ—¶å€™ï¼Œè¿™äº›ä¿¡æ¯ä¸åº”è¯¥è¢«ç¼–è¯‘è¿›å†…æ ¸é‡Œ | 614 | 的帮助。然而打å°è°ƒè¯•ä¿¡æ¯çš„å¤„ç†æ–¹å¼åŒæ‰“å°éžè°ƒè¯•ä¿¡æ¯ä¸åŒã€‚å…¶ä»– pr_XXX() å‡½æ•°èƒ½æ— æ¡ä»¶åœ° |
569 | (也就是说,默认地,它们ä¸åº”该被包å«åœ¨å†…ï¼‰ã€‚å¦‚æžœä½ ä½¿ç”¨dev_dbg()或者pr_debug(), | 615 | 打å°ï¼Œpr_debug() å´ä¸ï¼›é»˜è®¤æƒ…况下它ä¸ä¼šè¢«ç¼–译,除éžå®šä¹‰äº† DEBUG 或设定了 |
570 | 就能自动达到这个效果。很多å系统拥有Kconfig选项æ¥å¯ç”¨-DDEBUG。还有一个相关的惯例 | 616 | CONFIG_DYNAMIC_DEBUGã€‚å®žé™…è¿™åŒæ ·æ˜¯ä¸ºäº† dev_dbg(),一个相关约定是在一个已ç»å¼€å¯äº† |
571 | 是使用VERBOSE_DEBUGæ¥æ·»åŠ dev_vdbg()消æ¯åˆ°é‚£äº›å·²ç»ç”±DEBUGå¯ç”¨çš„æ¶ˆæ¯ä¹‹ä¸Šã€‚ | 617 | DEBUG 时,使用 VERBOSE_DEBUG æ¥æ·»åŠ dev_vdbg()。 |
618 | |||
619 | 许多å系统拥有 Kconfig 调试选项æ¥å¼€å¯ -DDEBUG 在对应的 Makefile 里é¢ï¼›åœ¨å…¶ä»– | ||
620 | 情况下,特殊文件使用 #define DEBUG。当一æ¡è°ƒè¯•ä¿¡æ¯éœ€è¦è¢«æ— æ¡ä»¶æ‰“å°æ—¶ï¼Œä¾‹å¦‚,如果 | ||
621 | å·²ç»åŒ…å«ä¸€ä¸ªè°ƒè¯•相关的 #ifdef æ¡ä»¶ï¼Œprintk(KERN_DEBUG ...) å°±å¯è¢«ä½¿ç”¨ã€‚ | ||
572 | 622 | ||
573 | 623 | ||
574 | 第åå››ç« ï¼šåˆ†é…å†…å˜ | 624 | 第åå››ç« ï¼šåˆ†é…å†…å˜ |
575 | 625 | ||
576 | å†…æ ¸æä¾›äº†ä¸‹é¢çš„一般用途的内å˜åˆ†é…函数:kmalloc(),kzalloc(),kcalloc()å’Œ | 626 | å†…æ ¸æä¾›äº†ä¸‹é¢çš„一般用途的内å˜åˆ†é…函数: |
577 | vmalloc()。请å‚考APIæ–‡æ¡£ä»¥èŽ·å–æœ‰å…³å®ƒä»¬çš„详细信æ¯ã€‚ | 627 | kmalloc(),kzalloc(),kmalloc_array(),kcalloc(),vmalloc() å’Œ vzalloc()。 |
628 | 请å‚考 API æ–‡æ¡£ä»¥èŽ·å–æœ‰å…³å®ƒä»¬çš„详细信æ¯ã€‚ | ||
578 | 629 | ||
579 | ä¼ é€’ç»“æž„ä½“å¤§å°çš„首选形弿˜¯è¿™æ ·çš„: | 630 | ä¼ é€’ç»“æž„ä½“å¤§å°çš„首选形弿˜¯è¿™æ ·çš„: |
580 | 631 | ||
581 | p = kmalloc(sizeof(*p), ...); | 632 | p = kmalloc(sizeof(*p), ...); |
582 | 633 | ||
583 | å¦å¤–一ç§ä¼ 递方å¼ä¸ï¼Œsizeofçš„æ“作数是结构体的åå—ï¼Œè¿™æ ·ä¼šé™ä½Žå¯è¯»æ€§ï¼Œå¹¶ä¸”å¯èƒ½ä¼šå¼• | 634 | å¦å¤–一ç§ä¼ 递方å¼ä¸ï¼Œsizeof çš„æ“作数是结构体的åå—ï¼Œè¿™æ ·ä¼šé™ä½Žå¯è¯»æ€§ï¼Œå¹¶ä¸”å¯èƒ½ä¼šå¼• |
584 | å…¥bug。有å¯èƒ½æŒ‡é’ˆå˜é‡ç±»åž‹è¢«æ”¹å˜æ—¶ï¼Œè€Œå¯¹åº”çš„ä¼ é€’ç»™å†…å˜åˆ†é…函数的sizeof的结果ä¸å˜ã€‚ | 635 | å…¥ bug。有å¯èƒ½æŒ‡é’ˆå˜é‡ç±»åž‹è¢«æ”¹å˜æ—¶ï¼Œè€Œå¯¹åº”çš„ä¼ é€’ç»™å†…å˜åˆ†é…函数的 sizeof 的结果ä¸å˜ã€‚ |
585 | 636 | ||
586 | 强制转æ¢ä¸€ä¸ªvoid指针返回值是多余的。Cè¯è¨€æœ¬èº«ä¿è¯äº†ä»Žvoid指针到其他任何指针类型 | 637 | 强制转æ¢ä¸€ä¸ª void 指针返回值是多余的。C è¯è¨€æœ¬èº«ä¿è¯äº†ä»Ž void 指针到其他任何指针类型 |
587 | çš„è½¬æ¢æ˜¯æ²¡æœ‰é—®é¢˜çš„。 | 638 | çš„è½¬æ¢æ˜¯æ²¡æœ‰é—®é¢˜çš„。 |
588 | 639 | ||
640 | 分é…ä¸€ä¸ªæ•°ç»„çš„é¦–é€‰å½¢å¼æ˜¯è¿™æ ·çš„: | ||
641 | |||
642 | p = kmalloc_array(n, sizeof(...), ...); | ||
643 | |||
644 | 分é…ä¸€ä¸ªé›¶é•¿æ•°ç»„çš„é¦–é€‰å½¢å¼æ˜¯è¿™æ ·çš„: | ||
645 | |||
646 | p = kcalloc(n, sizeof(...), ...); | ||
647 | |||
648 | 两ç§å½¢å¼æ£€æŸ¥åˆ†é…å¤§å° n * sizeof(...) 的溢出,如果溢出返回 NULL。 | ||
649 | |||
589 | 650 | ||
590 | 第åäº”ç« ï¼šå†…è”弊病 | 651 | 第åäº”ç« ï¼šå†…è”弊病 |
591 | 652 | ||
592 | 有一个常è§çš„误解是内è”函数是gccæä¾›çš„å¯ä»¥è®©ä»£ç è¿è¡Œæ›´å¿«çš„ä¸€ä¸ªé€‰é¡¹ã€‚è™½ç„¶ä½¿ç”¨å†…è” | 653 | 有一个常è§çš„误解是内è”函数是 gcc æä¾›çš„å¯ä»¥è®©ä»£ç è¿è¡Œæ›´å¿«çš„ä¸€ä¸ªé€‰é¡¹ã€‚è™½ç„¶ä½¿ç”¨å†…è” |
593 | 函数有时候是æ°å½“çš„ï¼ˆæ¯”å¦‚ä½œä¸ºä¸€ç§æ›¿ä»£å®çš„æ–¹å¼ï¼Œè¯·çœ‹ç¬¬åäºŒç« ï¼‰ï¼Œä¸è¿‡å¾ˆå¤šæƒ…况䏋䏿˜¯ | 654 | 函数有时候是æ°å½“çš„ï¼ˆæ¯”å¦‚ä½œä¸ºä¸€ç§æ›¿ä»£å®çš„æ–¹å¼ï¼Œè¯·çœ‹ç¬¬åäºŒç« ï¼‰ï¼Œä¸è¿‡å¾ˆå¤šæƒ…况䏋䏿˜¯ |
594 | è¿™æ ·ã€‚inline关键å—çš„è¿‡åº¦ä½¿ç”¨ä¼šä½¿å†…æ ¸å˜å¤§ï¼Œä»Žè€Œä½¿æ•´ä¸ªç³»ç»Ÿè¿è¡Œé€Ÿåº¦å˜æ…¢ã€‚å› ä¸ºå¤§å†…æ ¸ | 655 | è¿™æ ·ã€‚inline 关键å—çš„è¿‡åº¦ä½¿ç”¨ä¼šä½¿å†…æ ¸å˜å¤§ï¼Œä»Žè€Œä½¿æ•´ä¸ªç³»ç»Ÿè¿è¡Œé€Ÿåº¦å˜æ…¢ã€‚å› ä¸ºå¤§å†…æ ¸ |
595 | 会å 用更多的指令高速缓å˜ï¼ˆè¯‘注:一级缓å˜é€šå¸¸æ˜¯æŒ‡ä»¤ç¼“å˜å’Œæ•°æ®ç¼“å˜åˆ†å¼€çš„)而且会导 | 656 | 会å 用更多的指令高速缓å˜ï¼ˆè¯‘注:一级缓å˜é€šå¸¸æ˜¯æŒ‡ä»¤ç¼“å˜å’Œæ•°æ®ç¼“å˜åˆ†å¼€çš„)而且会导 |
596 | 致pagecacheçš„å¯ç”¨å†…å˜å‡å°‘。想象一下,一次pagecache未命ä¸å°±ä¼šå¯¼è‡´ä¸€æ¬¡ç£ç›˜å¯»å€ï¼Œå°† | 657 | 致 pagecache çš„å¯ç”¨å†…å˜å‡å°‘。想象一下,一次pagecache未命ä¸å°±ä¼šå¯¼è‡´ä¸€æ¬¡ç£ç›˜å¯»å€ï¼Œ |
597 | 耗时5毫秒。5毫秒的时间内CPU能执行很多很多指令。 | 658 | 将耗时 5 毫秒。5 毫秒的时间内 CPU 能执行很多很多指令。 |
598 | 659 | ||
599 | 一个基本的原则是如果一个函数有3行以上,就ä¸è¦æŠŠå®ƒå˜æˆå†…è”函数。这个原则的一个例 | 660 | 一个基本的原则是如果一个函数有 3 行以上,就ä¸è¦æŠŠå®ƒå˜æˆå†…è”函数。这个原则的一个例 |
600 | å¤–æ˜¯ï¼Œå¦‚æžœä½ çŸ¥é“æŸä¸ªå‚数是一个编译时常é‡ï¼Œè€Œä¸”å› ä¸ºè¿™ä¸ªå¸¸é‡ä½ 确定编译器在编译时能 | 661 | å¤–æ˜¯ï¼Œå¦‚æžœä½ çŸ¥é“æŸä¸ªå‚数是一个编译时常é‡ï¼Œè€Œä¸”å› ä¸ºè¿™ä¸ªå¸¸é‡ä½ 确定编译器在编译时能 |
601 | ä¼˜åŒ–æŽ‰ä½ çš„å‡½æ•°çš„å¤§éƒ¨åˆ†ä»£ç ,那ä»ç„¶å¯ä»¥ç»™å®ƒåŠ ä¸Šinline关键å—。kmalloc()内è”函数就 | 662 | ä¼˜åŒ–æŽ‰ä½ çš„å‡½æ•°çš„å¤§éƒ¨åˆ†ä»£ç ,那ä»ç„¶å¯ä»¥ç»™å®ƒåŠ ä¸Š inline 关键å—。kmalloc() 内è”函数就 |
602 | 是一个很好的例å。 | 663 | 是一个很好的例å。 |
603 | 664 | ||
604 | 人们ç»å¸¸ä¸»å¼ ç»™static的而且åªç”¨äº†ä¸€æ¬¡çš„å‡½æ•°åŠ ä¸Šinline,如æ¤ä¸ä¼šæœ‰ä»»ä½•æŸå¤±ï¼Œå› 为没 | 665 | 人们ç»å¸¸ä¸»å¼ ç»™ static 的而且åªç”¨äº†ä¸€æ¬¡çš„å‡½æ•°åŠ ä¸Š inline,如æ¤ä¸ä¼šæœ‰ä»»ä½•æŸå¤±ï¼Œå› 为没 |
605 | 有什么好æƒè¡¡çš„。虽然从技术上说这是æ£ç¡®çš„ï¼Œä½†æ˜¯å®žé™…ä¸Šè¿™ç§æƒ…况下å³ä½¿ä¸åŠ inline gcc | 666 | 有什么好æƒè¡¡çš„。虽然从技术上说这是æ£ç¡®çš„ï¼Œä½†æ˜¯å®žé™…ä¸Šè¿™ç§æƒ…况下å³ä½¿ä¸åŠ inline gcc |
606 | 也å¯ä»¥è‡ªåŠ¨ä½¿å…¶å†…è”。而且其他用户å¯èƒ½ä¼šè¦æ±‚移除inline,由æ¤è€Œæ¥çš„争论会抵消inline | 667 | 也å¯ä»¥è‡ªåŠ¨ä½¿å…¶å†…è”。而且其他用户å¯èƒ½ä¼šè¦æ±‚移除 inline,由æ¤è€Œæ¥çš„争论会抵消 inline |
607 | 自身的潜在价值,得ä¸å¿å¤±ã€‚ | 668 | 自身的潜在价值,得ä¸å¿å¤±ã€‚ |
608 | 669 | ||
609 | 670 | ||
@@ -613,37 +674,37 @@ vmalloc()。请å‚考APIæ–‡æ¡£ä»¥èŽ·å–æœ‰å…³å®ƒä»¬çš„详细信æ¯ã€‚ | |||
613 | 的一个值å¯ä»¥è¡¨ç¤ºä¸ºä¸€ä¸ªé”™è¯¯ä»£ç 整数(-Exxxï¼å¤±è´¥ï¼Œ0ï¼æˆåŠŸï¼‰æˆ–è€…ä¸€ä¸ªâ€œæˆåŠŸâ€å¸ƒå°”值( | 674 | 的一个值å¯ä»¥è¡¨ç¤ºä¸ºä¸€ä¸ªé”™è¯¯ä»£ç 整数(-Exxxï¼å¤±è´¥ï¼Œ0ï¼æˆåŠŸï¼‰æˆ–è€…ä¸€ä¸ªâ€œæˆåŠŸâ€å¸ƒå°”值( |
614 | 0ï¼å¤±è´¥ï¼Œéž0ï¼æˆåŠŸï¼‰ã€‚ | 675 | 0ï¼å¤±è´¥ï¼Œéž0ï¼æˆåŠŸï¼‰ã€‚ |
615 | 676 | ||
616 | æ··åˆä½¿ç”¨è¿™ä¸¤ç§è¡¨è¾¾æ–¹å¼æ˜¯éš¾äºŽå‘现的bugçš„æ¥æºã€‚如果Cè¯è¨€æœ¬èº«ä¸¥æ ¼åŒºåˆ†æ•´å½¢å’Œå¸ƒå°”åž‹å˜ | 677 | æ··åˆä½¿ç”¨è¿™ä¸¤ç§è¡¨è¾¾æ–¹å¼æ˜¯éš¾äºŽå‘现的 bug çš„æ¥æºã€‚如果 C è¯è¨€æœ¬èº«ä¸¥æ ¼åŒºåˆ†æ•´å½¢å’Œå¸ƒå°”åž‹å˜ |
617 | é‡ï¼Œé‚£ä¹ˆç¼–译器就能够帮我们å‘现这些错误……ä¸è¿‡Cè¯è¨€ä¸åŒºåˆ†ã€‚为了é¿å…产生这ç§bug,请 | 678 | é‡ï¼Œé‚£ä¹ˆç¼–译器就能够帮我们å‘现这些错误……ä¸è¿‡ C è¯è¨€ä¸åŒºåˆ†ã€‚为了é¿å…äº§ç”Ÿè¿™ç§ bug,请 |
618 | éµå¾ªä¸‹é¢çš„æƒ¯ä¾‹ï¼š | 679 | éµå¾ªä¸‹é¢çš„æƒ¯ä¾‹ï¼š |
619 | 680 | ||
620 | 如果函数的åå—æ˜¯ä¸€ä¸ªåŠ¨ä½œæˆ–è€…å¼ºåˆ¶æ€§çš„å‘½ä»¤ï¼Œé‚£ä¹ˆè¿™ä¸ªå‡½æ•°åº”è¯¥è¿”å›žé”™è¯¯ä»£ç æ•´ | 681 | 如果函数的åå—æ˜¯ä¸€ä¸ªåŠ¨ä½œæˆ–è€…å¼ºåˆ¶æ€§çš„å‘½ä»¤ï¼Œé‚£ä¹ˆè¿™ä¸ªå‡½æ•°åº”è¯¥è¿”å›žé”™è¯¯ä»£ç æ•´ |
621 | 数。如果是一个判æ–,那么函数应该返回一个“æˆåŠŸâ€å¸ƒå°”值。 | 682 | 数。如果是一个判æ–,那么函数应该返回一个“æˆåŠŸâ€å¸ƒå°”值。 |
622 | 683 | ||
623 | 比如,“add workâ€æ˜¯ä¸€ä¸ªå‘½ä»¤ï¼Œæ‰€ä»¥add_work()函数在æˆåŠŸæ—¶è¿”å›ž0,在失败时返回-EBUSY。 | 684 | 比如,“add work†是一个命令,所以 add_work() 函数在æˆåŠŸæ—¶è¿”å›ž 0,在失败时返回 -EBUSY。 |
624 | ç±»ä¼¼çš„ï¼Œå› ä¸ºâ€œPCI device presentâ€æ˜¯ä¸€ä¸ªåˆ¤æ–,所以pci_dev_present()函数在æˆåŠŸæ‰¾åˆ° | 685 | ç±»ä¼¼çš„ï¼Œå› ä¸º “PCI device present†是一个判æ–,所以 pci_dev_present() 函数在æˆåŠŸæ‰¾åˆ° |
625 | 一个匹é…的设备时应该返回1,如果找ä¸åˆ°æ—¶åº”该返回0。 | 686 | 一个匹é…的设备时应该返回 1,如果找ä¸åˆ°æ—¶åº”该返回 0。 |
626 | 687 | ||
627 | 所有导出(译注:EXPORT)的函数都必须éµå®ˆè¿™ä¸ªæƒ¯ä¾‹ï¼Œæ‰€æœ‰çš„公共函数也都应该如æ¤ã€‚ç§ | 688 | 所有导出(译注:EXPORT)的函数都必须éµå®ˆè¿™ä¸ªæƒ¯ä¾‹ï¼Œæ‰€æœ‰çš„公共函数也都应该如æ¤ã€‚ç§ |
628 | 有(static)函数ä¸éœ€è¦å¦‚æ¤ï¼Œä½†æ˜¯æˆ‘们也推èè¿™æ ·åšã€‚ | 689 | 有(static)函数ä¸éœ€è¦å¦‚æ¤ï¼Œä½†æ˜¯æˆ‘们也推èè¿™æ ·åšã€‚ |
629 | 690 | ||
630 | è¿”å›žå€¼æ˜¯å®žé™…è®¡ç®—ç»“æžœè€Œä¸æ˜¯è®¡ç®—æ˜¯å¦æˆåŠŸçš„æ ‡å¿—çš„å‡½æ•°ä¸å—æ¤æƒ¯ä¾‹çš„é™åˆ¶ã€‚一般的,他们 | 691 | è¿”å›žå€¼æ˜¯å®žé™…è®¡ç®—ç»“æžœè€Œä¸æ˜¯è®¡ç®—æ˜¯å¦æˆåŠŸçš„æ ‡å¿—çš„å‡½æ•°ä¸å—æ¤æƒ¯ä¾‹çš„é™åˆ¶ã€‚一般的,他们 |
631 | 通过返回一些æ£å¸¸å€¼èŒƒå›´ä¹‹å¤–的结果æ¥è¡¨ç¤ºå‡ºé”™ã€‚å…¸åž‹çš„ä¾‹åæ˜¯è¿”回指针的函数,他们使用 | 692 | 通过返回一些æ£å¸¸å€¼èŒƒå›´ä¹‹å¤–的结果æ¥è¡¨ç¤ºå‡ºé”™ã€‚å…¸åž‹çš„ä¾‹åæ˜¯è¿”回指针的函数,他们使用 |
632 | NULL或者ERR_PTRæœºåˆ¶æ¥æŠ¥å‘Šé”™è¯¯ã€‚ | 693 | NULL 或者 ERR_PTR æœºåˆ¶æ¥æŠ¥å‘Šé”™è¯¯ã€‚ |
633 | 694 | ||
634 | 695 | ||
635 | 第åä¸ƒç« ï¼šä¸è¦é‡æ–°å‘æ˜Žå†…æ ¸å® | 696 | 第åä¸ƒç« ï¼šä¸è¦é‡æ–°å‘æ˜Žå†…æ ¸å® |
636 | 697 | ||
637 | 头文件include/linux/kernel.h包å«äº†ä¸€äº›å®ï¼Œä½ 应该使用它们,而ä¸è¦è‡ªå·±å†™ä¸€äº›å®ƒä»¬çš„ | 698 | 头文件 include/linux/kernel.h 包å«äº†ä¸€äº›å®ï¼Œä½ 应该使用它们,而ä¸è¦è‡ªå·±å†™ä¸€äº›å®ƒä»¬çš„ |
638 | å˜ç§ã€‚æ¯”å¦‚ï¼Œå¦‚æžœä½ éœ€è¦è®¡ç®—ä¸€ä¸ªæ•°ç»„çš„é•¿åº¦ï¼Œä½¿ç”¨è¿™ä¸ªå® | 699 | å˜ç§ã€‚æ¯”å¦‚ï¼Œå¦‚æžœä½ éœ€è¦è®¡ç®—ä¸€ä¸ªæ•°ç»„çš„é•¿åº¦ï¼Œä½¿ç”¨è¿™ä¸ªå® |
639 | 700 | ||
640 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) | 701 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) |
641 | 702 | ||
642 | ç±»ä¼¼çš„ï¼Œå¦‚æžœä½ è¦è®¡ç®—æŸç»“构体æˆå‘˜çš„大å°ï¼Œä½¿ç”¨ | 703 | ç±»ä¼¼çš„ï¼Œå¦‚æžœä½ è¦è®¡ç®—æŸç»“构体æˆå‘˜çš„大å°ï¼Œä½¿ç”¨ |
643 | 704 | ||
644 | #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) | 705 | #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) |
645 | 706 | ||
646 | 还有å¯ä»¥åšä¸¥æ ¼çš„类型检查的min()å’Œmax()å®ï¼Œå¦‚æžœä½ éœ€è¦å¯ä»¥ä½¿ç”¨å®ƒä»¬ã€‚ä½ å¯ä»¥è‡ªå·±çœ‹çœ‹ | 707 | 还有å¯ä»¥åšä¸¥æ ¼çš„类型检查的 min() å’Œ max() å®ï¼Œå¦‚æžœä½ éœ€è¦å¯ä»¥ä½¿ç”¨å®ƒä»¬ã€‚ä½ å¯ä»¥è‡ªå·±çœ‹çœ‹ |
647 | é‚£ä¸ªå¤´æ–‡ä»¶é‡Œè¿˜å®šä¹‰äº†ä»€ä¹ˆä½ å¯ä»¥æ‹¿æ¥ç”¨çš„东西,如果有定义的è¯ï¼Œä½ å°±ä¸åº”åœ¨ä½ çš„ä»£ç 里 | 708 | é‚£ä¸ªå¤´æ–‡ä»¶é‡Œè¿˜å®šä¹‰äº†ä»€ä¹ˆä½ å¯ä»¥æ‹¿æ¥ç”¨çš„东西,如果有定义的è¯ï¼Œä½ å°±ä¸åº”åœ¨ä½ çš„ä»£ç 里 |
648 | è‡ªå·±é‡æ–°å®šä¹‰ã€‚ | 709 | è‡ªå·±é‡æ–°å®šä¹‰ã€‚ |
649 | 710 | ||
@@ -653,42 +714,100 @@ NULL或者ERR_PTRæœºåˆ¶æ¥æŠ¥å‘Šé”™è¯¯ã€‚ | |||
653 | 有一些编辑器å¯ä»¥è§£é‡ŠåµŒå…¥åœ¨æºæ–‡ä»¶é‡Œçš„ç”±ä¸€äº›ç‰¹æ®Šæ ‡è®°æ ‡æ˜Žçš„é…置信æ¯ã€‚比如,emacs | 714 | 有一些编辑器å¯ä»¥è§£é‡ŠåµŒå…¥åœ¨æºæ–‡ä»¶é‡Œçš„ç”±ä¸€äº›ç‰¹æ®Šæ ‡è®°æ ‡æ˜Žçš„é…置信æ¯ã€‚比如,emacs |
654 | èƒ½å¤Ÿè§£é‡Šè¢«æ ‡è®°æˆè¿™æ ·çš„行: | 715 | èƒ½å¤Ÿè§£é‡Šè¢«æ ‡è®°æˆè¿™æ ·çš„行: |
655 | 716 | ||
656 | -*- mode: c -*- | 717 | -*- mode: c -*- |
657 | 718 | ||
658 | æˆ–è€…è¿™æ ·çš„ï¼š | 719 | æˆ–è€…è¿™æ ·çš„ï¼š |
659 | 720 | ||
660 | /* | 721 | /* |
661 | Local Variables: | 722 | Local Variables: |
662 | compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c" | 723 | compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c" |
663 | End: | 724 | End: |
664 | */ | 725 | */ |
665 | 726 | ||
666 | Vimèƒ½å¤Ÿè§£é‡Šè¿™æ ·çš„æ ‡è®°ï¼š | 727 | Vim èƒ½å¤Ÿè§£é‡Šè¿™æ ·çš„æ ‡è®°ï¼š |
667 | 728 | ||
668 | /* vim:set sw=8 noet */ | 729 | /* vim:set sw=8 noet */ |
669 | 730 | ||
670 | ä¸è¦åœ¨æºä»£ç ä¸åŒ…å«ä»»ä½•è¿™æ ·çš„å†…å®¹ã€‚æ¯ä¸ªäººéƒ½æœ‰ä»–自己的编辑器é…ç½®ï¼Œä½ çš„æºæ–‡ä»¶ä¸åº” | 731 | ä¸è¦åœ¨æºä»£ç ä¸åŒ…å«ä»»ä½•è¿™æ ·çš„å†…å®¹ã€‚æ¯ä¸ªäººéƒ½æœ‰ä»–自己的编辑器é…ç½®ï¼Œä½ çš„æºæ–‡ä»¶ä¸åº” |
671 | 该覆盖别人的é…置。这包括有关缩进和模å¼é…ç½®çš„æ ‡è®°ã€‚äººä»¬å¯ä»¥ä½¿ç”¨ä»–们自己定制的模 | 732 | 该覆盖别人的é…置。这包括有关缩进和模å¼é…ç½®çš„æ ‡è®°ã€‚äººä»¬å¯ä»¥ä½¿ç”¨ä»–们自己定制的模 |
672 | å¼ï¼Œæˆ–者使用其他å¯ä»¥äº§ç”Ÿæ£ç¡®çš„缩进的巧妙方法。 | 733 | å¼ï¼Œæˆ–者使用其他å¯ä»¥äº§ç”Ÿæ£ç¡®çš„缩进的巧妙方法。 |
673 | 734 | ||
674 | 735 | ||
736 | 第åä¹ç« ï¼šå†…è”æ±‡ç¼– | ||
737 | |||
738 | 在特定架构的代ç ä¸ï¼Œä½ 也许需è¦å†…è”æ±‡ç¼–æ¥ä½¿ç”¨ CPU 接å£å’Œå¹³å°ç›¸å…³åŠŸèƒ½ã€‚åœ¨éœ€è¦ | ||
739 | è¿™ä¹ˆåšæ—¶ï¼Œä¸è¦çŠ¹è±«ã€‚ç„¶è€Œï¼Œå½“ C å¯ä»¥å®Œæˆå·¥ä½œæ—¶ï¼Œä¸è¦æ— ç«¯åœ°ä½¿ç”¨å†…è”æ±‡ç¼–。如果 | ||
740 | å¯èƒ½ï¼Œä½ å¯ä»¥å¹¶ä¸”应该用 C 和硬件交互。 | ||
741 | |||
742 | è€ƒè™‘åŽ»å†™é€šç”¨ä¸€ç‚¹çš„å†…è”æ±‡ç¼–ä½œä¸ºç®€æ˜Žçš„è¾…åŠ©å‡½æ•°ï¼Œè€Œä¸æ˜¯é‡å¤å†™ä¸‹å®ƒä»¬çš„ç»†èŠ‚ã€‚è®°ä½ | ||
743 | å†…è”æ±‡ç¼–å¯ä»¥ä½¿ç”¨ C 傿•°ã€‚ | ||
744 | |||
745 | 大而特殊的汇编函数应该放在 .S 文件ä¸ï¼Œå¯¹åº” C 的原型定义在 C 头文件ä¸ã€‚汇编 | ||
746 | 函数的 C 原型应该使用 “asmlinkageâ€ã€‚ | ||
747 | |||
748 | ä½ å¯èƒ½éœ€è¦å°†ä½ 的汇编è¯å¥æ ‡è®°ä¸º volatile,æ¥é˜»æ¢ GCC 在没å‘现任何副作用åŽå°± | ||
749 | ç§»é™¤äº†å®ƒã€‚ä½ ä¸å¿…æ€»æ˜¯è¿™æ ·åšï¼Œè™½ç„¶ï¼Œè¿™æ ·å¯ä»¥é™åˆ¶ä¸å¿…è¦çš„优化。 | ||
750 | |||
751 | 在写一个包å«å¤šæ¡æŒ‡ä»¤çš„å•ä¸ªå†…è”æ±‡ç¼–è¯å¥æ—¶ï¼ŒæŠŠæ¯æ¡æŒ‡ä»¤ç”¨å¼•å·å—符串分离,并写在 | ||
752 | å•独一行,在æ¯ä¸ªå—符串结尾,除了 \n\t 结尾之外,在汇编输出ä¸é€‚当地缩进下 | ||
753 | ä¸€æ¡æŒ‡ä»¤ï¼š | ||
754 | |||
755 | asm ("magic %reg1, #42\n\t" | ||
756 | "more_magic %reg2, %reg3" | ||
757 | : /* outputs */ : /* inputs */ : /* clobbers */); | ||
758 | |||
759 | |||
760 | 第二åç« ï¼šæ¡ä»¶ç¼–译 | ||
761 | |||
762 | åªè¦å¯èƒ½ï¼Œå°±ä¸è¦åœ¨ .c 文件里é¢ä½¿ç”¨é¢„å¤„ç†æ¡ä»¶ï¼›è¿™æ ·åšè®©ä»£ç 更难阅读并且逻辑难以 | ||
763 | 跟踪。替代方案是,在头文件定义函数在这些 .c 文件ä¸ä½¿ç”¨è¿™ç±»çš„æ¡ä»¶è¡¨è¾¾å¼ï¼Œæä¾›ç©º | ||
764 | æ“作的桩版本(译注:桩程åºï¼Œæ˜¯æŒ‡ç”¨æ¥æ›¿æ¢ä¸€éƒ¨åˆ†åŠŸèƒ½çš„ç¨‹åºæ®µï¼‰åœ¨ #else 情况下, | ||
765 | å†ä»Ž .c æ–‡ä»¶ä¸æ— æ¡ä»¶åœ°è°ƒç”¨è¿™äº›å‡½æ•°ã€‚编译器会é¿å…生æˆä»»ä½•桩调用的代ç ,产生一致 | ||
766 | çš„ç»“æžœï¼Œä½†é€»è¾‘å°†æ›´åŠ æ¸…æ™°ã€‚ | ||
767 | |||
768 | å®å¯ç¼–è¯‘æ•´ä¸ªå‡½æ•°ï¼Œè€Œä¸æ˜¯éƒ¨åˆ†å‡½æ•°æˆ–部分表达å¼ã€‚è€Œä¸æ˜¯åœ¨ä¸€ä¸ªè¡¨è¾¾å¼æ·»åŠ ifdef, | ||
769 | è§£æžéƒ¨åˆ†æˆ–全部表达å¼åˆ°ä¸€ä¸ªå•独的辅助函数,并应用æ¡ä»¶åˆ°è¯¥å‡½æ•°å†…。 | ||
770 | |||
771 | å¦‚æžœä½ æœ‰ä¸€ä¸ªåœ¨ç‰¹å®šé…ç½®ä¸å¯èƒ½æ˜¯æœªä½¿ç”¨çš„函数或å˜é‡ï¼Œç¼–译器将è¦å‘Šå®ƒå®šä¹‰äº†ä½†æœªä½¿ç”¨ï¼Œ | ||
772 | æ ‡è®°è¿™ä¸ªå®šä¹‰ä¸º __maybe_unused è€Œä¸æ˜¯å°†å®ƒåŒ…å«åœ¨ä¸€ä¸ªé¢„å¤„ç†æ¡ä»¶ä¸ã€‚(然而,如果 | ||
773 | 一个函数或å˜é‡æ€»æ˜¯æœªä½¿ç”¨çš„ï¼Œå°±ç›´æŽ¥åˆ é™¤å®ƒã€‚ï¼‰ | ||
774 | |||
775 | 在代ç ä¸ï¼Œå¯èƒ½çš„æƒ…况下,使用 IS_ENABLED 宿¥è½¬åŒ–æŸä¸ª Kconfig æ ‡è®°ä¸º C 的布尔 | ||
776 | 表达å¼ï¼Œå¹¶åœ¨æ£å¸¸çš„ C æ¡ä»¶ä¸ä½¿ç”¨å®ƒï¼š | ||
777 | |||
778 | if (IS_ENABLED(CONFIG_SOMETHING)) { | ||
779 | ... | ||
780 | } | ||
781 | |||
782 | ç¼–è¯‘å™¨ä¼šæ— æ¡ä»¶åœ°åšå¸¸æ•°åˆå¹¶ï¼Œå°±åƒä½¿ç”¨ #ifdef é‚£æ ·ï¼ŒåŒ…å«æˆ–排除代ç å—,所以这ä¸ä¼š | ||
783 | 带æ¥ä»»ä½•è¿è¡Œæ—¶å¼€é”€ã€‚ç„¶è€Œï¼Œè¿™ç§æ–¹æ³•便—§å…许 C 编译器查看å—内的代ç ,并检查它的æ£ç¡® | ||
784 | æ€§ï¼ˆè¯æ³•,类型,符å·å¼•用,ç‰ç‰ï¼‰ã€‚å› æ¤ï¼Œå¦‚æžœæ¡ä»¶ä¸æ»¡è¶³ï¼Œä»£ç å—内的引用符å·å°†ä¸å˜åœ¨ï¼Œ | ||
785 | ä½ å¿…é¡»ç»§ç»ä½¿ç”¨ #ifdef。 | ||
786 | |||
787 | 在任何有æ„义的 #if 或 #ifdef å—çš„æœ«å°¾ï¼ˆè¶…è¿‡å‡ è¡Œï¼‰ï¼Œåœ¨ #endif åŒä¸€è¡Œçš„åŽé¢å†™ä¸‹ | ||
788 | 注释,指出该æ¡ä»¶è¡¨è¾¾å¼è¢«ä½¿ç”¨ã€‚例如: | ||
789 | |||
790 | #ifdef CONFIG_SOMETHING | ||
791 | ... | ||
792 | #endif /* CONFIG_SOMETHING */ | ||
793 | |||
675 | 794 | ||
676 | 附录 I:å‚考 | 795 | 附录 I:å‚考 |
677 | 796 | ||
678 | The C Programming Language, 第二版, 作者Brian W. Kernighan和Denni | 797 | The C Programming Language, 第二版 |
679 | M. Ritchie. Prentice Hall, Inc., 1988. ISBN 0-13-110362-8 (软皮), | 798 | 作者:Brian W. Kernighan 和 Denni M. Ritchie. |
680 | 0-13-110370-9 (硬皮). URL: http://cm.bell-labs.com/cm/cs/cbook/ | 799 | Prentice Hall, Inc., 1988. |
800 | ISBN 0-13-110362-8 (软皮), 0-13-110370-9 (硬皮). | ||
681 | 801 | ||
682 | The Practice of Programming 作者Brian W. Kernighan和Rob Pike. Addison-Wesley, | 802 | The Practice of Programming |
683 | Inc., 1999. ISBN 0-201-61586-X. URL: http://cm.bell-labs.com/cm/cs/tpop/ | 803 | 作者:Brian W. Kernighan 和 Rob Pike. |
804 | Addison-Wesley, Inc., 1999. | ||
805 | ISBN 0-201-61586-X. | ||
684 | 806 | ||
685 | cpp,gcc,gcc internalså’Œindentçš„GNU手册——和K&RåŠæœ¬æ–‡ç›¸ç¬¦åˆçš„部分,全部å¯ä»¥åœ¨ | 807 | GNU 手册 - éµå¾ª K&R æ ‡å‡†å’Œæ¤æ–‡æœ¬ - cpp, gcc, gcc internals and indent, |
686 | http://www.gnu.org/manual/找到 | 808 | 都å¯ä»¥ä»Ž http://www.gnu.org/manual/ 找到 |
687 | 809 | ||
688 | WG14是Cè¯è¨€çš„å›½é™…æ ‡å‡†åŒ–å·¥ä½œç»„ï¼ŒURL: http://www.open-std.org/JTC1/SC22/WG14/ | 810 | WG14是Cè¯è¨€çš„å›½é™…æ ‡å‡†åŒ–å·¥ä½œç»„ï¼ŒURL: http://www.open-std.org/JTC1/SC22/WG14/ |
689 | 811 | ||
690 | Kernel CodingStyle,作者greg@kroah.comå‘表于OLS 2002: | 812 | Kernel CodingStyle,作者 greg@kroah.com å‘表于OLS 2002: |
691 | http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/ | 813 | http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/ |
692 | |||
693 | -- | ||
694 | æœ€åŽæ›´æ–°äºŽ2007å¹´7月13日。 | ||
@@ -1366,6 +1366,8 @@ help: | |||
1366 | @$(MAKE) $(build)=$(package-dir) help | 1366 | @$(MAKE) $(build)=$(package-dir) help |
1367 | @echo '' | 1367 | @echo '' |
1368 | @echo 'Documentation targets:' | 1368 | @echo 'Documentation targets:' |
1369 | @$(MAKE) -f $(srctree)/Documentation/Makefile.sphinx dochelp | ||
1370 | @echo '' | ||
1369 | @$(MAKE) -f $(srctree)/Documentation/DocBook/Makefile dochelp | 1371 | @$(MAKE) -f $(srctree)/Documentation/DocBook/Makefile dochelp |
1370 | @echo '' | 1372 | @echo '' |
1371 | @echo 'Architecture specific targets ($(SRCARCH)):' | 1373 | @echo 'Architecture specific targets ($(SRCARCH)):' |
@@ -1414,8 +1416,11 @@ $(help-board-dirs): help-%: | |||
1414 | 1416 | ||
1415 | # Documentation targets | 1417 | # Documentation targets |
1416 | # --------------------------------------------------------------------------- | 1418 | # --------------------------------------------------------------------------- |
1417 | %docs: scripts_basic FORCE | 1419 | DOC_TARGETS := xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs epubdocs cleandocs cleanmediadocs |
1420 | PHONY += $(DOC_TARGETS) | ||
1421 | $(DOC_TARGETS): scripts_basic FORCE | ||
1418 | $(Q)$(MAKE) $(build)=scripts build_docproc build_check-lc_ctype | 1422 | $(Q)$(MAKE) $(build)=scripts build_docproc build_check-lc_ctype |
1423 | $(Q)$(MAKE) $(build)=Documentation -f $(srctree)/Documentation/Makefile.sphinx $@ | ||
1419 | $(Q)$(MAKE) $(build)=Documentation/DocBook $@ | 1424 | $(Q)$(MAKE) $(build)=Documentation/DocBook $@ |
1420 | 1425 | ||
1421 | else # KBUILD_EXTMOD | 1426 | else # KBUILD_EXTMOD |
diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 2fc8fad5195e..4f2e9049e8fa 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc | |||
@@ -59,6 +59,12 @@ Output format selection (mutually exclusive): | |||
59 | -text Output plain text format. | 59 | -text Output plain text format. |
60 | 60 | ||
61 | Output selection (mutually exclusive): | 61 | Output selection (mutually exclusive): |
62 | -export Only output documentation for symbols that have been | ||
63 | exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL() | ||
64 | in any input FILE or -export-file FILE. | ||
65 | -internal Only output documentation for symbols that have NOT been | ||
66 | exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL() | ||
67 | in any input FILE or -export-file FILE. | ||
62 | -function NAME Only output documentation for the given function(s) | 68 | -function NAME Only output documentation for the given function(s) |
63 | or DOC: section title(s). All other functions and DOC: | 69 | or DOC: section title(s). All other functions and DOC: |
64 | sections are ignored. May be specified multiple times. | 70 | sections are ignored. May be specified multiple times. |
@@ -68,6 +74,11 @@ Output selection (mutually exclusive): | |||
68 | 74 | ||
69 | Output selection modifiers: | 75 | Output selection modifiers: |
70 | -no-doc-sections Do not output DOC: sections. | 76 | -no-doc-sections Do not output DOC: sections. |
77 | -enable-lineno Enable output of #define LINENO lines. Only works with | ||
78 | reStructuredText format. | ||
79 | -export-file FILE Specify an additional FILE in which to look for | ||
80 | EXPORT_SYMBOL() and EXPORT_SYMBOL_GPL(). To be used with | ||
81 | -export or -internal. May be specified multiple times. | ||
71 | 82 | ||
72 | Other parameters: | 83 | Other parameters: |
73 | -v Verbose output, more warnings and other information. | 84 | -v Verbose output, more warnings and other information. |
@@ -206,6 +217,10 @@ my $type_struct_xml = '\\&((struct\s*)*[_\w]+)'; | |||
206 | my $type_env = '(\$\w+)'; | 217 | my $type_env = '(\$\w+)'; |
207 | my $type_enum_full = '\&(enum)\s*([_\w]+)'; | 218 | my $type_enum_full = '\&(enum)\s*([_\w]+)'; |
208 | my $type_struct_full = '\&(struct)\s*([_\w]+)'; | 219 | my $type_struct_full = '\&(struct)\s*([_\w]+)'; |
220 | my $type_typedef_full = '\&(typedef)\s*([_\w]+)'; | ||
221 | my $type_union_full = '\&(union)\s*([_\w]+)'; | ||
222 | my $type_member = '\&([_\w]+)((\.|->)[_\w]+)'; | ||
223 | my $type_member_func = $type_member . '\(\)'; | ||
209 | 224 | ||
210 | # Output conversion substitutions. | 225 | # Output conversion substitutions. |
211 | # One for each output format | 226 | # One for each output format |
@@ -274,10 +289,16 @@ my $blankline_text = ""; | |||
274 | # rst-mode | 289 | # rst-mode |
275 | my @highlights_rst = ( | 290 | my @highlights_rst = ( |
276 | [$type_constant, "``\$1``"], | 291 | [$type_constant, "``\$1``"], |
277 | [$type_func, "\\:c\\:func\\:`\$1`"], | 292 | # Note: need to escape () to avoid func matching later |
293 | [$type_member_func, "\\:c\\:type\\:`\$1\$2\\\\(\\\\) <\$1>`"], | ||
294 | [$type_member, "\\:c\\:type\\:`\$1\$2 <\$1>`"], | ||
295 | [$type_func, "\\:c\\:func\\:`\$1()`"], | ||
278 | [$type_struct_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], | 296 | [$type_struct_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], |
279 | [$type_enum_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], | 297 | [$type_enum_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], |
280 | [$type_struct, "\\:c\\:type\\:`struct \$1 <\$1>`"], | 298 | [$type_typedef_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], |
299 | [$type_union_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], | ||
300 | # in rst this can refer to any type | ||
301 | [$type_struct, "\\:c\\:type\\:`\$1`"], | ||
281 | [$type_param, "**\$1**"] | 302 | [$type_param, "**\$1**"] |
282 | ); | 303 | ); |
283 | my $blankline_rst = "\n"; | 304 | my $blankline_rst = "\n"; |
@@ -303,12 +324,23 @@ my $verbose = 0; | |||
303 | my $output_mode = "man"; | 324 | my $output_mode = "man"; |
304 | my $output_preformatted = 0; | 325 | my $output_preformatted = 0; |
305 | my $no_doc_sections = 0; | 326 | my $no_doc_sections = 0; |
327 | my $enable_lineno = 0; | ||
306 | my @highlights = @highlights_man; | 328 | my @highlights = @highlights_man; |
307 | my $blankline = $blankline_man; | 329 | my $blankline = $blankline_man; |
308 | my $modulename = "Kernel API"; | 330 | my $modulename = "Kernel API"; |
309 | my $function_only = 0; | 331 | |
332 | use constant { | ||
333 | OUTPUT_ALL => 0, # output all symbols and doc sections | ||
334 | OUTPUT_INCLUDE => 1, # output only specified symbols | ||
335 | OUTPUT_EXCLUDE => 2, # output everything except specified symbols | ||
336 | OUTPUT_EXPORTED => 3, # output exported symbols | ||
337 | OUTPUT_INTERNAL => 4, # output non-exported symbols | ||
338 | }; | ||
339 | my $output_selection = OUTPUT_ALL; | ||
310 | my $show_not_found = 0; | 340 | my $show_not_found = 0; |
311 | 341 | ||
342 | my @export_file_list; | ||
343 | |||
312 | my @build_time; | 344 | my @build_time; |
313 | if (defined($ENV{'KBUILD_BUILD_TIMESTAMP'}) && | 345 | if (defined($ENV{'KBUILD_BUILD_TIMESTAMP'}) && |
314 | (my $seconds = `date -d"${ENV{'KBUILD_BUILD_TIMESTAMP'}}" +%s`) ne '') { | 346 | (my $seconds = `date -d"${ENV{'KBUILD_BUILD_TIMESTAMP'}}" +%s`) ne '') { |
@@ -327,6 +359,7 @@ my $man_date = ('January', 'February', 'March', 'April', 'May', 'June', | |||
327 | # CAVEAT EMPTOR! Some of the others I localised may not want to be, which | 359 | # CAVEAT EMPTOR! Some of the others I localised may not want to be, which |
328 | # could cause "use of undefined value" or other bugs. | 360 | # could cause "use of undefined value" or other bugs. |
329 | my ($function, %function_table, %parametertypes, $declaration_purpose); | 361 | my ($function, %function_table, %parametertypes, $declaration_purpose); |
362 | my $declaration_start_line; | ||
330 | my ($type, $declaration_name, $return_type); | 363 | my ($type, $declaration_name, $return_type); |
331 | my ($newsection, $newcontents, $prototype, $brcount, %source_map); | 364 | my ($newsection, $newcontents, $prototype, $brcount, %source_map); |
332 | 365 | ||
@@ -344,52 +377,62 @@ my $section_counter = 0; | |||
344 | 377 | ||
345 | my $lineprefix=""; | 378 | my $lineprefix=""; |
346 | 379 | ||
347 | # states | 380 | # Parser states |
348 | # 0 - normal code | 381 | use constant { |
349 | # 1 - looking for function name | 382 | STATE_NORMAL => 0, # normal code |
350 | # 2 - scanning field start. | 383 | STATE_NAME => 1, # looking for function name |
351 | # 3 - scanning prototype. | 384 | STATE_FIELD => 2, # scanning field start |
352 | # 4 - documentation block | 385 | STATE_PROTO => 3, # scanning prototype |
353 | # 5 - gathering documentation outside main block | 386 | STATE_DOCBLOCK => 4, # documentation block |
387 | STATE_INLINE => 5, # gathering documentation outside main block | ||
388 | }; | ||
354 | my $state; | 389 | my $state; |
355 | my $in_doc_sect; | 390 | my $in_doc_sect; |
356 | 391 | ||
357 | # Split Doc State | 392 | # Inline documentation state |
358 | # 0 - Invalid (Before start or after finish) | 393 | use constant { |
359 | # 1 - Is started (the /** was found inside a struct) | 394 | STATE_INLINE_NA => 0, # not applicable ($state != STATE_INLINE) |
360 | # 2 - The @parameter header was found, start accepting multi paragraph text. | 395 | STATE_INLINE_NAME => 1, # looking for member name (@foo:) |
361 | # 3 - Finished (the */ was found) | 396 | STATE_INLINE_TEXT => 2, # looking for member documentation |
362 | # 4 - Error - Comment without header was found. Spit a warning as it's not | 397 | STATE_INLINE_END => 3, # done |
363 | # proper kernel-doc and ignore the rest. | 398 | STATE_INLINE_ERROR => 4, # error - Comment without header was found. |
364 | my $split_doc_state; | 399 | # Spit a warning as it's not |
400 | # proper kernel-doc and ignore the rest. | ||
401 | }; | ||
402 | my $inline_doc_state; | ||
365 | 403 | ||
366 | #declaration types: can be | 404 | #declaration types: can be |
367 | # 'function', 'struct', 'union', 'enum', 'typedef' | 405 | # 'function', 'struct', 'union', 'enum', 'typedef' |
368 | my $decl_type; | 406 | my $decl_type; |
369 | 407 | ||
370 | my $doc_special = "\@\%\$\&"; | ||
371 | |||
372 | my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start. | 408 | my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start. |
373 | my $doc_end = '\*/'; | 409 | my $doc_end = '\*/'; |
374 | my $doc_com = '\s*\*\s*'; | 410 | my $doc_com = '\s*\*\s*'; |
375 | my $doc_com_body = '\s*\* ?'; | 411 | my $doc_com_body = '\s*\* ?'; |
376 | my $doc_decl = $doc_com . '(\w+)'; | 412 | my $doc_decl = $doc_com . '(\w+)'; |
377 | my $doc_sect = $doc_com . '([' . $doc_special . ']?[\w\s]+):(.*)'; | 413 | # @params and a strictly limited set of supported section names |
414 | my $doc_sect = $doc_com . | ||
415 | '\s*(\@\w+|description|context|returns?|notes?|examples?)\s*:(.*)'; | ||
378 | my $doc_content = $doc_com_body . '(.*)'; | 416 | my $doc_content = $doc_com_body . '(.*)'; |
379 | my $doc_block = $doc_com . 'DOC:\s*(.*)?'; | 417 | my $doc_block = $doc_com . 'DOC:\s*(.*)?'; |
380 | my $doc_split_start = '^\s*/\*\*\s*$'; | 418 | my $doc_inline_start = '^\s*/\*\*\s*$'; |
381 | my $doc_split_sect = '\s*\*\s*(@[\w\s]+):(.*)'; | 419 | my $doc_inline_sect = '\s*\*\s*(@[\w\s]+):(.*)'; |
382 | my $doc_split_end = '^\s*\*/\s*$'; | 420 | my $doc_inline_end = '^\s*\*/\s*$'; |
421 | my $export_symbol = '^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*;'; | ||
383 | 422 | ||
384 | my %constants; | ||
385 | my %parameterdescs; | 423 | my %parameterdescs; |
424 | my %parameterdesc_start_lines; | ||
386 | my @parameterlist; | 425 | my @parameterlist; |
387 | my %sections; | 426 | my %sections; |
388 | my @sectionlist; | 427 | my @sectionlist; |
428 | my %section_start_lines; | ||
389 | my $sectcheck; | 429 | my $sectcheck; |
390 | my $struct_actual; | 430 | my $struct_actual; |
391 | 431 | ||
392 | my $contents = ""; | 432 | my $contents = ""; |
433 | my $new_start_line = 0; | ||
434 | |||
435 | # the canonical section names. see also $doc_sect above. | ||
393 | my $section_default = "Description"; # default section | 436 | my $section_default = "Description"; # default section |
394 | my $section_intro = "Introduction"; | 437 | my $section_intro = "Introduction"; |
395 | my $section = $section_default; | 438 | my $section = $section_default; |
@@ -437,19 +480,30 @@ while ($ARGV[0] =~ m/^-(.*)/) { | |||
437 | } elsif ($cmd eq "-module") { # not needed for XML, inherits from calling document | 480 | } elsif ($cmd eq "-module") { # not needed for XML, inherits from calling document |
438 | $modulename = shift @ARGV; | 481 | $modulename = shift @ARGV; |
439 | } elsif ($cmd eq "-function") { # to only output specific functions | 482 | } elsif ($cmd eq "-function") { # to only output specific functions |
440 | $function_only = 1; | 483 | $output_selection = OUTPUT_INCLUDE; |
441 | $function = shift @ARGV; | 484 | $function = shift @ARGV; |
442 | $function_table{$function} = 1; | 485 | $function_table{$function} = 1; |
443 | } elsif ($cmd eq "-nofunction") { # to only output specific functions | 486 | } elsif ($cmd eq "-nofunction") { # output all except specific functions |
444 | $function_only = 2; | 487 | $output_selection = OUTPUT_EXCLUDE; |
445 | $function = shift @ARGV; | 488 | $function = shift @ARGV; |
446 | $function_table{$function} = 1; | 489 | $function_table{$function} = 1; |
490 | } elsif ($cmd eq "-export") { # only exported symbols | ||
491 | $output_selection = OUTPUT_EXPORTED; | ||
492 | %function_table = (); | ||
493 | } elsif ($cmd eq "-internal") { # only non-exported symbols | ||
494 | $output_selection = OUTPUT_INTERNAL; | ||
495 | %function_table = (); | ||
496 | } elsif ($cmd eq "-export-file") { | ||
497 | my $file = shift @ARGV; | ||
498 | push(@export_file_list, $file); | ||
447 | } elsif ($cmd eq "-v") { | 499 | } elsif ($cmd eq "-v") { |
448 | $verbose = 1; | 500 | $verbose = 1; |
449 | } elsif (($cmd eq "-h") || ($cmd eq "--help")) { | 501 | } elsif (($cmd eq "-h") || ($cmd eq "--help")) { |
450 | usage(); | 502 | usage(); |
451 | } elsif ($cmd eq '-no-doc-sections') { | 503 | } elsif ($cmd eq '-no-doc-sections') { |
452 | $no_doc_sections = 1; | 504 | $no_doc_sections = 1; |
505 | } elsif ($cmd eq '-enable-lineno') { | ||
506 | $enable_lineno = 1; | ||
453 | } elsif ($cmd eq '-show-not-found') { | 507 | } elsif ($cmd eq '-show-not-found') { |
454 | $show_not_found = 1; | 508 | $show_not_found = 1; |
455 | } | 509 | } |
@@ -467,6 +521,13 @@ sub get_kernel_version() { | |||
467 | return $version; | 521 | return $version; |
468 | } | 522 | } |
469 | 523 | ||
524 | # | ||
525 | sub print_lineno { | ||
526 | my $lineno = shift; | ||
527 | if ($enable_lineno && defined($lineno)) { | ||
528 | print "#define LINENO " . $lineno . "\n"; | ||
529 | } | ||
530 | } | ||
470 | ## | 531 | ## |
471 | # dumps section contents to arrays/hashes intended for that purpose. | 532 | # dumps section contents to arrays/hashes intended for that purpose. |
472 | # | 533 | # |
@@ -475,28 +536,32 @@ sub dump_section { | |||
475 | my $name = shift; | 536 | my $name = shift; |
476 | my $contents = join "\n", @_; | 537 | my $contents = join "\n", @_; |
477 | 538 | ||
478 | if ($name =~ m/$type_constant/) { | 539 | if ($name =~ m/$type_param/) { |
479 | $name = $1; | ||
480 | # print STDERR "constant section '$1' = '$contents'\n"; | ||
481 | $constants{$name} = $contents; | ||
482 | } elsif ($name =~ m/$type_param/) { | ||
483 | # print STDERR "parameter def '$1' = '$contents'\n"; | ||
484 | $name = $1; | 540 | $name = $1; |
485 | $parameterdescs{$name} = $contents; | 541 | $parameterdescs{$name} = $contents; |
486 | $sectcheck = $sectcheck . $name . " "; | 542 | $sectcheck = $sectcheck . $name . " "; |
543 | $parameterdesc_start_lines{$name} = $new_start_line; | ||
544 | $new_start_line = 0; | ||
487 | } elsif ($name eq "@\.\.\.") { | 545 | } elsif ($name eq "@\.\.\.") { |
488 | # print STDERR "parameter def '...' = '$contents'\n"; | ||
489 | $name = "..."; | 546 | $name = "..."; |
490 | $parameterdescs{$name} = $contents; | 547 | $parameterdescs{$name} = $contents; |
491 | $sectcheck = $sectcheck . $name . " "; | 548 | $sectcheck = $sectcheck . $name . " "; |
549 | $parameterdesc_start_lines{$name} = $new_start_line; | ||
550 | $new_start_line = 0; | ||
492 | } else { | 551 | } else { |
493 | # print STDERR "other section '$name' = '$contents'\n"; | ||
494 | if (defined($sections{$name}) && ($sections{$name} ne "")) { | 552 | if (defined($sections{$name}) && ($sections{$name} ne "")) { |
495 | print STDERR "${file}:$.: error: duplicate section name '$name'\n"; | 553 | # Only warn on user specified duplicate section names. |
496 | ++$errors; | 554 | if ($name ne $section_default) { |
555 | print STDERR "${file}:$.: warning: duplicate section name '$name'\n"; | ||
556 | ++$warnings; | ||
557 | } | ||
558 | $sections{$name} .= $contents; | ||
559 | } else { | ||
560 | $sections{$name} = $contents; | ||
561 | push @sectionlist, $name; | ||
562 | $section_start_lines{$name} = $new_start_line; | ||
563 | $new_start_line = 0; | ||
497 | } | 564 | } |
498 | $sections{$name} = $contents; | ||
499 | push @sectionlist, $name; | ||
500 | } | 565 | } |
501 | } | 566 | } |
502 | 567 | ||
@@ -512,15 +577,17 @@ sub dump_doc_section { | |||
512 | return; | 577 | return; |
513 | } | 578 | } |
514 | 579 | ||
515 | if (($function_only == 0) || | 580 | if (($output_selection == OUTPUT_ALL) || |
516 | ( $function_only == 1 && defined($function_table{$name})) || | 581 | ($output_selection == OUTPUT_INCLUDE && |
517 | ( $function_only == 2 && !defined($function_table{$name}))) | 582 | defined($function_table{$name})) || |
583 | ($output_selection == OUTPUT_EXCLUDE && | ||
584 | !defined($function_table{$name}))) | ||
518 | { | 585 | { |
519 | dump_section($file, $name, $contents); | 586 | dump_section($file, $name, $contents); |
520 | output_blockhead({'sectionlist' => \@sectionlist, | 587 | output_blockhead({'sectionlist' => \@sectionlist, |
521 | 'sections' => \%sections, | 588 | 'sections' => \%sections, |
522 | 'module' => $modulename, | 589 | 'module' => $modulename, |
523 | 'content-only' => ($function_only != 0), }); | 590 | 'content-only' => ($output_selection != OUTPUT_ALL), }); |
524 | } | 591 | } |
525 | } | 592 | } |
526 | 593 | ||
@@ -1736,7 +1803,10 @@ sub output_blockhead_rst(%) { | |||
1736 | my ($parameter, $section); | 1803 | my ($parameter, $section); |
1737 | 1804 | ||
1738 | foreach $section (@{$args{'sectionlist'}}) { | 1805 | foreach $section (@{$args{'sectionlist'}}) { |
1739 | print "**$section**\n\n"; | 1806 | if ($output_selection != OUTPUT_INCLUDE) { |
1807 | print "**$section**\n\n"; | ||
1808 | } | ||
1809 | print_lineno($section_start_lines{$section}); | ||
1740 | output_highlight_rst($args{'sections'}{$section}); | 1810 | output_highlight_rst($args{'sections'}{$section}); |
1741 | print "\n"; | 1811 | print "\n"; |
1742 | } | 1812 | } |
@@ -1753,19 +1823,14 @@ sub output_highlight_rst { | |||
1753 | die $@ if $@; | 1823 | die $@ if $@; |
1754 | 1824 | ||
1755 | foreach $line (split "\n", $contents) { | 1825 | foreach $line (split "\n", $contents) { |
1756 | if ($line eq "") { | 1826 | print $lineprefix . $line . "\n"; |
1757 | print $lineprefix, $blankline; | ||
1758 | } else { | ||
1759 | $line =~ s/\\\\\\/\&/g; | ||
1760 | print $lineprefix, $line; | ||
1761 | } | ||
1762 | print "\n"; | ||
1763 | } | 1827 | } |
1764 | } | 1828 | } |
1765 | 1829 | ||
1766 | sub output_function_rst(%) { | 1830 | sub output_function_rst(%) { |
1767 | my %args = %{$_[0]}; | 1831 | my %args = %{$_[0]}; |
1768 | my ($parameter, $section); | 1832 | my ($parameter, $section); |
1833 | my $oldprefix = $lineprefix; | ||
1769 | my $start; | 1834 | my $start; |
1770 | 1835 | ||
1771 | print ".. c:function:: "; | 1836 | print ".. c:function:: "; |
@@ -1783,6 +1848,10 @@ sub output_function_rst(%) { | |||
1783 | } | 1848 | } |
1784 | $count++; | 1849 | $count++; |
1785 | $type = $args{'parametertypes'}{$parameter}; | 1850 | $type = $args{'parametertypes'}{$parameter}; |
1851 | |||
1852 | # RST doesn't like address_space tags at function prototypes | ||
1853 | $type =~ s/__(user|kernel|iomem|percpu|pmem|rcu)\s*//; | ||
1854 | |||
1786 | if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { | 1855 | if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { |
1787 | # pointer-to-function | 1856 | # pointer-to-function |
1788 | print $1 . $parameter . ") (" . $2; | 1857 | print $1 . $parameter . ") (" . $2; |
@@ -1790,29 +1859,37 @@ sub output_function_rst(%) { | |||
1790 | print $type . " " . $parameter; | 1859 | print $type . " " . $parameter; |
1791 | } | 1860 | } |
1792 | } | 1861 | } |
1793 | print ")\n\n " . $args{'purpose'} . "\n\n"; | 1862 | print ")\n\n"; |
1863 | print_lineno($declaration_start_line); | ||
1864 | $lineprefix = " "; | ||
1865 | output_highlight_rst($args{'purpose'}); | ||
1866 | print "\n"; | ||
1794 | 1867 | ||
1795 | print ":Parameters:\n\n"; | 1868 | print "**Parameters**\n\n"; |
1869 | $lineprefix = " "; | ||
1796 | foreach $parameter (@{$args{'parameterlist'}}) { | 1870 | foreach $parameter (@{$args{'parameterlist'}}) { |
1797 | my $parameter_name = $parameter; | 1871 | my $parameter_name = $parameter; |
1798 | #$parameter_name =~ s/\[.*//; | 1872 | #$parameter_name =~ s/\[.*//; |
1799 | $type = $args{'parametertypes'}{$parameter}; | 1873 | $type = $args{'parametertypes'}{$parameter}; |
1800 | 1874 | ||
1801 | if ($type ne "") { | 1875 | if ($type ne "") { |
1802 | print " ``$type $parameter``\n"; | 1876 | print "``$type $parameter``\n"; |
1803 | } else { | 1877 | } else { |
1804 | print " ``$parameter``\n"; | 1878 | print "``$parameter``\n"; |
1805 | } | 1879 | } |
1806 | if ($args{'parameterdescs'}{$parameter_name} ne $undescribed) { | 1880 | |
1807 | my $oldprefix = $lineprefix; | 1881 | print_lineno($parameterdesc_start_lines{$parameter_name}); |
1808 | $lineprefix = " "; | 1882 | |
1883 | if (defined($args{'parameterdescs'}{$parameter_name}) && | ||
1884 | $args{'parameterdescs'}{$parameter_name} ne $undescribed) { | ||
1809 | output_highlight_rst($args{'parameterdescs'}{$parameter_name}); | 1885 | output_highlight_rst($args{'parameterdescs'}{$parameter_name}); |
1810 | $lineprefix = $oldprefix; | ||
1811 | } else { | 1886 | } else { |
1812 | print "\n _undescribed_\n"; | 1887 | print " *undescribed*\n"; |
1813 | } | 1888 | } |
1814 | print "\n"; | 1889 | print "\n"; |
1815 | } | 1890 | } |
1891 | |||
1892 | $lineprefix = $oldprefix; | ||
1816 | output_section_rst(@_); | 1893 | output_section_rst(@_); |
1817 | } | 1894 | } |
1818 | 1895 | ||
@@ -1820,10 +1897,11 @@ sub output_section_rst(%) { | |||
1820 | my %args = %{$_[0]}; | 1897 | my %args = %{$_[0]}; |
1821 | my $section; | 1898 | my $section; |
1822 | my $oldprefix = $lineprefix; | 1899 | my $oldprefix = $lineprefix; |
1823 | $lineprefix = " "; | 1900 | $lineprefix = ""; |
1824 | 1901 | ||
1825 | foreach $section (@{$args{'sectionlist'}}) { | 1902 | foreach $section (@{$args{'sectionlist'}}) { |
1826 | print ":$section:\n\n"; | 1903 | print "**$section**\n\n"; |
1904 | print_lineno($section_start_lines{$section}); | ||
1827 | output_highlight_rst($args{'sections'}{$section}); | 1905 | output_highlight_rst($args{'sections'}{$section}); |
1828 | print "\n"; | 1906 | print "\n"; |
1829 | } | 1907 | } |
@@ -1834,24 +1912,28 @@ sub output_section_rst(%) { | |||
1834 | sub output_enum_rst(%) { | 1912 | sub output_enum_rst(%) { |
1835 | my %args = %{$_[0]}; | 1913 | my %args = %{$_[0]}; |
1836 | my ($parameter); | 1914 | my ($parameter); |
1915 | my $oldprefix = $lineprefix; | ||
1837 | my $count; | 1916 | my $count; |
1838 | my $name = "enum " . $args{'enum'}; | 1917 | my $name = "enum " . $args{'enum'}; |
1839 | 1918 | ||
1840 | print "\n\n.. c:type:: " . $name . "\n\n"; | 1919 | print "\n\n.. c:type:: " . $name . "\n\n"; |
1841 | print " " . $args{'purpose'} . "\n\n"; | 1920 | print_lineno($declaration_start_line); |
1921 | $lineprefix = " "; | ||
1922 | output_highlight_rst($args{'purpose'}); | ||
1923 | print "\n"; | ||
1842 | 1924 | ||
1843 | print "..\n\n:Constants:\n\n"; | 1925 | print "**Constants**\n\n"; |
1844 | my $oldprefix = $lineprefix; | 1926 | $lineprefix = " "; |
1845 | $lineprefix = " "; | ||
1846 | foreach $parameter (@{$args{'parameterlist'}}) { | 1927 | foreach $parameter (@{$args{'parameterlist'}}) { |
1847 | print " `$parameter`\n"; | 1928 | print "``$parameter``\n"; |
1848 | if ($args{'parameterdescs'}{$parameter} ne $undescribed) { | 1929 | if ($args{'parameterdescs'}{$parameter} ne $undescribed) { |
1849 | output_highlight_rst($args{'parameterdescs'}{$parameter}); | 1930 | output_highlight_rst($args{'parameterdescs'}{$parameter}); |
1850 | } else { | 1931 | } else { |
1851 | print " undescribed\n"; | 1932 | print " *undescribed*\n"; |
1852 | } | 1933 | } |
1853 | print "\n"; | 1934 | print "\n"; |
1854 | } | 1935 | } |
1936 | |||
1855 | $lineprefix = $oldprefix; | 1937 | $lineprefix = $oldprefix; |
1856 | output_section_rst(@_); | 1938 | output_section_rst(@_); |
1857 | } | 1939 | } |
@@ -1859,30 +1941,37 @@ sub output_enum_rst(%) { | |||
1859 | sub output_typedef_rst(%) { | 1941 | sub output_typedef_rst(%) { |
1860 | my %args = %{$_[0]}; | 1942 | my %args = %{$_[0]}; |
1861 | my ($parameter); | 1943 | my ($parameter); |
1862 | my $count; | 1944 | my $oldprefix = $lineprefix; |
1863 | my $name = "typedef " . $args{'typedef'}; | 1945 | my $name = "typedef " . $args{'typedef'}; |
1864 | 1946 | ||
1865 | ### FIXME: should the name below contain "typedef" or not? | ||
1866 | print "\n\n.. c:type:: " . $name . "\n\n"; | 1947 | print "\n\n.. c:type:: " . $name . "\n\n"; |
1867 | print " " . $args{'purpose'} . "\n\n"; | 1948 | print_lineno($declaration_start_line); |
1949 | $lineprefix = " "; | ||
1950 | output_highlight_rst($args{'purpose'}); | ||
1951 | print "\n"; | ||
1868 | 1952 | ||
1953 | $lineprefix = $oldprefix; | ||
1869 | output_section_rst(@_); | 1954 | output_section_rst(@_); |
1870 | } | 1955 | } |
1871 | 1956 | ||
1872 | sub output_struct_rst(%) { | 1957 | sub output_struct_rst(%) { |
1873 | my %args = %{$_[0]}; | 1958 | my %args = %{$_[0]}; |
1874 | my ($parameter); | 1959 | my ($parameter); |
1960 | my $oldprefix = $lineprefix; | ||
1875 | my $name = $args{'type'} . " " . $args{'struct'}; | 1961 | my $name = $args{'type'} . " " . $args{'struct'}; |
1876 | 1962 | ||
1877 | print "\n\n.. c:type:: " . $name . "\n\n"; | 1963 | print "\n\n.. c:type:: " . $name . "\n\n"; |
1878 | print " " . $args{'purpose'} . "\n\n"; | 1964 | print_lineno($declaration_start_line); |
1965 | $lineprefix = " "; | ||
1966 | output_highlight_rst($args{'purpose'}); | ||
1967 | print "\n"; | ||
1879 | 1968 | ||
1880 | print ":Definition:\n\n"; | 1969 | print "**Definition**\n\n"; |
1881 | print " ::\n\n"; | 1970 | print "::\n\n"; |
1882 | print " " . $args{'type'} . " " . $args{'struct'} . " {\n"; | 1971 | print " " . $args{'type'} . " " . $args{'struct'} . " {\n"; |
1883 | foreach $parameter (@{$args{'parameterlist'}}) { | 1972 | foreach $parameter (@{$args{'parameterlist'}}) { |
1884 | if ($parameter =~ /^#/) { | 1973 | if ($parameter =~ /^#/) { |
1885 | print " " . "$parameter\n"; | 1974 | print " " . "$parameter\n"; |
1886 | next; | 1975 | next; |
1887 | } | 1976 | } |
1888 | 1977 | ||
@@ -1903,7 +1992,8 @@ sub output_struct_rst(%) { | |||
1903 | } | 1992 | } |
1904 | print " };\n\n"; | 1993 | print " };\n\n"; |
1905 | 1994 | ||
1906 | print ":Members:\n\n"; | 1995 | print "**Members**\n\n"; |
1996 | $lineprefix = " "; | ||
1907 | foreach $parameter (@{$args{'parameterlist'}}) { | 1997 | foreach $parameter (@{$args{'parameterlist'}}) { |
1908 | ($parameter =~ /^#/) && next; | 1998 | ($parameter =~ /^#/) && next; |
1909 | 1999 | ||
@@ -1912,14 +2002,14 @@ sub output_struct_rst(%) { | |||
1912 | 2002 | ||
1913 | ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; | 2003 | ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; |
1914 | $type = $args{'parametertypes'}{$parameter}; | 2004 | $type = $args{'parametertypes'}{$parameter}; |
1915 | print " `$type $parameter`" . "\n"; | 2005 | print_lineno($parameterdesc_start_lines{$parameter_name}); |
1916 | my $oldprefix = $lineprefix; | 2006 | print "``$type $parameter``\n"; |
1917 | $lineprefix = " "; | ||
1918 | output_highlight_rst($args{'parameterdescs'}{$parameter_name}); | 2007 | output_highlight_rst($args{'parameterdescs'}{$parameter_name}); |
1919 | $lineprefix = $oldprefix; | ||
1920 | print "\n"; | 2008 | print "\n"; |
1921 | } | 2009 | } |
1922 | print "\n"; | 2010 | print "\n"; |
2011 | |||
2012 | $lineprefix = $oldprefix; | ||
1923 | output_section_rst(@_); | 2013 | output_section_rst(@_); |
1924 | } | 2014 | } |
1925 | 2015 | ||
@@ -1969,9 +2059,13 @@ sub output_declaration { | |||
1969 | my $name = shift; | 2059 | my $name = shift; |
1970 | my $functype = shift; | 2060 | my $functype = shift; |
1971 | my $func = "output_${functype}_$output_mode"; | 2061 | my $func = "output_${functype}_$output_mode"; |
1972 | if (($function_only==0) || | 2062 | if (($output_selection == OUTPUT_ALL) || |
1973 | ( $function_only == 1 && defined($function_table{$name})) || | 2063 | (($output_selection == OUTPUT_INCLUDE || |
1974 | ( $function_only == 2 && !($functype eq "function" && defined($function_table{$name})))) | 2064 | $output_selection == OUTPUT_EXPORTED) && |
2065 | defined($function_table{$name})) || | ||
2066 | (($output_selection == OUTPUT_EXCLUDE || | ||
2067 | $output_selection == OUTPUT_INTERNAL) && | ||
2068 | !($functype eq "function" && defined($function_table{$name})))) | ||
1975 | { | 2069 | { |
1976 | &$func(@_); | 2070 | &$func(@_); |
1977 | $section_counter++; | 2071 | $section_counter++; |
@@ -2471,7 +2565,6 @@ sub dump_function($$) { | |||
2471 | 2565 | ||
2472 | sub reset_state { | 2566 | sub reset_state { |
2473 | $function = ""; | 2567 | $function = ""; |
2474 | %constants = (); | ||
2475 | %parameterdescs = (); | 2568 | %parameterdescs = (); |
2476 | %parametertypes = (); | 2569 | %parametertypes = (); |
2477 | @parameterlist = (); | 2570 | @parameterlist = (); |
@@ -2481,8 +2574,8 @@ sub reset_state { | |||
2481 | $struct_actual = ""; | 2574 | $struct_actual = ""; |
2482 | $prototype = ""; | 2575 | $prototype = ""; |
2483 | 2576 | ||
2484 | $state = 0; | 2577 | $state = STATE_NORMAL; |
2485 | $split_doc_state = 0; | 2578 | $inline_doc_state = STATE_INLINE_NA; |
2486 | } | 2579 | } |
2487 | 2580 | ||
2488 | sub tracepoint_munge($) { | 2581 | sub tracepoint_munge($) { |
@@ -2545,7 +2638,7 @@ sub syscall_munge() { | |||
2545 | } | 2638 | } |
2546 | } | 2639 | } |
2547 | 2640 | ||
2548 | sub process_state3_function($$) { | 2641 | sub process_proto_function($$) { |
2549 | my $x = shift; | 2642 | my $x = shift; |
2550 | my $file = shift; | 2643 | my $file = shift; |
2551 | 2644 | ||
@@ -2575,7 +2668,7 @@ sub process_state3_function($$) { | |||
2575 | } | 2668 | } |
2576 | } | 2669 | } |
2577 | 2670 | ||
2578 | sub process_state3_type($$) { | 2671 | sub process_proto_type($$) { |
2579 | my $x = shift; | 2672 | my $x = shift; |
2580 | my $file = shift; | 2673 | my $file = shift; |
2581 | 2674 | ||
@@ -2649,25 +2742,54 @@ sub local_unescape($) { | |||
2649 | return $text; | 2742 | return $text; |
2650 | } | 2743 | } |
2651 | 2744 | ||
2652 | sub process_file($) { | 2745 | sub map_filename($) { |
2653 | my $file; | 2746 | my $file; |
2654 | my $identifier; | ||
2655 | my $func; | ||
2656 | my $descr; | ||
2657 | my $in_purpose = 0; | ||
2658 | my $initial_section_counter = $section_counter; | ||
2659 | my ($orig_file) = @_; | 2747 | my ($orig_file) = @_; |
2660 | 2748 | ||
2661 | if (defined($ENV{'SRCTREE'})) { | 2749 | if (defined($ENV{'SRCTREE'})) { |
2662 | $file = "$ENV{'SRCTREE'}" . "/" . $orig_file; | 2750 | $file = "$ENV{'SRCTREE'}" . "/" . $orig_file; |
2663 | } | 2751 | } else { |
2664 | else { | ||
2665 | $file = $orig_file; | 2752 | $file = $orig_file; |
2666 | } | 2753 | } |
2754 | |||
2667 | if (defined($source_map{$file})) { | 2755 | if (defined($source_map{$file})) { |
2668 | $file = $source_map{$file}; | 2756 | $file = $source_map{$file}; |
2669 | } | 2757 | } |
2670 | 2758 | ||
2759 | return $file; | ||
2760 | } | ||
2761 | |||
2762 | sub process_export_file($) { | ||
2763 | my ($orig_file) = @_; | ||
2764 | my $file = map_filename($orig_file); | ||
2765 | |||
2766 | if (!open(IN,"<$file")) { | ||
2767 | print STDERR "Error: Cannot open file $file\n"; | ||
2768 | ++$errors; | ||
2769 | return; | ||
2770 | } | ||
2771 | |||
2772 | while (<IN>) { | ||
2773 | if (/$export_symbol/) { | ||
2774 | $function_table{$2} = 1; | ||
2775 | } | ||
2776 | } | ||
2777 | |||
2778 | close(IN); | ||
2779 | } | ||
2780 | |||
2781 | sub process_file($) { | ||
2782 | my $file; | ||
2783 | my $identifier; | ||
2784 | my $func; | ||
2785 | my $descr; | ||
2786 | my $in_purpose = 0; | ||
2787 | my $initial_section_counter = $section_counter; | ||
2788 | my ($orig_file) = @_; | ||
2789 | my $leading_space; | ||
2790 | |||
2791 | $file = map_filename($orig_file); | ||
2792 | |||
2671 | if (!open(IN,"<$file")) { | 2793 | if (!open(IN,"<$file")) { |
2672 | print STDERR "Error: Cannot open file $file\n"; | 2794 | print STDERR "Error: Cannot open file $file\n"; |
2673 | ++$errors; | 2795 | ++$errors; |
@@ -2681,15 +2803,18 @@ sub process_file($) { | |||
2681 | while (s/\\\s*$//) { | 2803 | while (s/\\\s*$//) { |
2682 | $_ .= <IN>; | 2804 | $_ .= <IN>; |
2683 | } | 2805 | } |
2684 | if ($state == 0) { | 2806 | if ($state == STATE_NORMAL) { |
2685 | if (/$doc_start/o) { | 2807 | if (/$doc_start/o) { |
2686 | $state = 1; # next line is always the function name | 2808 | $state = STATE_NAME; # next line is always the function name |
2687 | $in_doc_sect = 0; | 2809 | $in_doc_sect = 0; |
2810 | $declaration_start_line = $. + 1; | ||
2688 | } | 2811 | } |
2689 | } elsif ($state == 1) { # this line is the function name (always) | 2812 | } elsif ($state == STATE_NAME) {# this line is the function name (always) |
2690 | if (/$doc_block/o) { | 2813 | if (/$doc_block/o) { |
2691 | $state = 4; | 2814 | $state = STATE_DOCBLOCK; |
2692 | $contents = ""; | 2815 | $contents = ""; |
2816 | $new_start_line = $. + 1; | ||
2817 | |||
2693 | if ( $1 eq "" ) { | 2818 | if ( $1 eq "" ) { |
2694 | $section = $section_intro; | 2819 | $section = $section_intro; |
2695 | } else { | 2820 | } else { |
@@ -2702,7 +2827,12 @@ sub process_file($) { | |||
2702 | $identifier = $1; | 2827 | $identifier = $1; |
2703 | } | 2828 | } |
2704 | 2829 | ||
2705 | $state = 2; | 2830 | $state = STATE_FIELD; |
2831 | # if there's no @param blocks need to set up default section | ||
2832 | # here | ||
2833 | $contents = ""; | ||
2834 | $section = $section_default; | ||
2835 | $new_start_line = $. + 1; | ||
2706 | if (/-(.*)/) { | 2836 | if (/-(.*)/) { |
2707 | # strip leading/trailing/multiple spaces | 2837 | # strip leading/trailing/multiple spaces |
2708 | $descr= $1; | 2838 | $descr= $1; |
@@ -2740,13 +2870,25 @@ sub process_file($) { | |||
2740 | print STDERR "${file}:$.: warning: Cannot understand $_ on line $.", | 2870 | print STDERR "${file}:$.: warning: Cannot understand $_ on line $.", |
2741 | " - I thought it was a doc line\n"; | 2871 | " - I thought it was a doc line\n"; |
2742 | ++$warnings; | 2872 | ++$warnings; |
2743 | $state = 0; | 2873 | $state = STATE_NORMAL; |
2744 | } | 2874 | } |
2745 | } elsif ($state == 2) { # look for head: lines, and include content | 2875 | } elsif ($state == STATE_FIELD) { # look for head: lines, and include content |
2746 | if (/$doc_sect/o) { | 2876 | if (/$doc_sect/i) { # case insensitive for supported section names |
2747 | $newsection = $1; | 2877 | $newsection = $1; |
2748 | $newcontents = $2; | 2878 | $newcontents = $2; |
2749 | 2879 | ||
2880 | # map the supported section names to the canonical names | ||
2881 | if ($newsection =~ m/^description$/i) { | ||
2882 | $newsection = $section_default; | ||
2883 | } elsif ($newsection =~ m/^context$/i) { | ||
2884 | $newsection = $section_context; | ||
2885 | } elsif ($newsection =~ m/^returns?$/i) { | ||
2886 | $newsection = $section_return; | ||
2887 | } elsif ($newsection =~ m/^\@return$/) { | ||
2888 | # special: @return is a section, not a param description | ||
2889 | $newsection = $section_return; | ||
2890 | } | ||
2891 | |||
2750 | if (($contents ne "") && ($contents ne "\n")) { | 2892 | if (($contents ne "") && ($contents ne "\n")) { |
2751 | if (!$in_doc_sect && $verbose) { | 2893 | if (!$in_doc_sect && $verbose) { |
2752 | print STDERR "${file}:$.: warning: contents before sections\n"; | 2894 | print STDERR "${file}:$.: warning: contents before sections\n"; |
@@ -2759,14 +2901,16 @@ sub process_file($) { | |||
2759 | $in_doc_sect = 1; | 2901 | $in_doc_sect = 1; |
2760 | $in_purpose = 0; | 2902 | $in_purpose = 0; |
2761 | $contents = $newcontents; | 2903 | $contents = $newcontents; |
2904 | $new_start_line = $.; | ||
2905 | while ((substr($contents, 0, 1) eq " ") || | ||
2906 | substr($contents, 0, 1) eq "\t") { | ||
2907 | $contents = substr($contents, 1); | ||
2908 | } | ||
2762 | if ($contents ne "") { | 2909 | if ($contents ne "") { |
2763 | while ((substr($contents, 0, 1) eq " ") || | ||
2764 | substr($contents, 0, 1) eq "\t") { | ||
2765 | $contents = substr($contents, 1); | ||
2766 | } | ||
2767 | $contents .= "\n"; | 2910 | $contents .= "\n"; |
2768 | } | 2911 | } |
2769 | $section = $newsection; | 2912 | $section = $newsection; |
2913 | $leading_space = undef; | ||
2770 | } elsif (/$doc_end/) { | 2914 | } elsif (/$doc_end/) { |
2771 | if (($contents ne "") && ($contents ne "\n")) { | 2915 | if (($contents ne "") && ($contents ne "\n")) { |
2772 | dump_section($file, $section, xml_escape($contents)); | 2916 | dump_section($file, $section, xml_escape($contents)); |
@@ -2780,7 +2924,7 @@ sub process_file($) { | |||
2780 | } | 2924 | } |
2781 | 2925 | ||
2782 | $prototype = ""; | 2926 | $prototype = ""; |
2783 | $state = 3; | 2927 | $state = STATE_PROTO; |
2784 | $brcount = 0; | 2928 | $brcount = 0; |
2785 | # print STDERR "end of doc comment, looking for prototype\n"; | 2929 | # print STDERR "end of doc comment, looking for prototype\n"; |
2786 | } elsif (/$doc_content/) { | 2930 | } elsif (/$doc_content/) { |
@@ -2791,6 +2935,7 @@ sub process_file($) { | |||
2791 | dump_section($file, $section, xml_escape($contents)); | 2935 | dump_section($file, $section, xml_escape($contents)); |
2792 | $section = $section_default; | 2936 | $section = $section_default; |
2793 | $contents = ""; | 2937 | $contents = ""; |
2938 | $new_start_line = $.; | ||
2794 | } else { | 2939 | } else { |
2795 | $contents .= "\n"; | 2940 | $contents .= "\n"; |
2796 | } | 2941 | } |
@@ -2801,87 +2946,86 @@ sub process_file($) { | |||
2801 | $declaration_purpose .= " " . xml_escape($1); | 2946 | $declaration_purpose .= " " . xml_escape($1); |
2802 | $declaration_purpose =~ s/\s+/ /g; | 2947 | $declaration_purpose =~ s/\s+/ /g; |
2803 | } else { | 2948 | } else { |
2804 | $contents .= $1 . "\n"; | 2949 | my $cont = $1; |
2950 | if ($section =~ m/^@/ || $section eq $section_context) { | ||
2951 | if (!defined $leading_space) { | ||
2952 | if ($cont =~ m/^(\s+)/) { | ||
2953 | $leading_space = $1; | ||
2954 | } else { | ||
2955 | $leading_space = ""; | ||
2956 | } | ||
2957 | } | ||
2958 | |||
2959 | $cont =~ s/^$leading_space//; | ||
2960 | } | ||
2961 | $contents .= $cont . "\n"; | ||
2805 | } | 2962 | } |
2806 | } else { | 2963 | } else { |
2807 | # i dont know - bad line? ignore. | 2964 | # i dont know - bad line? ignore. |
2808 | print STDERR "${file}:$.: warning: bad line: $_"; | 2965 | print STDERR "${file}:$.: warning: bad line: $_"; |
2809 | ++$warnings; | 2966 | ++$warnings; |
2810 | } | 2967 | } |
2811 | } elsif ($state == 5) { # scanning for split parameters | 2968 | } elsif ($state == STATE_INLINE) { # scanning for inline parameters |
2812 | # First line (state 1) needs to be a @parameter | 2969 | # First line (state 1) needs to be a @parameter |
2813 | if ($split_doc_state == 1 && /$doc_split_sect/o) { | 2970 | if ($inline_doc_state == STATE_INLINE_NAME && /$doc_inline_sect/o) { |
2814 | $section = $1; | 2971 | $section = $1; |
2815 | $contents = $2; | 2972 | $contents = $2; |
2973 | $new_start_line = $.; | ||
2816 | if ($contents ne "") { | 2974 | if ($contents ne "") { |
2817 | while ((substr($contents, 0, 1) eq " ") || | 2975 | while ((substr($contents, 0, 1) eq " ") || |
2818 | substr($contents, 0, 1) eq "\t") { | 2976 | substr($contents, 0, 1) eq "\t") { |
2819 | $contents = substr($contents, 1); | 2977 | $contents = substr($contents, 1); |
2820 | } | 2978 | } |
2821 | $contents .= "\n"; | 2979 | $contents .= "\n"; |
2822 | } | 2980 | } |
2823 | $split_doc_state = 2; | 2981 | $inline_doc_state = STATE_INLINE_TEXT; |
2824 | # Documentation block end */ | 2982 | # Documentation block end */ |
2825 | } elsif (/$doc_split_end/) { | 2983 | } elsif (/$doc_inline_end/) { |
2826 | if (($contents ne "") && ($contents ne "\n")) { | 2984 | if (($contents ne "") && ($contents ne "\n")) { |
2827 | dump_section($file, $section, xml_escape($contents)); | 2985 | dump_section($file, $section, xml_escape($contents)); |
2828 | $section = $section_default; | 2986 | $section = $section_default; |
2829 | $contents = ""; | 2987 | $contents = ""; |
2830 | } | 2988 | } |
2831 | $state = 3; | 2989 | $state = STATE_PROTO; |
2832 | $split_doc_state = 0; | 2990 | $inline_doc_state = STATE_INLINE_NA; |
2833 | # Regular text | 2991 | # Regular text |
2834 | } elsif (/$doc_content/) { | 2992 | } elsif (/$doc_content/) { |
2835 | if ($split_doc_state == 2) { | 2993 | if ($inline_doc_state == STATE_INLINE_TEXT) { |
2836 | $contents .= $1 . "\n"; | 2994 | $contents .= $1 . "\n"; |
2837 | } elsif ($split_doc_state == 1) { | 2995 | # nuke leading blank lines |
2838 | $split_doc_state = 4; | 2996 | if ($contents =~ /^\s*$/) { |
2839 | print STDERR "Warning(${file}:$.): "; | 2997 | $contents = ""; |
2998 | } | ||
2999 | } elsif ($inline_doc_state == STATE_INLINE_NAME) { | ||
3000 | $inline_doc_state = STATE_INLINE_ERROR; | ||
3001 | print STDERR "${file}:$.: warning: "; | ||
2840 | print STDERR "Incorrect use of kernel-doc format: $_"; | 3002 | print STDERR "Incorrect use of kernel-doc format: $_"; |
2841 | ++$warnings; | 3003 | ++$warnings; |
2842 | } | 3004 | } |
2843 | } | 3005 | } |
2844 | } elsif ($state == 3) { # scanning for function '{' (end of prototype) | 3006 | } elsif ($state == STATE_PROTO) { # scanning for function '{' (end of prototype) |
2845 | if (/$doc_split_start/) { | 3007 | if (/$doc_inline_start/) { |
2846 | $state = 5; | 3008 | $state = STATE_INLINE; |
2847 | $split_doc_state = 1; | 3009 | $inline_doc_state = STATE_INLINE_NAME; |
2848 | } elsif ($decl_type eq 'function') { | 3010 | } elsif ($decl_type eq 'function') { |
2849 | process_state3_function($_, $file); | 3011 | process_proto_function($_, $file); |
2850 | } else { | 3012 | } else { |
2851 | process_state3_type($_, $file); | 3013 | process_proto_type($_, $file); |
2852 | } | 3014 | } |
2853 | } elsif ($state == 4) { | 3015 | } elsif ($state == STATE_DOCBLOCK) { |
2854 | # Documentation block | 3016 | if (/$doc_end/) |
2855 | if (/$doc_block/) { | ||
2856 | dump_doc_section($file, $section, xml_escape($contents)); | ||
2857 | $contents = ""; | ||
2858 | $function = ""; | ||
2859 | %constants = (); | ||
2860 | %parameterdescs = (); | ||
2861 | %parametertypes = (); | ||
2862 | @parameterlist = (); | ||
2863 | %sections = (); | ||
2864 | @sectionlist = (); | ||
2865 | $prototype = ""; | ||
2866 | if ( $1 eq "" ) { | ||
2867 | $section = $section_intro; | ||
2868 | } else { | ||
2869 | $section = $1; | ||
2870 | } | ||
2871 | } | ||
2872 | elsif (/$doc_end/) | ||
2873 | { | 3017 | { |
2874 | dump_doc_section($file, $section, xml_escape($contents)); | 3018 | dump_doc_section($file, $section, xml_escape($contents)); |
3019 | $section = $section_default; | ||
2875 | $contents = ""; | 3020 | $contents = ""; |
2876 | $function = ""; | 3021 | $function = ""; |
2877 | %constants = (); | ||
2878 | %parameterdescs = (); | 3022 | %parameterdescs = (); |
2879 | %parametertypes = (); | 3023 | %parametertypes = (); |
2880 | @parameterlist = (); | 3024 | @parameterlist = (); |
2881 | %sections = (); | 3025 | %sections = (); |
2882 | @sectionlist = (); | 3026 | @sectionlist = (); |
2883 | $prototype = ""; | 3027 | $prototype = ""; |
2884 | $state = 0; | 3028 | $state = STATE_NORMAL; |
2885 | } | 3029 | } |
2886 | elsif (/$doc_content/) | 3030 | elsif (/$doc_content/) |
2887 | { | 3031 | { |
@@ -2898,7 +3042,7 @@ sub process_file($) { | |||
2898 | } | 3042 | } |
2899 | if ($initial_section_counter == $section_counter) { | 3043 | if ($initial_section_counter == $section_counter) { |
2900 | print STDERR "${file}:1: warning: no structured comments found\n"; | 3044 | print STDERR "${file}:1: warning: no structured comments found\n"; |
2901 | if (($function_only == 1) && ($show_not_found == 1)) { | 3045 | if (($output_selection == OUTPUT_INCLUDE) && ($show_not_found == 1)) { |
2902 | print STDERR " Was looking for '$_'.\n" for keys %function_table; | 3046 | print STDERR " Was looking for '$_'.\n" for keys %function_table; |
2903 | } | 3047 | } |
2904 | if ($output_mode eq "xml") { | 3048 | if ($output_mode eq "xml") { |
@@ -2957,6 +3101,17 @@ if (open(SOURCE_MAP, "<.tmp_filelist.txt")) { | |||
2957 | close(SOURCE_MAP); | 3101 | close(SOURCE_MAP); |
2958 | } | 3102 | } |
2959 | 3103 | ||
3104 | if ($output_selection == OUTPUT_EXPORTED || | ||
3105 | $output_selection == OUTPUT_INTERNAL) { | ||
3106 | |||
3107 | push(@export_file_list, @ARGV); | ||
3108 | |||
3109 | foreach (@export_file_list) { | ||
3110 | chomp; | ||
3111 | process_export_file($_); | ||
3112 | } | ||
3113 | } | ||
3114 | |||
2960 | foreach (@ARGV) { | 3115 | foreach (@ARGV) { |
2961 | chomp; | 3116 | chomp; |
2962 | process_file($_); | 3117 | process_file($_); |