为啥 sys_read 系统调用在检测到新行时结束?

Posted

技术标签:

【中文标题】为啥 sys_read 系统调用在检测到新行时结束?【英文标题】:Why does the sys_read system call end when it detects a new line?为什么 sys_read 系统调用在检测到新行时结束? 【发布时间】:2017-01-04 18:24:01 【问题描述】:

我是汇编初学者(使用 nasm)。我正在通过大学课程学习组装。

我试图了解 sys_read linux 系统调用在被调用时的行为。具体来说,sys_read 在读取新行或换行时停止。根据我被教导的内容,这是真的。这个online tutorial article 也证实了这一事实/主张。

当 sys_read 检测到换行时,控制权返回给程序,用户输入位于您在 ECX 中传递的内存地址。

我查看了 linux 程序员手册中的 sys_read 调用(通过“man 2 read”)。它没有提到应该提到的行为,对吧?

read() 尝试从文件描述符 fd 中读取 count 个字节 从 buf 开始进入缓冲区。

在支持查找的文件上,读取操作从 文件偏移量,文件偏移量按字节数递增 读。如果文件偏移量位于或超过文件末尾,则没有字节 读取,并且 read() 返回零。

如果 count 为零,read() 可能会检测到下面描述的错误。在 没有任何错误,或者如果 read() 不检查错误,则 计数为 0 的 read() 返回零并且没有其他效果。

如果 count 大于 SSIZE_MAX,则结果未指定。

所以我的问题是,为什么会发生这种行为?这是应该发生的Linux内核规范还是其他原因的结果?

【问题讨论】:

【参考方案1】:

这是因为您正在从POSIX tty in canonical mode 读取数据(在您按回车键“提交”该行之前退格起作用;这一切都由内核的 tty 驱动程序处理)。查找 POSIX tty 语义/stty/ioctl。如果你运行./a.out < input.txt,你不会看到这种行为。

请注意,如果您按 control-d(EOF tty 控制序列),TTY 上的 read() 将不带换行符返回。

假设read() 读取整行对于玩具程序来说是可以的,但是不要开始假设任何需要健壮的东西,即使你已经检查过你是从 TTY 阅读。我忘记了如果用户将多行文本粘贴到终端模拟器中会发生什么。很可能它们最终都在一个 read() 缓冲区中。


另请参阅my answer on a question about small read()s leaving unread data on the terminal:如果您在一行中键入的字符数超过了read() 缓冲区大小,则您至少需要一个 read 系统调用来清除输入。


如您所述,read(2) libc 函数只是sys_read 的一个薄包装。这个问题的答案其实与汇编语言无关,C(或任何其他语言)的系统编程也是如此。

进一步阅读:

stty(1) 手册页:您可以在其中更改哪个控制字符做什么。 The TTY demystified:一些历史和一些图表显示了 xterm、内核和从 tty 读取的进程如何交互。还有关于会话管理和信号的内容。 https://en.wikipedia.org/wiki/POSIX_terminal_interface#Canonical_mode_processing 和该文章的相关部分。

【讨论】:

非常感谢您的解释和参考!【参考方案2】:

这不是read() 系统调用的属性,而是终端驱动程序termios 的属性。在默认配置中,termios 会缓冲传入的字符(即您键入的内容),直到您按 Enter,然后将整行发送到从终端读取的程序。这是为了方便起见,您可以在发送之前编辑该行。

正如 Peter Cordes 已经说过的,从其他类型的文件(如常规文件)读取时不会出现这种行为,并且可以通过配置 termios 来关闭。

教程说的都是垃圾,请无视。

【讨论】:

我喜欢最后一句话 :D 非常感谢您的解释 :) @Mercado 我很高兴!

以上是关于为啥 sys_read 系统调用在检测到新行时结束?的主要内容,如果未能解决你的问题,请参考以下文章

从asp到json和jquery的新行

过程也可以被调用?为啥?啥样的是?

UIPanGestureRecognizer:在滑动结束时检测触摸位置

java的System. out. println(),为啥out能调用println()?

SQL 错误“在批处理结束时检测到不可提交的事务”,数据库上没有事务

为啥当我调用 DataAdapter.Update() 时,此 C# 代码会生成语法错误?