本章的目的是讓讀者知道:
1.核心與使用者空間同步
2.如何使程序休眠(並喚醒)
3.如何實現非阻塞i/o
4.裝置可讀取或寫入時如何通知使用者空間
#include
這個標頭檔案宣告了用於定義ioctl命令的所有的巨集。它現在包含在中。
_ioc_nrbits
_ioc_typebits
_ioc_sizebits
_ioc_dirbits
ioctl命令的不同位字段的可用位數。還有四個巨集定義了不同的mask(掩碼),另外四個巨集定義了不同的shift(偏移),但它們基本上僅在內部使用。由於_ioc_sizebits在不同體系架構上的值不同,因此需要重點關注。
_ioc_none
_ioc_read
_ioc_write
「方向」位字段的可能值。「讀」和「寫」是不同的位,可以「or」在一起來指定讀/寫。這些值都是基於0的。
_ioc(dir,type,nr,size)
_io(type,nr)
_ioc(type,nr,size)
_iow(type,nr,size)
_iowr(type,nr,size)
用於生成ioctl命令的巨集。
_ioc_dir(nr)
_ioc_type(nr)
_ioc_nr(nr)
_ioc_size(nr)
用於解碼ioctl命令的巨集。特別地,_ioc_type(nr)是_ioc_read和_ioc_write進行「or」的結果。
#include
int access_ok(int type,const void *addr,unsigned long size);
這個函式驗證指向使用者空間的指標是否可用。如果允許訪問,access_ok返回非零值。
verify_read
verify_write
在access_ok中type引數可取的值。verify_write是verify_read的超集。
#include
int put_user(datum,ptr);
int get_user(local,ptr);
int __put_user(datum,ptr);
int __get_user(local,ptr);
用於向(或從)使用者空間儲存(或獲取)單個資料項的巨集。傳遞的位元組數目由sizeof(*ptr)決定。前兩個要先呼叫access_ok,後兩個(__put_user和__get_user)則假設access_ok已經被呼叫過了。
#include
定義有各種cap_符號,用於描述使用者空間程序可能擁有的權能操作。
int capable(int capability);
如果程序具有指定的權能,返回非零值。
#include
typedef struct wait_queue_head_t;
void init_waitqueue_head(wait_queue_head_t *queue);
declare_wait_queue_head(queue);
預先定義的linux等待佇列型別。wait_queue_head_t型別必須顯式地初始化,初始化方法可在執行時用init_waitqueue_head,或在編譯時用declare_wait_queue_head。
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);
使程序在指定的佇列上休眠,直到給定的condition值為真。
void wake_up(struct wait_queue **q);
void wakr_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);
這些函式喚醒休眠在佇列q上的程序。_interruptible形式的函式只能喚醒可中斷的程序。通常,只會喚醒乙個獨佔等待程序,但其行為通過_nr或_all形式改變。_sync版本的喚醒函式在返回前不會重新排程cpu。
#include
set_current_state(int state);
設定當前程序的執行狀態。task_running表示準備執行,而休眠狀態是task_interruptible和task_uninterruptible。
void schedule(void);
從執行佇列中選擇乙個可執行程序,選定的程序可以是current或另乙個不同的程序。
typedef struct wait_queue_t;
init_waitqueue_entry(wait_queue_t *entry,struct task_strcut *task);
wait_queue_t型別用來將某個程序放置到乙個等待佇列上。
void prepare_to_wait(wait_queue_head_t *queue,wait_queue_t *wait,int state);
void prepare_to_wait_exclisive(wait_queue_head_t *queue,wait_queue_t *wait,int state);
void finish_wait(wait_queue_head_t *queue,wait_queue_t *wait);
可用於手工休眠**的輔助函式。
void sleep_on(wait_queue_head_t *queue);
void interruptible_sleep_on(wait_queue_head_t *queue);
已廢棄的兩個函式,它們將當前程序無條件地置於休眠狀態。
#include
void poll_wait(struct file *filp,wait_queue_head_t *q,pool_table *p);
將當前程序置於某個等待佇列但並不立即排程。該函式主要用於裝置驅動程式的poll方法。
int fasync_helper(struct inode *inode,struct file *filp,int mode,struct fasync_struct **fa);
用來實現fasync裝置方法的輔助函式。mode引數取傳入該方法的同一值,而fa指向裝置專有的fasync_struct *。
void kill_fasync(struct fasync_struct *fa,int sig,int band);
如果驅動程式支援非同步通知,則這個函式可以用來傳送乙個訊號給註冊在fa中的程序。
int nonseekable_open(struct inode *inode,struct file *filp);
loff_t no_llseek(struct file *file,loff_t offset,int whence);
任何不支援定位的裝置都應該在其open方法中呼叫nonseekable_open。這類裝置還應該在其llseek方法中使用no_llseek。
LDD3讀書筆記(第3章 字元驅動)
include dev t dev t 是用來在核心裡代表裝置號的型別.int major dev t dev int minor dev t dev 從裝置編號中抽取主次編號的巨集.dev t mkdev unsigned int major,unsigned int minor 從主次編號來建立...
LDD3讀書筆記(第5章 記憶體分配)
include void kmalloc size t size,int flags 記憶體分配函式 後備快取記憶體 include kmem cache t kmem cache create const char name,size t size,size t offset,unsigned l...
LDD3 讀書筆記 之 第 3 章 字元驅動
本章介紹了下面符號和標頭檔案.struct file operations 和 struct file 中的成員的列表這裡不重複了.include dev t dev t 是用來在核心裡代表裝置號的型別.int major dev t dev int minor dev t dev 從裝置編號中抽取...