Основными операциями, предоставляемыми ядром операционной системы программам (а точнее — процессам) для работы с файлами, являются системные вызовы open read, write и close. В соответствии со своими именами, эти системные вызовы предназначены для открытия и закрытия файла, для чтения из файла и записи в файл. Дополнительный системный вызов ioctl (input output control) используется для управления драйверами устройств и, как следствие, применяется в основном для специальных файлов устройств.
При запросе процесса на открытие файла системным вызовом оpen производится его однократный (относительно медленный) поиск имени файла в дереве каталогов и для запросившего процесса создается так называемый файловый дескриптор (описатель, от англ, descriptor).
Файловый дескриптор «содержит» информацию, описывающую файл, например индексный дескриптор inode файла на файловой системе, номера major и minor устройства, на котором располагается файловая система файла, режим открытия файла, и прочую служебную информацию.
При последующих операциях read и write доступ к самим данным файла происходит с использованием файлового дескриптора (что исключает медленный поиск файла в дереве каталогов).
Файловые дескрипторы пронумерованы и содержатся в таблице открытых процессом файлов, которую можно получить при помощи диагностической программы lsof.
В обратную сторону получить список процессов, открывших тот или иной файл, можно при помощи программ lsof и fuser, что бывает полезно для идентификации программ, «занявших» файловую систему, подлежащую отмонтированию.
Таблица файловых дескрипторов
john@ubuntu:~$ lsof -р $$
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
. . . . . . . . .
bash 17975 john 1u CHR 136,2 0t0 5 /dev/pts/2
. . . . . . . . .
2) root@ubuntu:~# lsof /dev/log
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
rsyslogd 543 syslog 0u unix 0xefef5680 0t0 1338 /dev/log
root@ubuntu:~# fuser /dev/log
/dev/log: 543
root@ubuntu:~# ps p 543
PID TTY STAT TIME COMMAND
543 ? Sl 0:43 rsyslogd -c5
root@ubuntu:~# lsof /var/log/syslog
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
rsyslogd 543 syslog lw REG 252,0 29039 26214496 /var/log/syslog
В первом примере из листинга выше показано получение списка файловых дескрипторов (столбец FD) процесса командного интерпретатора bash пользователя john, на котором файловый дескриптор номер 1 описывает открытый на чтение и запись и специальный символьный CHR файл устройства /dev/pts/2.
Во втором примере показано получение информации о процессе, открывшем файловый сокет unix с именем /dev/log (файловый дескриптор номер 0 на чтение и запись u) и обычный файл REG с именем /var/log/sysog (файловый дескриптор номер 1 на запись w).
Пронаблюдать за использованием системных вызовов файлового программного интерфейса в момент выполнения программам позволяет системный трассировщик strace.
Трассировка файлового программного интерфейса
john@ubuntu:~$ date
Вт. окт. 15 18:17:42 MSK % 2018
john@ubuntu:~$ strace -fe open, close, read, write, ioctl date
. . . . . . . . .
open(«/etc/localtime», 0_RDONLY|0_CLOEXEC) = 3
. . . . . . . . .
john@ubuntu:~$ file /etc/localtime
/etc/localtime: timezone data, version 2, 13 gmt time flags, 13 std time flags, no leap
seconds, 77 transition tines, 13 abbreviation char
john@ubuntu:~$ ls -la /dev/dvd
lrwxrwxrwx 1 root root 3 окт. 16 18:09 /dev/dvd -> sr0
john@ubuntu:~$ strace -fe open,close, read,write,ioctl eject
. . . . . . . . .
open(«/dev/sr0», O_RDWR|O_N0NBLOCK) = 3
ioctl(3, CDROMEJECT, 0x804cb4e) = 0
closed(3) = 0
john@ubuntu: ~$ strace -fe open, read,write,close,ioctl setleds -L +num +scroll
ioctl(0, KDGKBLED, 0xbfe4f4ff) = 0
ioctl(0, KDGETLED, 0xbfe4f4fe) = 0
ioctl(0, KDSETLED, 0x3) = 0
Предположив, что программа date показывает правильное московское время, потому что узнаёт заданную временную зону MSK из некоего конфигурационного файла операционной системы, при трассировке ее «работы можно установить его точное имя — /etc/localtime.
Аналогично предположив, что программа eject открывает лоток привода CD/DVD при помощи специального файла устройства, при трассировке можно узнать имя файла /dev/sr0, номер файлового дескриптора при работе с файлом 3 и команду CDROMEJECT соответствующего устройству
драйвера ioctl_List.
Трассировка команды setleds показывает, что она вообще не открывает никаких файлов, но пользуется файловым дескриптором о так называемого стандартного потока ввода (прикрепленного, к текущему терминалу) и командами kdgetled и kdsetled драйвера консоли console_ioctl.