Karakter cihazı veya karakter özel dosyaları nasıl çalışır?


22

Karakter özel dosyaları anlamaya çalışıyorum. Gönderen wikipedia , ben bu dosyaları cihazlar için "bir arayüz sağlamak" olduğunu anlamak bir anda veri iletimi bir karakter olduğunu. Anladığım kadarıyla sistem bir şekilde doğrudan aygıt sürücüsünü çağırmak yerine karakter aygıtını çağırıyor. Fakat dosya bu arayüzü nasıl sağlıyor? Sistem çağrısını çeviren bir çalıştırılabilir mi? Biri ne olduğunu açıklayabilir mi?

Yanıtlar:


19

Onlar aslında sadece bu - arayüzler. "Büyük" ve "küçük" sayılarla kodlanan çekirdeğe bir kanca sağlarlar.

İki çeşit lezzet gelir (üç, ama adlandırılmış borular şimdilik bu açıklamanın kapsamı dışındadır): Karakter Cihazları ve Blok Cihazları.

Blok Aygıtları, çıkış tamponlama ve daha sonra geri almak için veri saklama yeteneğine sahip depolama aygıtları olma eğilimindedir.

Karakter Aygıtları, ses veya grafik kartları veya klavye ve fare gibi giriş aygıtlarıdır.

Her durumda, çekirdek doğru sürücüyü yüklediğinde (önyükleme sırasında veya udev gibi programlar aracılığıyla ), bu sürücü tarafından kullanılan aygıtların gerçekte sistemde olup olmadığını görmek için çeşitli otobüsleri tarar. Eğer öyleyse, uygun ana / küçük numarayı 'dinleyen' bir cihaz kurar.

(Örneğin, sisteminiz tarafından bulunan ilk ses kartının Dijital Sinyal İşlemcisi 14/3 büyük / küçük sayı çiftini alır; ikincisi 14,35 vb. Alır.)

Başlıca 14 küçük 3 olarak işaretlenmiş bir karakter aygıtı olarak /devadlandırılan bir giriş oluşturmak için udev kalmış dsp.

(Linux'un önemli ölçüde daha eski veya en az yer kaplayan sürümlerinde, /dev/dinamik olarak yüklenmeyebilir, ancak tüm olası aygıt dosyalarını statik olarak içerebilir.)

Daha sonra, bir kullanıcı programı uygun büyük / küçük sayılarla (örneğin, özel ses dosyası göndermeye çalışan müzik çalarınız) 'karakter özel dosya' olarak işaretlenmiş bir dosyaya erişmeye çalıştığında /dev/dsp, çekirdek bu verilerin gerekli olduğunu bilir. Büyük / az sayının eklendiği sürücü üzerinden iletilmelidir; Muhtemelen sürücü de onunla ne yapacağını biliyor.


1
1. Büyük / küçük sayılar portlara benziyor mu?
bernie2436,

2. Programlar herhangi bir dosyaya eriştiğinde, çekirdek programın belirli bir cihazdan kesilmesi gerekip gerekmediğini öğrenmek için bu özel arayüzleri okur mu? Ör: bir program bir kelime dosyası açarsa, programın klavye girişine cevap vermesi gerektiğini bilmesi için karakter cihazına özel dosyayı okur mu?
bernie2436

1) Biraz . Bu fakir bir adamın analojisi ama olacak.
Shadur

2
2) Orada üç veya dört soyutlama katmanını kaçırıyorsunuz. Bir metin dosyasını açtığınız program ne klavye cihazının ne olduğunu bilmiyor veya umursamıyor. Temel donanım ile iletişim, klavyeyi ve diğer sürücüleri dinleyecek ve ne karar vereceğine karar vermeden, terminal öykünücüsü aracılığıyla (konsol kipindeyseniz) veya X olay katmanı (grafik kipindeyseniz) gerçekleşir , bir şey varsa, programa geçmek için. Burada oldukça karmaşık bir çok katmanlı sistemi özetliyorum; Genel olarak X Pencere Sisteminde okumak için iyi olabilirsiniz.
Shadur

1
Ayrıca, UN * X'in bazı lezzetlerinde, depolama aygıtları için karakter özel dosyaları bulunduğunu unutmayın; özel dosyaya yapılan bir okuma veya yazma, cihazın üzerindeki bir blok sırasına bir okuma veya yazma işlemine dönüşür. (FreeBSD son sürümlerinde, olanlardır sadece depolama aygıtları için özel dosyalar; orada olan hiçbir blok özel dosyaları.)

10

Her dosya, aygıt veya başka türlü, VFS içindeki 6 temel işlemi destekler:

  1. Açık
  2. Kapat
  3. Okuma
  4. Yazmak
  5. Aramak
  6. Söylemek

Ek olarak, aygıt dosyaları, ilk 6 tarafından kapsanmayan diğer çeşitli işlemlere izin veren I / O Kontrolünü de destekler.

Özel bir karakter söz konusu olduğunda, bir akış arayüzünü desteklediklerinden arama ve söyleme uygulanmaz . Yani, doğrudan okuma veya yazma, kabuktaki yeniden yönlendirme ile yapılır.

echo 'foo' > /dev/some/char
sed ... < /dev/some/char

6

Minimum çalıştırılabilir file_operationsörnek

Minimal bir örnek gördüğünüzde her şey belirginleşir.

Anahtar fikirler:

  • file_operations Syscall ile ilgili her dosya için geri aramaları içerir.
  • mknod <path> c <major> <minor> bunları kullanan bir karakter cihazı yaratır file_operations
  • Cihaz numaralarını dinamik olarak tahsis eden karakter çatışmaları (uyuşmazlıklardan kaçınmak için norm) cat /proc/devices

character_device.ko çekirdek modülü:

#include <asm/uaccess.h> /* copy_from_user, copy_to_user */
#include <linux/errno.h> /* EFAULT */
#include <linux/fs.h> /* register_chrdev, unregister_chrdev */
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/printk.h> /* printk */
#include <uapi/linux/stat.h> /* S_IRUSR */

#define NAME "lkmc_character_device"

MODULE_LICENSE("GPL");

static int major;

static ssize_t read(struct file *filp, char __user *buf, size_t len, loff_t *off)
{
    size_t ret;
    char kbuf[] = {'a', 'b', 'c', 'd'};

    ret = 0;
    if (*off == 0) {
        if (copy_to_user(buf, kbuf, sizeof(kbuf))) {
            ret = -EFAULT;
        } else {
            ret = sizeof(kbuf);
            *off = 1;
        }
    }
    return ret;
}

static const struct file_operations fops = {
    .owner = THIS_MODULE,
    .read = read,
};

static int myinit(void)
{
    major = register_chrdev(0, NAME, &fops);
    return 0;
}

static void myexit(void)
{
    unregister_chrdev(major, NAME);
}

module_init(myinit)
module_exit(myexit)

Kullanıcı test programı:

insmod /character_device.ko
dev="lkmc_character_device"
major="$(grep "$dev" /proc/devices | cut -d ' ' -f 1)"
mknod "/dev/$dev" c "$major" 0
cat /dev/lkmc_character_device
# => abcd
rm /dev/lkmc_character_device
rmmod character_device

GitHub QEMU + Aslında çalıştırmak için kazan plakası ile yukarı akış oluşturun:

Daha karmaşık örnekler:


Bu süper yardımcı oldu! Sadece bir soru, bu tam olarak ne işe yarıyor *off = 1;ve neden ayarlandı 1?
SilverSlash

1
@SilverSlash, bu değerin readaynı open(dosya tanımlayıcısına yapılan birden fazla çağrı boyunca iletilir . Sürücü ne isterse yapabilir. Her zamanki anlamsal, okunan bayt sayısını içermektir. Bununla birlikte, bu örnekte, daha basit bir semantikimiz var: 0ilk okuma için, ilk okumadan 1sonra. Çalıştırmayı deneyin ve bir printk veya GDB adımı atarak hata ayıklayın.
Ciro Santilli 15

4

"Bir seferde karakter" bir yanlış isimdir (karakter cihazlarının mutlaka arama ve söylemeyi desteklemediği fikri olduğu gibi). Aslında, "bir seferde blok" (yani, bir teyp sürücüsü * gibi kesinlikle kayıt odaklı) cihazları , karakter cihazları olmalıdır . Bu nedenle, bir karakter cihazının mutlaka görülmemesi gerektiği düşüncesi var - karakter cihazı sürücüleri file_operations, cihazın işlemi destekleyip desteklemediğine göre llseek'i tanımlamakta serbest olan veya olmayan bir tam yapı tanımlarlar. Çoğu insanın örnek olarak düşündüğü karakter cihazları boş, urandom, TTY cihazları, ses kartı, fare vb ... hepsi, bu cihazların ne olduğu ile ilgili olarak görünmeyen, ancak / dev / vcs, / dev / fb0. ve / dev / kmem ayrıca karakter aygıtlarıdır ve hepsi aranabilirdir.

Bahsettiğim gibi, bir karakter aygıt sürücüsü, birinin bir dosya üzerinde çağırmak isteyebileceği tüm işlemler için işlev işaretçilerine sahip bir file_operations yapısını tanımlar - arama, okuma, yazma, ioctl, vb. bu aygıt dosyası açıkken yürütülür. Ve oku ve yaz bu nedenle argümanlarıyla ne isterse yapabilir - çok büyük olan bir yazıyı kabul etmeyi reddedebilir veya yalnızca uygun olanı yazmayı reddedebilir; İstenen bayt sayısının tamamı yerine yalnızca bir kayda karşılık gelen verileri okuyabilir.

Öyleyse blok aygıtı nedir o zaman? Temel olarak, blok aygıtları disk sürücüleridir. Başka hiçbir cihaz ( ramdisk ve loopback gibi sanal disk sürücüleri hariç ) blok cihaz değildir. Bir kullanıcı işleminden eg / sda'ya erişirken bile , G / Ç istek sistemine, dosya sistemi katmanına, tampon / önbellek sistemine ve sanal bellek sistemine karakter cihazlarının olmadığı şekilde entegre edilirler. . Bir istisna olarak bahsi geçen "ham cihazlar" bile karakter cihazlarıdır .

* Bazı UNIX sistemleri, şimdi "sabit blok modu" olarak adlandırılan bir uygulama gerçekleştirdi; bu, çekirdek grubunun ve G / Ç isteklerinin yapılandırılmış blok sınırlarına daha fazla veya daha az disk sürücüleri için yapılanlarla aynı şekilde sığmasını sağlar - blok olarak cihaz. Tek değişkenli bir yazma (2) çağrısı bir blok yazar ve bir tek okuma (2) çağrısı bir blok döndürürken kullanıcı programından blok sınırlarını koruyan "değişken blok modu" için bir karakter cihazı gereklidir. Mod değiştirme şimdi ayrı bir cihaz dosyası yerine bir ioctl olarak uygulandığından, bir karakter cihazı kullanılır. Değişken-kayıt teyp sürücüleri çoğunlukla "aranmaz" dır;


1

Karakter cihazları çekirdek modülleri (veya çekirdeğin kendisi) tarafından yaratılabilir. Bir cihaz oluşturulduğunda, yaratıcı, açık, okuma vb. Gibi standart çağrıları ele alma işlevlerini uygulayan işlevler için işaretçiler sağlar. Linux çekirdeği bu işlevleri daha sonra karakter cihazı ile ilişkilendirir; Bir karakter cihazı dosyasındaki işlev, sistemin çağrılmasına neden olur ve ardından çekirdek bu çağrıyı sürücüyü oluştururken belirtilen bir okuma işlevine yönlendirir. Burada bir karakter cihazı yaratma konusunda adım adım bir eğitim var , örnek bir proje oluşturabilir ve cihaz nesnesinin nasıl oluşturulduğunu ve işleyicilerin ne zaman çağrıldığını anlamak için bir hata ayıklayıcı kullanarak adım adım ilerleyebilirsiniz.

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.