如何在同一进程中从主线程向轮询stdin的子线程提供输入?
解决主线程为子线程scanf提供输入的问题
原代码问题分析
你原代码的核心错误在于,试图通过popen调用外部进程wc -c来操作stdin,但这本质是和第三方进程交互,并没有将数据写入当前进程的stdin流中。而且临时替换stdin后立刻恢复,子线程的scanf始终在等待终端输入,自然读不到预期的数值。
正确实现:用管道重定向stdin
利用线程共享进程文件描述符的特性,通过匿名管道将stdin重定向,让子线程的scanf从管道读取主线程写入的数据:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <pthread.h> void* child_thread_func(void* arg) { int num = 0; printf("Trying to read num from stdin\n"); scanf("%d", &num); printf("Entered number is %d\n", num); return NULL; } int main() { pthread_t tid; int pipe_fd[2]; // 创建匿名管道 if (pipe(pipe_fd) == -1) { perror("pipe failed"); exit(1); } // 保存原始stdin的文件描述符 int original_stdin = dup(STDIN_FILENO); if (original_stdin == -1) { perror("dup stdin failed"); exit(1); } // 将stdin重定向到管道的读端 if (dup2(pipe_fd[0], STDIN_FILENO) == -1) { perror("dup2 failed"); exit(1); } close(pipe_fd[0]); // 已通过stdin关联读端,关闭多余副本 // 创建子线程 if (pthread_create(&tid, NULL, child_thread_func, NULL) != 0) { printf("Failed to initialize thread\n"); exit(1); } sleep(2); // 等待子线程进入scanf等待状态 // 往管道写端写入数值(添加换行符,满足scanf的输入格式要求) const char* num_input = "9\n"; write(pipe_fd[1], num_input, strlen(num_input)); close(pipe_fd[1]); // 关闭写端,触发scanf的输入结束逻辑 // 等待子线程执行完成 pthread_join(tid, NULL); // 恢复原始stdin dup2(original_stdin, STDIN_FILENO); close(original_stdin); return 0; }
代码说明
pipe()创建匿名管道,生成读端和写端两个文件描述符- 通过
dup2()将进程的stdin重定向到管道读端,所有线程的stdin都会指向这个管道 - 子线程的
scanf会从管道读端等待输入,主线程往写端写入"9\n"后,scanf就能读取到整数9 - 写完数据后关闭写端,让
scanf知道输入已结束,避免子线程无限等待
替代方案:线程间直接通信(无需操作stdin)
如果不需要强制通过scanf从stdin读取,用互斥锁+条件变量的线程通信方式更高效简洁:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <pthread.h> int num = 0; pthread_mutex_t num_mutex; pthread_cond_t num_cond; void* child_thread_func(void* arg) { pthread_mutex_lock(&num_mutex); // 等待主线程设置数值 while (num == 0) { pthread_cond_wait(&num_cond, &num_mutex); } printf("Entered number is %d\n", num); pthread_mutex_unlock(&num_mutex); return NULL; } int main() { pthread_t tid; pthread_mutex_init(&num_mutex, NULL); pthread_cond_init(&num_cond, NULL); if (pthread_create(&tid, NULL, child_thread_func, NULL) != 0) { printf("Failed to initialize thread\n"); exit(1); } sleep(2); // 设置数值并通知子线程 pthread_mutex_lock(&num_mutex); num = 9; pthread_cond_signal(&num_cond); pthread_mutex_unlock(&num_mutex); pthread_join(tid, NULL); pthread_mutex_destroy(&num_mutex); pthread_cond_destroy(&num_cond); return 0; }
方案说明
- 用互斥锁保护全局变量
num的读写,避免线程安全问题 - 子线程通过条件变量等待主线程设置数值,主线程设置完成后发送唤醒信号
- 这种方式不需要操作标准输入流,是线程间传递数据的常规做法
内容的提问来源于stack exchange,提问作者Harish Reddy
相关产品推荐
相关产品推荐

