【问题标题】: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内核规范还是其他原因的结果?

【问题讨论】:

    标签: linux assembly nasm system-calls tty


    【解决方案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(或任何其他语言)的系统编程也是如此。

    进一步阅读:

    【讨论】:

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

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

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

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

    【讨论】:

    • 我喜欢最后一句话 :D 非常感谢您的解释 :)
    • @Mercado 我很高兴!
    猜你喜欢
    • 2020-07-17
    • 2019-10-26
    • 2017-03-14
    • 1970-01-01
    • 2018-11-10
    • 2014-05-11
    • 1970-01-01
    • 2012-12-11
    • 1970-01-01
    相关资源
    最近更新 更多