2016年2月22日月曜日

【Linux】 ioctl()っていったいなんなの?

Linux module(デバイスドライバ)についての前回の続きみたいなもんです.

moduleというと、open,close,read,writeは定番ですが、これらはストレージのようなブロックデバイスのアクセスには便利だけど、IOポートのような単発アクセスにはあまり向いてない.そこで存在するのがioctl()という関数であるらしい.

ユーザープログラムからioctl()をcallするときに、このような意味不明な引数を与えます.
 ioctl( fd, _IOR('U', 20, 7), buf );
fdはopenした時に得たファイルディスクリプタなので理解できる.bufはデータの入れ物だろう.だがしかし、_IOR(...)って何ですかと.'U'って何ですかと.一体何をやりたいのと.

_IORはこのようにマクロ定義されています.(ioctl.h)
 #define _IOR(type,num,size)    _IOC(_IOC_READ,type,num,_IOC_TYPECHECK(size))
さらに_IOCというのが出てきちゃいましたがまとめると、type,num,sizeという3つの引数を、下記のように32bitにアサインしているみたいです.
 33222222 22221111 11111100 00000000
 10987654 32109876 54321098 76543210
 **  direction[1:0]
   ****** ********   size[13:0]
                   ********  type[7:0]
                            ********  num[7:0]
4つの数の意味はこうなってます.
 ・direction  READ/WRITE
 ・size       バイト数
 ・type     用途を示すマジックナンバー  http://goo.gl/omKtYa
 ・num     コマンドかなぁ
typeはmodule識別子のようです.リンク先には様々なmoduleがアサインされています.module自作の際には重複を避けるべきだそうです.(fdでmoduleを指定するのでtypeの重要さは低いように思うんだがどうだろ)

つまり、ioctl()の引数は事実上はこのようにたくさんあるのです.
 ioctl( fd, direction, size, type, num, buf );
だったら最初からこうしとけばいいのにと思います.なお練習用プログラムでは_IORに従わない例もあります.

第2引数の_IORは以上のようにbitアサインしているわけですが、direction, size, type, num, bufをどう処理するのかは専らmodule次第であって、統一された処理法は存在しないようです.
moduleのソースコードには、このような定義が山のように記述されていて、switch-case文でブリブリと分岐させて各種処理を行っているのが見られます.
 #define  BNEPGETCONNLIST  _IOR('B', 210, int )
 #define  BNEPGETCONNINFO  _IOR('B', 211, int )
 #define  CMTPGETCONNLIST  _IOR('C', 210, int )
 #define  CMTPGETCONNINFO  _IOR('C', 211, int )

かしこ


人気ブÍグランキングへ

0 件のコメント:

コメントを投稿