C et); FD_集(管道fds[0],&集); rv=选择(管道fds[0]+1,&set,NULL,NULL,NULL); 如果(rv>>选择():发生错误,%d\n”,rv); 打破 } if(FD_ISSET(管道fds[0],&set)) { pr

C et); FD_集(管道fds[0],&集); rv=选择(管道fds[0]+1,&set,NULL,NULL,NULL); 如果(rv>>选择():发生错误,%d\n”,rv); 打破 } if(FD_ISSET(管道fds[0],&set)) { pr,c,pthreads,stdin,eof,C,Pthreads,Stdin,Eof,et); FD_集(管道fds[0],&集); rv=选择(管道fds[0]+1,&set,NULL,NULL,NULL); 如果(rv>>选择():发生错误,%d\n”,rv); 打破 } if(FD_ISSET(管道fds[0],&set)) { printf(“>>>pipe_fds[0]:已准备就绪\n”); 打破 } if(FD_ISSET(标准文件号和集合)) { 读取(标准文件号和目录,1); 写入(标准输出文件号和通道,1); } } pthread_exit(NULL); }

et); FD_集(管道fds[0],&集); rv=选择(管道fds[0]+1,&set,NULL,NULL,NULL); 如果(rv<0) { printf(“>>>选择():发生错误,%d\n”,rv); 打破 } if(FD_ISSET(管道fds[0],&set)) { printf(“>>>pipe_fds[0]:已准备就绪\n”); 打破 } if(FD_ISSET(标准文件号和集合)) { 读取(标准文件号和目录,1); 写入(标准输出文件号和通道,1); } } pthread_exit(NULL); }
我认为您只是想
关闭()
管道的另一端,但您的示例没有真正意义,因为主线程没有控制stdin的另一端。我在几周前尝试过,但我没有找到了解stdin另一端的任何方法。还有其他方法可以达到同样的目标吗?也许我遗漏了什么:我只是需要一种方法来避免阻塞控制台输入上的线程。stdin的另一端通常是终端的键盘。也许您需要的是非阻塞I/O?从你的问题很难判断。您应该更详细地解释您正在尝试执行的操作。不,我不需要非阻塞I/O。至少在某种意义上,我不应该使用select()或poll()超时轮询输入:这比尝试关闭终端键盘设备更错误。在我看来,我试图从不同的线程访问stdin,这是错误的。这可能是错误的,我应该通过将应用程序的状态保持在输入“读取器”的范围内来避免这种情况,这样我就可以轻松跟踪何时应该处理输入,与UNIX的control-D相当的Windows是control-Z。我不久前尝试过这个方法,但没有成功,但似乎不可移植,事实上它在linux上也不起作用。在fgetc()等待数据时尝试关闭stdin(或任何其他文件描述符)不会在此处阻塞。这里讨论了:关于select(),linux开发人员的回答是:“未定义的行为”。@ceztko:在一个线程中关闭标准输入,而另一个线程正在读取-是的,这不可靠…我一定是误读了这个问题。是的,这正是我问题的答案,非常感谢!在我的真实需求中,这可能是过分的,但无论如何,如果有人需要类似的模式,这是一种方式。几周前我尝试过这个解决方案,但我完全没有使用select()跟踪多个文件描述符的功能。在我之前关于不使用select()或poll()的评论中,我反对使用超时,但您似乎完全明白了这一点。再次感谢!我还没有测试过,但我想你的代码可以用。不过,我认为您的方法有点粗糙:您向线程发送信号,并且根据
reader()
函数的复杂性,您可能会导致不必要的意外退出点,因为在大代码区域(内核原语)中会产生副作用,您无法控制。我认为在标记答案中建议的方法更细粒度,允许在预期的退出点上精确地抢占线程。另请看我的答案和完整的例子。@ceztko:是的,我的方法比较简单,但针对性要小得多。有一点我不清楚:你能把它用于更高级别的函数,比如fscanf吗?显然,你可以用管道来使用
fscanf
,通过删去不起作用的代码并只保留好的部分来简化你的答案。你也可以评论原始答案并指出错误所在。在这种情况下,FD_零不是严格必要的,但重新设置信号描述符是必要的。我将在我的答案中修复用户数据描述符(另一个描述符用于控制/退出程序)。我想发表评论,但我的“声誉”太低了…:(很高兴你喜欢这些改进!
#include <pthread.h>
#include <stdio.h>

void* reader()
{
    char read_char;
    while((read_char = fgetc(stdin)) != EOF) {
        ;
    }

    pthread_exit(NULL);
}

int main(void)
{
    pthread_t thread;
    pthread_create(&thread, NULL, reader, NULL);

    // Do something so the fgetc in the reader thread will return

    pthread_exit(NULL);
}
fd_set descriptor_set
FD_ZERO(&descriptor_set); 
FD_SET(STDIN_FILENO, &descriptor_set); 
FD_SET(pipefd, &descriptor_set); 

if (select(FD_SETSIZE, &descriptor_set, NULL, NULL, NULL) < 0) 
{ 
  // select() error
} 

if (FD_ISSET(STDIN_FILENO, &descriptor_set)) {
  // read byte from stdin
  read(STDIN_FILENO, &c, 1);
}

if (FD_ISSET(pipefd, &descriptor_set)) 
  // Special event. Do something else
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/select.h>

static int pipe_fds[2];

void* user_interaction()
{
    char read_char;
    
    fd_set descriptor_set;
    FD_ZERO(&descriptor_set); 
    FD_SET(STDIN_FILENO, &descriptor_set); 
    FD_SET(pipe_fds[0], &descriptor_set);

    while(1)
    {
        if (select(FD_SETSIZE, &descriptor_set, NULL, NULL, NULL) < 0) {
            // select() error
        }

        if (FD_ISSET(STDIN_FILENO, &descriptor_set)) {
            // read byte from stdin
            read(STDIN_FILENO, &read_char, 1);
            // Re-set the selected file descriptor so it can
            // be signaled again
            FD_SET(STDIN_FILENO, &descriptor_set);
        }

        if (FD_ISSET(pipe_fds[0], &descriptor_set))
            // Special event. break
            break;
    }
    
    pthread_exit(NULL);
}

int main(void)
{
    pipe(pipe_fds);
    
    pthread_t thread;
    pthread_create(&thread, NULL, user_interaction, NULL);
    
    // Before closing write pipe endpoint you are supposed
    // to do something useful
    sleep(5);

    close(pipe_fds[1]);
    
    pthread_join(thread, NULL);
    
    pthread_exit(NULL);
}
#include <pthread.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>

static void SignalHandler(int signum)
{
}

void* reader(void *arg)
{
    char read_char;
    while((read_char = fgetc(stdin)) != EOF) {
        ;
    }
    printf("leaving reader\n");
    return NULL;
}

int main(int argc, const char * argv[])
{
    struct sigaction action;
    memset(&action, 0, sizeof(action));  // SA_RESTART bit not set
    action.sa_handler = SignalHandler;
    sigaction(SIGUSR1, &action, NULL);

    pthread_t thread;
    pthread_create(&thread, NULL, reader, NULL);

    sleep(1); // time to start reader thread
    // Do something so the fgetc in the reader thread will return
    pthread_kill(thread, SIGUSR1);
    sleep(1); // time to exit reader thread; could join it if set up

    return 0;
}