You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将stdin改为raw模式后stdout受影响,原因何在?

问题原因与解决方案

你的代码问题出在终端设备的输入输出属性是共享的——stdin和stdout默认指向同一个TTY终端,当调用cfmakeraw()修改终端属性时,这个函数会一次性修改输入、输出相关的多项设置,其中就包括关闭ONLCR选项。而ONLCR的作用正是让终端在输出时自动将\n转换为\r\n,关闭后printf里的\n自然不会再自动插入\r。

cfmakeraw()本质是把整个终端(输入+输出)切换到raw模式,如果你只需要让stdin进入raw模式、不影响stdout的换行行为,有两种解决方式:

方式一:手动设置raw输入模式,保留输出转换

不要直接用cfmakeraw(),精准修改输入相关属性,保留输出的ONLCR选项:

if (isatty(STDIN_FILENO)) {
    if (tcgetattr(STDIN_FILENO,&tiostdin) != 0) {
        perror("tcgetattr stdin");
        close(ttyfd);
        exit(1);
    }
    // 仅开启raw输入模式的必要设置
    tiostdin.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
    tiostdin.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
    tiostdin.c_cflag &= ~(CSIZE | PARENB);
    tiostdin.c_cflag |= CS8;
    tiostdin.c_cc[VMIN] = 1;
    tiostdin.c_cc[VTIME] = 0;
    // 确保输出保留\n转\r\n的功能
    tiostdin.c_oflag |= ONLCR;
    
    if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tiostdin) != 0) {
        perror("tcsetattr stdin");
        close(ttyfd);
        exit(1);
    }
}

方式二:用cfmakeraw后恢复输出转换

如果仍想使用cfmakeraw(),可以在调用后重新开启ONLCR选项:

if (isatty(STDIN_FILENO)) {
    if (tcgetattr(STDIN_FILENO,&tiostdin) != 0) {
        perror("tcgetattr stdin");
        close(ttyfd);
        exit(1);
    }
    cfmakeraw(&tiostdin);
    // 重新开启输出的\n转\r\n功能
    tiostdin.c_oflag |= ONLCR;
    
    if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tiostdin) != 0) {
        perror("tcsetattr stdin");
        close(ttyfd);
        exit(1);
    }
}

内容的提问来源于stack exchange,提问作者Ed.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 07:54:58