GNU/Linux >> Belajar Linux >  >> Linux

Pengandar perangkat IOCTL Linux

ioctl Fungsi ini berguna untuk mengimplementasikan driver perangkat untuk mengatur konfigurasi pada perangkat. misalnya printer yang memiliki opsi konfigurasi untuk memeriksa dan mengatur jenis font, ukuran font, dll. ioctl dapat digunakan untuk mendapatkan font saat ini serta mengatur font ke yang baru. Aplikasi pengguna menggunakan ioctl untuk mengirim kode ke printer yang memberitahukannya untuk mengembalikan font saat ini atau menyetel font ke yang baru.

int ioctl(int fd, int request, ...)
  1. fd adalah deskriptor file, yang dikembalikan oleh open;
  2. request adalah kode permintaan. misalnya GETFONT akan mendapatkan font saat ini dari printer, SETFONT akan mengatur font pada printer;
  3. argumen ketiga adalah void * . Bergantung pada argumen kedua, yang ketiga mungkin ada atau tidak ada, mis. jika argumen kedua adalah SETFONT , argumen ketiga bisa berupa nama font seperti "Arial";

int request bukan hanya makro. Aplikasi pengguna diperlukan untuk menghasilkan kode permintaan dan modul driver perangkat untuk menentukan konfigurasi perangkat mana yang harus dimainkan. Aplikasi mengirimkan kode permintaan menggunakan ioctl lalu gunakan kode permintaan di modul driver perangkat untuk menentukan tindakan mana yang harus dilakukan.

Kode permintaan memiliki 4 bagian utama

    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).  

Jika kode permintaan adalah SETFONT untuk mengatur font pada printer, arah transfer data akan dari aplikasi pengguna ke modul driver perangkat (Aplikasi pengguna mengirimkan nama font "Arial" ke printer). Jika kode permintaan adalah GETFONT , arah dari printer ke aplikasi pengguna.

Untuk menghasilkan kode permintaan, Linux menyediakan beberapa makro seperti fungsi yang telah ditentukan sebelumnya.

1._IO(MAGIC, SEQ_NO) keduanya 8 bit, 0 hingga 255, mis. katakanlah kita ingin menjeda printer. Ini tidak memerlukan transfer data. Jadi kami akan membuat kode permintaan seperti di bawah ini

#define PRIN_MAGIC 'P'
#define NUM 0
#define PAUSE_PRIN __IO(PRIN_MAGIC, NUM) 

dan sekarang gunakan ioctl sebagai

ret_val = ioctl(fd, PAUSE_PRIN);

Panggilan sistem yang sesuai dalam modul driver akan menerima kode dan menjeda printer.

  1. __IOW(MAGIC, SEQ_NO, TYPE) MAGIC dan SEQ_NO sama seperti di atas, dan TYPE berikan jenis argumen berikutnya, ingat argumen ketiga ioctl adalah void * . W di __IOW menunjukkan bahwa aliran data dari aplikasi pengguna ke modul driver. Sebagai contoh, misalkan kita ingin menyetel font printer ke "Arial" .
#define PRIN_MAGIC 'S'
#define SEQ_NO 1
#define SETFONT __IOW(PRIN_MAGIC, SEQ_NO, unsigned long)

selanjutnya,

char *font = "Arial";
ret_val = ioctl(fd, SETFONT, font); 

Sekarang font adalah sebuah pointer, yang berarti ini adalah sebuah alamat yang paling baik direpresentasikan sebagai unsigned long , maka bagian ketiga dari _IOW menyebutkan jenis seperti itu. Selain itu, alamat font ini diteruskan ke panggilan sistem terkait yang diimplementasikan dalam modul driver perangkat sebagai unsigned long dan kita perlu mentransmisikannya ke tipe yang tepat sebelum menggunakannya. Ruang kernel dapat mengakses ruang pengguna dan karenanya ini berfungsi. dua makro mirip fungsi lainnya adalah __IOR(MAGIC, SEQ_NO, TYPE) dan __IORW(MAGIC, SEQ_NO, TYPE) di mana aliran data akan dari ruang kernel ke ruang pengguna dan keduanya masing-masing.

Harap beri tahu saya jika ini membantu!


Sebuah ioctl , yang berarti "kontrol input-output" adalah semacam panggilan sistem khusus perangkat. Hanya ada beberapa panggilan sistem di Linux (300-400), yang tidak cukup untuk mengekspresikan semua fungsi unik yang mungkin dimiliki perangkat. Jadi seorang pengemudi dapat menentukan ioctl yang memungkinkan aplikasi userspace untuk mengirimkan pesanannya. Namun, ioctl tidak terlalu fleksibel dan cenderung sedikit berantakan (lusinan "angka ajaib" yang hanya berfungsi ... atau tidak), dan juga bisa tidak aman, saat Anda memasukkan buffer ke dalam kernel - penanganan yang buruk dapat merusak hal-hal dengan mudah.

Alternatifnya adalah sysfs antarmuka, tempat Anda menyiapkan file di bawah /sys/ dan baca/tulis itu untuk mendapatkan informasi dari dan ke pengemudi. Contoh cara menyiapkan ini:

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);

Dan selama penyiapan driver:

device_create_file(dev, &dev_attr_version);

Anda kemudian akan memiliki file untuk perangkat Anda di /sys/ , misalnya, /sys/block/myblk/version untuk driver blok.

Metode lain untuk penggunaan yang lebih berat adalah netlink, yang merupakan metode IPC (inter-process communication) untuk berbicara dengan driver Anda melalui antarmuka soket BSD. Ini digunakan, misalnya, oleh driver WiFi. Anda kemudian berkomunikasi dengannya dari ruang pengguna menggunakan libnl atau libnl3 perpustakaan.


Linux
  1. Linux:Bagaimana Menemukan Driver Perangkat yang Digunakan Untuk Perangkat?

  2. Linux – Bagaimana Kernel Linux Mengetahui Nomor Mayor dan Minor Perangkat?

  3. Mengapa metode probe diperlukan di driver perangkat Linux selain init?

  1. Cara menginstal driver perangkat di Linux

  2. Bagaimana cara memasang perangkat di Linux?

  3. setserial:Tidak bisa mendapatkan info serial:ioctl tidak sesuai untuk perangkat

  1. Linux – Dimaksudkan Dengan Memasang Perangkat Di Linux?

  2. Linux – Sysfs dan Devtmpfs?

  3. Linux – Bagaimana Cara Menemukan Driver (modul) yang Berhubungan Dengan Perangkat Di Linux?