【问题标题】:Does fgets() locks stdout preventing printffgets() 是否锁定标准输出以防止 printf
【发布时间】:2019-05-12 22:02:52
【问题描述】:

我有一个带有两个线程的 C 程序,其中一个线程几乎一直阻塞在 fgets() 中等待用户输入。第二个线程可能需要打印到终端,而第一个线程在 fgets() 上被阻塞。

从我的测试看来,程序等待第一个线程上的fgets() 返回,然后第二个线程可以打印。

这是它的工作原理还是我可以在另一个线程被 fgets() 阻塞时打印?

此实现在 eCos(嵌入式可配置操作系统)上运行。

线程锁定在fgets()

int my_getline (char** argv, int argvsize)
{
    static char line[MAX_LINE];
    char *p;
    int argc;

    fgets(line, MAX_LINE, stdin);


    for (argc=0,p=line; (*line != '\0') && (argc < argvsize); p=NULL,argc++) {
        p = strtok(p, " \t\n");
        argv[argc] = p;
        if (p == NULL) return argc;
    }
    argv[argc] = p;
    return argc;
}

线程试图打印:

while(1){
        unsigned char bufr[50];
        read_until(bufr);
        if (bufr[1] == (unsigned char)NMFL ){
            cyg_mutex_lock(&scree_mtx);
            printf("Memory half full!\n");
            cyg_mutex_unlock(&scree_mtx);
            continue;
        }
        cyg_mbox_put( mbx_serial_userH, bufr );     
}

输出(我确定该消息之前存在):

【问题讨论】:

  • 一个等待输入的线程不应阻塞另一个试图写入输出的线程。
  • 您的输出是否以\n 结尾? stdout 是行缓冲的,因此在您打印换行符之前它不会被刷新。
  • 是的,printf()\n@Barmar 结尾
  • 通过编辑,这个问题没有意义。显示的输出似乎与添加的源没有任何关系。
  • 我想我的意思是 - 从这些代码 sn-ps 和输出 sn-p 中非常不清楚你如何得出结论它被阻止尝试输出。你能提供更接近minimal test case的东西吗?

标签: c multithreading printf fgets ecos


【解决方案1】:

C 标准根本没有指定标准输入流和标准输出流之间的任何关联。特别是,它没有指定一个线程在通过任何标准函数从标准输入读取时阻塞应该导致任何输出函数阻塞。

但是,标准也没有说相反的情况,即线程阻塞来自stdin 的输入输入不能导致另一个线程阻塞stdout 的输出。是否会发生这种情况取决于 C 实现,并且可能与 stdinstdout 关联的特定设备有关。

您似乎正在使用 Windows C 实现,stdinstdout 都连接到 CMD.EXE 窗口。 Windows 有很多特性,我倾向于猜测您观察到的阻塞就是其中之一。我不希望在 Linux 或 OSX 上出现同样的情况,但这并不意味着它是错误的。

【讨论】:

  • 其实这是eCos(嵌入式可配置操作系统)的一个实现,有可能是eCos的工作方式……
  • 这似乎并没有真正回答这个问题。这更多是对 C 标准的评论,实际上是说这种观察到的行为不是 C 标准所要求的,可能与操作系统的底层 I/O 子系统实现或 CI/O 库如何实现输入/输出功能。从这个文档中可以看出,eCos 的 C 库至少有两种配置可以是线程安全的,也可以不是线程安全的。 ecos.sourceware.org/docs-latest/user-guide/… 然而,目前还不清楚线程安全的行为。
  • 我不认为该标准隐含地允许在指定的抽象机器向前进展的情况下不允许向前进展的实现。它确实在请求输入时为刷新输出流提供了一些(过时和有害的)允许,如果实现选择接受该允许,这会产生令人讨厌的死锁影响,我最初认为这与这个问题有关,但进一步考虑它似乎不是成为。
  • @RichardChambers,在我写完这个答案之后,这个问题被编辑以指定 eCos,显然是作为回应。 this 响应的原始版本是一个不确定的“这是如何工作的?”,“它取决于,C 本身没有指定”是尽可能响应。
  • @JohnBollinger 发布的问题确实缺少太多,无法提供相当好的答案。 eCos 似乎有相当标准的过山车专有和开源历史,并且由于它是嵌入式的,因此可能存在与硬件相关的考虑。在发布的上下文/环境问题中没有提及。例如,这是一个模拟器吗?这并不是一个真正的好问题,因为它缺少很多东西,包括一个最小且可验证的程序。任何答案都只是往墙上扔东西,直到问题重做到更可接受的标准。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-21
  • 1970-01-01
  • 2012-09-18
  • 2012-04-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多