單行註釋應採用/*␣comment␣*/
的形式,用空格把界定符和文字分開。多行註釋最常見的是這種形式:
/* ␣*␣Multi-line ␣*␣comment ␣*/
也有更花哨的形式:
/*************\ * Multi-line * * comment * \*************/
使用註釋的場合主要有以下幾種。
1、整個源檔案的頂部註釋。說明此模組的相關信息,例如檔案名、作者和版本歷史等,頂頭寫不縮進。例如內核原始碼目錄下的kernel/sched.c
檔案的開頭:
/* * kernel/sched.c * * Kernel scheduler and related syscalls * * Copyright (C) 1991-2002 Linus Torvalds * * 1996-12-23 Modified by Dave Grothe to fix bugs in semaphores and * make semaphores SMP safe * 1998-11-19 Implemented schedule_timeout() and related stuff * by Andrea Arcangeli * 2002-01-04 New ultra-scalable O(1) scheduler by Ingo Molnar: * hybrid priority-list and round-robin design with * an array-switch method of distributing timeslices * and per-CPU runqueues. Cleanups and useful suggestions * by Davide Libenzi, preemptible kernel bits by Robert Love. * 2003-09-03 Interactivity tuning by Con Kolivas. * 2004-04-02 Scheduler domains code by Nick Piggin */
2、函數註釋。說明此函數的功能、參數、返回值、錯誤碼等,寫在函數定義上側,和此函數定義之間不留空行,頂頭寫不縮進。
3、相對獨立的語句組註釋。對這一組語句做特別說明,寫在語句組上側,和此語句組之間不留空行,與當前語句組的縮進一致。
4、代碼行右側的簡短註釋。對當前代碼行做特別說明,一般為單行註釋,和代碼之間至少用一個空格隔開,一個源檔案中所有的右側註釋最好能上下對齊。儘管例 2.1 “帶更多註釋的Hello World”講過註釋可以穿插在一行代碼中間,但不建議這麼寫。內核原始碼目錄下的lib/radix-tree.c
檔案中的一個函數包含了上述三種註釋:
/** * radix_tree_insert - insert into a radix tree * @root: radix tree root * @index: index key * @item: item to insert * * Insert an item into the radix tree at position @index. */ int radix_tree_insert(struct radix_tree_root *root, unsigned long index, void *item) { struct radix_tree_node *node = NULL, *slot; unsigned int height, shift; int offset; int error; /* Make sure the tree is high enough. */ if ((!index && !root->rnode) || index > radix_tree_maxindex(root->height)) { error = radix_tree_extend(root, index); if (error) return error; } slot = root->rnode; height = root->height; shift = (height-1) * RADIX_TREE_MAP_SHIFT; offset = 0; /* uninitialised var warning */ do { if (slot == NULL) { /* Have to add a child node. */ if (!(slot = radix_tree_node_alloc(root))) return -ENOMEM; if (node) { node->slots[offset] = slot; node->count++; } else root->rnode = slot; } /* Go a level down */ offset = (index >> shift) & RADIX_TREE_MAP_MASK; node = slot; slot = node->slots[offset]; shift -= RADIX_TREE_MAP_SHIFT; height--; } while (height > 0); if (slot != NULL) return -EEXIST; BUG_ON(!node); node->count++; node->slots[offset] = item; BUG_ON(tag_get(node, 0, offset)); BUG_ON(tag_get(node, 1, offset)); return 0; }
[CodingStyle]中特別指出,函數內的註釋要儘可能少用。寫註釋主要是為了說明你的代碼“能做什麼”(比如函數介面定義),而不是為了說明“怎樣做”,只要代碼寫得足夠清晰,“怎樣做”是一目瞭然的,如果你需要用註釋才能解釋清楚,那就表示你的代碼可讀性很差,除非是特別需要提醒注意的地方纔使用函數內註釋。
5、複雜的結構體定義比函數更需要註釋。例如內核原始碼目錄下的kernel/sched.c
檔案中定義了這樣一個結構體:
/* * This is the main, per-CPU runqueue data structure. * * Locking rule: those places that want to lock multiple runqueues * (such as the load balancing or the thread migration code), lock * acquire operations must be ordered by ascending &runqueue. */ struct runqueue { spinlock_t lock; /* * nr_running and cpu_load should be in the same cacheline because * remote CPUs use both these fields when doing load calculation. */ unsigned long nr_running; #ifdef CONFIG_SMP unsigned long cpu_load[3]; #endif unsigned long long nr_switches; /* * This is part of a global counter where only the total sum * over all CPUs matters. A task can increase this counter on * one CPU and if it got migrated afterwards it may decrease * it on another CPU. Always updated under the runqueue lock: */ unsigned long nr_uninterruptible; unsigned long expired_timestamp; unsigned long long timestamp_last_tick; task_t *curr, *idle; struct mm_struct *prev_mm; prio_array_t *active, *expired, arrays[2]; int best_expired_prio; atomic_t nr_iowait; #ifdef CONFIG_SMP struct sched_domain *sd; /* For active balancing */ int active_balance; int push_cpu; task_t *migration_thread; struct list_head migration_queue; int cpu; #endif #ifdef CONFIG_SCHEDSTATS /* latency stats */ struct sched_info rq_sched_info; /* sys_sched_yield() stats */ unsigned long yld_exp_empty; unsigned long yld_act_empty; unsigned long yld_both_empty; unsigned long yld_cnt; /* schedule() stats */ unsigned long sched_switch; unsigned long sched_cnt; unsigned long sched_goidle; /* try_to_wake_up() stats */ unsigned long ttwu_cnt; unsigned long ttwu_local; #endif };
6、複雜的宏定義和變數聲明也需要註釋。例如內核原始碼目錄下的include/linux/jiffies.h
檔案中的定義:
/* TICK_USEC_TO_NSEC is the time between ticks in nsec assuming real ACTHZ and */ /* a value TUSEC for TICK_USEC (can be set bij adjtimex) */ #define TICK_USEC_TO_NSEC(TUSEC) (SH_DIV (TUSEC * USER_HZ * 1000, ACTHZ, 8)) /* some arch's have a small-data section that can be accessed register-relative * but that can only take up to, say, 4-byte variables. jiffies being part of * an 8-byte variable may not be correctly accessed unless we force the issue */ #define __jiffy_data __attribute__((section(".data"))) /* * The 64-bit value is not volatile - you MUST NOT read it * without sampling the sequence number in xtime_lock. * get_jiffies_64() will do this for you as appropriate. */ extern u64 __jiffy_data jiffies_64; extern unsigned long volatile __jiffy_data jiffies;