Файловые дескрипторы
Пытаюсь разобраться в файловых дескрипторах. Читаю разные статьи, пока не очень понятно как потрогать эти самые дескрипторы.
Вот я выбрал интересующий процесс (vlc с открытым фильмом).
По идее это покажет список всех файлов, открытых процессом, а заодно и их дескрипторы. Ожидал увидеть 1 строку с названием фильма. А там (помимо фильма) — просто МИЛЛИОННАЯ ПРОСТЫНЯ! Сотни файлов типа dir, reg, chr, fifo, unix, a_inode. Что это такое?
Неужели, чтобы плеер запустил простое видео, нужно действительно открыть сотни этих файлов?
Отдельно заинтересовала графа FD (думал что это файловый дескриптор). Там всякие cwd, rtd, mem, del, txt. а ближе к концу вида «0r, 1w, 2w, 3r. 26u. » и т.д. Что это означает? Я читал, что файловый дескриптор это целое число. Значит, это не файловый дескриптор?
Еще интересно что значат числа вроде «253,1» и «0,12» в графе device.
Еще нашел какую-то команду:
List File Descriptors in Kernel Memory
Но что-то не то выдает. Хотелось получить файловый дескриптор одного из файлов, вызванных процессом vlc, например.
Хотелось получить файловый дескриптор одного из файлов, вызванных процессом vlc, например.
А зачем? Это просто небольшое число. Обычно от 5 до 15.
Чтобы убедиться, у всех ли файлов он есть, уникальный ли он. Пока я что-то ни одной команды не нашел, чтобы посмотреть дескриптор, читаю man, как советовали выше.
Это просто небольшое число. Обычно от 5 до 15.
Про дескрипторы 0, 1 и 2 я уже прочитал в вики. С этими числами я уже сталкивался в теме перенаправления ввода-вывода в консоли. Думал что это какие-то особенные дескрипторы, а все остальные уникальны, вроде PID’ов. Но вот ты говоришь что это не так, осталось только найти способ проверить.
А зачем? Это просто небольшое число. Обычно от 5 до 15.
А существует ли практическая польза от этих знаний? Наверно где-то в программировании используется номер дескриптора?
чтобы плеер запустил простое видео
ну ты чел. хотел бы я посмотреть, как ты пишешь «простую» реализацию «простого» декодера h264, многопоточного и все дела. а потом собственно весь плеер с реализацией всех возможностей что он предоставляет
Неужели, чтобы плеер запустил простое видео, нужно действительно открыть сотни этих файлов?
Скорее всего открыты shared библиотеки, необходимые для запуска и работы приложения
Пытаюсь разобраться в файловых дескрипторах. Читаю разные статьи, пока не очень понятно как потрогать эти самые дескрипторы.
С какой целью интересуетесь? Тяжело внятно объяснить, не ударившись в программирование.
Сотни файлов типа dir, reg, chr, fifo, unix, a_inode. Что это такое?
Это разные типы. dir — понятно, каталог, reg — regular file (обычный файл), a_inode — анонимный (т.е. без соответствующего ему файла на диске) inode, и т.д. Кроме первых двух это уже «внутренности» системы.
Там всякие cwd, rtd, mem, del, txt… а ближе к концу вида «0r, 1w, 2w, 3r…26u…» и т.д. Что это означает?
cwd — это current working directory (текущий каталог), rtd — корневой, mem — это файлы, отображённые в память (см. mmap), и т.д. См. man lsof .
Еще интересно что значат числа вроде «253,1» и «0,12» в графе device.
Устройства в Linux однозначно идентифицируются парой чисел major-minor. Если упрощённо, то первое — это тип устройства, а второе — его индекс. Т.е. пара 253,1 означает «устройство типа 253 номер 1».
Неужели, чтобы плеер запустил простое видео, нужно действительно открыть сотни этих файлов?
Плеер — это довольно сложная программа, которой нужно взаимодействовать как с самой собой (между разными её компонентами), так и со средой, в которой она работает: графическая система, менеджер сессии (чтобы экран не гасился во время воспроизведения) и т.д. Чтобы не плодить 100500 специфических способов общения на каждый частный случай, всё строится поверх существующего файлового и сетевого API — отсюда и множество открытых файлов.
Rootlexx ★★★★ ( 20.01.20 19:17:20 MSK )
Последнее исправление: Rootlexx 20.01.20 19:18:26 MSK (всего исправлений: 1)
Ты зря начал с такой сложной программы, как видеоплеер. там и звук и аппаратное скорение декодирования и аппаратное ускорение вывода и сеть и интерфейс и ещё куча всего.
# cat < /dev/zero >/dev/null & [1] 19228 # lsof -p `pidof cat` lsof: WARNING: can't stat() tracefs file system /sys/kernel/debug/tracing Output information may be incomplete. COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME cat 19228 legolegs cwd DIR 253,16 12288 1721345 /home/legolegs cat 19228 legolegs rtd DIR 253,8 4096 2 / cat 19228 legolegs txt REG 253,8 52120 790266 /usr/bin/cat cat 19228 legolegs mem REG 253,8 217750512 940018 /usr/lib/locale/locale-archive cat 19228 legolegs mem REG 253,8 5591560 787730 /usr/lib64/libc-2.29.so cat 19228 legolegs mem REG 253,8 356392 786496 /usr/lib64/ld-2.29.so cat 19228 legolegs 0r CHR 1,5 0t0 3077 /dev/zero cat 19228 legolegs 1w CHR 1,3 0t0 3075 /dev/null cat 19228 legolegs 2u CHR 136,4 0t0 7 /dev/pts/4 # kill $! [1]+ Terminated cat < /dev/zero >/dev/null #
legolegs ★★★★★ ( 20.01.20 19:47:57 MSK )
Последнее исправление: legolegs 20.01.20 19:50:09 MSK (всего исправлений: 1)
- файловый дескриптор — это просто целое неотрицательное число, идентифицирующее поток ввода-вывода для процесса. Поток ввода-вывода — это в простейшем случае открытый файл, но сюда же попадают и сетевые сокеты, и пайпы.
lsof показывает больше, чем список дескрипторов — например, он показывает области памяти, полученные в результате mmap() (работа с файлом через отображение этого файла в память и работу с памятью). У таких областей памяти в столбце FD вместо дескриптора указана строка mem .
Там же показана текущая рабочая директория процесса ( cwd ), корневая директория процесса ( rtd ).
У обычных дескрипторов в этой колонке пишется номер дескриптора и режим, в котором он открыт (r — read, w — write, u — read+write). - дескрипторы могут быть связаны с разными типами файлов. Это отображается в столбце TYPE. Как я уже писал выше, это могут быть обычные файлы ( REG , regular file), пайпы ( FIFO ), юниксовые сокеты ( unix ), сетевые сокеты ( IPv4 ), символьные устройства ( CHR , character device), и т.д. Смотри в мане полный (на самом деле нет 🙂 ) список. В списке не описан тип a_inode . Если процесс работает с inotify, ему тоже возвращаются объекты-дескрипторы, они имеют тип a_inode (anonymous inode, вероятно).
- в моей бубунте vlc это динамический бинарник. Соответственно, в списке открытых файлов — все динамические библиотеки, которые нужны для его запуска; они обычно заммаплены (FD=mem).
Дальше идут нумерованные дескрипторы, в моём случае это:- 3 стандартных (0, 1, 2)
- две пары дескрипторов, связанных с одним и тем же пайпом (один на запись, другой на чтение, зачем — хз, возможно, для межпотокового взаимодействия)
- некоторое количество юниксовых сокетов, связанных с DM и около того (pulseaudio, dbus-daemon, mate-session)
- некоторое количество дескрипторов от inotify
- пара символьных устройств — /dev/urandom и /dev/dri/card0 (для direct rendering, вестимо)
- и, наконец-то, дескриптор, связанный с проигрываемым на данный момент файлом.
- числа в графе device — major и minor numbers — идентификаторы устройства, на котором лежит указанный файл.
- файловый дескриптор имеет смысл только в контексте процесса, работающего с вводом-выводом, у разных процессов одни и те же файловые дескрипторы могут быть (и будут!) связаны с разными файлами и прочими потоками ввода-вывода.
Чтобы оставить только обычные дескрипторы, используй команду lsof -a -d 0-9000 -p $(pidof vlc) .
tiandrey ★★★★★ ( 20.01.20 20:14:39 MSK )
Последнее исправление: tiandrey 20.01.20 20:16:24 MSK (всего исправлений: 1)
cwd — это current working directory (текущий каталог), rtd — корневой, mem — это файлы, отображённые в память (см. mmap), и т.д. См. man lsof.
(например, «0r», «1w», «26u») — это как раз то, что вас интересует. Число — дескриптор, символ — режим, в котором открыт файл: на чтение, на запись или оба.
Получается, что дескриптор есть не у всего?
90% того что находится в графе/столбце FD — это как раз «mem». И еще несколько записей вроде cwd, rtd, txt, dex.
И только где-то в конце последние 20-30 файлов имеют эти числа. Могу предположить, что файлы, которые находятся в памяти (mem) не имеют дескриптора? У файлов-каталогов его тоже нет?
Когда приложение запрашивает ОС открыть файл, то ОС такие запросы нумерует чтобы не тягаться с именами файлов. Когда-то давно это давало жуткую экономию. Этот номер собственно и есть файловым дескриптором.
первые три файла ОС открывает по собственной инициативе и присваивает им номера 0, 1, 2. Поэтому номера присваиваемые запросам самого приложения начинаются с 3. Запрос на открытие пользовательского файла идет после того как приложение запросило файлы нужные ему самому, ну там ресурсы, скины, кодеки и всякое такое. Поэтому номер для файла пользователя начинается где-то от 5. Хотя, впринцыпе, приложение может запросить любой номер для любого файла.
Прочитай уже маны к lsof. Не всё, что отображает lsof это файловые дескрипторы.
Сокет сервера Linux — неправильный дескриптор файла
У меня проблема с сокетом сервера под Linux. По неизвестной мне причине пропадает сокет сервера и я получаю Bad file descriptor ошибка в вызове выбора, ожидающего входящего соединения. Эта проблема всегда возникает, когда я закрываю несвязанное соединение сокета в другом потоке. Это происходит на встроенном Linux с ядром 2.6.36.
Кто-нибудь знает, почему это произойдет? Это нормально, что сокет сервера может просто исчезнуть, что приводит к Bad file descriptor ?
редактировать: другой код сокета реализует VNC-сервер и работает в совершенно другом потоке. Единственное, что особенного в этом другом коде — это использование setjmp/longjmp но это не должно быть проблемой.
Код, который создает сокет сервера, следующий:
int server_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); struct sockaddr_in saddr; memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(INADDR_ANY); saddr.sin_port = htons(1234); const int optionval = 1; setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &optionval, sizeof(optionval)); if (bind(server_socket, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) < perror("bind"); return 0; >if (listen(server_socket, 1)
Я жду входящего соединения, используя код ниже:
static int WaitForConnection(int server_socket, struct timeval *timeout) < fd_set read_fds; FD_ZERO(&read_fds); int max_sd = server_socket; FD_SET(server_socket, &read_fds); // This select will result in 'EBADFD' in the error case. // Even though the server socket was not closed with 'close'. int res = select(max_sd + 1, &read_fds, NULL, NULL, timeout); if (res >0) < struct sockaddr_in caddr; socklen_t clen = sizeof(caddr); return accept(server_socket, (struct sockaddr *) &caddr, &clen); >return -1; >
редактировать: когда возникает проблема, я просто перезагружаю сервер, но я не понимаю, почему идентификатор сокета сервера должен внезапно стать неверным дескриптором файла:
int error = 0; socklen_t len = sizeof (error); int retval = getsockopt (server_socket, SOL_SOCKET, SO_ERROR, &error, &len ); if (retval
CUPS 2.0 lpstat and lpinfo commands return «Bad file descriptor» [closed]
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
I have installed cups 2.0 on my Ubuntu box. I installed from source. When I type the first few commands in the CUPS manual it returns the message Bad file descriptor. Here is an example
VPCZ12V9E:~$ sudo lpinfo -m lpinfo: Bad file descriptor VPCZ12V9E:~$ lpstat -p lpstat: Bad file descriptor
Please suggest why this is happening? It implies to me that I have a problem. I have not tried adding a printer yet. I have only installed CUPS 2.0.
I got that error after installing cups-bsd apt install cups-bsd . After restarting cups service, it worked for me.
5 Answers 5
Ensure also you have Started Cupsd Service
Maybe the service name has changed or something. I just now started the services cups.service, cups.path, and cups.socket in order to make my printer start working again. (I don’t know whether all three were needed, but enabling cups.service caused the enablement of the other two, so I thought that I’d better start all three since they seemed to want to be together.) But other than that difference this answer solved my problem.