3/10/2011

淺談 ioctl 命令

最近因為某人開始實際碰driver, 每天照三餐靠北我.....

他拿出我二年前在某家公司寫的一份文件, 質疑了一些東西

本來呢, 我想重新整理一遍, 順便導正之前錯誤的觀念重寫一份貼上來

但....似乎想改的地方變動不大只好當作沒看見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

1 comment:

  1. 我是路人:
    能不能解釋這一段
    #define DICKY_CMD_MAGIC_NUMBER 0xdf
    #define DICKY_CMD _lOW(DICKY_CMD_MAGIC,1,unsigned int)
    ^^^^^^^^^^^^^^^^^
    DICKY_CMD_MAGIC是從哪來的?

    ReplyDelete