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
の 3 番目の引数を思い出してください。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
として渡されます。 使用する前に適切な型にキャストする必要があります。カーネル空間はユーザー空間にアクセスできるため、これは機能します。他の 2 つの関数のようなマクロは __IOR(MAGIC, SEQ_NO, TYPE)
です と __IORW(MAGIC, SEQ_NO, TYPE)
ここで、データ フローはカーネル空間からユーザー空間へ、そしてそれぞれ双方向になります。
これが役に立ったら教えてください!
ioctl
、これは「入出力制御」がデバイス固有のシステムコールの一種であることを意味します。 Linux にはわずかなシステム コール (300 ~ 400) しかなく、デバイスが持つ固有の機能をすべて表現するには不十分です。したがって、ドライバーは、ユーザー空間アプリケーションが注文を送信できるようにする ioctl を定義できます。ただし、ioctl はあまり柔軟ではなく、少し雑然とする傾向があり (何十もの "マジック ナンバー" が動作するかどうかに関係なく)、カーネルにバッファーを渡すと安全性が低下する可能性もあります。
代替手段は 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