GNU/Linux >> Linux の 問題 >  >> Linux

IOCTL Linux デバイス ドライバー

ioctl この関数は、デバイス ドライバーを実装してデバイスの構成を設定するのに役立ちます。例えばフォント ファミリ、フォント サイズなどを確認および設定するための構成オプションを備えたプリンター ioctl 現在のフォントを取得したり、フォントを新しいフォントに設定したりするために使用できます。ユーザー アプリケーションは ioctl を使用します 現在のフォントを返すか、フォントを新しいフォントに設定するように指示するコードをプリンターに送信します。

int ioctl(int fd, int request, ...)
<オール>
  • fd open によって返されるファイル記述子です。;
  • request リクエストコードです。例:GETFONT プリンターから現在のフォントを取得します SETFONT プリンターのフォントを設定します。
  • 3 番目の引数は 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);
    

    ドライバー モジュール内の対応するシステム コールがコードを受け取り、プリンターを一時停止します。

    1. __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


    Linux
    1. Linux – Linuxにデバイスをマウントすることを意味しますか?

    2. Linux:デバイスに使用されているデバイスドライバーを見つける方法は?

    3. Ubuntu13.04上のHuaweiLinuxドライバー?

    1. Linux で仮想ブロック デバイス (ループ デバイス/ファイルシステム) を作成する方法

    2. デバイスからユーザー空間メモリーへの DMA への Linux カーネル デバイス ドライバー

    3. Linux lsblk 出力

    1. Linux でデバイスをマウントするには?

    2. setserial:シリアル情報を取得できません:デバイスの ioctl が不適切です

    3. 一貫した Linux デバイスの列挙