Как работают файловые дескрипторы Perl в Windows? - PullRequest
0 голосов
/ 09 февраля 2010

Поддерживаются ли дескрипторы файлов в Windows? Почему в Perl что-то "работает" с fds?

Такие вещи, как «fileno», «dup» и «dup2» работали, но затем случайно в какой-то другой среде перестали работать. Трудно дать подробности, в основном я ищу ответы опытных программистов Windows и то, как файловые дескрипторы работают / не работают в Windows.

Я бы предположил, что это слой PerlIO, играющий в игры и создающий впечатление, что дескрипторы файлов работают, но это только предположение.

Пример того, что происходит:

open($saveout, ">&STDOUT") or die();
...
open(STDOUT, ">&=".fileno($saveout)) or die();

Вторая строка die () s, но только в определенных ситуациях (которые мне еще предстоит зафиксировать).

1 Ответ

1 голос
/ 03 июля 2010

Windows изначально использует файловые дескрипторы. См. Низкоуровневый ввод / вывод в MSDN. Все они сообщают об ошибках через переменную C errno, что означает, что они отображаются в Perl $!.

Обратите внимание, что вы можете немного сэкономить, набрав:

open(STDOUT, ">&=", $saveout) or ...;

Это работает, потому что документация для open в perlfunc содержит:

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

Наконец, всегда включает значимую диагностику, когда вы звоните die! Приведенная ниже программа идентифицирует себя ($0), сообщает, что она пыталась сделать (open) и почему это не удалось ($!). Кроме того, поскольку сообщение не заканчивается новой строкой, die добавляет имя файла и номер строки, в которой оно было вызвано.

my $fakefd = 12345;
open(STDOUT, ">&=", $fakefd) or die("$0: open: $!");

Это производит

prog.pl: open: Bad file descriptor at foo.pl line 2.

Согласно документации для _fdopen (поскольку вы использовали >&=, а не >&), он имеет два режима отказа:

Если выполнение разрешено продолжать, errno устанавливается либо на EBADF, что указывает на неверный дескриптор файла, либо на EINVAL, указывая, что режим был нулевым указателем.

Вторым будет ошибка в Perl, и это маловероятно, потому что я не вижу нигде в perlio.c, где используется вычислительный режим: все они являются статическими строками.

Что-то пошло не так с $saveout. Может быть $saveout были закрыты, прежде чем пытаться восстановить его? Из вашего примера неясно, включили ли вы прагму strict. Если это не лексическое (объявлено с my), вызываете ли вы функцию, которая также обезьяна с $saveout?

...