小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

LINUX DEVICE 第三版(快速參考)

 WUCANADA 2012-05-09

LINUX DEVICE 第三版(快速參考)

www.    時(shí)間 : 2011-09-30  作者:網(wǎng)絡(luò)   編輯:hawk 點(diǎn)擊:  26 [ 評(píng)論 ]



第 2 章 建立和運(yùn)行模塊
本節(jié)總結(jié)了我們?cè)诒菊陆佑|到的內(nèi)核函數(shù), 變量, 宏定義, 和 /proc 文件. 它的用意是作為一個(gè)參考. 每一項(xiàng)列都在相關(guān)頭文件的后面, 如果有. 從這里開始, 在幾乎每章的結(jié)尾會(huì)有類似一節(jié), 總結(jié)一章中介紹的新符號(hào). 本節(jié)中的項(xiàng)通常以在本章中出現(xiàn)的順序排列: 


insmod 
modprobe 
rmmod 
用戶空間工具, 加載模塊到運(yùn)行中的內(nèi)核以及去除它們.


#include <linux/init.h> 
module_init(init_function); 
module_exit(cleanup_function); 
指定模塊的初始化和清理函數(shù)的宏定義.


__init 
__initdata 
__exit 
__exitdata 
函 數(shù)( __init 和 __exit )和數(shù)據(jù) (__initdata 和 __exitdata)的標(biāo)記, 只用在模塊初始化或者清理時(shí)間. 為初始化所標(biāo)識(shí)的項(xiàng)可能會(huì)在初始化完成后丟棄; 退出的項(xiàng)可能被丟棄如果內(nèi)核沒有配置模塊卸載. 這些標(biāo)記通過(guò)使相關(guān)的目標(biāo)在可執(zhí)行文件的特定的 ELF 節(jié)里被替換來(lái)工作.


#include <linux/sched.h> 
最重要的頭文件中的一個(gè). 這個(gè)文件包含很多驅(qū)動(dòng)使用的內(nèi)核 API 的定義, 包括睡眠函數(shù)和許多變量聲明.


struct task_struct *current; 
當(dāng)前進(jìn)程.


current->pid 
current->comm 
進(jìn)程 ID 和 當(dāng)前進(jìn)程的命令名.


obj-m 
一個(gè) makefile 符號(hào), 內(nèi)核建立系統(tǒng)用來(lái)決定當(dāng)前目錄下的哪個(gè)模塊應(yīng)當(dāng)被建立.


/sys/module 
/proc/modules 
/sys/module 是一個(gè) sysfs 目錄層次, 包含當(dāng)前加載模塊的信息. /proc/moudles 是舊式的, 那種信息的單個(gè)文件版本. 其中的條目包含了模塊名, 每個(gè)模塊占用的內(nèi)存數(shù)量, 以及使用計(jì)數(shù). 另外的字串追加到每行的末尾來(lái)指定標(biāo)志, 對(duì)這個(gè)模塊當(dāng)前是活動(dòng)的.


vermagic.o 
來(lái)自內(nèi)核源碼目錄的目標(biāo)文件, 描述一個(gè)模塊為之建立的環(huán)境.


#include <linux/module.h> 
必需的頭文件. 它必須在一個(gè)模塊源碼中包含.


#include <linux/version.h> 
頭文件, 包含在建立的內(nèi)核版本信息.


LINUX_VERSION_CODE 
整型宏定義, 對(duì) #ifdef 版本依賴有用.


EXPORT_SYMBOL (symbol); 
EXPORT_SYMBOL_GPL (symbol); 
宏定義, 用來(lái)輸出一個(gè)符號(hào)給內(nèi)核. 第 2 種形式輸出沒有版本信息, 第 3 種限制輸出給 GPL 許可的模塊.


MODULE_AUTHOR(author); 
MODULE_DESCRIPTION(description); 
MODULE_VERSION(version_string); 
MODULE_DEVICE_TABLE(table_info); 
MODULE_ALIAS(alternate_name); 
放置文檔在目標(biāo)文件的模塊中.


module_init(init_function); 
module_exit(exit_function); 
宏定義, 聲明一個(gè)模塊的初始化和清理函數(shù).


#include <linux/moduleparam.h> 
module_param(variable, type, perm); 
宏定義, 創(chuàng)建模塊參數(shù), 可以被用戶在模塊加載時(shí)調(diào)整( 或者在啟動(dòng)時(shí)間, 對(duì)于內(nèi)嵌代碼). 類型可以是 bool, charp, int, invbool, short, ushort, uint, ulong, 或者 intarray.


#include <linux/kernel.h> 
int printk(const char * fmt, ...); 
內(nèi)核代碼的 printf 類似物.




第 3 章 字符驅(qū)動(dòng)
本章介紹了下面符號(hào)和頭文件. struct file_operations 和 struct file 中的成員的列表這里不重復(fù)了.


#include <linux/types.h> 
dev_t 
dev_t 是用來(lái)在內(nèi)核里代表設(shè)備號(hào)的類型.


int MAJOR(dev_t dev); 
int MINOR(dev_t dev); 
從設(shè)備編號(hào)中抽取主次編號(hào)的宏.


dev_t MKDEV(unsigned int major, unsigned int minor); 
從主次編號(hào)來(lái)建立 dev_t 數(shù)據(jù)項(xiàng)的宏定義.


#include <linux/fs.h> 
"文件系統(tǒng)"頭文件是編寫設(shè)備驅(qū)動(dòng)需要的頭文件. 許多重要的函數(shù)和數(shù)據(jù)結(jié)構(gòu)在此定義.


int register_chrdev_region(dev_t first, unsigned int count, char *name) 
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name) 
void unregister_chrdev_region(dev_t first, unsigned int count); 
允許驅(qū)動(dòng)分配和釋放設(shè)備編號(hào)的范圍的函數(shù). register_chrdev_region 應(yīng)當(dāng)用在事先知道需要的主編號(hào)時(shí); 對(duì)于動(dòng)態(tài)分配, 使用 alloc_chrdev_region 代替.


int register_chrdev(unsigned int major, const char *name, struct file_operations *fops); 
老的( 2.6 之前) 字符設(shè)備注冊(cè)函數(shù). 它在 2.6 內(nèi)核中被模擬, 但是不應(yīng)當(dāng)給新代碼使用. 如果主編號(hào)不是 0, 可以不變地用它; 否則一個(gè)動(dòng)態(tài)編號(hào)被分配給這個(gè)設(shè)備.


int unregister_chrdev(unsigned int major, const char *name); 
恢復(fù)一個(gè)由 register_chrdev 所作的注冊(cè)的函數(shù). major 和 name 字符串必須包含之前用來(lái)注冊(cè)設(shè)備時(shí)同樣的值.


struct file_operations; 
struct file; 
struct inode; 
大部分設(shè)備驅(qū)動(dòng)使用的 3 個(gè)重要數(shù)據(jù)結(jié)構(gòu). file_operations 結(jié)構(gòu)持有一個(gè)字符驅(qū)動(dòng)的方法; struct file 代表一個(gè)打開的文件, struct inode 代表磁盤上的一個(gè)文件.


#include <linux/cdev.h> 
struct cdev *cdev_alloc(void); 
void cdev_init(struct cdev *dev, struct file_operations *fops); 
int cdev_add(struct cdev *dev, dev_t num, unsigned int count); 
void cdev_del(struct cdev *dev); 
cdev 結(jié)構(gòu)管理的函數(shù), 它代表內(nèi)核中的字符設(shè)備.


#include <linux/kernel.h> 
container_of(pointer, type, field); 
一個(gè)傳統(tǒng)宏定義, 可用來(lái)獲取一個(gè)結(jié)構(gòu)指針, 從它里面包含的某個(gè)其他結(jié)構(gòu)的指針.


#include <asm/uaccess.h> 
這個(gè)包含文件聲明內(nèi)核代碼使用的函數(shù)來(lái)移動(dòng)數(shù)據(jù)到和從用戶空間.


unsigned long copy_from_user (void *to, const void *from, unsigned long count); 
unsigned long copy_to_user (void *to, const void *from, unsigned long count); 
在用戶空間和內(nèi)核空間拷貝數(shù)據(jù).


第 5 章 并發(fā)和競(jìng)爭(zhēng)情況
本章已介紹了很多符號(hào)給并發(fā)的管理. 最重要的這些在此總結(jié):


#include <asm/semaphore.h> 
定義旗標(biāo)和其上操作的包含文件.


DECLARE_MUTEX(name); 
DECLARE_MUTEX_LOCKED(name); 
2 個(gè)宏定義, 用來(lái)聲明和初始化一個(gè)在互斥模式下使用的旗標(biāo).


void init_MUTEX(struct semaphore *sem); 
void init_MUTEX_LOCKED(struct semaphore *sem); 
這 2 函數(shù)用來(lái)在運(yùn)行時(shí)初始化一個(gè)旗標(biāo).


void down(struct semaphore *sem); 
int down_interruptible(struct semaphore *sem); 
int down_trylock(struct semaphore *sem); 
void up(struct semaphore *sem); 
加鎖和解鎖旗標(biāo). down 使調(diào)用進(jìn)程進(jìn)入不可打斷睡眠, 如果需要; down_interruptible, 相反, 可以被信號(hào)打斷. down_trylock 不睡眠; 相反, 它立刻返回如果旗標(biāo)不可用. 加鎖旗標(biāo)的代碼必須最終使用 up 解鎖它.


struct rw_semaphore; 
init_rwsem(struct rw_semaphore *sem); 
旗標(biāo)的讀者/寫者版本和初始化它的函數(shù).


void down_read(struct rw_semaphore *sem); 
int down_read_trylock(struct rw_semaphore *sem); 
void up_read(struct rw_semaphore *sem); 
獲得和釋放對(duì)讀者/寫者旗標(biāo)的讀存取的函數(shù).


void down_write(struct rw_semaphore *sem); 
int down_write_trylock(struct rw_semaphore *sem); 
void up_write(struct rw_semaphore *sem); 
void downgrade_write(struct rw_semaphore *sem); 
管理對(duì)讀者/寫者旗標(biāo)寫存取的函數(shù).


#include <linux/completion.h> 
DECLARE_COMPLETION(name); 
init_completion(struct completion *c); 
INIT_COMPLETION(struct completion c); 
描述 Linux completion 機(jī)制的包含文件, 已經(jīng)初始化 completion 的正常方法. INIT_COMPLETION 應(yīng)當(dāng)只用來(lái)重新初始化一個(gè)之前已經(jīng)使用過(guò)的 completion. 


void wait_for_completion(struct completion *c); 
等待一個(gè) completion 事件發(fā)出.


void complete(struct completion *c); 
void complete_all(struct completion *c); 
發(fā)出一個(gè) completion 事件. completion 喚醒, 最多, 一個(gè)等待著的線程, 而 complete_all 喚醒全部等待者.


void complete_and_exit(struct completion *c, long retval); 
通過(guò)調(diào)用 complete 來(lái)發(fā)出一個(gè) completion 事件, 并且為當(dāng)前線程調(diào)用 exit.


#include <linux/spinlock.h> 
spinlock_t lock = SPIN_LOCK_UNLOCKED; 
spin_lock_init(spinlock_t *lock); 
定義自旋鎖接口的包含文件, 以及初始化鎖的 2 個(gè)方法.


void spin_lock(spinlock_t *lock); 
void spin_lock_irqsave(spinlock_t *lock, unsigned long flags); 
void spin_lock_irq(spinlock_t *lock); 
void spin_lock_bh(spinlock_t *lock); 
加鎖一個(gè)自旋鎖的各種方法, 并且, 可能地, 禁止中斷.


int spin_trylock(spinlock_t *lock); 
int spin_trylock_bh(spinlock_t *lock); 
上面函數(shù)的非自旋版本; 在獲取鎖失敗時(shí)返回 0, 否則非零.


void spin_unlock(spinlock_t *lock); 
void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags); 
void spin_unlock_irq(spinlock_t *lock); 
void spin_unlock_bh(spinlock_t *lock); 
釋放一個(gè)自旋鎖的相應(yīng)方法.


rwlock_t lock = RW_LOCK_UNLOCKED 
rwlock_init(rwlock_t *lock); 
初始化讀者/寫者鎖的 2 個(gè)方法.


void read_lock(rwlock_t *lock); 
void read_lock_irqsave(rwlock_t *lock, unsigned long flags); 
void read_lock_irq(rwlock_t *lock); 
void read_lock_bh(rwlock_t *lock); 
獲得一個(gè)讀者/寫者鎖的讀存取的函數(shù).


void read_unlock(rwlock_t *lock); 
void read_unlock_irqrestore(rwlock_t *lock, unsigned long flags); 
void read_unlock_irq(rwlock_t *lock); 
void read_unlock_bh(rwlock_t *lock); 
釋放一個(gè)讀者/寫者自旋鎖的讀存取.


void write_lock(rwlock_t *lock); 
void write_lock_irqsave(rwlock_t *lock, unsigned long flags); 
void write_lock_irq(rwlock_t *lock); 
void write_lock_bh(rwlock_t *lock); 
獲得一個(gè)讀者/寫者鎖的寫存取的函數(shù).


void write_unlock(rwlock_t *lock); 
void write_unlock_irqrestore(rwlock_t *lock, unsigned long flags); 
void write_unlock_irq(rwlock_t *lock); 
void write_unlock_bh(rwlock_t *lock); 
釋放一個(gè)讀者/寫者自旋鎖的寫存取的函數(shù).


#include <asm/atomic.h> 
atomic_t v = ATOMIC_INIT(value); 
void atomic_set(atomic_t *v, int i); 
int atomic_read(atomic_t *v); 
void atomic_add(int i, atomic_t *v); 
void atomic_sub(int i, atomic_t *v); 
void atomic_inc(atomic_t *v); 
void atomic_dec(atomic_t *v); 
int atomic_inc_and_test(atomic_t *v); 
int atomic_dec_and_test(atomic_t *v); 
int atomic_sub_and_test(int i, atomic_t *v); 
int atomic_add_negative(int i, atomic_t *v); 
int atomic_add_return(int i, atomic_t *v); 
int atomic_sub_return(int i, atomic_t *v); 
int atomic_inc_return(atomic_t *v); 
int atomic_dec_return(atomic_t *v); 
原子地存取整數(shù)變量. atomic_t 變量必須只通過(guò)這些函數(shù)存取.


#include <asm/bitops.h> 
void set_bit(nr, void *addr); 
void clear_bit(nr, void *addr); 
void change_bit(nr, void *addr); 
test_bit(nr, void *addr); 
int test_and_set_bit(nr, void *addr); 
int test_and_clear_bit(nr, void *addr); 
int test_and_change_bit(nr, void *addr); 
原子地存取位值; 它們可用做標(biāo)志或者鎖變量. 使用這些函數(shù)阻止任何與并發(fā)存取這個(gè)位相關(guān)的競(jìng)爭(zhēng)情況.


#include <linux/seqlock.h> 
seqlock_t lock = SEQLOCK_UNLOCKED; 
seqlock_init(seqlock_t *lock); 
定義 seqlock 的包含文件, 已經(jīng)初始化它們的 2 個(gè)方法.


unsigned int read_seqbegin(seqlock_t *lock); 
unsigned int read_seqbegin_irqsave(seqlock_t *lock, unsigned long flags); 
int read_seqretry(seqlock_t *lock, unsigned int seq); 
int read_seqretry_irqrestore(seqlock_t *lock, unsigned int seq, unsigned long flags); 
獲得一個(gè) seqlock-保護(hù) 的資源的讀權(quán)限的函數(shù).


void write_seqlock(seqlock_t *lock); 
void write_seqlock_irqsave(seqlock_t *lock, unsigned long flags); 
void write_seqlock_irq(seqlock_t *lock); 
void write_seqlock_bh(seqlock_t *lock); 
獲取一個(gè) seqlock-保護(hù)的資源的寫權(quán)限的函數(shù).


void write_sequnlock(seqlock_t *lock); 
void write_sequnlock_irqrestore(seqlock_t *lock, unsigned long flags); 
void write_sequnlock_irq(seqlock_t *lock); 
void write_sequnlock_bh(seqlock_t *lock); 
釋放一個(gè) seqlock-保護(hù)的資源的寫權(quán)限的函數(shù).


#include <linux/rcupdate.h> 
需要使用讀取-拷貝-更新(RCU)機(jī)制的包含文件.


void rcu_read_lock; 
void rcu_read_unlock; 
獲取對(duì)由 RCU 保護(hù)的資源的原子讀權(quán)限的宏定義.


void call_rcu(struct rcu_head *head, void (*func)(void *arg), void *arg); 
安排一個(gè)回調(diào)在所有處理器已經(jīng)被調(diào)度以及一個(gè) RCU-保護(hù)的資源可用被安全的釋放之后運(yùn)行.


第 6 章 高級(jí)字符驅(qū)動(dòng)操作
本章介紹了下面的符號(hào)和頭文件:


#include <linux/ioctl.h> 
聲明用來(lái)定義 ioctl 命令的宏定義. 當(dāng)前被 <linux/fs.h> 包含.


_IOC_NRBITS 
_IOC_TYPEBITS 
_IOC_SIZEBITS 
_IOC_DIRBITS 
ioctl 命令的不同位段所使用的位數(shù). 還有 4 個(gè)宏來(lái)指定 MASK 和 4 個(gè)指定 SHIFT, 但是它們主要是給內(nèi)部使用. _IOC_SIZEBIT 是一個(gè)要檢查的重要的值, 因?yàn)樗珞w系改變.


_IOC_NONE 
_IOC_READ 
_IOC_WRITE 
"方向"位段可能的值. "read" 和 "write" 是不同的位并且可相或來(lái)指定 read/write. 這些值是基于 0 的.


_IOC(dir,type,nr,size) 
_IO(type,nr) 
_IOR(type,nr,size) 
_IOW(type,nr,size) 
_IOWR(type,nr,size) 
用來(lái)創(chuàng)建 ioclt 命令的宏定義.


_IOC_DIR(nr) 
_IOC_TYPE(nr) 
_IOC_NR(nr) 
_IOC_SIZE(nr) 
用來(lái)解碼一個(gè)命令的宏定義. 特別地, _IOC_TYPE(nr) 是 _IOC_READ 和 _IOC_WRITE 的 OR 結(jié)合.


#include <asm/uaccess.h> 
int access_ok(int type, const void *addr, unsigned long size); 
檢查一個(gè)用戶空間的指針是可用的. access_ok 返回一個(gè)非零值, 如果應(yīng)當(dāng)允許存取.


VERIFY_READ 
VERIFY_WRITE 
access_ok 中 type 參數(shù)的可能取值. VERIFY_WRITE 是 VERIFY_READ 的超集.


#include <asm/uaccess.h> 
int put_user(datum,ptr); 
int get_user(local,ptr); 
int __put_user(datum,ptr); 
int __get_user(local,ptr); 
用來(lái)存儲(chǔ)或獲取一個(gè)數(shù)據(jù)到或從用戶空間的宏. 傳送的字節(jié)數(shù)依賴 sizeof(*ptr). 常規(guī)的版本調(diào)用 access_ok , 而常規(guī)版本( __put_user 和 __get_user ) 假定 access_ok 已經(jīng)被調(diào)用了.


#include <linux/capability.h> 
定義各種 CAP_ 符號(hào), 描述一個(gè)用戶空間進(jìn)程可有的能力.


int capable(int capability); 
返回非零值如果進(jìn)程有給定的能力.


#include <linux/wait.h> 
typedef struct { /* ... */ } wait_queue_head_t; 
void init_waitqueue_head(wait_queue_head_t *queue); 
DECLARE_WAIT_QUEUE_HEAD(queue); 
Linux 等待隊(duì)列的定義類型. 一個(gè) wait_queue_head_t 必須被明確在運(yùn)行時(shí)使用 init_waitqueue_head 或者編譯時(shí)使用 DEVLARE_WAIT_QUEUE_HEAD 進(jìn)行初始化.


void wait_event(wait_queue_head_t q, int condition); 
int wait_event_interruptible(wait_queue_head_t q, int condition); 
int wait_event_timeout(wait_queue_head_t q, int condition, int time); 
int wait_event_interruptible_timeout(wait_queue_head_t q, int condition,int time); 
使進(jìn)程在給定隊(duì)列上睡眠, 直到給定條件值為真值.


void wake_up(struct wait_queue **q); 
void wake_up_interruptible(struct wait_queue **q); 
void wake_up_nr(struct wait_queue **q, int nr); 
void wake_up_interruptible_nr(struct wait_queue **q, int nr); 
void wake_up_all(struct wait_queue **q); 
void wake_up_interruptible_all(struct wait_queue **q); 
void wake_up_interruptible_sync(struct wait_queue **q); 
喚醒在隊(duì)列 q 上睡眠的進(jìn)程. _interruptible 的形式只喚醒可中斷的進(jìn)程. 正常地, 只有一個(gè)互斥等待者被喚醒, 但是這個(gè)行為可被 _nr 或者 _all 形式所改變. _sync 版本在返回之前不重新調(diào)度 CPU.


#include <linux/sched.h> 
set_current_state(int state); 
設(shè)置當(dāng)前進(jìn)程的執(zhí)行狀態(tài). TASK_RUNNING 意味著它已經(jīng)運(yùn)行, 而睡眠狀態(tài)是 TASK_INTERRUPTIBLE 和 TASK_UNINTERRUPTIBLE.


void schedule(void); 
選擇一個(gè)可運(yùn)行的進(jìn)程從運(yùn)行隊(duì)列中. 被選中的進(jìn)程可是當(dāng)前進(jìn)程或者另外一個(gè).


typedef struct { /* ... */ } wait_queue_t; 
init_waitqueue_entry(wait_queue_t *entry, struct task_struct *task); 
wait_queue_t 類型用來(lái)放置一個(gè)進(jìn)程到一個(gè)等待隊(duì)列.


void prepare_to_wait(wait_queue_head_t *queue, wait_queue_t *wait, int state); 
void prepare_to_wait_exclusive(wait_queue_head_t *queue, wait_queue_t *wait, int state); 
void finish_wait(wait_queue_head_t *queue, wait_queue_t *wait); 
幫忙函數(shù), 可用來(lái)編碼一個(gè)手工睡眠.


void sleep_on(wiat_queue_head_t *queue); 
void interruptible_sleep_on(wiat_queue_head_t *queue); 
老式的不推薦的函數(shù), 它們無(wú)條件地使當(dāng)前進(jìn)程睡眠.


#include <linux/poll.h> 
void poll_wait(struct file *filp, wait_queue_head_t *q, poll_table *p); 
將當(dāng)前進(jìn)程放入一個(gè)等待隊(duì)列, 不立刻調(diào)度. 它被設(shè)計(jì)來(lái)被設(shè)備驅(qū)動(dòng)的 poll 方法使用.


int fasync_helper(struct inode *inode, struct file *filp, int mode, struct fasync_struct **fa); 
一個(gè)"幫忙者", 來(lái)實(shí)現(xiàn) fasync 設(shè)備方法. mode 參數(shù)是傳遞給方法的相同的值, 而 fa 指針指向一個(gè)設(shè)備特定的 fasync_struct *.


void kill_fasync(struct fasync_struct *fa, int sig, int band); 
如果這個(gè)驅(qū)動(dòng)支持異步通知, 這個(gè)函數(shù)可用來(lái)發(fā)送一個(gè)信號(hào)到登記在 fa 中的進(jìn)程.


int nonseekable_open(struct inode *inode, struct file *filp); 
loff_t no_llseek(struct file *file, loff_t offset, int whence); 
nonseekable_open 應(yīng)當(dāng)在任何不支持移位的設(shè)備的 open 方法中被調(diào)用. 這樣的設(shè)備應(yīng)當(dāng)使用 no_llseek 作為它們的 llseek 方法.


第 7 章 時(shí)間, 延時(shí), 和延后工作
本章介紹了下面的符號(hào).


7.7.1. 時(shí)間管理
#include <linux/param.h> 
HZ 
HZ 符號(hào)指定了每秒產(chǎn)生的時(shí)鐘嘀噠的數(shù)目.


#include <linux/jiffies.h> 
volatile unsigned long jiffies; 
u64 jiffies_64; 
jiffies_64 變量每個(gè)時(shí)鐘嘀噠時(shí)被遞增; 因此, 它是每秒遞增 HZ 次. 內(nèi)核代碼幾乎常常引用 jiffies, 它在 64-位平臺(tái)和 jiffies_64 相同并且在 32-位平臺(tái)是它低有效的一半.


int time_after(unsigned long a, unsigned long b); 
int time_before(unsigned long a, unsigned long b); 
int time_after_eq(unsigned long a, unsigned long b); 
int time_before_eq(unsigned long a, unsigned long b); 
這些布爾表達(dá)式以一種安全的方式比較 jiffies, 沒有萬(wàn)一計(jì)數(shù)器溢出的問(wèn)題和不需要存取 jiffies_64.


u64 get_jiffies_64(void); 
獲取 jiffies_64 而沒有競(jìng)爭(zhēng)條件.


#include <linux/time.h> 
unsigned long timespec_to_jiffies(struct timespec *value); 
void jiffies_to_timespec(unsigned long jiffies, struct timespec *value); 
unsigned long timeval_to_jiffies(struct timeval *value); 
void jiffies_to_timeval(unsigned long jiffies, struct timeval *value); 
在 jiffies 和其他表示之間轉(zhuǎn)換時(shí)間表示.


#include <asm/msr.h> 
rdtsc(low32,high32); 
rdtscl(low32); 
rdtscll(var32); 
x86-特定的宏定義來(lái)讀取時(shí)戳計(jì)數(shù)器. 它們作為 2 半 32-位來(lái)讀取, 只讀低一半, 或者全部讀到一個(gè) long long 變量.


#include <linux/timex.h> 
cycles_t get_cycles(void); 
以平***立的方式返回時(shí)戳計(jì)數(shù)器. 如果 CPU 沒提供時(shí)戳特性, 返回 0.


#include <linux/time.h> 
unsigned long mktime(year, mon, day, h, m, s); 
返回自 Epoch 以來(lái)的秒數(shù), 基于 6 個(gè) unsigned int 參數(shù).


void do_gettimeofday(struct timeval *tv); 
返回當(dāng)前時(shí)間, 作為自 Epoch 以來(lái)的秒數(shù)和微秒數(shù), 用硬件能提供的最好的精度. 在大部分的平臺(tái)這個(gè)解決方法是一個(gè)微秒或者更好, 盡管一些平臺(tái)只提供 jiffies 精度.


struct timespec current_kernel_time(void); 
返回當(dāng)前時(shí)間, 以一個(gè) jiffy 的精度.


7.7.2. 延遲
#include <linux/wait.h> 
long wait_event_interruptible_timeout(wait_queue_head_t *q, condition, signed long timeout); 
使當(dāng)前進(jìn)程在等待隊(duì)列進(jìn)入睡眠, 安裝一個(gè)以 jiffies 表達(dá)的超時(shí)值. 使用 schedule_timeout( 下面) 給不可中斷睡眠.


#include <linux/sched.h> 
signed long schedule_timeout(signed long timeout); 
調(diào)用調(diào)度器, 在確保當(dāng)前進(jìn)程在超時(shí)到的時(shí)候被喚醒后. 調(diào)用者首先必須調(diào)用 set_curret_state 來(lái)使自己進(jìn)入一個(gè)可中斷的或者不可中斷的睡眠狀態(tài).


#include <linux/delay.h> 
void ndelay(unsigned long nsecs); 
void udelay(unsigned long usecs); 
void mdelay(unsigned long msecs); 
引入一個(gè)整數(shù)納秒, 微秒和毫秒的延遲. 獲得的延遲至少是請(qǐng)求的值, 但是可能更多. 每個(gè)函數(shù)的參數(shù)必須不超過(guò)一個(gè)平臺(tái)特定的限制(常常是幾千).


void msleep(unsigned int millisecs); 
unsigned long msleep_interruptible(unsigned int millisecs); 
void ssleep(unsigned int seconds); 
使進(jìn)程進(jìn)入睡眠給定的毫秒數(shù)(或者秒, 如果使 ssleep).


7.7.3. 內(nèi)核定時(shí)器
#include <asm/hardirq.h> 
int in_interrupt(void); 
int in_atomic(void); 
返回一個(gè)布爾值告知是否調(diào)用代碼在中斷上下文或者原子上下文執(zhí)行. 中斷上下文是在一個(gè)進(jìn)程上下文之外, 或者在硬件或者軟件中斷處理中. 原子上下文是當(dāng)你不能調(diào)度一個(gè)中斷上下文或者一個(gè)持有一個(gè)自旋鎖的進(jìn)程的上下文.


#include <linux/timer.h> 
void init_timer(struct timer_list * timer); 
struct timer_list TIMER_INITIALIZER(_function, _expires, _data); 
這個(gè)函數(shù)和靜態(tài)的定時(shí)器結(jié)構(gòu)的聲明是初始化一個(gè) timer_list 數(shù)據(jù)結(jié)構(gòu)的 2 個(gè)方法.


void add_timer(struct timer_list * timer); 
注冊(cè)定時(shí)器結(jié)構(gòu)來(lái)在當(dāng)前 CPU 上運(yùn)行.


int mod_timer(struct timer_list *timer, unsigned long expires); 
改變一個(gè)已經(jīng)被調(diào)度的定時(shí)器結(jié)構(gòu)的超時(shí)時(shí)間. 它也能作為一個(gè) add_timer 的替代.


int timer_pending(struct timer_list * timer); 
宏定義, 返回一個(gè)布爾值說(shuō)明是否這個(gè)定時(shí)器結(jié)構(gòu)已經(jīng)被注冊(cè)運(yùn)行.


void del_timer(struct timer_list * timer); 
void del_timer_sync(struct timer_list * timer); 
從激活的定時(shí)器鏈表中去除一個(gè)定時(shí)器. 后者保證這定時(shí)器當(dāng)前沒有在另一個(gè) CPU 上運(yùn)行.


7.7.4. Tasklets 機(jī)制
#include <linux/interrupt.h> 
DECLARE_TASKLET(name, func, data); 
DECLARE_TASKLET_DISABLED(name, func, data); 
void tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data); 
前 2 個(gè)宏定義聲明一個(gè) tasklet 結(jié)構(gòu), 而 tasklet_init 函數(shù)初始化一個(gè)已經(jīng)通過(guò)分配或其他方式獲得的 tasklet 結(jié)構(gòu). 第 2 個(gè) DECLARE 宏標(biāo)識(shí)這個(gè) tasklet 為禁止的.


void tasklet_disable(struct tasklet_struct *t); 
void tasklet_disable_nosync(struct tasklet_struct *t); 
void tasklet_enable(struct tasklet_struct *t); 
禁止和使能一個(gè) tasklet. 每個(gè)禁止必須配對(duì)一個(gè)使能( 你可以禁止這個(gè) tasklet 即便它已經(jīng)被禁止). 函數(shù) tasklet_disable 等待 tasklet 終止如果它在另一個(gè) CPU 上運(yùn)行. 這個(gè)非同步版本不采用這個(gè)額外的步驟.


void tasklet_schedule(struct tasklet_struct *t); 
void tasklet_hi_schedule(struct tasklet_struct *t); 
調(diào)度一個(gè) tasklet 運(yùn)行, 或者作為一個(gè)"正常" tasklet 或者一個(gè)高優(yōu)先級(jí)的. 當(dāng)軟中斷被執(zhí)行, 高優(yōu)先級(jí) tasklets 被首先處理, 而正常 tasklet 最后執(zhí)行.


void tasklet_kill(struct tasklet_struct *t); 
從激活的鏈表中去掉 tasklet, 如果它被調(diào)度執(zhí)行. 如同 tasklet_disable, 這個(gè)函數(shù)可能在 SMP 系統(tǒng)中阻塞等待 tasklet 終止, 如果它當(dāng)前在另一個(gè) CPU 上運(yùn)行.


7.7.5. 工作隊(duì)列
#include <linux/workqueue.h> 
struct workqueue_struct; 
struct work_struct; 
這些結(jié)構(gòu)分別表示一個(gè)工作隊(duì)列和一個(gè)工作入口.


struct workqueue_struct *create_workqueue(const char *name); 
struct workqueue_struct *create_singlethread_workqueue(const char *name); 
void destroy_workqueue(struct workqueue_struct *queue); 
創(chuàng)建和銷毀工作隊(duì)列的函數(shù). 一個(gè)對(duì) create_workqueue 的調(diào)用創(chuàng)建一個(gè)有一個(gè)工作者線程在系統(tǒng)中每個(gè)處理器上的隊(duì)列; 相反, create_singlethread_workqueue 創(chuàng)建一個(gè)有一個(gè)單個(gè)工作者進(jìn)程的工作隊(duì)列.


DECLARE_WORK(name, void (*function)(void *), void *data); 
INIT_WORK(struct work_struct *work, void (*function)(void *), void *data); 
PREPARE_WORK(struct work_struct *work, void (*function)(void *), void *data); 
聲明和初始化工作隊(duì)列入口的宏.


int queue_work(struct workqueue_struct *queue, struct work_struct *work); 
int queue_delayed_work(struct workqueue_struct *queue, struct work_struct *work, unsigned long delay); 
從一個(gè)工作隊(duì)列對(duì)工作進(jìn)行排隊(duì)執(zhí)行的函數(shù).


int cancel_delayed_work(struct work_struct *work); 
void flush_workqueue(struct workqueue_struct *queue); 
使用 cancel_delayed_work 來(lái)從一個(gè)工作隊(duì)列中去除入口; flush_workqueue 確保沒有工作隊(duì)列入口在系統(tǒng)中任何地方運(yùn)行.


int schedule_work(struct work_struct *work); 
int schedule_delayed_work(struct work_struct *work, unsigned long delay); 
void flush_scheduled_work(void); 


第 8 章 分配內(nèi)存
相關(guān)于內(nèi)存分配的函數(shù)和符號(hào)是:


#include <linux/slab.h> 
void *kmalloc(size_t size, int flags); 
void kfree(void *obj); 
內(nèi)存分配的最常用接口.


#include <linux/mm.h> 
GFP_USER 
GFP_KERNEL 
GFP_NOFS 
GFP_NOIO 
GFP_ATOMIC 
控 制內(nèi)存分配如何進(jìn)行的標(biāo)志, 從最少限制的到最多的. GFP_USER 和 GFP_KERNEL 優(yōu)先級(jí)允許當(dāng)前進(jìn)程被置為睡眠來(lái)滿足請(qǐng)求. GFP_NOFS 和 GFP_NOIO 禁止文件系統(tǒng)操作和所有的 I/O 操作, 分別地, 而 GFP_ATOMIC 分配根本不能睡眠.


__GFP_DMA 
__GFP_HIGHMEM 
__GFP_COLD 
__GFP_NOWARN 
__GFP_HIGH 
__GFP_REPEAT 
__GFP_NOFAIL 
__GFP_NORETRY 
這些標(biāo)志修改內(nèi)核的行為, 當(dāng)分配內(nèi)存時(shí).


#include <linux/malloc.h> 
kmem_cache_t *kmem_cache_create(char *name, size_t size, size_t offset, unsigned long flags, constructor(), destructor( )); 
int kmem_cache_destroy(kmem_cache_t *cache); 
創(chuàng)建和銷毀一個(gè) slab 緩存. 這個(gè)緩存可被用來(lái)分配幾個(gè)相同大小的對(duì)象.


SLAB_NO_REAP 
SLAB_HWCACHE_ALIGN 
SLAB_CACHE_DMA 
在創(chuàng)建一個(gè)緩存時(shí)可指定的標(biāo)志.


SLAB_CTOR_ATOMIC 
SLAB_CTOR_CONSTRUCTOR 
分配器可用傳遞給構(gòu)造函數(shù)和析構(gòu)函數(shù)的標(biāo)志.


void *kmem_cache_alloc(kmem_cache_t *cache, int flags); 
void kmem_cache_free(kmem_cache_t *cache, const void *obj); 
從緩存中分配和釋放一個(gè)單個(gè)對(duì)象. /proc/slabinfo 一個(gè)包含對(duì) slab 緩存使用情況統(tǒng)計(jì)的虛擬文件.


#include <linux/mempool.h> 
mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn, mempool_free_t *free_fn, void *data); 
void mempool_destroy(mempool_t *pool); 
創(chuàng)建內(nèi)存池的函數(shù), 它試圖避免內(nèi)存分配設(shè)備, 通過(guò)保持一個(gè)已分配項(xiàng)的"緊急列表".


void *mempool_alloc(mempool_t *pool, int gfp_mask); 
void mempool_free(void *element, mempool_t *pool); 
從(并且返回它們給)內(nèi)存池分配項(xiàng)的函數(shù).


unsigned long get_zeroed_page(int flags); 
unsigned long __get_free_page(int flags); 
unsigned long __get_free_pages(int flags, unsigned long order); 
面向頁(yè)的分配函數(shù). get_zeroed_page 返回一個(gè)單個(gè)的, 零填充的頁(yè). 這個(gè)調(diào)用的所有的其他版本不初始化返回頁(yè)的內(nèi)容.


int get_order(unsigned long size); 
返回關(guān)聯(lián)在當(dāng)前平臺(tái)的大小的分配級(jí)別, 根據(jù) PAGE_SIZE. 這個(gè)參數(shù)必須是 2 的冪, 并且返回值至少是 0.


void free_page(unsigned long addr); 
void free_pages(unsigned long addr, unsigned long order); 
釋放面向頁(yè)分配的函數(shù).


struct page *alloc_pages_node(int nid, unsigned int flags, unsigned int order); 
struct page *alloc_pages(unsigned int flags, unsigned int order); 
struct page *alloc_page(unsigned int flags); 
Linux 內(nèi)核中最底層頁(yè)分配器的所有變體.


void __free_page(struct page *page); 
void __free_pages(struct page *page, unsigned int order); 
void free_hot_page(struct page *page); 
使用一個(gè) alloc_page 形式分配的頁(yè)的各種釋放方法.


#include <linux/vmalloc.h> 
void * vmalloc(unsigned long size); 
void vfree(void * addr); 
#include <asm/io.h> 
void * ioremap(unsigned long offset, unsigned long size); 
void iounmap(void *addr); 
分配或釋放一個(gè)連續(xù)虛擬地址空間的函數(shù). iormap 存取物理內(nèi)存通過(guò)虛擬地址, 而 vmalloc 分配空閑頁(yè). 使用 ioreamp 映射的區(qū)是 iounmap 釋放, 而從 vmalloc 獲得的頁(yè)使用 vfree 來(lái)釋放.


#include <linux/percpu.h> 
DEFINE_PER_CPU(type, name); 
DECLARE_PER_CPU(type, name); 
定義和聲明每-CPU變量的宏.


per_cpu(variable, int cpu_id) 
get_cpu_var(variable) 
put_cpu_var(variable) 
提供對(duì)靜態(tài)聲明的每-CPU變量存取的宏.


void *alloc_percpu(type); 
void *__alloc_percpu(size_t size, size_t align); 
void free_percpu(void *variable); 
進(jìn)行運(yùn)行時(shí)分配和釋放每-CPU變量的函數(shù).


int get_cpu( ); 
void put_cpu( ); 
per_cpu_ptr(void *variable, int cpu_id) 
get_cpu 獲得對(duì)當(dāng)前處理器的引用(因此, 阻止搶占和移動(dòng)到另一個(gè)處理器)并且返回處理器的ID; put_cpu 返回這個(gè)引用. 為存取一個(gè)動(dòng)態(tài)分配的每-CPU變量, 用應(yīng)當(dāng)被存取版本所在的 CPU 的 ID 來(lái)使用 per_cpu_ptr. 對(duì)一個(gè)動(dòng)態(tài)的每-CPU 變量當(dāng)前 CPU 版本的操作, 應(yīng)當(dāng)用對(duì) get_cpu 和 put_cpu 的調(diào)用來(lái)包圍. 


#include <linux/bootmem.h> 
void *alloc_bootmem(unsigned long size); 
void *alloc_bootmem_low(unsigned long size); 
void *alloc_bootmem_pages(unsigned long size); 
void *alloc_bootmem_low_pages(unsigned long size); 
void free_bootmem(unsigned long addr, unsigned long size); 
在系統(tǒng)啟動(dòng)時(shí)進(jìn)行分配和釋放內(nèi)存的函數(shù)(只能被直接連接到內(nèi)核中去的驅(qū)動(dòng)使用)


第 9 章 與硬件通訊
本章介紹下列與硬件管理相關(guān)的符號(hào):


#include <linux/kernel.h> 
void barrier(void) 
這個(gè)"軟件"內(nèi)存屏蔽要求編譯器對(duì)待所有內(nèi)存是跨這個(gè)指令而非易失的.


#include <asm/system.h> 
void rmb(void); 
void read_barrier_depends(void); 
void wmb(void); 
void mb(void); 
硬件內(nèi)存屏障. 它們請(qǐng)求 CPU(和編譯器)來(lái)檢查所有的跨這個(gè)指令的內(nèi)存讀, 寫, 或都有.


#include <asm/io.h> 
unsigned inb(unsigned port); 
void outb(unsigned char byte, unsigned port); 
unsigned inw(unsigned port); 
void outw(unsigned short word, unsigned port); 
unsigned inl(unsigned port); 
void outl(unsigned doubleword, unsigned port); 
用來(lái)讀和寫 I/O 端口的函數(shù). 它們還可以被用戶空間程序調(diào)用, 如果它們有正當(dāng)?shù)臋?quán)限來(lái)存取端口.


unsigned inb_p(unsigned port); 
如果在一次 I/O 操作后需要一個(gè)小延時(shí), 你可以使用在前一項(xiàng)中介紹的這些函數(shù)的 6 個(gè)暫停對(duì)應(yīng)部分; 這些暫停函數(shù)有以 _p 結(jié)尾的名子.


void insb(unsigned port, void *addr, unsigned long count); 
void outsb(unsigned port, void *addr, unsigned long count); 
void insw(unsigned port, void *addr, unsigned long count); 
void outsw(unsigned port, void *addr, unsigned long count); 
void insl(unsigned port, void *addr, unsigned long count); 
void outsl(unsigned port, void *addr, unsigned long count); 
這些"字串函數(shù)"被優(yōu)化為傳送數(shù)據(jù)從一個(gè)輸入端口到一個(gè)內(nèi)存區(qū), 或者其他的方式. 這些傳送通過(guò)讀或?qū)懙酵欢丝?count 次來(lái)完成.


#include <linux/ioport.h> 
struct resource *request_region(unsigned long start, unsigned long len, char *name); 
void release_region(unsigned long start, unsigned long len); 
int check_region(unsigned long start, unsigned long len); 
I/O 端口的資源分配器. 這個(gè)檢查函數(shù)成功返回 0 并且在錯(cuò)誤時(shí)小于 0.


struct resource *request_mem_region(unsigned long start, unsigned long len, char *name); 
void release_mem_region(unsigned long start, unsigned long len); 
int check_mem_region(unsigned long start, unsigned long len); 
為內(nèi)存區(qū)處理資源分配的函數(shù)


#include <asm/io.h> 
void *ioremap(unsigned long phys_addr, unsigned long size); 
void *ioremap_nocache(unsigned long phys_addr, unsigned long size); 
void iounmap(void *virt_addr); 
ioremap 重映射一個(gè)物理地址范圍到處理器的虛擬地址空間, 使它對(duì)內(nèi)核可用. iounmap 釋放映射當(dāng)不再需要它時(shí).


#include <asm/io.h> 
unsigned int ioread8(void *addr); 
unsigned int ioread16(void *addr); 
unsigned int ioread32(void *addr); 
void iowrite8(u8 value, void *addr); 
void iowrite16(u16 value, void *addr); 
void iowrite32(u32 value, void *addr); 
用來(lái)使用 I/O 內(nèi)存的存取者函數(shù).


void ioread8_rep(void *addr, void *buf, unsigned long count); 
void ioread16_rep(void *addr, void *buf, unsigned long count); 
void ioread32_rep(void *addr, void *buf, unsigned long count); 
void iowrite8_rep(void *addr, const void *buf, unsigned long count); 
void iowrite16_rep(void *addr, const void *buf, unsigned long count); 
void iowrite32_rep(void *addr, const void *buf, unsigned long count); 
I/O 內(nèi)存原語(yǔ)的"重復(fù)"版本.


unsigned readb(address); 
unsigned readw(address); 
unsigned readl(address); 
void writeb(unsigned value, address); 
void writew(unsigned value, address); 
void writel(unsigned value, address); 
memset_io(address, value, count); 
memcpy_fromio(dest, source, nbytes); 
memcpy_toio(dest, source, nbytes); 
舊的, 類型不安全的存取 I/O 內(nèi)存的函數(shù).


void *ioport_map(unsigned long port, unsigned int count); 
void ioport_unmap(void *addr); 
一個(gè)想對(duì)待 I/O 端口如同它們是 I/O 內(nèi)存的驅(qū)動(dòng)作者, 可以傳遞它們的端口給 ioport_map. 這個(gè)映射應(yīng)當(dāng)在不需要的時(shí)候恢復(fù)( 使用 ioport_unmap )


第 10 章 中斷處理 
本章中介紹了這些關(guān)于中斷管理的符號(hào):


#include <linux/interrupt.h> 
int request_irq(unsigned int irq, irqreturn_t (*handler)( ), unsigned long flags, const char *dev_name, void *dev_id); 
void free_irq(unsigned int irq, void *dev_id); 
調(diào)用這個(gè)注冊(cè)和注銷一個(gè)中斷處理.


#include <linux/irq.h.h> 
int can_request_irq(unsigned int irq, unsigned long flags); 
這個(gè)函數(shù), 在 i386 和 x86_64 體系上有, 返回一個(gè)非零值如果一個(gè)分配給定中斷線的企圖成功.


#include <asm/signal.h> 
SA_INTERRUPT 
SA_SHIRQ 
SA_SAMPLE_RANDOM 
給 request_irq 的標(biāo)志. SA_INTERRUPT 請(qǐng)求安裝一個(gè)快速處理者( 相反是一個(gè)慢速的). SA_SHIRQ 安裝一個(gè)共享的處理者, 并且第 3 個(gè) flag 聲稱中斷時(shí)戳可用來(lái)產(chǎn)生系統(tǒng)熵.


/proc/interrupts 
/proc/stat 
報(bào)告硬件中斷和安裝的處理者的文件系統(tǒng)節(jié)點(diǎn).


unsigned long probe_irq_on(void); 
int probe_irq_off(unsigned long); 
驅(qū)動(dòng)使用的函數(shù), 當(dāng)它不得不探測(cè)來(lái)決定哪個(gè)中斷線被設(shè)備在使用. probe_irq_on 的結(jié)果必須傳回給 probe_irq_off 在中斷產(chǎn)生之后. probe_irq_off 的返回值是被探測(cè)的中斷號(hào).


IRQ_NONE 
IRQ_HANDLED 
IRQ_RETVAL(int x) 
從一個(gè)中斷處理返回的可能值, 指示是否一個(gè)來(lái)自設(shè)備的真正的中斷出現(xiàn)了.


void disable_irq(int irq); 
void disable_irq_nosync(int irq); 
void enable_irq(int irq); 
驅(qū)動(dòng)可以使能和禁止中斷報(bào)告. 如果硬件試圖在中斷禁止時(shí)產(chǎn)生一個(gè)中斷, 這個(gè)中斷永遠(yuǎn)丟失了. 一個(gè)使用一個(gè)共享處理者的驅(qū)動(dòng)必須不使用這個(gè)函數(shù).


void local_irq_save(unsigned long flags); 
void local_irq_restore(unsigned long flags); 
使用 local_irq_save 來(lái)禁止本地處理器的中斷并且記住它們之前的狀態(tài). flags 可以被傳遞給 local_irq_restore 來(lái)恢復(fù)之前的中斷狀態(tài).


void local_irq_disable(void); 
void local_irq_enable(void); 
在當(dāng)前處理器熵?zé)o條件禁止和使能中斷的函數(shù).


第 11 章 內(nèi)核中的數(shù)據(jù)類型
下列符號(hào)在本章中介紹了:


#include <linux/types.h> 
typedef u8; 
typedef u16; 
typedef u32; 
typedef u64; 
保證是 8-位, 16-位, 32-位 和64-位 無(wú)符號(hào)整型值的類型. 對(duì)等的有符號(hào)類型也存在. 在用戶空間, 你可用 __u8, __u16, 等等來(lái)引用這些類型.


#include <asm/page.h> 
PAGE_SIZE 
PAGE_SHIFT 
給當(dāng)前體系定義每頁(yè)的字節(jié)數(shù), 以及頁(yè)偏移的位數(shù)( 對(duì)于 4 KB 頁(yè)是 12, 8 KB 是 13 )的符號(hào).


#include <asm/byteorder.h> 
__LITTLE_ENDIAN 
__BIG_ENDIAN 
這 2 個(gè)符號(hào)只有一個(gè)定義, 依賴體系.


#include <asm/byteorder.h> 
u32 __cpu_to_le32 (u32); 
u32 __le32_to_cpu (u32); 
在已知字節(jié)序和處理器字節(jié)序之間轉(zhuǎn)換的函數(shù). 有超過(guò) 60 個(gè)這樣的函數(shù): 在 include/linux/byteorder/ 中的各種文件有完整的列表和它們以何種方式定義.


#include <asm/unaligned.h> 
get_unaligned(ptr); 
put_unaligned(val, ptr); 
一些體系需要使用這些宏保護(hù)不對(duì)齊的數(shù)據(jù)存取. 這些宏定義擴(kuò)展成通常的指針解引用, 為那些允許你存取不對(duì)齊數(shù)據(jù)的體系.


#include <linux/err.h> 
void *ERR_PTR(long error); 
long PTR_ERR(const void *ptr); 
long IS_ERR(const void *ptr); 
允許錯(cuò)誤碼由返回指針值的函數(shù)返回.


#include <linux/list.h> 
list_add(struct list_head *new, struct list_head *head); 
list_add_tail(struct list_head *new, struct list_head *head); 
list_del(struct list_head *entry); 
list_del_init(struct list_head *entry); 
list_empty(struct list_head *head); 
list_entry(entry, type, member); 
list_move(struct list_head *entry, struct list_head *head); 
list_move_tail(struct list_head *entry, struct list_head *head); 
list_splice(struct list_head *list, struct list_head *head); 
操作環(huán)形, 雙向鏈表的函數(shù).


list_for_each(struct list_head *cursor, struct list_head *list) 
list_for_each_prev(struct list_head *cursor, struct list_head *list) 
list_for_each_safe(struct list_head *cursor, struct list_head *next, struct list_head *list) 
list_for_each_entry(type *cursor, struct list_head *list, member) 
list_for_each_entry_safe(type *cursor, type *next struct list_head *list, member) 
方便的宏定義, 用在遍歷鏈表上.


第 12 章 PCI 驅(qū)動(dòng)
本節(jié)總結(jié)在本章中介紹的符號(hào):


#include <linux/pci.h> 
包含 PCI 寄存器的符號(hào)名和幾個(gè)供應(yīng)商和設(shè)備 ID 值的頭文件.


struct pci_dev; 
表示內(nèi)核中一個(gè) PCI 設(shè)備的結(jié)構(gòu).


struct pci_driver; 
代表一個(gè) PCI 驅(qū)動(dòng)的結(jié)構(gòu). 所有的 PCI 驅(qū)動(dòng)必須定義這個(gè).


struct pci_device_id; 
描述這個(gè)驅(qū)動(dòng)支持的 PCI 設(shè)備類型的結(jié)構(gòu).


int pci_register_driver(struct pci_driver *drv); 
int pci_module_init(struct pci_driver *drv); 
void pci_unregister_driver(struct pci_driver *drv); 
從內(nèi)核注冊(cè)或注銷一個(gè) PCI 驅(qū)動(dòng)的函數(shù).


struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device, struct pci_dev *from); 
struct pci_dev *pci_find_device_reverse(unsigned int vendor, unsigned int device, const struct pci_dev *from); 
struct pci_dev *pci_find_subsys (unsigned int vendor, unsigned int device, unsigned int ss_vendor, unsigned int ss_device, const struct pci_dev *from); 
struct pci_dev *pci_find_class(unsigned int class, struct pci_dev *from); 
在 設(shè)備列表中搜尋帶有一個(gè)特定簽名的設(shè)備, 或者屬于一個(gè)特定類的. 返回值是 NULL 如果沒找到. from 用來(lái)繼續(xù)一個(gè)搜索; 在你第一次調(diào)用任一個(gè)函數(shù)時(shí)它必須是 NULL, 并且它必須指向剛剛找到的設(shè)備如果你尋找更多的設(shè)備. 這些函數(shù)不推薦使用, 用 pci_get_ 變體來(lái)代替.


struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from); 
struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device, unsigned int ss_vendor, unsigned int ss_device, struct pci_dev *from); 
struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn); 
在 設(shè)備列表中搜索一個(gè)特定簽名的設(shè)備, 或者屬于一個(gè)特定類. 返回值是 NULL 如果沒找到. from 用來(lái)繼續(xù)一個(gè)搜索; 在你第一次調(diào)用任一個(gè)函數(shù)時(shí)它必須是 NULL, 并且它必須指向剛剛找到的設(shè)備如果你尋找更多的設(shè)備. 返回的結(jié)構(gòu)使它的引用計(jì)數(shù)遞增, 并且在調(diào)用者完成它, 函數(shù) pci_dev_put 必須被調(diào)用.


int pci_read_config_byte(struct pci_dev *dev, int where, u8 *val); 
int pci_read_config_word(struct pci_dev *dev, int where, u16 *val); 
int pci_read_config_dword(struct pci_dev *dev, int where, u32 *val); 
int pci_write_config_byte (struct pci_dev *dev, int where, u8 *val); 
int pci_write_config_word (struct pci_dev *dev, int where, u16 *val); 
int pci_write_config_dword (struct pci_dev *dev, int where, u32 *val); 
讀或?qū)?PCI 配置寄存器的函數(shù). 盡管 Linux 內(nèi)核負(fù)責(zé)字節(jié)序, 程序員必須小心字節(jié)序當(dāng)從單個(gè)字節(jié)組合多字節(jié)值時(shí). PCI 總線是小端.


int pci_enable_device(struct pci_dev *dev); 
使能一個(gè) PCI 設(shè)備.


unsigned long pci_resource_start(struct pci_dev *dev, int bar); 
unsigned long pci_resource_end(struct pci_dev *dev, int bar); 
unsigned long pci_resource_flags(struct pci_dev *dev, int bar); 
處理 PCI 設(shè)備資源的函數(shù).


第 13 章 USB 驅(qū)動(dòng)
本節(jié)總結(jié)本章介紹的符號(hào):


#include <linux/usb.h> 
所有和 USB 相關(guān)的頭文件. 它必須被所有的 USB 設(shè)備驅(qū)動(dòng)包含.


struct usb_driver; 
描述 USB 驅(qū)動(dòng)的結(jié)構(gòu).


struct usb_device_id; 
描述這個(gè)驅(qū)動(dòng)支持的 USB 設(shè)備的結(jié)構(gòu).


int usb_register(struct usb_driver *d); 
用來(lái)從USB核心注冊(cè)和注銷一個(gè) USB 驅(qū)動(dòng)的函數(shù).


struct usb_device *interface_to_usbdev(struct usb_interface *intf); 
從 struct usb_interface 獲取控制 struct usb_device *.


struct usb_device; 
控制完整 USB 設(shè)備的結(jié)構(gòu).


struct usb_interface; 
主 USB 設(shè)備結(jié)構(gòu), 所有的 USB 驅(qū)動(dòng)用來(lái)和 USB 核心通訊的.


void usb_set_intfdata(struct usb_interface *intf, void *data); 
void *usb_get_intfdata(struct usb_interface *intf); 
設(shè)置和獲取在 struct usb_interface 中的私有數(shù)據(jù)指針部分的函數(shù).


struct usb_class_driver; 
描述 USB 驅(qū)動(dòng)的一個(gè)結(jié)構(gòu), 這個(gè)驅(qū)動(dòng)要使用 USB 主編號(hào)來(lái)和用戶空間程序通訊.


int usb_register_dev(struct usb_interface *intf, struct usb_class_driver *class_driver); 
void usb_deregister_dev(struct usb_interface *intf, struct usb_class_driver *class_driver); 
用來(lái)注冊(cè)和注銷一個(gè)特定 struct usb_interface * 結(jié)構(gòu)到 struct usb_class_driver 結(jié)構(gòu)的函數(shù).


struct urb; 
描述一個(gè) USB 數(shù)據(jù)傳輸?shù)慕Y(jié)構(gòu).


struct urb *usb_alloc_urb(int iso_packets, int mem_flags); 
void usb_free_urb(struct urb *urb); 
用來(lái)創(chuàng)建和銷毀一個(gè) struct usb urb*的函數(shù).


int usb_submit_urb(struct urb *urb, int mem_flags); 
int usb_kill_urb(struct urb *urb); 
int usb_unlink_urb(struct urb *urb); 
用來(lái)啟動(dòng)和停止一個(gè) USB 數(shù)據(jù)傳輸?shù)暮瘮?shù).


void usb_fill_int_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe, void *transfer_buffer, int buffer_length, usb_complete_t complete, void *context, int interval); 
void usb_fill_bulk_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe, void *transfer_buffer, int buffer_length, usb_complete_t complete, void *context); 
void usb_fill_control_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe, unsigned char *setup_packet, void *transfer_buffer, int buffer_ length, usb_complete_t complete, void *context); 
用來(lái)在被提交給 USB 核心之前初始化一個(gè) struct urb 的函數(shù). 


int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout); 
int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout); 
用來(lái)發(fā)送和接受 USB 數(shù)據(jù)的函數(shù), 不必使用一個(gè) struct urb. 


第 14 章 Linux 設(shè)備模型
許多函數(shù)在本章中已經(jīng)被介紹過(guò); 這是它們?nèi)康囊粋€(gè)快速總結(jié).


14.9.1. Kobjects結(jié)構(gòu)
#include <linux/kobject.h> 
包含文件, 包含 kobject 的定義, 相關(guān)結(jié)構(gòu), 和函數(shù).


void kobject_init(struct kobject *kobj); 
int kobject_set_name(struct kobject *kobj, const char *format, ...); 
用作 kobject 初始化的函數(shù)


struct kobject *kobject_get(struct kobject *kobj); 
void kobject_put(struct kobject *kobj); 
為 kobjects 管理引用計(jì)數(shù)的函數(shù).


struct kobj_type; 
struct kobj_type *get_ktype(struct kobject *kobj); 
表示一個(gè)kobjct 被嵌入的結(jié)構(gòu)類型. 使用 get_ktype 來(lái)獲得關(guān)聯(lián)到一個(gè)給定 kobject 的 kobj_type.


int kobject_add(struct kobject *kobj); 
extern int kobject_register(struct kobject *kobj); 
void kobject_del(struct kobject *kobj); 
void kobject_unregister(struct kobject *kobj); 
kobject_add 添加一個(gè) kobject 到系統(tǒng), 處理 kset 成員關(guān)系, sysfs 表示, 以及熱插拔事件產(chǎn)生. kobject_register 是一個(gè)方便函數(shù), 它結(jié)合 kobject_init 和 kobject_add. 使用 kobject_del 來(lái)去除一個(gè) kobject 或者 kobject_unregister, 它結(jié)合了 kobject_del 和 kobject_put.


void kset_init(struct kset *kset); 
int kset_add(struct kset *kset); 
int kset_register(struct kset *kset); 
void kset_unregister(struct kset *kset); 
為 ksets 初始化和注冊(cè)的函數(shù).


decl_subsys(name, type, hotplug_ops); 
易于聲明子系統(tǒng)的一個(gè)宏.


void subsystem_init(struct subsystem *subsys); 
int subsystem_register(struct subsystem *subsys); 
void subsystem_unregister(struct subsystem *subsys); 
struct subsystem *subsys_get(struct subsystem *subsys); 
void subsys_put(struct subsystem *subsys); 
對(duì)子系統(tǒng)的操作.


14.9.2. sysfs 操作
#include <linux/sysfs.h> 
包含 sysfs 聲明的包含文件.


int sysfs_create_file(struct kobject *kobj, struct attribute *attr); 
int sysfs_remove_file(struct kobject *kobj, struct attribute *attr); 
int sysfs_create_bin_file(struct kobject *kobj, struct bin_attribute *attr); 
int sysfs_remove_bin_file(struct kobject *kobj, struct bin_attribute *attr); 
int sysfs_create_link(struct kobject *kobj, struct kobject *target, char *name); 
void sysfs_remove_link(struct kobject *kobj, char *name); 
創(chuàng)建和去除和一個(gè) kobject 關(guān)聯(lián)的屬性文件的函數(shù).


14.9.3. 總線, 設(shè)備, 和驅(qū)動(dòng)
int bus_register(struct bus_type *bus); 
void bus_unregister(struct bus_type *bus); 
在設(shè)備模型中進(jìn)行注冊(cè)和注銷總線的函數(shù).


int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, int (*fn)(struct device *, void *)); 
int bus_for_each_drv(struct bus_type *bus, struct device_driver *start, void *data, int (*fn)(struct device_driver *, void *)); 


列舉每個(gè)設(shè)備和驅(qū)動(dòng)的函數(shù), 特別地, 綁定到給定總線的設(shè)備. 
BUS_ATTR(name, mode, show, store); 
int bus_create_file(struct bus_type *bus, struct bus_attribute *attr); 
void bus_remove_file(struct bus_type *bus, struct bus_attribute *attr); 
BUS_ATTR 宏可能用來(lái)聲明一個(gè) bus_attribute 結(jié)構(gòu), 它可能接著被添加和去除, 使用上面 2 個(gè)函數(shù).


int device_register(struct device *dev); 
void device_unregister(struct device *dev); 
處理設(shè)備注冊(cè)的函數(shù).


DEVICE_ATTR(name, mode, show, store); 
int device_create_file(struct device *device, struct device_attribute *entry); 
void device_remove_file(struct device *dev, struct device_attribute *attr); 
處理設(shè)備屬性的宏和函數(shù).


int driver_register(struct device_driver *drv); 
void driver_unregister(struct device_driver *drv); 
注冊(cè)和注銷一個(gè)設(shè)備驅(qū)動(dòng)的函數(shù).


DRIVER_ATTR(name, mode, show, store); 
int driver_create_file(struct device_driver *drv, struct driver_attribute *attr); 
void driver_remove_file(struct device_driver *drv, struct driver_attribute *attr); 
關(guān)聯(lián)驅(qū)動(dòng)屬性的宏和函數(shù).


14.9.4. 類
struct class_simple *class_simple_create(struct module *owner, char *name); 
void class_simple_destroy(struct class_simple *cs); 
struct class_device *class_simple_device_add(struct class_simple *cs, dev_t devnum, struct device *device, const char *fmt, ...); 
void class_simple_device_remove(dev_t dev); 
int class_simple_set_hotplug(struct class_simple *cs, int (*hotplug)(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size)); 
實(shí)現(xiàn) class_simple 接口的函數(shù); 它們管理包含一個(gè) dev 屬性和很少其他屬性的簡(jiǎn)單的類入口


int class_register(struct class *cls); 
void class_unregister(struct class *cls); 
注冊(cè)和注銷類.


CLASS_ATTR(name, mode, show, store); 
int class_create_file(struct class *cls, const struct class_attribute *attr); 
void class_remove_file(struct class *cls, const struct class_attribute *attr); 
處理類屬性的常用宏和函數(shù).


int class_device_register(struct class_device *cd); 
void class_device_unregister(struct class_device *cd); 
int class_device_rename(struct class_device *cd, char *new_name); 
CLASS_DEVICE_ATTR(name, mode, show, store); 
int class_device_create_file(struct class_device *cls, const struct class_device_attribute *attr); 
屬性類設(shè)備接口的函數(shù)和宏.


int class_interface_register(struct class_interface *intf); 
void class_interface_unregister(struct class_interface *intf); 
添加一個(gè)接口到一個(gè)類(或去除它)的函數(shù).


14.9.5. 固件
#include <linux/firmware.h> 
int request_firmware(const struct firmware **fw, char *name, struct device *device); 
int request_firmware_nowait(struct module *module, char *name, struct device *device, void *context, void (*cont)(const struct firmware *fw, void *context)); 
void release_firmware(struct firmware *fw); 
屬性內(nèi)核固件加載接口的函數(shù).


第 15 章 內(nèi)存映射和 DMA 
15.5. 快速參考
本章介紹了下列關(guān)于內(nèi)存處理的符號(hào):


15.5.1. 介紹性材料
#include <linux/mm.h> 
#include <asm/page.h> 
和內(nèi)存管理相關(guān)的大部分函數(shù)和結(jié)構(gòu), 原型和定義在這些頭文件.


void *__va(unsigned long physaddr); 
unsigned long __pa(void *kaddr); 
在內(nèi)核邏輯地址和物理地址之間轉(zhuǎn)換的宏定義.


PAGE_SIZE 
PAGE_SHIFT 
常量, 給出底層硬件的頁(yè)的大小(字節(jié))和一個(gè)頁(yè)面號(hào)必須被移位來(lái)轉(zhuǎn)變?yōu)橐粋€(gè)物理地址的位數(shù).


struct page 
在系統(tǒng)內(nèi)存映射中表示一個(gè)硬件頁(yè)的結(jié)構(gòu).


struct page *virt_to_page(void *kaddr); 
void *page_address(struct page *page); 
struct page *pfn_to_page(int pfn); 
宏定義, 在內(nèi)核邏輯地址和它們相關(guān)的內(nèi)存映射入口之間轉(zhuǎn)換的. page_address 只用在低地址頁(yè)或者已被明確映射的高地址頁(yè). pfn_to_page 轉(zhuǎn)換一個(gè)頁(yè)面號(hào)到它的相關(guān)的 struct page 指針.


unsigned long kmap(struct page *page); 
void kunmap(struct page *page); 
kmap 返回一個(gè)內(nèi)核虛擬地址, 被映射到給定頁(yè), 如果需要并創(chuàng)建映射. kunmap 為給定頁(yè)刪除映射.


#include <linux/highmem.h> 
#include <asm/kmap_types.h> 
void *kmap_atomic(struct page *page, enum km_type type); 
void kunmap_atomic(void *addr, enum km_type type); 
kmap 的高性能版本; 結(jié)果的映射只能被原子代碼持有. 對(duì)于驅(qū)動(dòng), type 應(yīng)當(dāng)是 KM_USER1, KM_USER1, KM_IRQ0, 或者 KM_IRQ1.


struct vm_area_struct; 
描述一個(gè) VMA 的結(jié)構(gòu).


15.5.2. 實(shí)現(xiàn) mmap
int remap_pfn_range(struct vm_area_struct *vma, unsigned long virt_add, unsigned long pfn, unsigned long size, pgprot_t prot); 
int io_remap_page_range(struct vm_area_struct *vma, unsigned long virt_add, unsigned long phys_add, unsigned long size, pgprot_t prot); 
位于 mmap 核心的函數(shù). 它們映射 size 字節(jié)的物理地址, 從 pfn 指出的頁(yè)號(hào)開始到虛擬地址 virt_add. 和虛擬空間相關(guān)聯(lián)的保護(hù)位在 prot 里指定. io_remap_page_range 應(yīng)當(dāng)在目標(biāo)地址在 I/O 內(nèi)存空間里時(shí)被使用.


struct page *vmalloc_to_page(void *vmaddr); 
轉(zhuǎn)換一個(gè)由 vmalloc 獲得的內(nèi)核虛擬地址到它的對(duì)應(yīng)的 struct page 指針.


15.5.3. 實(shí)現(xiàn)直接 I/O
int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start, int len, int write, int force, struct page **pages, struct vm_area_struct **vmas); 
函數(shù), 加鎖一個(gè)用戶空間緩沖到內(nèi)存并且返回對(duì)應(yīng)的 struct page 指針. 調(diào)用者必須持有 mm->mmap_sem.


SetPageDirty(struct page *page); 
宏定義, 標(biāo)識(shí)給定的頁(yè)為"臟"(被修改)并且需要寫到它的后備存儲(chǔ), 在它被釋放前.


void page_cache_release(struct page *page); 
釋放給定的頁(yè)從頁(yè)緩存中.


int is_sync_kiocb(struct kiocb *iocb); 
宏定義, 返回非零如果給定的 IOCB 需要同步執(zhí)行.


int aio_complete(struct kiocb *iocb, long res, long res2); 
函數(shù), 指示一個(gè)異步 I/O 操作完成.


15.5.4. 直接內(nèi)存存取
#include <asm/io.h> 
unsigned long virt_to_bus(volatile void * address); 
void * bus_to_virt(unsigned long address); 
過(guò)時(shí)的不好的函數(shù), 在內(nèi)核, 虛擬, 和總線地址之間轉(zhuǎn)換. 總線地址必須用來(lái)和外設(shè)通訊.


#include <linux/dma-mapping.h> 
需要來(lái)定義通用 DMA 函數(shù)的頭文件.


int dma_set_mask(struct device *dev, u64 mask); 
對(duì)于無(wú)法尋址整個(gè) 32-位范圍的外設(shè), 這個(gè)函數(shù)通知內(nèi)核可尋址的地址范圍并且如果可進(jìn)行 DMA 返回非零.


void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *bus_addr, int flag); 
void dma_free_coherent(struct device *dev, size_t size, void *cpuaddr, dma_handle_t bus_addr); 
分配和釋放一致 DMA 映射, 對(duì)一個(gè)將持續(xù)在驅(qū)動(dòng)的生命周期中的緩沖.


#include <linux/dmapool.h> 
struct dma_pool *dma_pool_create(const char *name, struct device *dev, size_t size, size_t align, size_t allocation); 
void dma_pool_destroy(struct dma_pool *pool); 
void *dma_pool_alloc(struct dma_pool *pool, int mem_flags, dma_addr_t *handle); 
void dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t handle); 
創(chuàng)建, 銷毀, 和使用 DMA 池來(lái)管理小 DMA 區(qū)的函數(shù).


enum dma_data_direction; 
DMA_TO_DEVICE 
DMA_FROM_DEVICE 
DMA_BIDIRECTIONAL 
DMA_NONE 
符號(hào), 用來(lái)告知流映射函數(shù)在什么方向數(shù)據(jù)移入或出緩沖. 


dma_addr_t dma_map_single(struct device *dev, void *buffer, size_t size, enum dma_data_direction direction); 
void dma_unmap_single(struct device *dev, dma_addr_t bus_addr, size_t size, enum dma_data_direction direction); 
創(chuàng)建和銷毀一個(gè)單使用, 流 DMA 映射.


void dma_sync_single_for_cpu(struct device *dev, dma_handle_t bus_addr, size_t size, enum dma_data_direction direction); 
void dma_sync_single_for_device(struct device *dev, dma_handle_t bus_addr, size_t size, enum dma_data_direction direction); 
同步一個(gè)由一個(gè)流映射的緩沖. 必須使用這些函數(shù), 如果處理器必須存取一個(gè)緩沖當(dāng)使用流映射時(shí).(即, 當(dāng)設(shè)備擁有緩沖時(shí)).


#include <asm/scatterlist.h> 
struct scatterlist { /* ... */ }; 
dma_addr_t sg_dma_address(struct scatterlist *sg); 
unsigned int sg_dma_len(struct scatterlist *sg); 
這個(gè)散布表結(jié)構(gòu)描述一個(gè)涉及不止一個(gè)緩沖的 I/O 操作. 宏 sg_dma_address he sg_dma_len 可用來(lái)抽取總線地址和緩沖長(zhǎng)度來(lái)傳遞給設(shè)備, 當(dāng)實(shí)現(xiàn)發(fā)散/匯聚操作時(shí).


dma_map_sg(struct device *dev, struct scatterlist *list, int nents, enum dma_data_direction direction); 
dma_unmap_sg(struct device *dev, struct scatterlist *list, int nents, enum dma_data_direction direction); 
void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction direction); 
void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction direction); 
dma_map_sg 映射一個(gè) 發(fā)散/匯聚 操作, 并且 dma_unmap_sg 恢復(fù)這些映射. 如果在這個(gè)映射被激活時(shí)緩沖必須被存取, dma_sync_sg_* 可用來(lái)同步.


/proc/dma 
包含在 DMA 控制器中的被分配的通道的文本快照的文件. 基于 PCI 的 DMA 不顯示, 因?yàn)槊總€(gè)板獨(dú)立工作, 不需要分配一個(gè)通道在 DMA 控制器中.


#include <asm/dma.h> 
定義或者原型化所有和 DMA 相關(guān)的函數(shù)和宏定義. 它必須被包含來(lái)使用任何下面符號(hào).


int request_dma(unsigned int channel, const char *name); 
void free_dma(unsigned int channel); 
存取 DMA 注冊(cè). 注冊(cè)必須在使用 ISA DMA 通道之前進(jìn)行.


unsigned long claim_dma_lock( ); 
void release_dma_lock(unsigned long flags); 
獲取和釋放 DMA 自旋鎖, 它必須被持有, 在調(diào)用其他的在這個(gè)列表中描述的 ISA DMA 函數(shù)之前. 它們?cè)诒镜靥幚砥魃弦碴P(guān)閉和重新使能中斷


void set_dma_mode(unsigned int channel, char mode); 
void set_dma_addr(unsigned int channel, unsigned int addr); 
void set_dma_count(unsigned int channel, unsigned int count); 
編程 DMA 信息在 DMA 控制器中. addr 是一個(gè)總線地址. 


void disable_dma(unsigned int channel); 
void enable_dma(unsigned int channel); 
一個(gè) DMA 通道必須被關(guān)閉在配置期間. 這些函數(shù)改變 DMA 通道的狀態(tài).


int get_dma_residue(unsigned int channel); 
如果這驅(qū)動(dòng)需要知道一個(gè) DMA 傳送在進(jìn)行, 它可調(diào)用這個(gè)函數(shù), 返回尚未完成的數(shù)據(jù)傳輸?shù)臄?shù)目. 在成功的 DMA 完成后, 這個(gè)函數(shù)返回 0; 值是不可預(yù)測(cè)的當(dāng)數(shù)據(jù)仍然在傳送時(shí).


void clear_dma_ff(unsigned int channel); 
DMA flip-flop 被控制器用來(lái)傳送 16-位值, 通過(guò) 2 個(gè) 8 位操作. 它必須被清除, 在發(fā)送任何數(shù)據(jù)給處理器之前.




第 16 章 塊驅(qū)動(dòng)
#include <linux/fs.h> 
int register_blkdev(unsigned int major, const char *name); 
int unregister_blkdev(unsigned int major, const char *name); 
register_blkdev 注冊(cè)一個(gè)塊驅(qū)動(dòng)到內(nèi)核, 并且, 可選地, 獲得一個(gè)主編號(hào). 一個(gè)驅(qū)動(dòng)可被注銷, 使用 unregister_blkdev.


struct block_device_operations 
持有大部分塊驅(qū)動(dòng)的方法的結(jié)構(gòu).


#include <linux/genhd.h> 
struct gendisk; 
描述內(nèi)核中單個(gè)塊設(shè)備的結(jié)構(gòu).


struct gendisk *alloc_disk(int minors); 
void add_disk(struct gendisk *gd); 
分配 gendisk 結(jié)構(gòu)的函數(shù), 并且返回它們到系統(tǒng). 


void set_capacity(struct gendisk *gd, sector_t sectors); 
存儲(chǔ)設(shè)備能力(以 512-字節(jié))在 gendisk 結(jié)構(gòu)中. 


void add_disk(struct gendisk *gd); 
添加一個(gè)磁盤到內(nèi)核. 一旦調(diào)用這個(gè)函數(shù), 你的磁盤的方法可被內(nèi)核調(diào)用. 


int check_disk_change(struct block_device *bdev); 
一個(gè)內(nèi)核函數(shù), 檢查在給定磁盤驅(qū)動(dòng)器中的介質(zhì)改變, 并且采取要求的清理動(dòng)作當(dāng)檢測(cè)到這樣一個(gè)改變.


#include <linux/blkdev.h> 
request_queue_t blk_init_queue(request_fn_proc *request, spinlock_t *lock); 
void blk_cleanup_queue(request_queue_t *); 
處理塊請(qǐng)求隊(duì)列的創(chuàng)建和刪除的函數(shù).


struct request *elv_next_request(request_queue_t *queue); 
void end_request(struct request *req, int success); 
elv_next_request 從一個(gè)請(qǐng)求隊(duì)列中獲得下一個(gè)請(qǐng)求; end_request 可用在每個(gè)簡(jiǎn)單驅(qū)動(dòng)器中來(lái)標(biāo)識(shí)一個(gè)(或部分)請(qǐng)求完成.


void blkdev_dequeue_request(struct request *req); 
void elv_requeue_request(request_queue_t *queue, struct request *req); 
從隊(duì)列中除去一個(gè)請(qǐng)求, 并且放回它的函數(shù)如果需要.


void blk_stop_queue(request_queue_t *queue); 
void blk_start_queue(request_queue_t *queue); 
如果你需要阻止對(duì)你的請(qǐng)求函數(shù)的進(jìn)一步調(diào)用, 調(diào)用 blk_stop_queue 來(lái)完成. 調(diào)用 blk_start_queue 來(lái)使你的請(qǐng)求方法被再次調(diào)用.


void blk_queue_bounce_limit(request_queue_t *queue, u64 dma_addr); 
void blk_queue_max_sectors(request_queue_t *queue, unsigned short max); 
void blk_queue_max_phys_segments(request_queue_t *queue, unsigned short max); 
void blk_queue_max_hw_segments(request_queue_t *queue, unsigned short max); 
void blk_queue_max_segment_size(request_queue_t *queue, unsigned int max); 
blk_queue_segment_boundary(request_queue_t *queue, unsigned long mask); 
void blk_queue_dma_alignment(request_queue_t *queue, int mask); 
void blk_queue_hardsect_size(request_queue_t *queue, unsigned short max); 
設(shè)置各種隊(duì)列參數(shù)的函數(shù), 來(lái)控制請(qǐng)求如何被創(chuàng)建給一個(gè)特殊設(shè)備; 這些參數(shù)在"隊(duì)列控制函數(shù)"一節(jié)中描述.


#include <linux/bio.h> 
struct bio; 
低級(jí)函數(shù), 表示一個(gè)塊 I/O 請(qǐng)求的一部分.


bio_sectors(struct bio *bio); 
bio_data_dir(struct bio *bio); 
2 個(gè)宏定義, 表示一個(gè)由 bio 結(jié)構(gòu)描述的傳送的大小和方向.


bio_for_each_segment(bvec, bio, segno); 
一個(gè)偽控制結(jié)構(gòu), 用來(lái)循環(huán)組成一個(gè) bio 結(jié)構(gòu)的各個(gè)段.


char *__bio_kmap_atomic(struct bio *bio, int i, enum km_type type); 
void __bio_kunmap_atomic(char *buffer, enum km_type type); 
__bio_kmap_atomic 可用來(lái)創(chuàng)建一個(gè)內(nèi)核虛擬地址給一個(gè)在 bio 結(jié)構(gòu)中的給定的段. 映射必須使用 __bio_kunmap_atomic 來(lái)恢復(fù).


struct page *bio_page(struct bio *bio); 
int bio_offset(struct bio *bio); 
int bio_cur_sectors(struct bio *bio); 
char *bio_data(struct bio *bio); 
char *bio_kmap_irq(struct bio *bio, unsigned long *flags); 
void bio_kunmap_irq(char *buffer, unsigned long *flags); 
一組存取者宏定義, 提供對(duì)一個(gè) bio 結(jié)構(gòu)中的"當(dāng)前"段的存取.


void blk_queue_ordered(request_queue_t *queue, int flag); 
int blk_barrier_rq(struct request *req); 
如果你的驅(qū)動(dòng)實(shí)現(xiàn)屏障請(qǐng)求, 調(diào)用 blk_queue_ordered -- 如同它應(yīng)當(dāng)做的. 宏 blk_barrier_rq 返回一個(gè)非零值如果當(dāng)前請(qǐng)求是一個(gè)屏障請(qǐng)求.


int blk_noretry_request(struct request *req); 
這個(gè)宏返回一個(gè)非零值, 如果給定的請(qǐng)求不應(yīng)當(dāng)在出錯(cuò)時(shí)重新嘗試.


int end_that_request_first(struct request *req, int success, int count); 
void end_that_request_last(struct request *req); 
使用 end_that_request_firest 來(lái)指示一個(gè)塊 I/O 請(qǐng)求的一部分完成. 當(dāng)那個(gè)函數(shù)返回 0, 請(qǐng)求完成并且應(yīng)當(dāng)被傳遞給 end_that_request_last.


rq_for_each_bio(bio, request) 
另一個(gè)用宏定義來(lái)實(shí)現(xiàn)的控制結(jié)構(gòu); 它步入構(gòu)成一個(gè)請(qǐng)求的每個(gè) bio.


int blk_rq_map_sg(request_queue_t *queue, struct request *req, struct scatterlist *list); 
為一次 DMA 傳送填充給定的散布表, 用需要來(lái)映射給定請(qǐng)求中的緩沖的信息


typedef int (make_request_fn) (request_queue_t *q, struct bio *bio); 
make_request 函數(shù)的原型.


void bio_endio(struct bio *bio, unsigned int bytes, int error); 
指示一個(gè)給定 bio 的完成. 這個(gè)函數(shù)應(yīng)當(dāng)只用在你的驅(qū)動(dòng)直接獲取 bio , 通過(guò) make_request 函數(shù)從塊層.


request_queue_t *blk_alloc_queue(int flags); 
void blk_queue_make_request(request_queue_t *queue, make_request_fn *func); 
使用 blk_alloc_queue 來(lái)分配由定制的 make_request 函數(shù)使用的請(qǐng)求隊(duì)列, . 那個(gè)函數(shù)應(yīng)當(dāng)使用 blk_queue_make_request 來(lái)設(shè)置.


typedef int (prep_rq_fn) (request_queue_t *queue, struct request *req); 
void blk_queue_prep_rq(request_queue_t *queue, prep_rq_fn *func); 
一個(gè)命令準(zhǔn)備函數(shù)的原型和設(shè)置函數(shù), 它可用來(lái)準(zhǔn)備必要的硬件命令, 在請(qǐng)求被傳遞給你的請(qǐng)求函數(shù)之前.


int blk_queue_init_tags(request_queue_t *queue, int depth, struct blk_queue_tag *tags); 
int blk_queue_resize_tags(request_queue_t *queue, int new_depth); 
int blk_queue_start_tag(request_queue_t *queue, struct request *req); 
void blk_queue_end_tag(request_queue_t *queue, struct request *req); 
struct request *blk_queue_find_tag(request_queue_t *qeue, int tag); 
void blk_queue_invalidate_tags(request_queue_t *queue); 
驅(qū)動(dòng)使用被標(biāo)記的命令隊(duì)列的支持函數(shù).


第 17 章 網(wǎng)絡(luò)驅(qū)動(dòng)
本節(jié)提供了本章中介紹的概念的參考. 也解釋了每個(gè)驅(qū)動(dòng)需要包含的頭文件的角色. 在 net_device 和 sk_buff 結(jié)構(gòu)中成員的列表, 但是, 這里沒有重復(fù).


#include <linux/netdevice.h> 
定義 struct net_device 和 struct net_device_stats 的頭文件, 包含了幾個(gè)其他網(wǎng)絡(luò)驅(qū)動(dòng)需要的頭文件.


struct net_device *alloc_netdev(int sizeof_priv, char *name, void (*setup)(struct net_device *); 
struct net_device *alloc_etherdev(int sizeof_priv); 
void free_netdev(struct net_device *dev); 
分配和釋放 net_device 結(jié)構(gòu)的函數(shù)


int register_netdev(struct net_device *dev); 
void unregister_netdev(struct net_device *dev); 
注冊(cè)和注銷一個(gè)網(wǎng)絡(luò)設(shè)備.


void *netdev_priv(struct net_device *dev); 
獲取網(wǎng)絡(luò)設(shè)備結(jié)構(gòu)的驅(qū)動(dòng)私有區(qū)域的指針的函數(shù).


struct net_device_stats; 
持有設(shè)備統(tǒng)計(jì)的結(jié)構(gòu).


netif_start_queue(struct net_device *dev); 
netif_stop_queue(struct net_device *dev); 
netif_wake_queue(struct net_device *dev); 
控制傳送給驅(qū)動(dòng)來(lái)發(fā)送的報(bào)文的函數(shù). 沒有報(bào)文被傳送, 直到 netif_start_queue 被調(diào)用. netif_stop_queue 掛起發(fā)送, netif_wake_queue 重啟隊(duì)列并刺探網(wǎng)絡(luò)層重啟發(fā)送報(bào)文.


skb_shinfo(struct sk_buff *skb); 
宏定義, 提供對(duì)報(bào)文緩存的"shared info"部分的存取.


void netif_rx(struct sk_buff *skb); 
調(diào)用來(lái)通知內(nèi)核一個(gè)報(bào)文已經(jīng)收到并且封裝到一個(gè) socket 緩存中的函數(shù).


void netif_rx_schedule(dev); 
來(lái)告訴內(nèi)核報(bào)文可用并且應(yīng)當(dāng)啟動(dòng)查詢接口; 它只是被 NAPI 兼容的驅(qū)動(dòng)使用.


int netif_receive_skb(struct sk_buff *skb); 
void netif_rx_complete(struct net_device *dev); 
應(yīng) 當(dāng)只被 NAPI 兼容的驅(qū)動(dòng)使用. netif_receive_skb 是對(duì)于 netif_rx 的 NAPI 對(duì)等函數(shù); 它遞交一個(gè)報(bào)文給內(nèi)核. 當(dāng)一個(gè) NAPI 兼容的驅(qū)動(dòng)已耗盡接收?qǐng)?bào)文的供應(yīng), 它應(yīng)當(dāng)重開中斷, 并且調(diào)用 netif_rx_complete 來(lái)停止查詢.


#include <linux/if.h> 
由 netdevice.h 包含, 這個(gè)文件聲明接口標(biāo)志( IFF_ 宏定義 )和 struct ifmap, 它在網(wǎng)絡(luò)驅(qū)動(dòng)的 ioctl 實(shí)現(xiàn)中有重要地位.


void netif_carrier_off(struct net_device *dev); 
void netif_carrier_on(struct net_device *dev); 
int netif_carrier_ok(struct net_device *dev); 
前 2 個(gè)函數(shù)可用來(lái)告知內(nèi)核是否接口上有載波信號(hào). netif_carrier_ok 測(cè)試載波狀態(tài), 如同在設(shè)備結(jié)構(gòu)中反映的.


#include <linux/if_ether.h> 
ETH_ALEN 
ETH_P_IP 
struct ethhdr; 
由 netdevice.h 包含, if_ether.h 定義所有的 ETH_ 宏定義, 用來(lái)代表字節(jié)長(zhǎng)度( 例如地址長(zhǎng)度 )以及網(wǎng)絡(luò)協(xié)議(例如 IP). 它也定義 ethhdr 結(jié)構(gòu).


#include <linux/skbuff.h> 
struct sk_buff 和相關(guān)結(jié)構(gòu)的定義, 以及幾個(gè)操作緩存的內(nèi)聯(lián)函數(shù). 這個(gè)頭文件由 netdevice.h 包含.


struct sk_buff *alloc_skb(unsigned int len, int priority); 
struct sk_buff *dev_alloc_skb(unsigned int len); 
void kfree_skb(struct sk_buff *skb); 
void dev_kfree_skb(struct sk_buff *skb); 
void dev_kfree_skb_irq(struct sk_buff *skb); 
void dev_kfree_skb_any(struct sk_buff *skb); 
處理 socket 緩存的分配和釋放的函數(shù). 通常驅(qū)動(dòng)應(yīng)當(dāng)使用 dev_ 變體, 其意圖就是此目的.


unsigned char *skb_put(struct sk_buff *skb, int len); 
unsigned char *__skb_put(struct sk_buff *skb, int len); 
unsigned char *skb_push(struct sk_buff *skb, int len); 
unsigned char *__skb_push(struct sk_buff *skb, int len); 
添加數(shù)據(jù)到一個(gè) skb 的函數(shù); skb_put 在 skb 的尾部放置數(shù)據(jù), 而 skb_push 放在開始. 正常版本進(jìn)行檢查以確保有足夠的空間; 雙下劃線版本不進(jìn)行檢查.


int skb_headroom(struct sk_buff *skb); 
int skb_tailroom(struct sk_buff *skb); 
void skb_reserve(struct sk_buff *skb, int len); 
進(jìn)行 skb 中的空間管理的函數(shù). skb_headroom 和 skb_tailroom 說(shuō)明在開始和結(jié)尾分別有多少空間可用. skb_reserve 可用來(lái)保留空間, 在一個(gè)必須為空的 skb 開始.


unsigned char *skb_pull(struct sk_buff *skb, int len); 
skb_pull "去除" 數(shù)據(jù)從一個(gè) skb, 通過(guò)調(diào)整內(nèi)部指針.


int skb_is_nonlinear(struct sk_buff *skb); 
如果這個(gè) skb 是為發(fā)散/匯聚 I/O 分隔為幾個(gè)片, 函數(shù)返回一個(gè)真值.


int skb_headlen(struct sk_buff *skb); 
返回 skb 的第一個(gè)片的長(zhǎng)度, 由 skb->data 指向.


void *kmap_skb_frag(skb_frag_t *frag); 
void kunmap_skb_frag(void *vaddr); 
提供對(duì)非線性 skb 中的片直接存取的函數(shù).


#include <linux/etherdevice.h> 
void ether_setup(struct net_device *dev); 
為以太網(wǎng)驅(qū)動(dòng)設(shè)置大部分方法為通用實(shí)現(xiàn)的函數(shù). 它還設(shè)置 dev->flags 和安排下一個(gè)可用的 ethx 給 dev->name, 如果名子的第一個(gè)字符是一個(gè)空格或者 NULL 字符.


unsigned short eth_type_trans(struct sk_buff *skb, struct net_device *dev); 
當(dāng)一個(gè)以太網(wǎng)接口收到一個(gè)報(bào)文, 這個(gè)函數(shù)被調(diào)用來(lái)設(shè)置 skb->pkt_type. 返回值是一個(gè)協(xié)議號(hào), 通常存儲(chǔ)于 skb->protocol.


#include <linux/sockios.h> 
SIOCDEVPRIVATE 
前 16 個(gè) ioctl 命令, 每個(gè)驅(qū)動(dòng)可為它們自己的私有用途而實(shí)現(xiàn). 所有的網(wǎng)絡(luò) ioctl 命令都在 sockios.h 中定義.


#include <linux/mii.h> 
struct mii_if_info; 
聲明和一個(gè)結(jié)構(gòu), 支持實(shí)現(xiàn) MII 標(biāo)準(zhǔn)的設(shè)備的驅(qū)動(dòng).


#include <linux/ethtool.h> 
struct ethtool_ops; 
聲明和結(jié)構(gòu), 使得設(shè)備與 ethtool 工具一起工作.


第 18 章 TTY 驅(qū)動(dòng)
本節(jié)提供了對(duì)本章介紹的概念的參考. 它還解釋了每個(gè) tty 驅(qū)動(dòng)需要包含的頭文件的角色. 在 tty_driver 和 tty_device 結(jié)構(gòu)中的成員變量的列表, 但是, 在這里不重復(fù).


#include <linux/tty_driver.h> 
頭文件, 包含 struct tty_driver 的定義和聲明一些在這個(gè)結(jié)構(gòu)中的不同的標(biāo)志.


#include <linux/tty.h> 
頭文件, 包含 tty_struct 結(jié)構(gòu)的定義和幾個(gè)不同的宏定義來(lái)易于存取 struct termios 的成員的單個(gè)值. 它還含有 tty 驅(qū)動(dòng)核心的函數(shù)聲明.


#include <linux/tty_flip.h> 
頭文件, 包含幾個(gè) tty flip 緩沖內(nèi)聯(lián)函數(shù), 使得易于操作 flip 緩沖結(jié)構(gòu).


#include <asm/termios.h> 
頭文件, 包含 struct termio 的定義, 用于內(nèi)核所建立的特定硬件平臺(tái).


struct tty_driver *alloc_tty_driver(int lines); 
函數(shù), 創(chuàng)建一個(gè) struct tty_driver, 可之后傳遞給 tty_register_driver 和 tty_unregister_driver 函數(shù).


void put_tty_driver(struct tty_driver *driver); 
函數(shù), 清理尚未成功注冊(cè)到 tty 內(nèi)核的 struct tty_driver 結(jié)構(gòu).


void tty_set_operations(struct tty_driver *driver, struct tty_operations *op); 
函數(shù), 初始化 struct tty_driver 的函數(shù)回調(diào). 有必要在 tty_register_driver 可被調(diào)用前調(diào)用.


int tty_register_driver(struct tty_driver *driver); 
int tty_unregister_driver(struct tty_driver *driver); 
函數(shù), 從 tty 核心注冊(cè)和注銷一個(gè) tty 驅(qū)動(dòng).


void tty_register_device(struct tty_driver *driver, unsigned minor, struct device *device); 
void tty_unregister_device(struct tty_driver *driver, unsigned minor); 
對(duì) tty 核心注冊(cè)和注銷一個(gè)單個(gè) tty 設(shè)備的函數(shù).


void tty_insert_flip_char(struct tty_struct *tty, unsigned char ch, char flag); 
插入字符到 tty 設(shè)備的要被用戶讀的 flip 緩沖的函數(shù).


TTY_NORMAL 
TTY_BREAK 
TTY_FRAME 
TTY_PARITY 
TTY_OVERRUN 
flag 參數(shù)的不同值, 用在 tty_insert_flip_char 函數(shù).


int tty_get_baud_rate(struct tty_struct *tty); 
函數(shù), 獲取當(dāng)前為特定 tty 設(shè)備設(shè)置的波特率.


void tty_flip_buffer_push(struct tty_struct *tty); 
函數(shù), 將當(dāng)前 flip 緩沖中的數(shù)據(jù)推給用戶.


tty_std_termios 
變量, 使用一套通用的缺省線路設(shè)置來(lái)初始化一個(gè) termios 結(jié)構(gòu).

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多