by:
潘雲登
對於商業目的下對本文的任何行為需經作者同意。
寫在前面
1.本文內容對應《
linux
裝置驅動程式》第六章。 2.
參考俞永昌的《裝置驅動開發技術及應用》,以及
documentation/ioctl-number.txt
和include/asm/ioctl.h
兩個檔案。 3.
裝置控制
ioctl
對於那種不傳送資料而只響應命令的裝置,如機械人
j,可以通過向裝置寫入控制序列進行控制。然而,對於具備讀寫操作的裝置,通過列印序列進行控制將給裝置增加策略限制。更好的裝置控制方式是
ioctl
方法。在使用者空間,
ioctl
系統呼叫具有如下原型:
int ioctl(int fd, unsigned long cmd, char *argp);
控制命令
cmd由使用者空間不加修改地傳遞到驅動程式的
ioctl
方法。argp
為可選引數,它可以是乙個整型引數或者是乙個指標引數,具體形式依賴於要完成的控制命令
cmd。使用指標可以向
ioctl
呼叫傳遞任意資料,從而與使用者空間交換任意數量的資料。不論
argp
是何種型別,它都以
unsigned long
的形式傳遞給驅動程式。然後,由驅動程式根據具體情況進行型別轉換,如轉換為整型指標(
int __user *
)arg
,__user
表明指標是乙個使用者空間位址,不能直接引用。驅動程式的
ioctl
方法原型如下:
int (*ioctl) (struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
其返回值,也是系統呼叫的返回值,可以向使用者空間提供裝置資訊。負的返回值被認為是乙個錯誤,通常為
-enotty (
不合適的裝置
ioctl)
或-einval (
非法引數
),被用來設定使用者空間的
errno
變數。
控制命令
高位低位 2
位 14位
8位 8位
direction
size
number
type
øtype
:幻數,可以在
documentation/ioctl-number.txt
中選擇乙個未使用的號碼。如果整個控制命令能夠被核心識別,將無法到達驅動程式。 ø
number
:序數,一般從
0開始順序編號。 ø
size
:使用者資料大小,用於檢查引數型別的大小,如
sizeof(int) < (1 << size)。
ødirection
:資料傳輸方向,可以使用的值包括
_ioc_none (
無資料傳輸),
_ioc_read (
從裝置中讀資料),
_ioc_write (
向裝置寫資料
),以及
_ioc_read|_ioc_write (
雙向資料傳輸)。
中包含的
標頭檔案定義了一些構造命令編號的巨集:
_io(type,nr)
_ior(type,nr,datatype)
_iow(type,nr,datatype)
_iowr(type,nr,datatype)
以及用於解開位字段的巨集:
_ioc_type(nr)
_ioc_nr(nr)
_ioc_size(nr)
_ioc_dir(nr)
大多數ioctl
的實現中都包含了乙個
switch
語句來根據控制命令選擇對應的操作。
ioctl
工作模型
scull
中的幾處檢查
ø控制命令檢查
檢查裝置幻數和命令序數。
if (_ioc_type(cmd) != scull_ioc_magic) return -enotty;
if (_ioc_nr(cmd) > scull_ioc_maxnr) return -enotty;
ø使用者位址空間檢查
當用乙個指標指向使用者空間時,必須確保指向的使用者空間是合法的,這通過
access_ok
函式完成。通常不需要真正呼叫
access_ok
,因為資料交換函式
copy_to_user, copy_from_user, put_user, get_user
會處理它。
int access_ok(int type, const void *addr, unsigned long size);
/*scull*/
if (_ioc_dir(cmd) & _ioc_read)
err = !access_ok(verify_write, (void __user *)arg, _ioc_size(cmd));
else if (_ioc_dir(cmd) & _ioc_write)
err =!access_ok(verify_read, (void __user *)arg, _ioc_size(cmd));
if (err) return -efault;
ø權能檢查
對裝置的讀寫訪問由裝置檔案的許可權控制,驅動程式通常不進行許可權檢查。然而,當使用者試圖修改裝置引數時,裝置驅動程式應該檢查呼叫程序是否有合適的權能,這通過
capable
函式完成。
int capable(int capability);
/*scull*/
if (! capable (cap_sys_admin))
return -eperm;
裝置驅動程式學習筆記 6 裝置訪問控制
by 潘雲登 對於商業目的下對本文的任何行為需經作者同意。寫在前面 1.本文內容對應 linux 裝置驅動程式 第六章。2.修改scull load 指令碼中的 mode 為 666 使普通使用者具有裝置讀寫許可權。3.希望本文對您有所幫助,也歡迎您給我提意見和建議。這裡描述的裝置訪問控制是在檔案系...
筆記 裝置驅動程式
驅動程式一般指的是裝置驅動程式 device driver 是一種可以使 計算機和裝置通訊的特殊程式。相當於 硬體的介面,作業系統只有通過這個介面,才能控制 硬體裝置的工作,假如某裝置的驅動程式未能正確安裝,便不能正常工作。因此,驅動程式被比作 硬體的靈魂 硬體的主宰 和 硬體和系統之間的橋梁 等。...
linux裝置驅動程式 字元裝置驅動程式
先留個 有一起學習驅動程式的加qq295699450 字元裝置驅動 這篇比較惱火。載入成功,但是讀不出來資料,有知道怎麼回事的,留個言,一起討論下 資料結構 struct scull mem struct scull dev dev 整個驅動程式 如下 include include include...