誰も私を説明できますか、
IOCTL
とは何ですか?IOCTL
と同じ動作をする新しい関数を定義できないのはなぜですか?__input_output_controlがデバイス固有のシステムコールの一種であることを意味する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
)。
より重く使用する別の方法は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)
は両方とも8ビット、0〜255です。プリンターを一時停止したいとします。これにはデータ転送は必要ありません。以下のようにリクエストコードを生成します
#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 *
であることを思い出してください。 __IOW
のWは、データフローがユーザーアプリケーションからドライバーモジュールへのものであることを示します。例として、プリンターフォントを"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)
で、データフローはそれぞれカーネル空間からユーザー空間へ、そしてその両方の方向になります。
これが役立つかどうか教えてください!