gpt4 book ai didi

linux - 从 x86 中的特定位置读取文件

转载 作者:行者123 更新时间:2023-12-03 09:53:46 25 4
gpt4 key购买 nike

是否可以从特定行或字节开始读取文件。目前我使用这段代码读取一个文件的 4 个字节:

section .data
filename db "file.txt", 0

section .bss
read_data resb 4

section .text
global _start

_start:
mov rax, SYS_OPEN
mov rdi, filename
mov rsi, O_RDONLY
mov rdx, 0
syscall

push rax
mov rdi, rax
mov rax, SYS_READ
mov rsi, read_data
mov rdx, 4
syscall

mov rax, SYS_CLOSE
pop rdi
syscall

此代码始终读取前 4 个字节,但我想从文件的其他部分开始读取,例如中间部分。我需要添加或更改什么?

最佳答案

一个新打开的文件描述符从 position = 0 开始。如果你在一个循环中继续从同一个 fd 读取,你会得到连续的 block 。 (使用更大的缓冲区,如 8kiB,并在用户空间中循环双字,使用 read 返回的值作为上限!系统调用在 CPU 时间上非常昂贵。)

Is it possible to start reading a file from a specific line or byte.

  • 字节:是
  • 线路:没有。在 Unix/Linux 中,内核没有行起始字节偏移量索引或任何其他面向行的 API。例如,stdio fgets 中的行处理纯粹是在用户空间中完成的。有一些历史操作系统使用基于记录的文件,但 Unix 文件是平面字​​节数组。 (它们可能有漏洞、未写入的范围和扩展属性……但主要文件内容的内核 API 仅使用字节偏移量进行操作)。

如果你想换行,读取一个大块并向前循环,直到你看到一些换行符。如果您还没有,请阅读另一个街区;重复直到找到所需行号的开始和结束,或者您点击 EOF。 x86-64 可以使用 pcmpeqb/pmovmskb/popcnt 一次高效地搜索 16 个字节(popcnt 需要 SSE4.2 或特定的 popcnt 功能位).

或者仅使用 SSE2,或者在针对大块进行优化时,使用 pcmpeqb/psadbw(针对全零)将 hsum 字节转换为 qwords/padd。然后用一些标量代码检查你经常去多少行。或者保持简单并在 SIMD 向量中找到第一个换行符。

显然,缓慢而简单的选项是一个每次一个字节的循环,它计算 '\n' 个字符 - 如果您知道如何使用 SSE2 执行 strchr,那么向量化应该很简单使用上述建议进行搜索。


但如果您只想要一些特定的字节位置,您有两个主要选择:

  • read(2) 之前使用 lseek(2) 进行搜索(参见@Nicolae Natea 的回答)

  • 使用 POSIX/Linux pread(2)从指定的偏移量读取,而不移动 fd 的文件偏移量以供将来的 read 调用使用。 Linux 系统调用名称为 pread64(__NR_pread64 equ 17 来自 asm/unistd_64.h)

    ssize_t pread(int fd, void *buf, size_t count, off_t offset);read的唯一区别是偏移量arg,第4个arg因此传入R10(不像用户空间函数调用约定那样的 RCX)。 off_t 是一个 64 位类型,只是在 64 位代码中传入一个寄存器。

除了 .h 中的 pread64 名称外,asm 接口(interface)与 C 接口(interface)相比没有什么特别之处,它遵循标准的系统调用约定。 (自 Linux 2.1.60 以来就存在;在 glibc 的包装器使用 lseek 模拟它之前。)


您还可以执行其他操作,例如 mmappreadv 系统调用,但如果您的位置已知,pread 正是您要查找的内容你想阅读。

关于linux - 从 x86 中的特定位置读取文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60687591/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com