如何读取或查找大于最大 off64_t 的文件?出现问题的原因是进程的地址空间是在/proc/.../as
文件中表示的,该文件是一个巨大的64 位进程的稀疏文件。它确实非常大:在 Solaris x86-64 上的示例进程上,argv 的地址是 0xFFFFFD7FFFxxxxxx,即使用了地址空间的最顶部。指针是无符号的,但 off64_t 是有符号的,因此无法到达地址空间文件上半部分中的任何内容。
这显然取决于地址空间的布局。在 32 位系统上,这不是问题(long
偏移量不够大,但是off64_t
很容易工作),并且在 Linux 上的 x86-64 上(例如),进程的顶部是 0x7fffxxxxxxxx(48 位) ,因此 off64_t 可以引用进程地址空间中的任何内容。
因此,令人遗憾的是 x86-64 上的 Solaris 似乎使用整个 64 位地址空间,而 50 位就已经足够了。 Sun 使用 psinfo_t.pr_argv 的示例似乎仅在 SPARC 和 x86 上不起作用。有什么办法可以解决这个问题吗?
答案1
Solaris x86-64 上有一些非常大的文件,其大小超过 2 63,即off64_t
.这包括代表进程地址空间的文件proc
(/proc/<pid>/as
。
处理这些文件:
- 不要使用
fopen
、fseek
等。不要相信 libc 流例程,它(在我测试的 Solaris 版本上)会严重破坏“非法”偏移量。 - 使用
open64
,read
。 寻求:
static off64_t lseeku64(int file, uint64_t offset /* eg from pr_argv */) { #ifndef __sun if (offset > 0x7FFFFFFFFFFFFFFFllu) return -1; #endif return lseek64(file, offset, SEEK_SET); }
也就是说,在 Solaris 上,我们知道我们可以通过检查 OpenSolaris 源代码来进行此转换,但我们应该避免假设它可以在具有 和 的其他平台上工作
psinfo
(pr_argv
例如 AIX)。但是,传递非常大的偏移量,它就会“正常工作”。