回答:
ioctl
デバイス固有のシステムコールの一種である手段「入出力制御」。Linuxのシステムコールはほんのわずか(300〜400)であり、デバイスが持つ可能性のあるすべての固有の機能を表現するには不十分です。そのため、ドライバーは、ユーザースペースアプリケーションがオーダーを送信できるようにするioctlを定義できます。ただし、ioctlはあまり柔軟ではなく、少し雑然とする傾向があります(機能する数十の「マジックナンバー」...かどうかにかかわらず)。また、カーネルにバッファを渡すと、安全性が低下する可能性があります。不適切な処理は失敗する可能性があります。物事は簡単に。
もう1つの方法は、ドライバーで情報を取得するためにsysfs
ファイルを設定して/sys/
読み取り/書き込みを行うインターフェイスです。これを設定する方法の例:
static ssize_t mydrvr_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", DRIVER_RELEASE);
}
static DEVICE_ATTR(version, S_IRUGO, mydrvr_version_show, NULL);
そして、ドライバーのセットアップ中:
device_create_file(dev, &dev_attr_version);
次に/sys/
、たとえば、/sys/block/myblk/version
ブロックドライバー用のデバイス用のファイルを作成します。
より頻繁に使用するもう1つの方法はnetlinkです。これは、BSDソケットインターフェイスを介してドライバーと通信するためのIPC(プロセス間通信)メソッドです。これは、たとえばWiFiドライバーによって使用されます。次に、libnl
またはlibnl3
ライブラリを使用して、ユーザー空間から通信します。
このioctl
関数は、デバイスに構成を設定するデバイスドライバーを実装するのに役立ちます。たとえば、フォントファミリ、フォントサイズなどをチェックおよび設定する設定オプションを持つプリンタをioctl
使用して、現在のフォントを取得するだけでなく、フォントを新しいフォントに設定することもできます。ユーザーアプリケーションはioctl
、コードをプリンターに送信して、現在のフォントを返すように、またはフォントを新しいフォントに設定するように指示するために使用します。
int ioctl(int fd, int request, ...)
fd
によって返されるファイル記述子open
です。request
リクエストコードです。たとえばGETFONT
、プリンターから現在のフォントを取得し、プリンターにSETFONT
フォントを設定します。void *
です。2番目の引数に応じて、3番目が存在する場合と存在しない場合があります。たとえば、2番目の引数がのSETFONT
場合、3番目の引数はのようなフォント名になり"Arial"
ます。int request
単なるマクロではありません。ユーザーアプリケーションは、要求コードとデバイスドライバーモジュールを生成して、デバイスのどの構成で操作する必要があるかを決定する必要があります。アプリケーションはを使用して要求コードを送信ioctl
し、デバイスドライバーモジュールの要求コードを使用して、実行するアクションを決定します。
要求コードには4つの主要部分があります
1. A Magic number - 8 bits
2. A sequence number - 8 bits
3. Argument type (typically 14 bits), if any.
4. Direction of data transfer (2 bits).
要求コードがSETFONT
プリンターにフォントを設定することである場合、データ転送の方向はユーザーアプリケーションからデバイスドライバーモジュールへです(ユーザーアプリケーションはフォント名"Arial"
をプリンターに送信します)。要求コードがの場合GETFONT
、方向はプリンターからユーザーアプリケーションへです。
リクエストコードを生成するために、Linuxはいくつかの事前定義された関数のようなマクロを提供しています。
1. _IO(MAGIC, SEQ_NO)
どちらも0〜255の8ビットです。たとえば、プリンタを一時停止したいとします。これはデータ転送を必要としません。したがって、以下のようにリクエストコードを生成します
#define PRIN_MAGIC 'P'
#define NUM 0
#define PAUSE_PRIN __IO(PRIN_MAGIC, NUM)
そして今使用ioctl
する
ret_val = ioctl(fd, PAUSE_PRIN);
ドライバモジュール内の対応するシステムコールがコードを受け取り、プリンタを一時停止します。
__IOW(MAGIC, SEQ_NO, TYPE)
MAGIC
そしてSEQ_NO
上記と同じであり、TYPE
次の引数の型を与え、第三引数を思い出すioctl
ですvoid *
。W in __IOW
は、データフローがユーザーアプリケーションからドライバーモジュールへのものであることを示します。例として、プリンターのフォントをに設定するとし"Arial"
ます。#define PRIN_MAGIC 'S'
#define SEQ_NO 1
#define SETFONT __IOW(PRIN_MAGIC, SEQ_NO, unsigned long)
さらに、
char *font = "Arial";
ret_val = ioctl(fd, SETFONT, font);
これfont
はポインタです。つまり、それはとして最もよく表されるアドレスであることを意味しますunsigned long
。したがって、_IOW
言及の3番目の部分はそのようなものです。また、このフォントのアドレスは、デバイスドライバーモジュールに実装されている対応するシステムコールに渡されるため、unsigned long
使用する前に適切なタイプにキャストする必要があります。カーネル空間はユーザー空間にアクセスできるため、これは機能します。他の二つの関数のようなマクロがある__IOR(MAGIC, SEQ_NO, TYPE)
と__IORW(MAGIC, SEQ_NO, TYPE)
どこのデータフローは、それぞれカーネル空間からユーザ空間との両方の方法になります。
これが役立つかどうか私に知らせてください!