Не удалось получить файловый дескриптор, указывающий на консоль

Обновлено: 20.11.2024

Я читаю реализацию программы оболочки на C (оболочка xv6 из курса 6.828 Operating System Engineering MIT).

Функция main() для этой оболочки начинается со следующего кода:

Это цитата из книги xv6, объясняющая приведенный выше код:

"Оболочка гарантирует, что в ней всегда открыты три файловых дескриптора, которые являются файловыми дескрипторами по умолчанию для консоли."

Я понимаю, что open() вернет дескриптор файла с наименьшим доступным номером, поэтому этот код гарантирует, что открыто не более трех дескрипторов файлов, что довольно очевидно после прочтения объяснения автора.

Но вот что я не понимаю:

Почему оболочка хочет закрыть все файловые дескрипторы, кроме 0, 1 и 2? Ведь гарантировано, что 0, 1 и 2 будут связаны с консолью, не так ли? Почему оболочка должна заботиться о файловых дескрипторах с большим числом закрытых?

Думаю, я не очень понимаю назначение файла консоли ( /dev/console ? ) здесь.

Он не закрывает "все файловые дескрипторы, кроме 0, 1 и 2", он закрывает один дополнительный файловый дескриптор для только что открытой консоли. Он не закрывает ничего, что уже было открыто до выполнения цикла.

Спасибо за быстрый ответ. Я не обратил внимания на заявление «перерыв». Не могли бы вы прокомментировать и эту часть моего вопроса: "Ведь гарантировано, что 0, 1 и 2 будут связаны с консолью, не так ли?" ? Спасибо.

2 ответа 2

Этот фрагмент кода открывает /dev/console . Результирующий файловый дескриптор — это файловый дескриптор с наименьшим номером, который еще не открыт. Если это число не больше 2, цикл выполняется снова. Если это число равно 3 или больше, дескриптор закрывается и цикл останавливается.

По завершении цикла файловые дескрипторы с 0 по 2 (stdin, stdout и stderr) гарантированно будут открыты. Либо они были открыты ранее и могут быть подключены к любому файлу, либо они только что были открыты и подключены к /dev/console .

Выбор /dev/console странный. Я бы ожидал /dev/tty , который всегда является управляющим терминалом, связанным с группой процессов вызывающего процесса. Это один из немногих файлов, существование которых требует стандарт POSIX. /dev/console — это системная консоль, куда отправляются сообщения системного журнала, отправляемые на консоль; оболочке бесполезно заботиться об этом.

У меня возникла проблема с Bash в Ubuntu в Windows. Если я набираю «открыть (имя файла)» на терминале Mac, он открывает файл с помощью правильной программы, но если я пытаюсь использовать его в Windows bash, он говорит: «Не удалось найти дескриптор файла, относящийся к консоли». < /p>

Я также пробовал xdg-open и gnome-open, но ни один из них не работает. Может кто-нибудь объяснить, как решить проблему и как работает команда open?
Заранее спасибо!

Можно попробовать запустить команду start из командного файла. Однако это внутренняя команда cmd. Поэтому вам нужно обернуть его как cmd /c start "" "filename"

Какую ошибку вы видите с командой, упомянутой выше? Кстати, вам может понадобиться преобразовать пути из Windows в Linux или наоборот.

5 ответов 5

Вместо open вы можете использовать xdg-open, который делает то же самое, независимо от приложения, т. е. pdf, изображения и т. д. Он откроет новый виртуальный терминал (я пробовал это в Linux)

Для Linux используйте xdg-open. open для Mac OS. open в linux — это псевдоним openvt (открытый виртуальный терминал).

Для упрощения вы можете добавить следующую строку в ~/.bashrc или ~/.zshrc в зависимости от используемой вами оболочки.

Тогда в следующий раз вы можете просто ввести следующее, чтобы уменьшить количество нажатий на клавиатуре.

Не по теме: я также определяю свои удаленные команды таким образом! s показывает запущенные задания p печатает самые последние выходные данные o отображает файл

Это связано с тем, что команда open предназначена для Mac и недоступна в Linux (ubuntu). Mac open может выполнить файл (если файл является исполняемым) или открыть файл в текстовом редакторе (если это документ). или текстовый файл) или откройте каталог.

Имеет смысл. Но в Linux и Ubuntu есть аналогичная команда под названием «xdg-open», поэтому я думаю, что есть способ реализовать ее и в Windows bash @hcheung. Я только что установил пакет xdg-utils, но он открывает файлы и папки внутри bash. Есть ли способ открыть файлы через программы Windows?

В Linux команда open является псевдонимом для openvt , который запускает команду в новом виртуальном терминале. Виртуальные терминалы открываются консолью. Консоль любит реагировать только на реальные терминалы (а не на эмулированные терминалы), поэтому консоль не давала эмулируемому терминалу контроль FD. Попробуйте запустить jpg, pdf, . команду просмотра прямо в вашем терминале. (Попробуйте sudo openvt -f -s -c 7 -- echo hi в реальном терминале Linux Ctrl Alt 3+.

Как уже отмечали другие, на Mac open делает то, что вы предполагаете. Я не пользователь Mac, поэтому не могу расширить этот абзац.

Однако в Windows есть собственная версия этих команд: start example.txt открывает Блокнот, start example.docx запускает Word, ну вы поняли. Однако Windows есть Windows, поэтому запуск может быть таким же умным, как и авторы обновлений: start "my file.txt" открывает окно командной строки под названием my file.txt .

Недавно собрал вещи, Малиновый пирожок, который уже больше четырех лет как пыльный 3B Host пришел, Уберите пыль, Подсоедините блок питания, Я еще могу пройти ранее установленный VNC Даже вкл. Я рад, Начать клонировать мой проект git, Расширить для них новую платформу. Выполняется проект cnblogs (Справочные ресурсы 《 Прогнозирование рейтинга Blog Park 》) При соответствующей команде рисования создается диаграмма тенденций 、 Прогнозная диаграмма, но изображение не открывается автоматически. Эта проблема была решена после некоторого исследования. Эта статья поделится процессом решения задач.

Первое сообщение об ошибке, которое вы видите:

Здесь я настроил язык консоли на китайском языке. Если он на английском языке, вот результаты:

Решительно искал в Интернете эту ошибку. Результаты меньше. В зависимости от решения она в основном делится на следующие типы:

Я не звонил. Вот команда setfont или loadkeys. Их прямое выполнение также сообщит о той же ошибке. Вам нужно выполнить ее в сценарии входа в систему? Попробуйте, я здесь ~/.bashrc Добавил такое предложение:

Перезапустите raspberry pie, на этот раз войдите через ssh, в результате появится ошибка:

Похоже, что заявление в Интернете отличается от того, что я встречал, я должен изучить его самостоятельно. К счастью, я не решаюсь 、 квантовая механика, о нет, strace, посмотрите, какая ссылка основного вызова имеет проблему :

brk (строка 53) Вам не нужно смотреть на предыдущий вывод, он принадлежит логике инициализации программы; Примечательным пунктом сообщения об ошибке является строка 70 и 79:

Эти две ошибки похожи, Все открыто tty У вас нет разрешения при установке устройства, И я пробовал все три разрешения и не смог, Соответственно: Чтение и запись (O_RDWR), Просто запись (O_WRONLY), только чтение (O_RDONLY), Похоже, чтобы включить это устройство ,открыть я старался изо всех сил ~

Почему у хороших людей нет авторитета? Посмотрим, что получилось:

Это устройство имеет root-доступ 、root Have 、 и не открывает никаких разрешений для других пользователей, неудивительно, что загрузка не удалась.

Поскольку основная причина вызвана разрешением , Затем начните с разрешения для решения , Система была обобщена до правил linux для разрешений на файлы ( Справочные ресурсы 《[apue] linux Доступ к файлам 》), Чтобы поставить root Созданный файл совместно с текущим пользователем, не так ли сложно?

консольная группа

Первая идея, которая возникла, заключается в том, чтобы создать новую группу пользователей (например, консоль), удерживать root и текущего пользователя pi. Присоединиться к этой группе, затем указать все группы устройства в качестве консоли и открыть соответствующие разрешения группы. , Таким образом, обмен может быть реализован. Некоторым это может показаться хлопотным. Просто установите неправильное оборудование tty для текущего пользователя. Для обычных файлов данных я часто делаю это. может не завести машину (личные страдания не разворачиваются). Кроме того, есть дополнительное преимущество. Когда новые пользователи сталкиваются с той же проблемой, просто добавьте его в эту группу (консоль). Так же, как и ! Ниже приведен соответствующий скрипт:

Clip in usermod Передняя и задняя группы Команда используется для отображения группы пользователей, к которой принадлежит текущий пользователь, чтобы проверить, успешно ли добавлены дополнительные группы (это не работает, см. следующее описание). Обратите внимание на то, что root Для работы учетной записи требуется su Switch , После переключения проверьте файлы, которые у него есть (/dev/console) Для работы , Во избежание ошибок в разрешениях , Наконец, после завершения выполнения выйдите Вернитесь к текущему пользователю . Вот два момента, на которые следует обратить внимание:

  • usermod -a Требуются параметры и -G В сочетании с , я использовал его раньше -a когда usemod будет печатать напрямую Использование, найдите человека, чтобы понять ;
  • После добавления пользователей в групповые группы результаты не отображаются сразу. Чтобы изменения вступили в силу, необходимо снова войти в систему. Специально для VNC Вход, выход Меню не работает, необходимо перезагрузить устройство.

Студенты, которым неудобно стучать по приказу, также могут напрямую войти в /etc/group Модификация файла:

Последняя строка . Ниже приведены новые результаты после успешной реализации ls Output:

Снова запустите в этот момент strace open, открытие направлено на консоль. Ваш визит прошел успешно!

Хотя из-за другого tty все еще есть ошибка без изменений, но хотя бы докажите, что направление правильное.

телефонная группа

Приведенная выше схема возможна. В представлении tty устройство непреднамеренно получает следующий вывод:

кроме tty0 / tty2 / tty3 Ваша группа пользователей принадлежит root Outside , Другие tty Оборудование принадлежит группе tty User , Оригинальная система уже подготовила для них готовые группы , которые я создал. На нем консоль Группа как бы добавляется к змейке, И наблюдайте за пользователями пи Дополнительная группа к которой она принадлежит :

Одним из них является tty, поэтому я решил использовать tty 了 . Таким образом, сценарий из предыдущего раздела можно упростить до:

Что создает группу пользователей 、 Добавьте дополнительные группы для пользователей, все из которых не нужны, Просто исправьте tty Группа пользователей файла устройства в порядке.

разрешение группы

Перезагрузите устройство, чтобы модификация вступила в силу, снова запустите strace open, проблема не устранена:

строка 70 Один раз не удалось, Но сразу строка 71 Успешная операция на том же устройстве, Разрешения в конце недостаточно. Ошибка соответствует /dev/tty2 Файл даже не появляется раньше, удивительно~

используй Дафа, посмотри:

all tty Установленные групповые разрешения становятся только для записи. Я забыл установить разрешения для каждого файла перед перезапуском устройства на предыдущем шаге? используйте номер корневой учетной записи chmod один раз, на этот раз вывод нормальный:

Но после повторного перезапуска права доступа к файлу все равно будут сброшены. Перед использованием группы консоли, когда я также обнаружил, что после перезапуска устройства /dev/console пользовательская группа файла автоматически сбрасывается на root, сбрасывает групповые разрешения на нулевой . К счастью, он просто сбрасывает разрешение только на запись. Вам нужно устанавливать его каждый раз, когда вы входите в tty. Разрешения на доступ к файлам?

xdg-открыть

Ответ: нет, не потому, что мы нашли решение, а даже при наличии соответствующих разрешений 、open Больше никаких искажений, изображение по-прежнему не открывается автоматически (Хан, ). Поэтому я решил попробовать другие команды. После Baidu нашел одну в Ubuntu. Это широко используемая команда xdg-open. Параметр - это путь к картинке, которую нужно открыть, Режим вызова и открытие одинаково. Вернись, открой Это я. mac Команды, используемые на , Не применять raspberrypi Это разумно , Что касается этого открытого Что такое , я не нашел соответствующей записи человека (это все еще три без заказов). Кроме того, если вы используете xdg-open, не нужно ли устанавливать группу пользователей и права доступа к файлу устройства? Я не пробовал, непонятно.

В этой статье исследуются причудливые права доступа к файлам устройств, комбинация Linux. Знания, связанные с разрешениями файлов, предприняли смелую попытку. Наконец, он нашел другой способ решить проблему. Если вы столкнулись с подобными проблемами в реальности, вы можете попробовать описанную выше схему. Независимо от того, работает она или нет, добро пожаловать, чтобы оставить сообщение и отзыв внизу статьи.

Это все о проблеме. Теперь давайте поговорим о двух отступлениях. На этот раз, очистив пыльный малиновый пирог, я глубоко осознал важность простой установки пароля, ssh, я перепробовал все свои общие пароли во время входа в систему, ни то, ни другое. , в итоге 1-6 меня спасли , а root это тоже пароль ~

Наконец, я посмотрел на сломанную акриловую пластиковую оболочку, я не могу этого вынести, Taobao решительно заменил новую оболочку. Сравнение до и после замены оболочки очевидно:

Последний малиновый пирог VNC Скриншоты:

Не удалось получить дескриптор файла, указывающий на консоль (не удалось получить дескриптор файла, указывающий на консоль) Дополнительные статьи о

Один файловый дескриптор .linux для дескриптора файла (FD:файловые дескрипторы). Его также можно назвать дескриптором файла. Когда программа открывает файл, ядро ​​возвращает соответствующий файловый дескриптор. Программа должна ссылаться на этот дескриптор. для обработки файла . Дескриптор файла — .

Программу можно понимать как обычный бинарный файл на жестком диске: Процесс - это бинарный файл, загружаемый в память, В дополнение к бинарным файлам, загружаемым в память, Также прилагаются все структуры, описывающие бинарный файл, Структура, описывающая процесс называется PCB(Process control block), здесь нет.

<р>1. Понимание перенаправления 2. Аппаратное устройство и файловые дескрипторы Что такое файловый дескриптор 3. Перенаправление вывода оболочки Linux 4. Перенаправление ввода оболочки Linux 5. Комбинация файловых дескрипторов Linux говорит о перенаправлении 6. Оболочка .

Обзор понять Linux Как работать с вводом и выводом очень важно. Как только мы узнаем, как это работает, мы сможем умело использовать сценарий для вывода содержимого в нужное место. Кроме того, мы можем лучше понять перенаправление ввода и перенаправление вывода. Линукс .

<р>1. Понимание перенаправления Оболочка Linux Существует два типа перенаправления: перенаправление ввода и перенаправление вывода. Буквально, перенаправление ввода-вывода означает 「Изменение направления ввода и вывода」. Направление ввода — это то, куда данные поступают в программу. Стандартный ввод .

Один . Подготовка знаний 1. Оставайтесь в Linux, Все является документом, Все различные типы абстрагируются в файлы. Например: Обычные документы. Каталог . Устройство персонажа. Блокировать устройство. Сокет и т. д. 2. Когда файл открывается процессом, создается дескриптор файла. Теперь путь к файлу .

Версия ядра: linux-2.6.11 Дескриптор файла (файловый дескриптор) остается Linux Программирование можно увидеть везде, Устройство читает/записывает. Сетевое общение. Процесс общения, можно сказать, ключ в ключ. Глубокое понимание может увеличить нашу уверенность в его использовании. .

Случайная рекомендация

ListView Оптимизация: (Первые два пункта - это использование ListView. Его собственный механизм оптимизации [Кэш-оптимизация]) 1. Использование ListView. Его собственный механизм кэширования. Он кэширует один из элементов записей, Когда список отображается на первом экране. показывает завершенный .

Недавно начал писать пул потоков, я хочу использовать общий шаблон функции, чтобы каждый поток выполнял разные задачи, eureka Boost В библиотечной функции function. Boost::function Является оболочкой функции, То есть шаблоном функции, Может использоваться для замены.

/** * Получить все каталоги, соответствующие условиям каталога, через обычный * @param luceneFilePathRegular Обычный каталог, например /user/solrindex/ Регулярные выражения * @return Удовлетворить обычную таблицу .

Введение в список Связанный список представляет собой общую структуру данных. Он связывает данные в ряд узлов данных. По сравнению с массивом Связанные списки более динамичны. При создании связанного списка нет необходимости заранее знать общий объем данных. Вы можете распределять пространство случайным образом. связанный список .

Мучась этим скромным атрибутом целый день, Наконец-то успокоилась. Потому что проект нужен, Чтобы объединить два приложения для Android, Так что скопируйте код, Скопируйте файл макета, Истязайте значения, После того, как все будет сделано, программа все еще часто вылетает, Не было причин, изучите время Android.

Docker в Windows 10 не запускается после удаления MobyLinuxVM в Hyper-V вручную Перезапустите Hyper-V Вот и все

Spring Cloud Интеграция различных компонентов. Каждый компонент часто имеет различные параметры. В этой статье подробно рассматриваются параметры Spring Cloud Tuning для каждого компонента. Параметры конфигурации Tomcat 1 сервер: 2 tomcat: 3 max-c .

Мы рассмотрели перенаправление ввода-вывода ранее в этом курсе. Помните, у нас было:

< td align="left">дескриптор файла 1 < td align="left">stderr
дескриптор файла 0 стандартный ввод
stdout
дескриптор файла 2

Мы были ограничены только этими тремя файловыми дескрипторами (FD)?

Нет, любой процесс может иметь до 9 файловых дескрипторов, пока мы обсудили только 3. По умолчанию каждый создаваемый терминал создается с тремя указанными выше файловыми дескрипторами.

Сначала давайте установим, на каком терминале мы в данный момент вошли в систему:

Вывод может быть одним из описанных ниже:

Это показывает список открытых файлов для этого PID (помните, что $$ был текущим PID).

Прочитайте справочные страницы для lsof, если вам нужна дополнительная информация об этой команде.

Если вы запустите приведенную выше команду, поскольку все терминалы открыты с указанными выше тремя файловыми дескрипторами, вы должны увидеть наши три файловых дескриптора. Все трое должны указывать на одно и то же место, на мой терминал.

Вывод, сгенерированный этими командами, показан ниже (конечно, вы увидите несколько отличающийся от моего вывод):

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

Это не очень привлекательное решение.

Еще один способ добиться этого — создать новый файловый дескриптор или, альтернативно, назначить наш существующий файловый дескриптор stdout файлу журнала (последний вариант показан ниже).

Переназначение существующего файлового дескриптора с помощью команды exec:

Вы заметите, что строка 3 перенаправляет стандартный вывод в $LOGFILE, поэтому строки 4 и 5 не должны явно перенаправлять свой вывод.

Теперь каждая команда, которую мы запускаем после этого, гарантирует, что ее вывод направляется в LOGFILE, который используется в качестве нового стандартного вывода.

Попробуйте это в своей командной строке следующим образом:

Помните, что у вас должны быть права на запись, чтобы иметь возможность писать в системный файл, такой как /var/log, поэтому здесь мы просто записываем файл журнала в наш текущий каталог.

Теперь мы перенаправили любой вывод из консоли (или терминала) в script.log. Что ж, это достаточно справедливо, но как это проверить? В командной строке введите:

Что происходит? Вы НЕ ПОЛУЧИТЕ то, что ожидали! Тип:

и он также не показывает рабочий каталог. Кажется, что команда завершена, но ничего не происходит — или, по крайней мере, мы не видим, происходит ли что-нибудь. На самом деле происходит то, что вывод этих команд поступает в наш файл script.log, как мы его настроили.

Снова выходные данные отправляются в script.log. Что ж, конечно, мы можем просто просмотреть файл журнала:

Что происходит? То же самое происходит, когда вы набираете pwd , ls или lsof — ничего (или вы даже можете получить ошибку). Вопрос в том, как вернуть свой стандартный вывод? Ответ: ВЫ НЕ МОЖЕТЕ!

Видите ли, перед переназначением stdout вы не сохранили исходный дескриптор стандартного выходного файла. Так что в некотором смысле вы фактически потеряли свой стандартный вывод. Единственный способ вернуть стандартный вывод — убить оболочку с помощью:

или нажмите Ctrl-D, чтобы выйти из оболочки. Затем это сбросит стандартный вывод, но также уничтожит оболочку. Это довольно экстремально и немного бесполезно!

Нам нужен лучший способ сделать это, поэтому вместо простого перенаправления моего стандартного вывода я собираюсь сохранить свой файловый дескриптор стандартного вывода в новый файловый дескриптор.

Посмотрите на следующее:

Вы заметите, что теперь у нас есть четыре файловых дескриптора (0,1,2 и 3), которые указывают на одно и то же имя узла.

С помощью exec мы можем создать до 9 новых файловых дескрипторов, но нам следует сохранить существующие файловые дескрипторы, если мы хотим впоследствии вернуть их в прежнее состояние.

Попробуем переназначить FD 3 файлу riaan.log

Теперь вы должны увидеть что-то другое, потому что имя узла было обновлено и теперь указывает на riaan.log для файлового дескриптора 3.

Помните, что это перенаправление файловых дескрипторов допустимо только для этой оболочки, а не для дочерних процессов. [21]

Мы можем создать до 9 файловых дескрипторов для каждого процесса и сохранить существующие файловые дескрипторы, чтобы восстановить их позже. Мы можем закрыть файловый дескриптор с помощью:

Чтобы убедиться, что файловый дескриптор 3 действительно закрыт, выполните:

и вы увидите только файловые дескрипторы 0,1 и 2.

Управление файловыми дескрипторами может быть очень эффективно использовано в наших сценариях, потому что вместо перенаправления каждой команды в файл журнала теперь мы можем просто перенаправить стандартный вывод:

Затем на консоли появится сообщение "Готово", потому что мы сохранили дескриптор файла stdout в дескрипторе файла 3.

Перенаправление ввода будет работать аналогичным образом:

Тогда все входные данные будут взяты из файла restaurant.txt.

Упражнения

Измените свой скрипт foodout таким образом, чтобы любые ошибки, создаваемые скриптом, перенаправлялись в файл с именем eatout.err в вашем домашнем каталоге.

Разрешите пользователю выбирать из меню в eatout.sh, но убедитесь, что его нажатия клавиш записываются в файл с именем eatout.log

Напишите сценарий, который должен принимать два аргумента: входной файл (-i infile) и выходной файл (-o outfile). Используя перенаправление дескриптора файла, скрипт должен преобразовать все данные из входного файла (infile) в верхний регистр и записать файл в верхнем регистре в выходной файл (outfile). Убедитесь, что ваш сценарий выполняет всю необходимую проверку ошибок, что его нельзя «сломать», убить и т. д., и что все пользовательские параметры надлежащим образом проверены, чтобы убедиться, что они соответствуют требуемым. Убедитесь, что при обнаружении ошибок предоставляется статус выхода. Пример командной строки приведен ниже:

Сейчас самое время собрать воедино все, чему вы научились в пути. Всегда полезно завершать сценарий комментариями о том, что он делает, давать пользователю сообщение об использовании, если он использует опцию -h или -help, и сделать сценарий почти не требующим пояснений. Не будьте небрежны, потому что вы пожалеете об этом, когда сценарий нужно будет поддерживать.

[21] вы можете проверить, что это так, запустив другой bash и выполнив команду lsof для этого нового процесса. Выход из этого bash вернет вас к исходным файловым дескрипторам

Читает данные из указанного файла или устройства ввода-вывода (I/O). Чтение происходит в позиции, указанной указателем файла, если это поддерживается устройством.

Эта функция предназначена как для синхронных, так и для асинхронных операций. Аналогичную функцию, предназначенную исключительно для асинхронной работы, см. в разделе ReadFileEx.

Синтаксис

Параметры

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

Параметр hFile должен быть создан с доступом для чтения. Дополнительные сведения см. в разделах «Общие права доступа» и «Безопасность файлов и права доступа».

Для асинхронных операций чтения hFile может быть любым дескриптором, открытым с флагом FILE_FLAG_OVERLAPPED функцией CreateFile, или дескриптором сокета, возвращаемым функцией сокета или принятия.

Указатель на буфер, который получает данные, считанные из файла или устройства.

Этот буфер должен оставаться действительным на протяжении операции чтения. Вызывающий не должен использовать этот буфер, пока операция чтения не будет завершена.

Максимальное количество байтов для чтения.

[выходной, необязательный] lpNumberOfBytesRead

Указатель на переменную, которая получает количество прочитанных байтов при использовании синхронного параметра hFile. ReadFile устанавливает это значение равным нулю перед выполнением каких-либо действий или проверкой ошибок. Используйте NULL для этого параметра, если это асинхронная операция, чтобы избежать потенциально ошибочных результатов.

Этот параметр может иметь значение NULL, только если параметр lpOverlapped не равен NULL.

Дополнительную информацию см. в разделе "Примечания".

[вход, выход, необязательно] lpOverlapped

Указатель на структуру OVERLAPPED требуется, если параметр hFile был открыт с флагом FILE_FLAG_OVERLAPPED, в противном случае он может иметь значение NULL.

Если hFile открывается с FILE_FLAG_OVERLAPPED, параметр lpOverlapped должен указывать на действительную и уникальную структуру OVERLAPPED, иначе функция может неправильно сообщить о завершении операции чтения.

Для hFile, который поддерживает смещения в байтах, если вы используете этот параметр, вы должны указать смещение в байтах, с которого начинается чтение из файла или устройства. Это смещение задается путем установки членов Offset и OffsetHigh структуры OVERLAPPED. Для hFile, не поддерживающего смещения в байтах, Offset и OffsetHigh игнорируются.

Дополнительную информацию о различных комбинациях lpOverlapped и FILE_FLAG_OVERLAPPED см. в разделах "Примечания" и "Синхронизация и положение файла".

Возвращаемое значение

Если функция завершается успешно, возвращаемое значение не равно нулю (ИСТИНА).

Если функция завершается со сбоем или завершается асинхронно, возвращаемое значение равно нулю (FALSE). Чтобы получить расширенную информацию об ошибке, вызовите функцию GetLastError.

Примечание. Код GetLastError ERROR_IO_PENDING не является ошибкой; это означает, что операция чтения ожидает завершения асинхронно. Дополнительные сведения см. в разделе «Примечания».

Примечания

Функция ReadFile возвращает значение при выполнении одного из следующих условий:

Функция ReadFile может завершиться с ошибкой ERROR_INVALID_USER_BUFFER или ERROR_NOT_ENOUGH_MEMORY при наличии слишком большого количества необработанных запросов асинхронного ввода-вывода.

Чтобы отменить все ожидающие операции асинхронного ввода-вывода, используйте:

Используйте CancelSynchronousIo для отмены ожидающих синхронных операций ввода-вывода.

Операции ввода-вывода, которые отменены, завершаются с ошибкой ERROR_OPERATION_ABORTED.

Функция ReadFile может завершиться с ошибкой ERROR_NOT_ENOUGH_QUOTA, что означает, что буфер вызывающего процесса не может быть заблокирован на странице. Дополнительные сведения см. в разделе SetProcessWorkingSetSize.

Если часть файла заблокирована другим процессом и операция чтения перекрывает заблокированную часть, эта функция не работает.

Доступ к входному буферу, когда операция чтения использует буфер, может привести к повреждению данных, считываемых в этот буфер. Приложения не должны читать, записывать, перераспределять или освобождать входной буфер, используемый операцией чтения, до завершения операции чтения. Это может быть особенно проблематично при использовании асинхронного дескриптора файла. Дополнительную информацию о синхронных и асинхронных дескрипторах файлов можно найти в разделе «Синхронизация и положение файла» и в справочном разделе CreateFile.

Символы можно считывать из буфера ввода консоли с помощью ReadFile с дескриптором ввода в консоль. Режим консоли определяет точное поведение функции ReadFile. По умолчанию режим консоли — ENABLE_LINE_INPUT, что указывает на то, что ReadFile должен читать до тех пор, пока не дойдет до возврата каретки. Если вы нажмете Ctrl+C, вызов завершится успешно, но GetLastError вернет ERROR_OPERATION_ABORTED. Дополнительные сведения см. в разделе CreateFile.

При чтении с устройства связи поведение ReadFile определяется текущим тайм-аутом связи, установленным и полученным с помощью функций SetCommTimeouts и GetCommTimeouts. Непредсказуемые результаты могут возникнуть, если вы не установите значения тайм-аута.Дополнительные сведения о тайм-аутах связи см. в разделе COMMTIMEOUTS.

Если ReadFile пытается прочитать из почтового ящика со слишком маленьким буфером, функция возвращает FALSE, а GetLastError возвращает ERROR_INSUFFICIENT_BUFFER.

Существуют строгие требования для успешной работы с файлами, открытыми с помощью CreateFile с использованием флага FILE_FLAG_NO_BUFFERING. Подробнее см. в разделе «Буферизация файлов».

Если hFile был открыт с FILE_FLAG_OVERLAPPED, действуют следующие условия:

Синхронизация и расположение файла

Если hFile открывается с FILE_FLAG_OVERLAPPED, это асинхронный дескриптор файла; в противном случае это синхронно. Как отмечалось ранее, правила использования структуры OVERLAPPED немного различаются для каждой из них.

  • ReadFile может вернуться до завершения операции чтения. В этом сценарии ReadFile возвращает FALSE, а функция GetLastError возвращает ERROR_IO_PENDING, что позволяет продолжить вызывающий процесс, пока система завершает операцию чтения.
  • Параметр lpOverlapped не должен иметь значение NULL и должен использоваться с учетом следующих фактов:
    • Хотя событие, указанное в структуре OVERLAPPED, устанавливается и сбрасывается системой автоматически, смещение, указанное в структуре OVERLAPPED, не обновляется автоматически.
    • ReadFile сбрасывает событие в несигнальное состояние, когда оно начинает операцию ввода-вывода.
    • Событие, указанное в структуре OVERLAPPED, устанавливается в сигнальное состояние, когда операция чтения завершена; до этого момента операция чтения считается отложенной.
    • Поскольку операция чтения начинается со смещения, указанного в структуре OVERLAPPED, и ReadFile может вернуться до завершения операции чтения на системном уровне (ожидание чтения), ни смещение, ни любую другую часть структуры не следует изменять. , освобождается или повторно используется приложением до тех пор, пока не будет сообщено о событии (то есть чтение не завершится).
    • Если во время асинхронных операций обнаружен конец файла (EOF), вызов GetOverlappedResult для этой операции возвращает FALSE, а GetLastError возвращает ERROR_HANDLE_EOF.
    • Если lpOverlapped имеет значение NULL, операция чтения начинается с текущей позиции в файле, и ReadFile не возвращает значение до тех пор, пока операция не будет завершена, а система обновляет указатель файла перед возвратом из ReadFile.
    • Если lpOverlapped не равно NULL, операция чтения начинается со смещения, указанного в структуре OVERLAPPED, и функция ReadFile не возвращается до завершения операции чтения. Система обновляет смещение OVERLAPPED перед возвратом ReadFile.
    • Если lpOverlapped имеет значение NULL, то, когда операция синхронного чтения достигает конца файла, ReadFile возвращает TRUE и устанавливает *lpNumberOfBytesRead в ноль.
    • Если lpOverlapped не равно NULL, то когда операция синхронного чтения достигает конца файла, ReadFile возвращает FALSE, а GetLastError возвращает ERROR_HANDLE_EOF.

    Трубы

    Если используется анонимный канал и дескриптор записи закрыт, когда ReadFile пытается выполнить чтение с использованием соответствующего дескриптора чтения канала, функция возвращает FALSE, а GetLastError возвращает ERROR_BROKEN_PIPE.

    Если именованный канал читается в режиме сообщений и следующее сообщение длиннее, чем указано в параметре nNumberOfBytesToRead, ReadFile возвращает FALSE, а GetLastError возвращает ERROR_MORE_DATA. Оставшуюся часть сообщения можно прочитать с помощью последующего вызова функции ReadFile или PeekNamedPipe.

    Если параметр lpNumberOfBytesRead равен нулю, когда ReadFile возвращает значение TRUE для канала, другой конец канала вызывает функцию WriteFile с параметром nNumberOfBytesToWrite, равным нулю.

    Дополнительную информацию о каналах см. в разделе Каналы.

    Транзакционные операции

    Если есть транзакция, связанная с дескриптором файла, функция возвращает данные из транзакционного представления файла. Дескриптор чтения с транзакцией гарантированно отображает одно и то же представление файла на протяжении всего дескриптора. Дополнительные сведения см. в разделе О транзакционной NTFS.

    В Windows 8 и Windows Server 2012 эта функция поддерживается следующими технологиями.

    Технология Поддерживается
    Протокол Server Message Block (SMB) 3.0 Да
    SMB 3.0 Transparent Failover (TFO) Да
    SMB 3.0 с масштабированием Общие файловые ресурсы (SO) Да
    Файловая система общих томов кластера (CsvFS) Да
    Отказоустойчивая файловая система (ReFS) Да

    Примеры

    Пример кода, показывающий, как проверить конец файла, см. в разделе Проверка конца файла. Другие примеры см. в разделах «Создание и использование временного файла» и «Открытие файла для чтения или записи».

    Читайте также: