IOCTL Linux aygıt sürücüsü [kapalı]


126

Biri bana açıklayabilir mi

  1. Nedir IOCTL?
  2. Ne için kullanılır?
  3. Nasıl kullanabilirim?
  4. Neden aynı işi yapan yeni işlevi tanımlayamıyorum IOCTL?

Yanıtlar:


99

Bir ioctlcihaza özel sistem çağrısı bir tür olan araçları "giriş-çıkış kontrol",. Linux'ta (300-400) yalnızca birkaç sistem çağrısı vardır ve bunlar aygıtların sahip olabileceği tüm benzersiz işlevleri ifade etmek için yeterli değildir. Böylece bir sürücü, bir kullanıcı alanı uygulamasının siparişleri göndermesine izin veren bir ioctl tanımlayabilir. Ancak, ioctl'ler çok esnek değildir ve biraz dağınık olma eğilimindedir (işe yarayan düzinelerce "sihirli sayı") ve ayrıca çekirdeğe bir arabellek geçirdiğinizde güvensiz olabilir - kötü kullanım bozulabilir şeyler kolayca.

Bir alternatif, sysfsaltında bir dosya /sys/oluşturduğunuz ve sürücüden ve sürücüden bilgi almak için onu okuduğunuz / yazdığınız arabirimdir . Bunun nasıl kurulacağına dair bir örnek:

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

Ve sürücü kurulumu sırasında:

device_create_file(dev, &dev_attr_version);

Daha sonra cihazınız için /sys/, örneğin /sys/block/myblk/versionbir blok sürücüsü için bir dosyanız olur .

Daha ağır kullanım için başka bir yöntem, sürücünüzle BSD soket arabirimi üzerinden konuşmak için bir IPC (süreçler arası iletişim) yöntemi olan netlinktir. Bu, örneğin WiFi sürücüleri tarafından kullanılır. Daha sonra libnlveya libnl3kitaplıklarını kullanarak kullanıcı alanından onunla iletişim kurarsınız .


3
Bu cevap, soruyu kısmen 'cevaplar'.
Vishal Sahu

163

ioctlFonksiyon cihazda yapılandırmayı ayarlamak için bir aygıt sürücüsü uygulamak için yararlıdır. Örneğin, yazı tipi ailesini, yazı tipi boyutunu vb. kontrol etmek ve ayarlamak için yapılandırma seçeneklerine sahip bir yazıcı ioctl, mevcut yazı tipini almak ve yazı tipini yenisine ayarlamak için kullanılabilir. Bir kullanıcı uygulaması, ioctlyazıcıya geçerli yazı tipini döndürmesini veya yazı tipini yenisine ayarlamasını söyleyen bir kod göndermek için kullanır .

int ioctl(int fd, int request, ...)
  1. fddosya tanımlayıcısıdır, döndüren open;
  2. requestistek kodudur. örneğin GETFONTyazıcıdan geçerli yazı tipini SETFONTalacak, yazıcıdaki yazı tipini ayarlayacaktır;
  3. üçüncü argüman şudur void *. İkinci argümana bağlı olarak, üçüncü argüman mevcut olabilir veya olmayabilir, örneğin ikinci argüman ise SETFONT, üçüncü argüman "Arial";

int requestsadece bir makro değildir. Bir talep kodu oluşturmak için bir kullanıcı uygulaması ve cihaz üzerindeki hangi konfigürasyonun oynatılması gerektiğini belirlemek için cihaz sürücüsü modülü gereklidir. Uygulama, kullanarak istek kodunu gönderir ioctlve ardından hangi eylemin gerçekleştirileceğini belirlemek için aygıt sürücüsü modülündeki istek kodunu kullanır.

Bir istek kodunun 4 ana bölümü vardır

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

İstek kodu ise SETFONT bir yazıcıda yazı tipini ayarlamaksa, veri aktarımının yönü kullanıcı uygulamasından aygıt sürücüsü modülüne olacaktır (Kullanıcı uygulaması yazı tipi adını "Arial"yazıcıya gönderir ). Talep kodu ise GETFONT, yön yazıcıdan kullanıcı uygulamasına doğrudur.

Bir istek kodu oluşturmak için, Linux önceden tanımlanmış bazı işlev benzeri makrolar sağlar.

1. _IO(MAGIC, SEQ_NO)her ikisi de 8 bit, 0 - 255, örneğin yazıcıyı duraklatmak istediğimizi söyleyelim. Bu, veri aktarımı gerektirmez. Bu nedenle istek kodunu aşağıdaki gibi oluşturacağız

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

ve artık kullanıma ioctlkadar

ret_val = ioctl(fd, PAUSE_PRIN);

Sürücü modülündeki ilgili sistem çağrısı kodu alacak ve yazıcıyı duraklatacaktır.

  1. __IOW(MAGIC, SEQ_NO, TYPE) MAGICve SEQ_NOyukarıdaki ile aynıdır ve TYPEaşağıdaki tartışma tipini verir, üçüncü bağımsız değişken hatırlamak ioctlolup void *. W in __IOW, veri akışının kullanıcı uygulamasından sürücü modülüne olduğunu gösterir. Örnek olarak, yazıcı yazı tipini olarak ayarlamak istediğimizi varsayalım "Arial".
#define PRIN_MAGIC 'S'
#define SEQ_NO 1
#define SETFONT __IOW(PRIN_MAGIC, SEQ_NO, unsigned long)

Daha ileri,

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

Şimdi fontbir göstericidir, yani en iyi şekilde temsil edilen bir adres olduğu anlamına gelir unsigned long, bu nedenle _IOWtüründen bahseden üçüncü bölümü bu şekilde. Ayrıca, bu yazı tipi adresi, aygıt sürücüsü modülünde uygulanan karşılık gelen sistem çağrısına iletilir unsigned long ve kullanmadan önce uygun türe çevirmemiz gerekir. Çekirdek alanı kullanıcı alanına erişebilir ve dolayısıyla bu çalışır. diğer iki işlev benzeri makrolar __IOR(MAGIC, SEQ_NO, TYPE)ve __IORW(MAGIC, SEQ_NO, TYPE)veri akışının çekirdek alanından kullanıcı alanına ve sırasıyla her iki yönde olacağı yer.

Bunun yardımcı olup olmadığını lütfen bana bildirin!


Yukarıdaki __IOW, __IOR ve __IORW işlevlerinin doğru olup olmadığını merak ediyorum (bazı durumlarda çift alt çizgiyi kastediyorum, bazı durumlarda değil. Çift alt çizgiyi hiç kullanmadım) ... Açık bir açıklama için teşekkürler!
jcoppens

Çok iyi açıklanmış .. Teşekkürler! Lütfen bu ioctl'yi kullanan sürücü tarafı için küçük bir kod parçası verebilir misiniz?
Aadişri


Çok iyi açıkladı. Teşekkür ederim. Sanırım _IOWR değil _IORW
Mohamed Samy,

Bir blog yazısı gibi cevaplayın.
Fredrick Gauss
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.