Driver perangkat IOCTL Linux [ditutup]

126

Adakah yang bisa menjelaskan saya,

  1. Apa IOCTL?
  2. Untuk apa ini digunakan?
  3. Bagaimana saya bisa menggunakannya?
  4. Mengapa saya tidak bisa mendefinisikan fungsi baru yang berfungsi sama IOCTL?
flashdisk
sumber

Jawaban:

99

An ioctl, yang berarti "kontrol input-output" adalah sejenis 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 driver dapat mendefinisikan ioctl yang memungkinkan aplikasi userspace mengirim pesanan. Namun, ioctl tidak terlalu fleksibel dan cenderung menjadi sedikit berantakan (lusinan "angka ajaib" yang hanya berfungsi ... atau tidak), dan juga tidak aman, saat Anda mengirimkan buffer ke kernel - penanganan yang buruk dapat merusak hal-hal dengan mudah.

Alternatifnya adalah sysfsantarmuka, tempat Anda mengatur file di bawah /sys/dan membaca / menulis itu untuk mendapatkan informasi dari dan ke driver. Contoh cara mengatur 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 pengaturan driver:

device_create_file(dev, &dev_attr_version);

Anda kemudian akan memiliki file untuk perangkat Anda /sys/, misalnya, /sys/block/myblk/versionuntuk driver blokir.

Metode lain untuk penggunaan yang lebih berat adalah netlink, yang merupakan metode IPC (komunikasi antar proses) untuk berbicara dengan driver Anda melalui antarmuka soket BSD. Ini digunakan, misalnya, oleh driver WiFi. Anda kemudian berkomunikasi dengannya dari userspace menggunakan libnlatau libnl3perpustakaan.

Inductiveload
sumber
3
Jawaban ini 'menjawab' sebagian pertanyaan.
Vishal Sahu
163

The ioctlFungsi ini berguna untuk menerapkan driver perangkat untuk mengatur konfigurasi pada perangkat. mis. printer yang memiliki opsi konfigurasi untuk memeriksa dan mengatur kelompok font, ukuran font, dll. ioctldapat digunakan untuk mendapatkan font yang sekarang serta mengatur font ke font yang baru. Aplikasi pengguna digunakan ioctluntuk mengirim kode ke printer yang memberitahukannya untuk mengembalikan font saat ini atau untuk mengatur font ke yang baru.

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

int requestbukan hanya makro. Aplikasi pengguna diperlukan untuk membuat kode permintaan dan modul driver perangkat untuk menentukan konfigurasi mana pada perangkat yang harus dimainkan. Aplikasi mengirimkan kode permintaan menggunakan ioctldan kemudian menggunakan kode permintaan dalam modul driver perangkat untuk menentukan tindakan 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 SETFONTmengatur font pada printer, arah untuk transfer data akan dari aplikasi pengguna ke modul driver perangkat (Aplikasi pengguna mengirimkan nama font "Arial"ke printer). Jika kode permintaannya GETFONT, arahnya dari printer ke aplikasi pengguna.

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

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

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

dan sekarang gunakan ioctlsebagai

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) MAGICdan SEQ_NOsama seperti di atas, dan TYPEmemberikan jenis argumen berikutnya, ingat argumen ketiga ioctladalah void *. W in __IOWmenunjukkan bahwa aliran data dari aplikasi pengguna ke modul driver. Sebagai contoh, misalkan kita ingin mengatur font printer "Arial".
#define PRIN_MAGIC 'S'
#define SEQ_NO 1
#define SETFONT __IOW(PRIN_MAGIC, SEQ_NO, unsigned long)

lebih lanjut,

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

Sekarang fontadalah sebuah pointer, yang berarti itu adalah alamat yang direpresentasikan dengan sebaik-baiknya unsigned long, maka bagian ketiga dari _IOWtipe tersebut disebut demikian. Juga, alamat font ini diteruskan ke panggilan sistem yang sesuai yang diimplementasikan dalam modul driver perangkat unsigned long dan kita perlu mengubahnya ke jenis yang tepat sebelum menggunakannya. Ruang kernel dapat mengakses ruang pengguna dan karenanya ini berfungsi. dua makro seperti fungsi lainnya adalah __IOR(MAGIC, SEQ_NO, TYPE)dan di __IORW(MAGIC, SEQ_NO, TYPE)mana aliran data akan dari ruang kernel ke ruang pengguna dan keduanya secara berurutan.

Tolong beri tahu saya jika ini membantu!

anukalp
sumber
Saya ingin tahu apakah fungsi __IOW, __IOR dan __IORW di atas benar (maksud saya, garis bawah dua kali lipat dalam beberapa kasus, dalam beberapa kasus tidak. Saya tidak pernah menggunakan garis bawah ganda) ... Terima kasih atas penjelasan yang jelas!
jcoppens
Dijelaskan dengan sangat baik .. Terima kasih! Bisakah Anda memberikan potongan kode kecil dari sisi driver yang menggunakan ioctl ini?
Aadishri
Sangat dijelaskan. Terima kasih. Saya pikir itu adalah _IOWR bukan _IORW
Mohamed Samy
Jawab seperti posting blog.
Fredrick Gauss