“/ Dev” Linux dosyaları nasıl oluşturulur?


112

Linux'ta gerçekten dosya olmayan özel dosyalar var.

Bunların en dikkat çekici ve net örnekleri devklasörde, "files" like:

  • /dev/null - Dosyaya yazdığınız her şeyi yok sayar
  • /dev/random - Bir dosyanın içeriği yerine rastgele verileri çıkarır
  • /dev/tcp - Bu dosyaya yazdığınız verileri ağ üzerinden gönderir

Her şeyden önce, kılık değiştirmiş bir tür komut dosyası veya ikili dosya türü olan bu tür "dosyaların" adı nedir?

İkincisi, nasıl yaratılırlar? Bu dosyalar sistemde bir çekirdek seviyesinde var mı, yoksa kendin de "sihirli bir dosya" yaratmanın bir yolu var /dev/rickrollmı?


1
Bu soruyu nasıl etiketleyeceğime dair hiçbir fikrim yoktu, özellikle de aradığım şeyin adını bilmiyordum. İlgili etiketlerde düzenleme yapmaktan çekinmeyin.
IQAndreas

15
BTW, bu unix ve unix benzeri işletim sistemlerinin tasarımının temel bir parçasıdır: (hemen hemen her şey) bir dosyadır veya bir dosya gibi görünmek için yapılabilir.
cas

5
Ayrıca bakınız: mknod (2) man 2 mknod
RobertL

4
Bunlar "cihaz düğümleri". Bununla birlikte, bahsettiğiniz aygıtlar (diskler, klavye, fareler, ses kartları ve diğer aygıtlarla ilişkili olanların aksine) "gerçek aygıtlar" olmadıkları ve yalnızca çekirdekte bulundukları için "sözde aygıtlar" olarak adlandırılırlar. Uygun bir aygıt sürücüsü yazıp çekirdeğe ekleyerek yenilerini oluşturmak mümkündür (örn. Bilgisayardaki bazı etkinlikleri izlemek için sözde bir aygıt). / Dev-dizini diskte bulunmadan önce - bugünlerde çekirdek tarafından oluşturulan sanal bir dosya sistemidir (devfs türünde).
Baard Kopperud

10
Tüm dosyalar, hatta "gerçek" dosyalar bile yazılım eseridir. Henüz icat edilecek her cihaz, dosya soket, özel dosyası veya bir şeye arkasındaki yazılım işlemek için fonksiyonları bir tablo sağlar open(), read(), close()bu yazılımın kalmış, Bundan sonra, vb
waltinator

Yanıtlar:


101

/dev/zero"özel bir dosya" örneği - özellikle "cihaz düğümü". Normalde bunlar dağıtım kurulum işlemiyle yaratılır, ancak isterseniz bunları tamamen kendiniz oluşturabilirsiniz.

Eğer lshakkında sorarsanız /dev/zero:

# ls -l /dev/zero
crw-rw-rw- 1 root root 1, 5  Nov 5 09:34 /dev/zero

Başındaki "c", bunun bir "karakter cihazı" olduğunu; diğer tür "blok aygıtı" dır ( ls"b" ile basılmıştır ). Çok kabaca, sabit diskler gibi rasgele erişimli aygıtlar, blok aygıtları veya ses kartınız gibi sıralı şeyler karakter aygıtı olma eğilimindedir.

"1, 5" kısmı "ana cihaz numarası" ve "küçük cihaz numarası" dır.

Bu bilgilerle mknodkomutu kendi aygıt düğümümüzü yapmak için kullanabiliriz :

# mknod foobar c 1 5

Bu foobar, tam olarak aynı şeyi yapan geçerli klasörde adında yeni bir dosya oluşturur /dev/zero. (İsterseniz elbette farklı izinler belirleyebilirsiniz.) Tüm bu "dosya" gerçekten içerdiği üç öğedir - cihaz tipi, büyük sayı, küçük sayı. lsDiğer cihazların kodlarını aramak ve bunları da yeniden oluşturmak için kullanabilirsiniz . Sıkıldığınızda, rmyeni oluşturduğunuz aygıt düğümlerini kaldırmak için kullanın .

Temelde asıl sayı, Linux çekirdeğine hangi aygıt sürücüsünün konuşacağını, küçük sayı ise aygıt sürücüsüne hangi aygıttan bahsettiğinizi söyler. (Örneğin, muhtemelen bir SATA denetleyiciniz vardır, ancak belki birden çok sabit diske bağlı olabilir.)

Yeni şeyler yapan yeni cihazlar icat etmek istiyorsanız ... peki, Linux çekirdeğinin kaynak kodunu düzenlemeniz ve kendi özel çekirdeğinizi derlemeniz gerekir. Öyleyse bunu yapmayalım! :-) Ancak, zaten iyi durumda olanları kopyalayan aygıt dosyaları ekleyebilirsiniz. Udev gibi otomatik bir sistem sadece cihaz olaylarını izliyor ve mknod/ rmsizi otomatik olarak arıyor . Bundan daha fazla sihir yok.

Hala başka tür özel dosyalar var:

  • Linux bir dizini özel bir dosya türü olarak görür. (Genellikle bir dizini doğrudan açamazsınız, ancak eğer yapabilseydiniz, özel bir biçimde veri içeren normal bir dosya bulursunuz ve çekirdeğe bu dizindeki tüm dosyaları nerede bulacağını söylersiniz.)

  • Bir bağlantı, özel bir dosyadır. (Fakat bir hard link değildir.) ln -sKomutu kullanarak sembolik linkler oluşturabilirsiniz . (Bunun için manpage bakın.)

  • Ayrıca "adlandırılmış yöneltme" veya "FIFO" (ilk giren ilk çıkar sırası) adı verilen bir şey de var. İle bir tane oluşturabilirsiniz mkfifo. Bir FIFO aynı anda iki program tarafından açılabilen büyülü bir dosyadır - bir okuma, bir yazma. Bu olduğunda, normal bir kabuk borusu gibi çalışır. Ancak her programa ayrı ayrı başlayabilirsiniz ...

Herhangi bir şekilde "özel" olmayan bir dosya "normal dosya" olarak adlandırılır. Bunu zaman zaman Unix belgelerinde göreceksiniz. Şu anlama gelmektedir; bir aygıt düğümü ya da sembolik bağlantı olmayan bir dosya ya da her neyse. Sadece normal, her gün büyülü özellikleri olmayan bir dosya.


4
Ayrıca dosya sistemine bağlı bir Unix alan soketi olan başka bir özel dosya türü daha vardır.
Brian Bi,

8
Oynamak istiyorsanız mknod, cat /proc/devicestüm sürücüler için ana sayıları görmek üzere koşun . Bu da bizi bir başka tür özel dosyaya getiriyor /procdosya sistemi ( bu cevap bunun hakkında konuşuyor).
ugoren

8
Diğer Unices kendi özel dosyalarını icat etti, örneğin Solaris'in kapıları vardı .
Kevin

6
Minor nitpick: Yeni bir karakter / blok aygıtı yazmak için çekirdeği yeniden derlemeniz gerekmiyor :) crashcourse.ca/introduction-linux-kernel-programming/… Aksi halde bu gerçekten iyi bir cevap, +1!
Komutan Coriander Salamander

1
@MathematicalOrchid: Cevabınızın eksik olduğu bir adım (veya en azından sadece dolaylı olarak ifade eden), bu özel dosyaların gizlenmiş kabuk betikleri veya ikilileri gizlememesi, (soruya göre) değil, mevcut olan işlevselliğe erişmek için bir arayüz olmasıdır. OS çekirdeğinde.
Hayalperest

34

Çoğu /devgirişler blok aygıtlarının düğümleri veya karakter aygıtlarının düğümleri vardır. Vikipedi'nin tekrarlayamayacağım birçok ayrıntı var.

Ancak /dev/tcp, sorunuzda bahsedilenler mevcut cevapların hiçbiri tarafından açıklanmamaktadır. /dev/tcpve /dev/udpdiğer /devgirişlerin çoğundan farklıdır . Blok ve karakter aygıtı çekirdek tarafından uygulanmaktadır ancak /dev/tcpve /dev/udpkullanıcı modunda uygulanmaktadır.

Beşinci kabuk, bir uygulaması olan /dev/tcpve /dev/udp(kopyalanan ksh93) bir programdır . Bash yönlendirme operatörleri ile altındaki bir yolu açmaya çalıştığınızda, normal bir opensistem çağrısı gerçekleştirmez. Bunun yerine bash bir TCP soketi oluşturur ve belirtilen bağlantı noktasına bağlar.

Bu, kullanıcı modunda ve yalnızca izin verme bashve cataçmaya çalışma arasındaki farkı gösteren aşağıdaki örnekte görülebileceği gibi bazı programlarda uygulanır./dev/tcp/::1/22

$ cat /dev/tcp/::1/22
cat: /dev/tcp/::1/22: No such file or directory
$ cat < /dev/tcp/::1/22
SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.3

A fark ksh93olduğunu bashsadece o gibi dosyaları açabilir başka yerlerde, yönlendirme operatörleriyle olanlar TCP bağlantılarını yapacak sourceya da .yerleşik.


Ayrıca, GNU 2010'da bir yerlerden beri gawkbenzer şekilde özel durumlar uyandırdı /inet{,4,6}/{tcp,udp}/$port/$remote/$rport(Tam olarak hatırlamıyorum ve sürüm notları bulamıyorum).
dave_thompson_085

6
IMO, konuyu belirtmenin daha iyi bir yolu, /dev/tcpbir dosya DEĞİLDİR. Bu adında bir dosya asla yoktur . Bash'in soketleri açmak için kullandığı sözdizimi, /dev/tcp/addressdosya adı gibi bir dizge kullanır , ancak onu "kullanıcı alanında uygulanan dosya" olarak adlandırmak garip gelir. O İlginç ksholsa da, yönlendirme yapmadan hemen her şey için bu dosya adlarını değil kanca. Bu "bir dosyayı uygulamak" için daha yakın.
Peter Cordes,

@PeterCordes UWIN'in bunları gerçek dosyalar olarak ayarladığına inanıyorum. ve bence 3dfs de aynı şeyi yapıyor. unutmayın, bashyalnızca bu davranışı kopyaladım, ancak başka bir yerden kaynaklanıyor.
mikeserv 7:15

19

Diğer cevaplarda ( mknod (2) ile oluşturulan veya bazı devfs'ler tarafından sağlanan ) açıklanan cihaz düğümlerinin yanı sıra , Linux, özel sanal dosya sistemleri tarafından sağlanan diğer "sihirli" dosyalara sahiptir , özellikle /proc/(bakınız proc (5) , procfs hakkında bilgi edinin). ) ve içeri/sys/ ( sysfs hakkında okuyun ).

Bu sözde dosyalar ( - (stat (e) - göründüğü gibi - sıradan dosyalar, aygıtlar değil)) çekirdek tarafından sağlanan sanal bir görünümdür; Özellikle, /proc/(örneğin cat /proc/$$/maps, programınızdaki veya ile (açık) (ile) yazarak okumak /proc/self/statusgenellikle disk veya ağdan herhangi bir fiziksel G / Ç içermez, bu yüzden oldukça hızlıdır.

Bazı ek sözde dosyası oluşturmak için /proc/genellikle kendi yazmalısınız çekirdek modülü ve yüklemek (bkz mesela bu ).


3
AFAIK / proc uzatma ile ilgili bilgiler eskidir. Teknik olarak hala mümkün olsa da, / proc (veya procfs) yalnızca çalışan işlemler hakkında bilgi sahibi olmalıdır. Çalışma zamanı bilgisi veya çekirdek için yapılandırma seçenekleri içerenler de dahil olmak üzere diğer tüm sahte dosyalar / sys (sysfs) içine girmelidir. Uyumluluk nedenlerinden dolayı / proc (örneğin meminfo, cpuinfo) içinde işlemle ilgili olmayan bazı sahte dosyalar var, ancak yeni sahte dosyalar sysfs'e girmeli.
Hayalperest

13

Bunlara cihaz düğümleri denir ve bunlar ile manuel olarak mknodveya otomatik olarak oluşturulur udev. Bunlar genellikle çekirdekte sürücüleri olan karakterleri veya blok aygıtlarını dosyaya benzeyen arayüzlerdir - örneğin diskler blok aygıtları, tty'ler ve seri portlar vb. Karakter aygıtlarıdır.

Ayrıca adlandırılmış yöneltmeler ve beşlik ve soketler dahil olmak üzere başka "özel" dosya türleri de vardır.


9

Diğer kullanıcılar zaten ayrıntılı olarak açıkladığından, özel dosyaların yedeklenmesi için kod gerekir. Bununla birlikte, hiç kimse Linux'un bu kodu kullanıcı alanına yazmak için birkaç yol sağladığından bahsetmiyor gibi görünmüyor:

A. FUSE (USErspace’deki Dosya Sistemi) /procçekirdeği çökme riski olmadan bir şey yazmanıza izin verir ve Go , Node.js , Perl , PHP , Python , Ruby , Rust , vb .

Ayrıca, FUSE dosya sistemlerinin sudo, montajı yapan kullanıcı olarak çalıştığı için olmadan da monte edilebilme avantajı vardır .

İşte insanların FUSE kullanarak yazdıkları bazı örnekler:

  • mp3fs (FLAC dosyalarınızı MP3 çalarınıza kopyaladığınızda / tıkladığınızda anında oluşturduğunuz MP3 dosyaları olarak görüntüleyin)
  • PyTagsFS ( Medyanızı , meta veri etiketlerinden oluşturulmuş bir sanal klasör ağacında görüntüleyin)
  • fuse-zip (Zip dosyalarını klasör olarak bağla)
  • FuseISO (Kök izni olmadan ISO'ları bağla )
  • iFUSE (iDevices Dağı)
  • FuseDAV (Mount WebDAV paylaşımları)
  • sigorta exfat (Mount exFAT biçimli dosya sistemleri)
  • NTFS-3g ( Linux NTFS sürücüsü)

B. Klavye, fare, oyun çubuğu, vb. Gibi sanal bir giriş aygıtı oluşturmak istiyorsanız (örneğin, kullanmak istediğiniz bir USB aygıtı için bir kullanıcı alanı sürücüsü yazmak için libusb), kullanıcı girişi yoktur .

Bağlamaları bulmak daha zor, ama Go (yalnızca Klavye), Python ve Ruby (2) için var olduklarını biliyorum .

Gerçek dünya kullanıcı girişi kullanımına örnekler:

  • G15Daemon (Logitech G15 oyun klavyelerinde LCD ve oyun tuşları için Linux sürücüsü)
  • ds4drv (Sony DualShock 4 denetleyicileri için sürücü)
  • xboxdrv (Alternatif XBox 360 denetleyicisi sürücüsü ve Linux x360ce'ye eşdeğer derecede kötü bir şekilde tasarlanmış olan Runner2: Geleceğin Ritmi Efsanesi Alien , olmadıklarında gerçek bir XBox denetleyicisiyle konuştuğunu düşünebilir)
  • Cwiid gibi eski Wiimote sürücüleri birisinin nihayet bir çekirdek Wiimote sürücüsü yazmasından önce gerekliydi;

C. Genel karakter cihazları için, CUSE var (USErspace'deki karakter cihazları). Yine de çok daha az popüler.

: Ben kişisel olarak farkında değilim Cuse API sadece kullanıcı meclisin kurulmasına istendiğinde aynı programdır osspd , uygular /dev/dsp, /dev/adspve /dev/mixeronlar PulseAudio veya dmix üzerinden yönlendirilen böylece kullanıcı ortamında (ÖSS ses API).

Bulabildiğim tek CUSE bağlaması 2010'dan beri güncellenmemiş olan harika.

D. Yeni bir özel dosyaya hiç ihtiyacınız olmayabilir.

Örneğin, libusb (sayfadaki cilt listesi) kullanarak herhangi bir USB cihazıyla ham iletişimi açabilir ve daha sonra diğer programlarla (TCP / UDP soketleri, stdin / stdout okuma / yazma veya diskteki normal dosyaları okuma / yazma yoluyla diğer programlar ile iletişim kurabilirsiniz). , vb.).


1
cusepy bir süredir güncellenmemiş olabilir (aslında, hiç güncellenmedi; yalnızca bir taahhüdü var!), ancak birkaç hafta önce cusepy kullanarak cusepy kullanarak bir karakter aygıtı yazdıktan sonra hala düzgün çalıştığını onaylayabilirim. Uygulamayla ilgili birkaç işlev eksikti poll, ancak çok korkutucu kripti kullandığı ve ciltlemeler C başlık dosyalarına göre otomatik olarak oluşturulduğundan, eksik işlevleri düzeltmek, istenen işlev adını dışa aktarılan işlevler listesine eklemekle ilgili bir meseledir setup.py.
Aleksi Torhamo,

1
FUSE kullanımının ilginç bir örneği sshfs'dir . Uzaktaki dosya sistemine, altındaki SSH bağlantısını kullanarak yerelmiş gibi göz atmanızı sağlar.
Bay Ölümsüz

@ Mr.Deathless Evet. Aslında bunu kullandım ve bahsetmek istedim ama unuttum.
ssokolow

6

Linux Aygıt Sürücüleri (şiddetle tavsiye edilir) kitabı bunu ayrıntılı olarak açıklar ve hatta bunu örnek olarak yapan bir çekirdek modülü oluşturdunuz, ancak kısaca, her aygıt sürücüsünün bir dosya açıldığında, çağrıldığında çağrılan belirli işlevleri vardır , okuyun, yazın, vb. "Özel" dosyalar, diskteki depolama donanımına erişmek yerine, bu işlevlerin içinde özel bir şey yapar.

Örneğin, yazma işlevi /dev/nullsadece hiçbir şey yapmaz, baytları yok sayar. İçin okuma işlevi /dev/randomrastgele bir sayı döndürür.


1

mount -t devtmpfs

Modern sistemlerde /devnormalde istediğiniz yere monte edilebilen bir dosya sistemi türüdür. Ubuntu 16.04:

mkdir d
sudo mount -t devtmpfs none d
head -c 10 d/random
sudo umount d

Bu, etkinleştirilir CONFIG_DEVTMPFS=yve çekirdeğin gerektiğinde aygıt dosyaları oluşturmasını ve yok etmesini sağlar.

CONFIG_DEVTMPFS_MOUNT=y

Bu seçenek, çekirdeğin otomatik montaj devtmpf'lerini açık hale getirir /dev.

drivers/base/Kconfig belgeler:

config DEVTMPFS_MOUNT
    bool "Automount devtmpfs at /dev, after the kernel mounted the rootfs"
    depends on DEVTMPFS
    help
      This will instruct the kernel to automatically mount the
      devtmpfs filesystem at /dev, directly after the kernel has
      mounted the root filesystem. The behavior can be overridden
      with the commandline parameter: devtmpfs.mount=0|1.
      This option does not affect initramfs based booting, here
      the devtmpfs filesystem always needs to be mounted manually
      after the rootfs is mounted.
      With this option enabled, it allows to bring up a system in
      rescue mode with init=/bin/sh, even when the /dev directory
      on the rootfs is completely empty.

file_operations

Sonunda, tam olarak ne olduğunu görmek için kendi karakter cihazı çekirdek modülünüzü oluşturmalısınız.

İşte minimal bir çalıştırılabilir örnek: Karakter aygıtı (veya karakter özel) dosyalarını anlama

En önemli adım, file_operationsyapıyı ayarlamaktır , örneğin:

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

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

her dosya ile ilgili sistem çağrısı için çağrılan işlev işaretçilerinden oluşur.

Ardından, dosya bağlantılı sistem çağrıları istediğinizi yapmak için yapılan aramaları geçersiz kıldığınızı ve böylece çekirdeğin bu gibi aygıtları nasıl uygulayacağını açıkça ortaya çıkarır /dev/zero.

/devGirişleri otomatik olarak olmadan oluşturmknod

Son gizem, çekirdeğin otomatik olarak /devgirdileri nasıl oluşturduğu .

Mekanizma, kendiniz için yaptığınız gibi bir çekirdek modülü yapılarak görülebilir: https://stackoverflow.com/questions/5970595/how-to-create-a-device-node-from-the-init-module- linux-çekirdek-modülü / 45531867 # 45531867 ve bir device_createçağrı geliyor .


OpenBSD'de bu biraz basitleştiren bir senaryo MAKEDEV var, bakınız man.openbsd.org/MAKEDEV.8 bu yol daha karışık hariç Linux bu yok neden emin. Belki parçalar uyarlanabilirdi. Örneğin MKNOD tty diyebilirsiniz ve detayları ele alır.
Alan Corey
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.