2016-11-02 3 views
4

Я пытаюсь использовать Perl для разбора некоторых псевдо-файлов из /proc и /sys линукса псевдо файловых систем (procfs и sysfs). Такие файлы отличаются от обычных файлов - они реализуются обработчиками операций с пользовательскими файлами. Большинство из них имеют нулевой размер для stat, некоторые не могут быть открыты для чтения, другие не могут быть записаны. Иногда они выполняются неправильно (это ошибка, но она уже находится в ядре), и я все же хочу читать их напрямую из perl, не запуская некоторые вспомогательные инструменты.Чтения системных файлов с 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 

Eсть lseek системный вызов, используемый open функцией perl.

С трассированием из cat /proc/loadavg было никаких дополнительных seek -typed система не называет:

$ 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 

Специальный файл я хочу прочитать (или написать) misimplement seek файловые операции и не будет давать какие-либо полезные данные для read (или до write) syscall после seek.

Есть ли способ открыть файлы для чтения в perl5 (без внешних модулей) без дополнительных вызовов lseek? (и без использования system("cat < /proc/loadavg"))

Есть ли способ открытия файлов для записи в perl5 без дополнительных дополнительных lseek?

Там будет SysOpen, но это дополнительный lseek тоже: perl -e 'use Fcntl;sysopen(F,"/proc/loadavg",O_RDONLY);sysread(F,$_,2048); print '

+2

В ящике linux, на котором я его пробовал, 'open F, <: unix", "/ proc/loadavg" 'делает только' fstat' и устанавливает close на exec – ikegami

+0

@ikegami, Какая черная магия (' <: unix') используется в вашем ответе (может быть полезна ссылка на документ или источник)? Он тоже не искал мой тестовый Linux. – osgx

+1

Как указано в документации для ['open'] (http://perldoc.perl.org/functions/open.html), уровни PerlIO документируются в [PerlIO] (http://perldoc.perl.org/PerlIO .html). – ikegami

ответ

1

Как вы уже заметили, встроенные open масок в Perl совсем немного магии. Если эта магия мешает вам, есть sysopen и POSIX::open(), которые предлагают уменьшающиеся степени магии. POSIX::open() достаточно не магический, чтобы он возвращал дескрипторы файлов, а не дескрипторы файлов Perl, и вместо обычных операторов Perl вы должны использовать POSIX::read(), чтобы получать данные от него. Если это недостаточно для ваших обстоятельств, вам может быть не повезло.

Модуль POSIX является частью основного распределения perl с самого первого выпуска Perl 5, поэтому, если у вас его нет, ваша установка Perl будет искалечена.

+0

Кайл, пожалуйста, добавьте ссылки на документацию. Ikegami рекомендуется '<: unix' black волшебный вариант для open, можете ли вы добавить его в качестве другого альтернативного решения для вашего ответа? – osgx

+0

Calle, thanks, POSIX :: open + read работает без каких-либо дополнительных системных вызовов: 'perl -e 'использовать POSIX(); $ fd = POSIX :: open ("/ proc/loadavg"); $ bytes = POSIX :: read ($ fd, $ buf, 30); POSIX :: close ($ fd); print $ bytes. " читать: ". $ buf; с результатом '27 читать: 0.16 0.09 0.02 ....' – osgx

+0

В конце чтения есть специальный символ '\ 0'. Как я могу разобрать многострочный код из POSIX :: read, нет 'while ()' now , – osgx

Смежные вопросы