Я пытаюсь использовать perl для разбора некоторых псевдофайлов из псевдофайловых систем /proc
и /sys
linux (procfs и sysfs). Такие файлы отличаются от обычных файлов — они реализуются пользовательскими обработчиками операций с файлами. Большинство из них имеют нулевой размер для stat
, некоторые не могут быть открыты для чтения, другие не могут быть записаны. Иногда они реализованы неправильно (что является ошибкой, но она уже есть в ядре), и я все равно хочу прочитать их прямо из perl, не запуская какие-то вспомогательные инструменты.
Вот быстрый пример чтения /proc/loadavg
с помощью perl, этот файл реализован корректно:
perl -e 'open F,"</proc/loadavg"; $_=<F>; print '
С помощью strace
команды я могу проверить, как Perl реализует функцию open
:
$ strace perl -e 'open F,"</proc/loadavg"; $_=<F>; print ' 2>&1 | egrep -A5 ^open.*loadavg
open("/proc/loadavg", O_RDONLY) = 3
ioctl(...something strange...) = -1 ENOTTY
lseek(3, 0, SEEK_CUR) = 0
fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
fcntl(3, F_SETFD, FD_CLOEXEC) = 0
Существует lseek
системный вызов, используемый open
perl-функцией.
При использовании strace cat /proc/loadavg
не было лишних системных вызовов типа seek
:
$ strace cat /proc/loadavg 2>&1 | egrep -A2 ^open.*loadavg
open("/proc/loadavg", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
Специальный файл, который я хочу прочитать (или записать), неправильно реализует seek
операции с файлами и не даст никаких полезных данных системному вызову read
(или write
) после seek
.
Есть ли способ открыть файлы для чтения в perl5 (без внешних модулей) без вызова дополнительных lseek
? (и без использования system("cat < /proc/loadavg")
)
Есть ли способ открыть файлы для записи в perl5 без вызова дополнительных lseek
?
Есть sysopen, но он тоже выполняет дополнительный поиск: perl -e 'use Fcntl;sysopen(F,"/proc/loadavg",O_RDONLY);sysread(F,$_,2048); print '
open F, "<:unix", "/proc/loadavg"
делает толькоfstat
и устанавливает close на exec - person ikegami   schedule 02.11.2016<:unix
) используется в вашем ответе (может быть полезна ссылка на документ или источник)? В моем тестовом Linux он тоже не искал. - person osgx   schedule 02.11.2016open
, слои PerlIO задокументированы в PerlIO. - person ikegami   schedule 02.11.2016perl -MPerlIO -E'open F, "<", $ARGV[0] or die $!; say for PerlIO::get_layers(\*F);' ~/.bashrc
, затем повторите попытку, указав:unix
. - person ikegami   schedule 02.11.2016fstat
сmy $SET,">:unix",".../driver_command; print $SET $COMMAND."\n"; close $SET
; я могу отключить его? Мой скрипт все еще не может общаться с драйвером; но обычныйecho SAME_COMMAND > .../driver_command
работает, я вижу здесь только лишний fstat. - person osgx   schedule 14.11.2016