Deskryptor pliku
W komputerowych systemach operacyjnych Unix i Unix deskryptor pliku ( FD , rzadziej fildes ) jest unikalnym dla procesu identyfikatorem ( uchwytem ) pliku lub innego zasobu wejścia/wyjścia , takiego jak potok lub gniazdo sieciowe .
Deskryptory plików mają zwykle nieujemne wartości całkowite , przy czym wartości ujemne są zarezerwowane do wskazania „brak wartości” lub warunki błędu.
Deskryptory plików są częścią POSIX API . Każdy proces uniksowy (może z wyjątkiem demonów ) powinien mieć trzy standardowe deskryptory plików POSIX, odpowiadające trzem standardowym strumieniom :
Wartość całkowita | Nazwa | < unistd.h > stała symboliczna | < stdio.h > strumień plików |
---|---|---|---|
0 | Wejście standardowe | STDIN_FILENO | stdin |
1 | Standardowe wyjście | STDOUT_FILENO | stdout |
2 | Standardowy błąd | STDERR_FILENO | stderr |
Przegląd
tabeli deskryptorów plików dla poszczególnych procesów, utrzymywanej przez jądro, która z kolei indeksuje do ogólnosystemowej tabeli plików otwieranych przez wszystkie procesy, zwanej tablicą plików . Ta tabela rejestruje tryb , w jakim plik (lub inny zasób) został otwarty: do odczytu, zapisu, dołączania i ewentualnie innych trybów. Indeksuje również do trzeciej tabeli zwanej tablicą i-węzłów , która opisuje rzeczywiste pliki bazowe. Aby wykonać wejście lub wyjście, proces przekazuje deskryptor pliku do jądra poprzez wywołanie systemowe , a jądro uzyskuje dostęp do pliku w imieniu procesu. Proces nie ma bezpośredniego dostępu do pliku ani tabel i-węzłów.
W systemie Linux zestaw deskryptorów plików otwartych w procesie można uzyskać pod ścieżką /proc/PID/fd/
, gdzie PID jest identyfikatorem procesu . Deskryptor pliku /proc/PID/fd/0
to stdin
, /proc/PID/fd/1
to stdout
, a /proc/PID/fd/2
to stderr
. Jako skrót do nich, każdy działający proces może również uzyskać dostęp do własnych deskryptorów plików poprzez foldery /proc/self/fd
i /dev/fd
.
W systemach uniksopodobnych deskryptory plików mogą odnosić się do dowolnego typu pliku uniksowego nazwanego w systemie plików. Oprócz zwykłych plików obejmuje to katalogi , urządzenia blokowe i znakowe (zwane także „plikami specjalnymi”), gniazda domeny Unix i nazwane potoki . Deskryptory plików mogą również odnosić się do innych obiektów, które normalnie nie istnieją w systemie plików, takich jak anonimowe potoki i gniazda sieciowe .
Struktura danych FILE w standardowej bibliotece we/wy języka C zwykle zawiera deskryptor pliku niskiego poziomu dla danego obiektu w systemach typu Unix. Ogólna struktura danych zapewnia dodatkową abstrakcję i zamiast tego jest nazywana uchwytem pliku .
Operacje na deskryptorach plików
Poniżej wymieniono typowe operacje na deskryptorach plików w nowoczesnych systemach typu Unix . Większość z tych funkcji jest zadeklarowana w <unistd.h>
, ale niektóre zamiast tego znajdują się w nagłówku <fcntl.h>
.
Tworzenie deskryptorów plików
- otwórz ()
- utwórz()
- gniazdo elektryczne()
- zaakceptować()
- para gniazd()
- rura()
- epoll_create() (Linux)
- signalfd() (Linux)
- eventfd() (Linux)
- timerfd_create() (Linux)
- memfd_create() (Linux)
- userfaultfd() (Linux)
- fanotify_init() (Linux)
- inotify_init() (Linux)
- clone() (z flagą CLONE_PIDFD, Linux)
- pidfd_open() (Linux)
- open_by_handle_at() (Linux)
Wyprowadzanie deskryptorów plików
- dirfd()
- plik numer()
Operacje na pojedynczym deskryptorze pliku
- czytać (), pisać ()
- czytajv() , piszv()
- pread() , pwrite()
- recv() , wyślij()
- recvfrom() , sendto()
- recvmsg() , sendmsg() (używane również do wysyłania FD do innych procesów przez gniazdo domeny Unix)
- recvmmsg() , sendmmsg()
- szukaj() , szukaj()
- fstat()
- fstatvfs()
- fchmod()
- fchown()
- fruncate()
- fsync()
- fdatasync()
- fdopendir()
- fgetxattr() , fsetxattr() (Linux)
- flistxattr() , fremovexattr() (Linux)
- statx (Linux)
- zestawy (Linux)
- vmsplice() (Linux)
- pidfd_send_signal() (Linux)
- waitid() (z typem identyfikatora P_PIDFD, Linux)
- fdopen() (funkcja stdio: konwertuje deskryptor pliku na PLIK*)
- dprintf() (funkcja stdio: drukuje do deskryptora pliku)
Operacje na wielu deskryptorach plików
- wybierz() , pwybierz()
- ankieta() , ppoll()
- epoll_wait() , epoll_pwait() , epoll_pwait2() (Linux, pobiera pojedynczy filedescriptor epoll, aby czekać na wiele innych deskryptorów plików)
- epoll_ctl() (dla Linuksa)
- kqueue() (dla systemów opartych na BSD).
- Wyślij plik()
- splice() , tee() (dla Linuksa)
- copy_file_range() (dla Linuksa)
- close_range() (dla Linuksa)
Operacje na tablicy deskryptorów plików
Funkcja fcntl() służy do wykonywania różnych operacji na deskryptorze pliku, w zależności od przekazanego mu argumentu polecenia. Istnieją polecenia do pobierania i ustawiania atrybutów powiązanych z deskryptorem pliku, w tym F_GETFD, F_SETFD, F_GETFL i F_SETFL .
- zamknąć()
- closefrom() (tylko BSD i Solaris; usuwa wszystkie deskryptory plików większe lub równe podanej liczbie)
- dup() (duplikuje istniejący deskryptor pliku, gwarantując, że będzie to deskryptor pliku o najniższej dostępnej liczbie)
- dup2 () , dup3() (w razie potrzeby zamknij fd1 i ustaw deskryptor pliku fd1 na otwarty plik fd2)
- fcntl (F_DUPFD)
Operacje modyfikujące stan procesu
- fchdir() (ustawia bieżący katalog roboczy procesu na podstawie deskryptora pliku katalogu)
- mmap () (odwzorowuje zakresy pliku na przestrzeń adresową procesu)
Blokowanie plików
- trzoda()
- fcntl() (F_GETLK, F_SETLK i F_SETLKW)
- blokada()
Gniazda
- łączyć()
- wiązać()
- Słuchać()
- accept() (tworzy nowy deskryptor pliku dla połączenia przychodzącego)
- dostaje nazwę skarpetki()
- getpeername()
- getockopt()
- setsockopt()
- shutdown() (zamyka jedną lub obie połowy pełnego dupleksu połączenia)
Różnorodny
- ioctl() (duży zbiór różnych operacji na jednym deskryptorze pliku, często powiązany z urządzeniem)
Nadchodzące operacje
Szereg nowych operacji na deskryptorach plików został dodany do wielu nowoczesnych systemów uniksopodobnych, a także do licznych bibliotek C, które mają zostać ujednolicone w przyszłej wersji POSIX . Sufiks at
oznacza, że funkcja przyjmuje dodatkowy pierwszy argument dostarczający deskryptor pliku, z którego są rozwiązywane ścieżki względne , formularze pozbawione przyrostka at
stają się w ten sposób równoważne z przekazaniem deskryptora pliku odpowiadającego bieżącemu katalogowi roboczemu . Celem tych nowych operacji jest obrona przed określoną klasą TOCTOU .
- otwórz()
- faccess()
- fchmodat()
- fchownat()
- fstat()
- futimesat()
- łącze()
- mkdirat()
- mknodat()
- Odczyt łącza()
- zmień nazwę()
- dowiązanie symboliczne ()
- odłącz ()
- mkfifoat()
- fdopendir()
Deskryptory plików jako możliwości
Uniksowe deskryptory plików zachowują się na wiele sposobów jako możliwości . Mogą być przekazywane między procesami w gniazdach domeny Unix za pomocą wywołania systemowego sendmsg()
. Należy jednak zauważyć, że to, co jest faktycznie przekazywane, to odniesienie do „opisu otwartego pliku”, który ma zmienny stan (przesunięcie pliku oraz status pliku i flagi dostępu). To komplikuje bezpieczne korzystanie z deskryptorów plików jako możliwości, ponieważ gdy programy współużytkują dostęp do tego samego otwartego opisu pliku, mogą zakłócać wzajemne korzystanie z niego, zmieniając na przykład jego przesunięcie lub to, czy jest blokujący, czy nieblokujący. W systemach operacyjnych, które są specjalnie zaprojektowane jako systemy możliwości, bardzo rzadko istnieje zmienny stan powiązany z samą zdolnością.
Tabela deskryptorów plików procesu Unix jest przykładem listy C.
Zobacz też
- utrwalacz (Unix)
- lsof
- File Control Block (FCB) - alternatywny schemat w CP/M i wczesnych wersjach DOS