Linux下读取控制台时,如何实现WaitForSingleObject的等效功能?
Linux下实现控制台输入的条件等待方案
Linux没有直接对应Windows WaitForSingleObject()的控制台等待API,要实现带超时的输入检查+读取,可以通过以下两种常用方式完成:
方式一:使用select()系统调用
select()可以监听文件描述符的可读状态,同时支持设置超时时间,完全匹配Windows代码的等待逻辑。默认终端处于规范模式(会缓存输入直到回车),如果需要实时读取输入(无需回车触发),要先修改终端属性。
代码示例
#include <stdio.h> #include <stdlib.h> #include <sys/select.h> #include <termios.h> #include <unistd.h> int main() { struct termios old_attr, new_attr; char buf[512] = {0}; ssize_t r = 0; // 保存原有终端属性,切换为非规范模式(禁用回车缓冲与回显) tcgetattr(STDIN_FILENO, &old_attr); new_attr = old_attr; new_attr.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &new_attr); // 初始化select的文件描述符集合 fd_set read_fds; FD_ZERO(&read_fds); FD_SET(STDIN_FILENO, &read_fds); // 设置3秒超时(秒+微秒) struct timeval timeout = {3, 0}; // 等待输入或超时 int ret = select(STDIN_FILENO + 1, &read_fds, NULL, NULL, &timeout); if (ret > 0 && FD_ISSET(STDIN_FILENO, &read_fds)) { // 有输入可读 r = read(STDIN_FILENO, buf, sizeof(buf) - 1); if (r > 0) { printf("读取到内容:%s\n", buf); } } else if (ret == 0) { printf("等待超时\n"); } else { perror("select失败"); } // 恢复原有终端属性 tcsetattr(STDIN_FILENO, TCSANOW, &old_attr); return 0; }
关键说明
select()返回值:>0表示存在可读描述符,0表示超时,-1表示调用出错- 若需保留规范模式(必须输入回车才触发读取),可删除终端属性修改相关代码
方式二:使用poll()系统调用
poll()是select()的替代方案,用法更简洁,同样支持超时设置:
代码示例
#include <stdio.h> #include <stdlib.h> #include <poll.h> #include <termios.h> #include <unistd.h> int main() { struct termios old_attr, new_attr; char buf[512] = {0}; ssize_t r = 0; // 切换终端为非规范模式 tcgetattr(STDIN_FILENO, &old_attr); new_attr = old_attr; new_attr.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &new_attr); // 定义poll监听结构体 struct pollfd fds[1]; fds[0].fd = STDIN_FILENO; fds[0].events = POLLIN; // 监听可读事件 // 等待3000毫秒(3秒) int ret = poll(fds, 1, 3000); if (ret > 0 && (fds[0].revents & POLLIN)) { r = read(STDIN_FILENO, buf, sizeof(buf) - 1); if (r > 0) { printf("读取到内容:%s\n", buf); } } else if (ret == 0) { printf("等待超时\n"); } else { perror("poll失败"); } // 恢复终端属性 tcsetattr(STDIN_FILENO, TCSANOW, &old_attr); return 0; }
读取前检查控制台输入的核心逻辑
无论使用select还是poll,核心都是监听标准输入文件描述符(STDIN_FILENO,值为0)的可读事件:
- 当控制台有输入时(是否需要回车取决于终端模式),文件描述符会变为可读状态
- 超时时间可精确到毫秒级,完全对应Windows代码中的3秒等待需求
编译与运行
使用gcc编译执行:
gcc -o console_wait console_wait.c ./console_wait
内容的提问来源于stack exchange,提问作者Irbis
相关产品推荐
相关产品推荐

