将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.
相关产品推荐
相关产品推荐

