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

如何在同一进程中从主线程向轮询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;
}

代码说明

  1. pipe()创建匿名管道,生成读端和写端两个文件描述符
  2. 通过dup2()将进程的stdin重定向到管道读端,所有线程的stdin都会指向这个管道
  3. 子线程的scanf会从管道读端等待输入,主线程往写端写入"9\n"后,scanf就能读取到整数9
  4. 写完数据后关闭写端,让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;
}

方案说明

  1. 用互斥锁保护全局变量num的读写,避免线程安全问题
  2. 子线程通过条件变量等待主线程设置数值,主线程设置完成后发送唤醒信号
  3. 这种方式不需要操作标准输入流,是线程间传递数据的常规做法

内容的提问来源于stack exchange,提问作者Harish Reddy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 04:01:18