assembly - 从 NASM 中的非阻塞标准输入读取
问题描述
将标准输入设置为非阻塞的示例代码,然后进行读取系统调用。
section .text
global _start
_start:
mov eax, 55 ; __NR_fcntl
mov ebx, 0
mov ecx, 4 ; F_SETFL
mov edx, 2048 ; O_RDONLY|O_NONBLOCK
int 0x80
mov eax, 3 ; __NR_read
mov ebx, 0
mov ecx, buf
mov edx, 1024
int 0x80
mov [br], eax
mov eax, 4 ; __NR_write
mov ebx, 1
mov ecx, buf
mov edx, [br]
int 0x80
mov eax, 1 ; __NR_exit
mov ebx, 0
int 0x80
section .bss
buf resb 1024
br resd 1
预期行为:程序退出而不打印任何内容,因为我希望在没有可读取的内容时(在终端上)read
返回EAX。0
当前行为:当没有任何内容传递给标准输入时,程序打印 4 个随机字节作为read
返回。-11
$ strace ./nonblocking
execve("./nonblocking", ["./nonblocking"], 0x7fff196fcb40 /* 53 vars */) = 0
strace: [ Process PID=4112759 runs in 32 bit mode. ]
fcntl(0, F_SETFL, O_RDONLY|O_NONBLOCK) = 0
read(0, 0x804a000, 1024) = -1 EAGAIN (Resource temporarily unavailable)
write(1, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4294967285����) = 4096
exit(0) = ?
(编者注:\0
在终端上打印为零宽度,但问题所讨论的 4个非零-11
字节是dword in br
,从输出的 1024 个字节开始。)
解决方案
Linux 系统调用-errno
出错时返回值。 read
在没有字节“就绪”的设备上返回-EAGAIN
非阻塞 I/O 的文档,因此 EAX =-11
在其位模式中有 4 个非零字节。
您实际上并没有打印 4 个字节,而是将一个巨大的值传递给write
. 它一直写到页面的末尾。它不是返回-EFAULT
,而是返回它实际从缓冲区复制到文件描述符的字节数,即使它因为遇到未映射的页面而停止。
将输出写入终端会使其不那么明显,除非您查看 strace 输出。ASCII NUL ( \0
,零字节) 在标准 VT100 风格的终端上打印为零宽度,但在其他上下文中,这与不写任何东西非常不同。运行
./nonblocking | hexdump -C --no-squeezing
以查看您写入标准输出的 4kB 零字节。
顺便说一句,将 EAX 存储到内存中只是为了重新加载它是没有意义的。只是mov edx, eax
。
当用户键入 control-D 时,您只会在 TTY 上获得 EOF。(假设“熟”模式和默认stty
设置)。
非阻塞不会把 no-data-ready 变成 EOF;这将无法区分文件的实际结尾!(常规文件上的非阻塞 I/O 将在文件末尾为您提供 EOF,或者-EAGAIN
如果尚未从磁盘获取文件,则您必须阻塞 I/O。)
对于阻塞和非阻塞,read
返回(意思是 EOF)的情况是相同的。0
read
如果阻塞read
会坐在那里等待用户输入某些内容(并在行缓冲熟模式下使用 return 或 control-D “提交”它),非阻塞read
将返回-EAGAIN
.
从 Linuxread(2)
手册页:
EAGAIN
文件描述符 fd 指的是不是套接字的文件,并且已被标记为非阻塞(O_NONBLOCK),读取将阻塞。有关 O_NONBLOCK 标志的更多详细信息,请参见 open(2)。
推荐阅读
- loops - Netlogo:海龟执行动作后停止动作循环
- php - PowerShell 在 Azure 上返回空响应
- java - 将外部 jars 添加到 ModCoderPack (MCP)
- scala - 从外部 .jar 运行代码时出现 java.lang.NoSuchMethodError
- javascript - 检查 Hulu 是否在 Applescript/Javascript 中播放
- java - Java模型到源代码转换的问题
- php - Slim 框架和自动组路由
- reactjs - 无法读取未定义的属性,但已定义
- node.js - 为酒店预订应用程序寻找最佳 MongoDB 结构和模式
- amp-html - 在现场或本地环境中加速移动页面测试