Что такое файловый дескриптор простыми словами
Файловый дескриптор — это неотрицательное число, которое является идентификатором потока ввода-вывода. Дескриптор может быть связан с файлом, каталогом, сокетом.
Например, когда вы открываете или создаете новый файл, операционная система формирует для себя запись для представления этого файла и хранения информации о нем. У каждого файла индивидуальный файловый дескриптор Linux. Открыли 100 файлов — где-то в ядре появились 100 записей, представленных целыми числами.
Как файлы получают дескрипторы
Обычно файловые дескрипторы выделяются последовательно. Есть пул свободных номеров. Когда вы создаете новый файл или открываете существующий, ему присваивается номер. Следующий файл получает очередной номер — например, 101, 102, 103 и так далее.
Дескриптор для каждого процесса является уникальным. Но есть три жестко закрепленных индекса — это первые три номера (0, 1, 2).
- 0 — стандартный ввод (stdin), место, из которого программа получает интерактивный ввод.
- 1 — стандартный вывод (stdout), на который направлена большая часть вывода программы.
- 2 — стандартный поток ошибок (stderror), в который направляются сообщения об ошибках.
Когда вы завершаете работу с файлом, присвоенный ему дескриптор освобождается и возвращается в пул свободных номеров. Он снова доступен для выделения под новый файл.
В Unix-подобных системах файловые дескрипторы могут относиться к любому типу файлов Unix: обычным файлам, каталогам, блочным и символьным устройствам, сокетам домена, именованным каналам. Дескрипторы также могут относиться к объектам, которые не существуют в файловой системе: анонимным каналам и сетевым сокетам.
Понятием «файловый дескриптор» оперируют и в языках программирования. Например, в Python функция os.open(path, flags, mode=0o777, *, dir_fd=None) открывает путь к файлу path, добавляет флаги и режим, а также возвращает дескриптор для вновь открытого файла. Начиная с версии 3.4 файловые дескрипторы в дочернем процессе Python не наследуются. В Unix они закрываются в дочерних процессах при выполнении новой программы.
Комьюнити теперь в Телеграм
Подпишитесь и будьте в курсе последних IT-новостей
Для чего нужны файловые дескрипторы
Чтобы оценить важность файловых дескрипторов, нужно разобраться, как работает файловая система.
- В традиционной реализации Unix дескрипторы индексируются в таблицу дескрипторов для каждого процесса, поддерживаемого ядром.
- Таблица файловых дескрипторов индексирует общесистемную таблицу файлов, открытых всеми процессами.
- В таблице файлов записывается режим, в котором открыт файл или другой ресурс — например, для чтения, записи, чтения и записи.
- Режим индексируется в таблицу индексных дескрипторов, описывающих фактические базовые файлы. В каждом индексном дескрипторе хранятся атрибуты и расположение дисковых блоков переданного объекта.
Когда нужно выполнить ввод или вывод, процесс через системный вызов передает ядру дескриптор нужного файла. Ядро обращается к файлу от имени процесса. При этом у самого процесса нет доступа к файлу или таблице индексных дескрипторов.
Что такое плохой файловый дескриптор
Это ошибка, которая может возникнуть в многопоточных приложениях, — Bad file descriptor. Чтобы исправить ее, нужно найти код, который закрывает один и тот же дескриптор файла. Может произойти и другая ситуация — например, один поток уже закрыл файл, а другой поток пытается получить к нему доступ.
В однопоточных приложениях такая проблема обычно не возникает.
Что можно делать с файловыми дескрипторами
Файловые дескрипторы можно использовать для исправления ошибок. Например, если на диске нет свободного места, но вы не видите файлы, которые занимают пространство, то можно посмотреть открытые дескрипторы. Это поможет понять, какое приложение заняло весь доступный объем.
Важно понимать, что если мы один раз открыли файл, и он получил файловый дескриптор, то мы можем взаимодействовать с ним дальше. Не имеет значения, что с этим файлом происходит. Его могут переименовать, удалить, могут изменить его владельца, отобрать права на запись и чтение. Если вы уже начали работать с файлом и знаете его дескриптор, то можете продолжать с ним работать.
BSDPORTAL.RU
Здравствуйте!
FreeBSD у меня установлена на виртуальной машине и у меня возникла проблема с запуском сессий MATE.
Когда у меня была запущена сессия MATE, произошла аварийная перезагрузка Windows. После этого запустить MATE стало невозможно, при запуске в консоли пишется Failed to open file ‘home/eicosane/.config/dconf/user’: Permission denied.
Ранее я эту проблему решал, удаляя этот файл user. Но теперь я сделать этого не могу, при попытке удаления пишется:
rm: user: bad file descriptor.
Я пытался бороться, прописав в rc.conf:
fsck_y_enable=»YES»
fsck_y_flags=»-f»
background_fsck=»NO».
Но это не помогло.
Заголовок сообщения: Re: Bad file descriptor
Добавлено: Вс 31 янв, 2016 10:15 pm
Загрузитесь в single user mode и запустите руками fsck.
Bad file descriptor что это
Есть сервер, который используя жаббероподобный протокол, обслуживает клиентов. Всё многопоточно, работает в режиме один поток — один клиент, блокирующий режим.
В теле цикла select, который следит за несколькими сокетами. один сокет к клиенту, другие — для внутренних целей (синхронизация и так дальше, используются unix сокеты).
все чтения/записи с/в сокет и другие блокирующие операции с сокетами (open, close. ) завернуты в TEMP_FAILURE_RETRY или делается проверка на errno==-1 и EINT. Это надо, так как приложение активно использует сигналы (Основную массу времени поток спит в select. А другие потоки посылают SIGUSR1/SIGUSR2 что бы пробудить поток (обычно это нужно только для удаления дубликатов — пользователи любят подключаться несколько раз — старые сессии удаляем). На другие сигналы (например SIGSERV) тоже повешены обработчики, которые находят поток-вредитель и завершают его.
И вот время от времени на клиентах при попытке сделать select возникает ошибка и errno возвращает Bad file descriptor. Интересно то, что возникает в нескольких потоках практически одновременно.
Интересуют методы выявления, какой сокет может быть плохим или как не допустить вообще такой ситуации, может есть какой-нибудь макрос/функция, что бы проверить, что сокет стал плохим.
Re: Ошибка Bad file descriptor
От: | zaufi |
Дата: | 17.02.09 10:46 |
Оценка: |
Здравствуйте, OdesitVadim, Вы писали:
OV>Есть сервер, который используя жаббероподобный протокол, обслуживает клиентов. Всё многопоточно, работает в режиме один поток — один клиент, блокирующий режим.
?? чото я недопонял кто кого блокирует ??
OV>В теле цикла select, который следит за несколькими сокетами. один сокет к клиенту, другие — для внутренних целей (синхронизация и так дальше, используются unix сокеты).
OV>все чтения/записи с/в сокет и другие блокирующие операции с сокетами (open, close. ) завернуты в TEMP_FAILURE_RETRY или делается проверка на errno==-1 и EINT. Это надо, так как приложение активно использует сигналы (Основную массу времени поток спит в select. А другие потоки посылают SIGUSR1/SIGUSR2 что бы пробудить поток (обычно это нужно только для удаления дубликатов — пользователи любят подключаться несколько раз — старые сессии удаляем).
OMG! зачем так сложно то все? чем mutexы с conditionами не устраивают?
OV> На другие сигналы (например SIGSERV) тоже повешены обработчики, которые находят поток-вредитель и завершают его.
может SIGSEGV?? я конечно не знаю деталей твоего приложения но еси оно валицо по SIGSEGV нада найти баг и исправить его а не закрывать на это глаза делая вид что ничо страшного не происходит
OV>И вот время от времени на клиентах при попытке сделать select возникает ошибка и errno возвращает Bad file descriptor. Интересно то, что возникает в нескольких потоках практически одновременно.
OV>Интересуют методы выявления, какой сокет может быть плохим или как не допустить вообще такой ситуации, может есть какой-нибудь макрос/функция, что бы проверить, что сокет стал плохим.
сокет сам по себе «плохим» не становится. еси полоть закрытый (не существующий) сокет (дескриптор) получишь именна эту ошибку. погоняй свою прогу под valgrindом — imho многа нового узнаешь о поведении своей проги
Re[2]: Ошибка Bad file descriptor
От: | OdesitVadim |
Дата: | 17.02.09 14:59 |
Оценка: |
Здравствуйте, zaufi, Вы писали:
Z>Здравствуйте, OdesitVadim, Вы писали:
OV>>Есть сервер, который используя жаббероподобный протокол, обслуживает клиентов. Всё многопоточно, работает в режиме один поток — один клиент, блокирующий режим.
Z>?? чото я недопонял кто кого блокирует ??
Сокеты в блокирующем режиме.
Z>OMG! зачем так сложно то все? чем mutexы с conditionами не устраивают?
Не все мютексами можно разрулить.
OV>> На другие сигналы (например SIGSERV) тоже повешены обработчики, которые находят поток-вредитель и завершают его.
Z>может SIGSEGV?? я конечно не знаю деталей твоего приложения но еси оно валицо по SIGSEGV нада найти баг и исправить его а не закрывать на это глаза делая вид что ничо страшного не происходит
Да, соскользнула рука. да эти события как неуловимые джо. Нет, нет. а потом хоп. но отрубать сразу всех клиентов как то не с руки.
Z>сокет сам по себе «плохим» не становится. еси полоть закрытый (не существующий) сокет (дескриптор) получишь именна эту ошибку. погоняй свою прогу под valgrindом — imho многа нового узнаешь о поведении своей проги
Да в том то дело, что если я сокет закрываю, то переменная для сокета получает значение -1. и кругом есть проверки на это -1.
под valgrindом гонял. часть отловил. Но к сожалению, он не всё может розрулить и основная масса сообщений — это либо баги валгринда, на их сайте написано «не обращать внимания», либо то, что даже непонятно, как устранить.
Но это не так важно, так как на отладочной машине я не могу воспроизвести ситуацию. А на продакшине — повторяется.
Чувствую, буду ещё жесче проверять сокеты.
asio, bad file descriptor(EBADF)
есть некоторый код, написанный с использованием asio, реализующий обмен некоторыми данными между клиентом и сервером.
- подключение к серверу
- обмен публичными ключами
- отсылает один пакет данных
- в основном находится в ожидании
проблема в том, что первые три пункта выполняются успешно, но после некоторого ожидания, при попытке послать серверу очередные данные, запись завершается с ошибкой «bad file descriptor»(EBADF)
попытки понять кто/кодга и почему закрывает сокет — ничего не дали. (сокет, вроде бы, ни клиент, ни сервер, не закрывают)
вопрос в том, есть ли какой-то софт, которым я могу мониторить состояние сокета извне?
ну и вообще, какие мысли?