他拿出我二年前在某家公司寫的一份文件, 質疑了一些東西
本來呢, 我想重新整理一遍, 順便導正之前錯誤的觀念重寫一份貼上來
但....似乎想改的地方變動不大只好當作沒看見0.0
其實也只是教如何寫出在Linux虛擬出一個Driver, 仔細研究LDD3這本書就可以應付了.
剛巧他問了ioctl和magic number的問題, 我也在這稍微對這個ioctl分享自己的想法.
=======================
一般除了使用ioctl來搭建與kernel space橋樑之外, 常見的還有信號量(singel)和socket
談ioctl之前, 有一份kernel文件請一定要看, 通常它的路徑都會在 :
Kernel/Documentation/ioctl/ioctl-number.txt
其實kernel文件有很多寶,像是Kbuild.txt,devices.txt等等,滿多相關知識從那汲取的,值得一讀.
關係及使用到ioctl的頭文件, 它的路徑是在 :
Kernel/include/asm-generic/ioctl.h
其中有一個很重要的定義, 這個定義確保了每個命令都是唯一的"算法" :
#define _IOC(dir,type,nr,size) \
(((dir) << _IOC_DIRSHIFT) | \
((type) << _IOC_TYPESHIFT) | \
((nr) << _IOC_NRSHIFT) | \
((size) << _IOC_SIZESHIFT))
怎麼說是算法呢 ? 因為IOC這個定義, 它把dir, type, nr, size 劃分成4個段
每段都有它自己的意義存在, 但從看上面到, 確保每個命令是系統唯一, 主要是靠type和nr
怎說呢 ? 且看下面.
在頭文件一開始的地方, 定義各個參數的資料段, 可以參考下圖 :
接著看頭文件它描述_IO等行為 :
#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
其中dir代表如下 :
# define _IOC_NONE 0U
# define _IOC_WRITE 1U
# define _IOC_READ 2U
不管是dir或size, 每個使用者都有可能傳相同的方向和大小的"值".
關於type和nr的解釋, 參考LDD3的說明 :
type
The magic number. Just choose one number (after consulting ioctl-number.txt)
and use it throughout the driver. This field is eight bits wide (_IOC_TYPEBITS).
type, LDD3稱它為魔數, 也說明此魔數可以從loctl-number.txt挑選, 佔用1byte
number
The ordinal (sequential) number. It's eight bits (_IOC_NRBITS) wide.
即序號, 也可以是命令的編號, 一般我們定義從0開始, 總共可以定義255個cmd.
簡單來說, type 加 第一個nr 對應 "唯一"一個CMD
舉個例子來說, 假設我定義了一個DICKY_CMD :
#define DICKY_CMD_MAGIC_NUMBER 0xdf
#define DICKY_CMD _lOW(DICKY_CMD_MAGIC,1,unsigned int)
整個展開就會變成這樣 :
01(dir seg) , 1101 1111(Magic seg) , 0000 0000(Nr seg), ... (size就不寫了 ...)
這些就是ioctl的命令碼, 正確的說, 此命令碼, 代表是DICKY_CMD的身份, 系統才會做相對應的事.
========================
那個圖似乎有錯 ?? 與頭文件定義的順序不同....size和tyep相反了....
另, file_operations的ioctl要準備消失囉 !!
不過不會那麼快.....一樣還是會保留....就跟舊的register_char_device一樣, 都會存在
但可以的話, 還是用新的方式比較好 ! (不過我還沒看...哭了)
Kill ioctl.file_opreations
我是路人:
ReplyDelete能不能解釋這一段
#define DICKY_CMD_MAGIC_NUMBER 0xdf
#define DICKY_CMD _lOW(DICKY_CMD_MAGIC,1,unsigned int)
^^^^^^^^^^^^^^^^^
DICKY_CMD_MAGIC是從哪來的?