macOS 上 tty 的 lseek 是做什么的?

问题描述 投票:0回答:1

考虑下面的 C 程序,名为

weird.c
(因为它所做的事情没有意义):

#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>

int main(void) {
    off_t result = lseek(STDOUT_FILENO, (off_t)INT64_MAX, SEEK_SET);
    if (result != (off_t)-1)
        printf("Seek successful to position %" PRId64 "\n", (int64_t)INT64_MAX);
    else
        perror("lseek failed");
    return 0;
}

从终端窗口编译并运行它,例如

gcc -o weird weird.c && ./weird
。从 tty(终端窗口、SSH 会话等)运行它非常重要,因此
stdout
是一个 tty。

在 Linux 上,它将失败并出现错误

lseek failed: Illegal seek
– 这是有道理的,在 tty 上查找没有多大意义。

但是,在 macOS 上,它的行为有所不同 - 程序退出而不打印任何内容,然后 shell 也退出。我只能假设这是因为 tty 已进入某种非法状态。但这里到底发生了什么?

顺便说一句,我猜测 macOS 的行为与 FreeBSD 类似。但是 FreeBSD 14.1-RELEASE (amd64) 再次有不同的行为 – 它打印:

Seek successful to position 9223372036854775807

这比 macOS 的做法更容易理解(例如,将无意义的操作视为无操作,而不是像 Linux 那样出错。)

c macos tty pty lseek
1个回答
0
投票

黑客新闻上的用户

jepler
指出了解释

注意

vn_write
函数中的这段代码
bsd/vfs/vfs_vnops.c

        if (write_offset == INT64_MAX) {
                /* writes are not possible */
                error = EFBIG;
                goto error_out;
        }

基本上发生的事情是这样的:

  1. 在 macOS 中,与 Linux 不同,您可以使用
    lseek
    设置终端的偏移量 - 即使偏移量实际上没有执行任何操作
  2. 但是,一旦偏移量达到
    INT64_MAX
    ,进一步的写入尝试就会失败并出现
    EFBIG
    ,除非您返回到更早的某个位置。

shell 退出的原因是大多数 shell 在无法写入 stdout/stderr 时退出。

如果您修改我的测试程序以寻求例如

INT64_MAX-100
,在所有输出开始失败之前,您将能够打印 100 个字节的输出。

此代码似乎已在

xnu-7195.50.7.100.1
(macOS 11 Big Sur) 中引入 - 它在
xnu-6153.11.26
(macOS 10.15 Catalina) 中不存在。

FreeBSD 似乎还允许您在终端中

lseek
到任意偏移量 - 但与 macOS 11+ 不同,如果您查找到
INT64_MAX
,则不会拒绝进一步写入。

© www.soinside.com 2019 - 2024. All rights reserved.