LDD3讀書筆記(第11章 高階字元驅動程式操作)

2021-06-09 04:42:53 字數 3945 閱讀 5474

本章的目的是讓讀者知道:

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 從裝置編號中抽取...