Как проверить, является ли данный файловый дескриптор, сохраненный в переменной, действительным?

У меня есть файловый дескриптор, хранящийся в переменной скажем var. Как я могу проверить, является ли этот дескриптор допустимым на более позднем этапе?

  fdvar1= open(.....);
  fdvar2 = fdvar1;       // Please ignore the bad design

  ....
  // lots of loops , conditionals and threads. It can call close(fdvar2) also.  
  ....

  if(CheckValid(fdvar1)) // How can I do this check  ?
    write(fdvar1, ....);

Теперь я хочу проверить, действительно ли var1 (который все еще содержит открытый дескриптор) все еще действителен. Любой API для этого?

6 ответов

Решение

fcntl(fd, F_GETFD) канонический самый дешевый способ проверить, что fd является допустимым дескриптором открытого файла. Если вам нужно много раз проверить пакет, используя poll с нулевым таймаутом и тому events элемент установлен в 0 и проверка на POLLNVAL в revents после того, как это возвращается, более эффективно.

С учетом сказанного, операция "проверить, является ли данный дескриптор ресурса по-прежнему действительным", почти всегда в корне неверна. После освобождения дескриптора ресурса (например, fd close d) его значение может быть переназначено следующему такому ресурсу, который вы выделите. Если есть какие-либо оставшиеся ссылки, которые могут быть использованы, они будут неправильно работать с новым ресурсом, а не со старым. Таким образом, реальный ответ, вероятно, таков: если вы еще не знаете по логике своей программы, у вас есть серьезные фундаментальные логические ошибки, которые необходимо исправить.

Вы можете использовать fcntl() функция:

int fd_is_valid(int fd)
{
    return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
}

Я не думаю, что есть какая-либо функция, которая может сказать вам, если дескриптор все еще действителен. Дескриптор обычно представляет собой небольшое целое число, например 6, и ваш libc может выбрать повторное использование этого числа, если вы закроете файл и откроете новый позже.

Вместо этого вы должны рассмотреть возможность использования dup() скопировать дескриптор файла. Дублируя файловый дескриптор вместо использования одного и того же дескриптора в нескольких местах, вам может быть проще узнать, является ли файловый дескриптор все еще действительным. Вам просто нужно помнить, чтобы закрыть как оригинальный дескриптор, так и дублированный, когда вы закончите.

Из этой статьи на форуме:

int is_valid_fd(int fd)
{
    return fcntl(fd, F_GETFL) != -1 || errno != EBADF;
}

fcntl (GETFL), вероятно, является самой дешевой и наименее вероятной ошибочной операцией, которую вы можете выполнить с дескриптором файла. В частности, спецификация предполагает, что он не может быть прерван сигналами и не подвержен влиянию какой-либо блокировки, удерживаемой где-либо.

Мне кажется, что если вы хотите знать, указывает ли он на тот же ресурс, один (неидеальный) подход будет fstat() дескриптор сразу после открытия, а затем вы можете сделать это снова и сравнить результаты. Начните с просмотра .st_mode& S_IFMT и оттуда - это объект файловой системы? смотреть на .st_dev / .st_ino. Это гнездо? Пытаться getsockname(), getpeername(), Он не будет на 100% уверен, но он может сказать вам, если это точно не то же самое.

Я решил эту проблему для себя. я не знаю, можно ли его использовать для общего назначения, но для последовательных соединений он работает нормально (например, /dev/ttyUSB0)!

struct stat s;
fstat(m_fileDescriptor, &s);

// struct stat::nlink_t   st_nlink;   ... number of hard links 
if( s.st_nlink < 1 ){
 // treat device disconnected case
}

Подробности смотрите, например, на странице man http://linux.die.net/man/2/fstat

Ура, Фло

Другие вопросы по тегам