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, ...)
fd
adalah deskriptor file, yang dikembalikan olehopen
;request
adalah kode permintaan. misalnyaGETFONT
akan mendapatkan font saat ini dari printer,SETFONT
akan mengatur font pada printer;- argumen ketiga adalah
void *
. Bergantung pada argumen kedua, yang ketiga mungkin ada atau tidak ada, mis. jika argumen kedua adalahSETFONT
, 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.
__IOW(MAGIC, SEQ_NO, TYPE)
MAGIC
danSEQ_NO
sama seperti di atas, danTYPE
berikan jenis argumen berikutnya, ingat argumen ketigaioctl
adalahvoid *
. 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.