使用perl读取系统文件而不在打开时发出额外的搜索系统调用

osg*_*sgx 5 linux perl file-io seek procfs

我正在尝试使用perl来解析来自/proc/syslinux伪文件系统(procfssysfs)的一些伪文件.这些文件与常规文件不同 - 它们由自定义文件操作处理程序实现.其中大多数都是零大小stat,有些不能打开阅读,其他不能写.有时它们被错误地实现(这是错误的,但它已经在内核中)并且我仍然希望直接从perl读取它们而无需启动一些帮助工具.

有一个/proc/loadavg使用perl 读取的快速示例,此文件已正确实现:

perl -e 'open F,"</proc/loadavg"; $_=<F>; print '
Run Code Online (Sandbox Code Playgroud)

使用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
Run Code Online (Sandbox Code Playgroud)

目前lseek所使用的系统调用openPerl函数.

有了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
Run Code Online (Sandbox Code Playgroud)

我想要读取(或写入)错误实现seek文件操作的特殊文件,并且不会给read(或write)之后的系统调用提供任何有用的数据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 '

Cal*_*ahl 3

正如您所注意到的,Perl 的内置掩盖了open相当多的魔力。如果这种魔法妨碍了你,那么魔法的程度就会sysopen降低POSIX::open()POSIX::open()它返回文件描述符而不是 Perl 文件句柄,并且您必须使用POSIX::read()而不是普通的 Perl 运算符来从中获取数据,这一点并不神奇。如果这对于您的情况来说还不够原始,那么您可能会不走运。

自 Perl 5 的第一个版本以来,该POSIX模块就是核心 Perl 发行版的一部分,因此,如果您没有它,您的 Perl 安装就会受到影响。