W Linuksie są specjalne pliki, które tak naprawdę nie są plikami.
Najbardziej godne uwagi i wyraźne przykłady znajdują się w dev
folderze „pliki”, takie jak:
/dev/null
- Ignoruje wszystko, co piszesz do pliku/dev/random
- Wyprowadza losowe dane zamiast zawartości pliku/dev/tcp
- Wysyła dane zapisywane do tego pliku przez sieć
Przede wszystkim, jak nazywają się te typy „plików”, które są w rzeczywistości jakimś skryptu lub pliku binarnego w przebraniu?
Po drugie, w jaki sposób są tworzone? Czy te pliki są wbudowane w system na poziomie jądra, czy też istnieje sposób, aby samodzielnie stworzyć „magiczny plik” (a może a /dev/rickroll
)?
man 2 mknod
open()
,read()
,close()
, itd. Po tym, to zależy od oprogramowaniaOdpowiedzi:
/dev/zero
jest przykładem „specjalnego pliku” - w szczególności „węzła urządzenia”. Zwykle są one tworzone przez proces instalacji dystrybucji, ale możesz je całkowicie stworzyć samodzielnie, jeśli chcesz.Jeśli zapytasz
ls
o/dev/zero
:Litera „c” na początku informuje, że jest to „urządzenie znakowe”; drugim typem jest „urządzenie blokowe” (wydrukowane
ls
jako „b”). Z grubsza urządzenia o swobodnym dostępie, takie jak dyski twarde, są zwykle urządzeniami blokowymi, podczas gdy sekwencyjne rzeczy, takie jak napędy taśm lub karta dźwiękowa, są zwykle urządzeniami znakowymi.Część „1, 5” to „główny numer urządzenia” i „mniejszy numer urządzenia”.
Dzięki tym informacjom możemy użyć
mknod
polecenia, aby utworzyć własny węzeł urządzenia:Spowoduje to utworzenie nowego pliku o nazwie
foobar
w bieżącym folderze, który działa dokładnie tak samo jak/dev/zero
. (Jeśli chcesz, możesz oczywiście ustawić różne uprawnienia). Cały ten „plik” naprawdę zawiera trzy powyższe elementy - typ urządzenia, numer główny, mniejszy numer. Możesz użyćls
do wyszukania kodów dla innych urządzeń i ich odtworzenia. Kiedy się nudzisz, po prostu użyj,rm
aby usunąć właśnie utworzone węzły urządzenia.Zasadniczo liczba główna informuje jądro Linuksa, z którym sterownikiem urządzenia ma rozmawiać, a liczba mniejsza informuje sterownik urządzenia, o którym urządzeniu mówisz. (Na przykład prawdopodobnie masz jeden kontroler SATA, ale może podłączono do niego wiele dysków twardych.)
Jeśli chcesz wymyślić nowe urządzenia, które zrobią coś nowego ... musisz edytować kod źródłowy jądra Linux i skompilować własne niestandardowe jądro. Więc nie róbmy tego! :-) Ale możesz dodać pliki urządzeń, które powielają te, które już masz dobrze. Zautomatyzowany system, taki jak udev, po prostu obserwuje zdarzenia urządzenia i automatycznie dzwoni
mknod
/rm
do ciebie. Nic więcej magii niż to.Istnieją jeszcze inne rodzaje plików specjalnych:
Linux uważa katalog za specjalny rodzaj pliku. (Zwykle nie możesz bezpośrednio otworzyć katalogu, ale gdybyś mógł, znajdziesz normalny plik, który zawiera dane w specjalnym formacie i informuje jądro, gdzie znaleźć wszystkie pliki w tym katalogu).
Dowiązanie symboliczne to specjalny plik. (Ale twardy link nie jest.) Możesz tworzyć dowiązania symboliczne za pomocą
ln -s
polecenia. (Poszukaj w nim strony podręcznika.)Jest też coś o nazwie „nazwany potok” lub „FIFO” (kolejka pierwsze wejście, pierwsze wyjście). Możesz go utworzyć za pomocą
mkfifo
. FIFO to magiczny plik, który można otworzyć jednocześnie przez dwa programy - jeden odczyt, jeden zapis. Kiedy tak się dzieje, działa jak normalna rura osłonowa. Ale możesz uruchomić każdy program osobno ...Plik, który w żaden sposób nie jest „specjalny”, nazywany jest „zwykłym plikiem”. Od czasu do czasu zobaczysz wzmiankę o tym w dokumentacji Uniksa. To właśnie oznacza; plik, który nie jest węzłem urządzenia, dowiązaniem symbolicznym ani niczym innym. Po prostu zwykły, codzienny plik bez magicznych właściwości.
źródło
mknod
, biegnij,cat /proc/devices
aby zobaczyć główne liczby dla wszystkich sterowników. Co prowadzi nas do jeszcze innego rodzaju specjalnego/proc
systemu plików ( ta odpowiedź mówi o tym).Większość
/dev
wpisów to i-węzły urządzeń blokowych lub i-węzły urządzeń znakowych. Wikipedia ma wiele szczegółów na ten temat, których nie zamierzam powtarzać.Ale
/dev/tcp
które jest wymienione w twoim pytaniu, nie jest wyjaśnione żadną z istniejących odpowiedzi./dev/tcp
i/dev/udp
różnią się od większości innych/dev
pozycji. Urządzenia blokowe i znakowe są realizowane przez jądro, ale/dev/tcp
i/dev/udp
są realizowane w trybie użytkownika.Powłoka bash to jeden program, który ma implementację
/dev/tcp
i/dev/udp
(skopiowany zksh93
). Gdy spróbujesz otworzyć ścieżkę poniżej operatorów przekierowujących bash, nie wykona ona zwykłegoopen
wywołania systemowego. Zamiast tego bash utworzy gniazdo TCP i podłączy je do określonego portu.Jest to zaimplementowane w trybie użytkownika i tylko w niektórych programach, co widać w poniższym przykładzie, który pokazuje różnicę między wynajmowaniem
bash
acat
próbą otwarcia/dev/tcp/::1/22
Różnica
ksh93
polega na tymbash
, że będzie wykonywać tylko połączenia TCP z operatorami przekierowania, a nie w innych miejscach, w których może otwierać pliki takie jaksource
lub.
wbudowane.źródło
gawk
podobne przypadki specjalne/inet{,4,6}/{tcp,udp}/$port/$remote/$rport
, ponieważ gdzieś około 2010 roku (nie pamiętam dokładnie i nie mogę znaleźć informacji o wydaniu)./dev/tcp
, że NIE jest to plik. Nigdy nie ma pliku o nazwie to. Składnia Basha do otwierania gniazd używa łańcucha/dev/tcp/address
jak nazwy pliku, ale nazywanie go „plikiem zaimplementowanym w przestrzeni użytkownika” po prostu brzmi dziwnie. Interesujące jest to, żeksh
przechwytuje te nazwy plików do wszystkiego, nie tylko przekierowań. Jest to bliższe „implementacji pliku”.bash
skopiowałem tylko to zachowanie, ale pochodzi ono z innego miejsca.Oprócz węzłów urządzeń wyjaśnionych w innych odpowiedziach (utworzonych za pomocą mknod (2) lub dostarczonych przez niektóre devfs ), Linux ma inne „magiczne” pliki dostarczane przez specjalne wirtualne systemy plików , w szczególności w
/proc/
(patrz proc (5) , przeczytaj o procfs ) i we/sys/
(czytaj o sysfs ).Te pseudopliki (które pojawiają się jako -eg do stat (2) - jako zwykłe pliki, a nie jako urządzenia) są wirtualnym widokiem udostępnianym przez jądro; w szczególności czytanie z
/proc/
(np. przy pomocycat /proc/$$/maps
lub przez otwarte (2) -wpisywanie/proc/self/status
w twoim programie) zasadniczo nie wymaga fizycznego wejścia / wyjścia z dysku lub sieci, więc jest dość szybkie.Aby utworzyć dodatkowy pseudoplik
/proc/
należy na ogół napisać własny moduł jądra i załadować go (patrz np. To ).źródło
Są nazywane węzłami urządzeń i są tworzone ręcznie
mknod
lub automatycznieudev
. Zazwyczaj są to interfejsy przypominające pliki do urządzeń znakowych lub blokowych ze sterownikami w jądrze - np. Dyski to urządzenia blokowe, tty i porty szeregowe itp. To urządzenia znakowe.Istnieją również inne „specjalne” typy plików, w tym nazwane potoki oraz fifos i gniazda.
źródło
Jak już szczegółowo wyjaśnili inni użytkownicy, specjalne pliki wymagają kodu, aby wykonać ich kopię zapasową. Jednak wydaje się, że nikt nie wspomniał, że Linux zapewnia kilka sposobów pisania tego kodu w przestrzeni użytkownika:
A. FUSE (system plików w USErspace) pozwala napisać coś takiego
/proc
bez ryzyka awarii jądra i zrobić to w wybranym przez siebie języku / środowisku wykonawczym, takim jak Go , Node.js , Perl , PHP , Python , Ruby , Rust , itp .Ma również tę zaletę, że systemy plików FUSE mogą być montowane bez,
sudo
ponieważ działają jako użytkownik wykonujący montaż.Oto kilka przykładów rzeczy, które ludzie napisali za pomocą FUSE:
B. Jeśli chcesz utworzyć wirtualne urządzenie wejściowe, takie jak klawiatura, mysz, joystick itp. (Np. Aby napisać sterownik przestrzeni użytkownika dla urządzenia USB, z którym rozmawiasz
libusb
), nie ma danych wejściowych .Wiązania są trudniejsze do znalezienia, ale wiem, że istnieją dla Go (tylko klawiatura), Python i Ruby (2) .
Przykłady użycia wejścia rzeczywistego obejmują:
C. W przypadku ogólnych urządzeń postaci istnieje CUSE (urządzenia postaci w USErspace). Jest jednak znacznie mniej popularny.
Jedynym użytkownikiem API Cuse że jestem osobiście świadomy jest ten sam program co skłoniło jej utworzenia: osspd , który realizuje
/dev/dsp
,/dev/adsp
oraz/dev/mixer
(API dźwięku OSS) w przestrzeni użytkownika, więc mogą być kierowane przez PulseAudio lub dmix.Jedyne wiązanie CUSE , które udało mi się znaleźć, to cusepy , które nie było aktualizowane od 2010 roku.
D. W ogóle może nie być potrzebny nowy plik specjalny.
Na przykład możesz otworzyć surową komunikację z dowolnym urządzeniem USB za pomocą libusb (Lista powiązań na stronie), a następnie komunikować się z innymi programami za pomocą innego mechanizmu (gniazda TCP / UDP, odczyt / zapis stdin / stdout lub zwykłe pliki na dysku itp.).
źródło
poll
, ale ponieważ cusepy używa ctypów, a powiązania są generowane automatycznie na podstawie plików nagłówkowych C, naprawienie wszelkich brakujących funkcji jest tylko kwestią dodania pożądanej nazwy funkcji do listy eksportowanych funkcji wsetup.py
.Książka Sterowniki urządzeń Linux (wysoce zalecane) szczegółowo to wyjaśnia, a nawet stworzyłeś moduł jądra, który robi to jako przykład, ale w skrócie, każdy sterownik urządzenia ma określone funkcje, które są wywoływane, gdy plik jest otwierany, zamykany , czytanie, pisanie itp. Pliki „specjalne” po prostu robią coś specjalnego w obrębie tych funkcji, zamiast uzyskiwać dostęp do pamięci na dysku.
Na przykład funkcja zapisu po
/dev/null
prostu nic nie robi, ignorując bajty. Funkcja odczytu dla/dev/random
zwraca liczbę losową.źródło
mount -t devtmpfs
Interesujące jest również to, że we współczesnych systemach
/dev
zwykle jest to typ systemu plików, który można zamontować w dowolnym miejscu. Ubuntu 16.04:Jest to włączone przez
CONFIG_DEVTMPFS=y
i pozwala samemu jądru tworzyć i niszczyć pliki urządzeń w razie potrzeby.CONFIG_DEVTMPFS_MOUNT=y
Ta opcja powoduje automatyczne podłączanie devtmpfs do jądra
/dev
.drivers/base/Kconfig
dokumenty:file_operations
Na koniec powinieneś stworzyć własny moduł jądra urządzenia postaci, aby zobaczyć dokładnie, co się dzieje.
Oto minimalny możliwy do uruchomienia przykład: Zrozumienie plików urządzeń znakowych (lub znaków specjalnych)
Najważniejszym krokiem jest skonfigurowanie
file_operations
struktury, np .:który zawiera wskaźniki funkcji wywoływane dla każdego wywołania systemowego związanego z plikiem.
Wtedy staje się oczywiste, że przesłonisz wywołania systemowe związane z plikami, aby zrobić, co chcesz, i tak jądro implementuje takie urządzenia
/dev/zero
.Twórz
/dev
wpisy automatycznie bezmknod
Ostatnia tajemnica polega na tym, jak jądro automatycznie tworzy
/dev
wpisy.Mechanizm można zaobserwować, tworząc moduł jądra, który robi to sam, jak pokazano na stronie : https://stackoverflow.com/questions/5970595/how-to-create-a-device-node-from-the-init-module- code-of-a-linux-kernel-module / 45531867 # 45531867 i sprowadza się do
device_create
wywołania.źródło