在 Linux 中的不同线程之间缓冲 `printf` 输出
Buffering `printf` outputs between different threads in Linux
这是我的代码:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
pthread_t ntid;void
printids(const char *s) {
printf("%s \n", s);
}
void *
thr_fn(void *arg) {
printids("new thread: ");
return((void *)0);
}
int
main(void) {
pthread_create(&ntid, NULL, thr_fn, NULL);
printids("main thread:");
}
我运行在 Red Hat Enterprise Linux 工作站版本 6.5 上安装它。
这是我的编译命令
gcc -ansi -g -std=c99 -Wall -DLINUX -D_GNU_SOURCE threadid.c -o threadid -pthread -lrt -lbsd
这是输出:
main thread:
new thread:
new thread:
为什么"new thread"被打印了两次?
我怀疑这可能与 Linux 中的缓冲机制有关。但是在我在每个函数的末尾添加 fflush(stdout)
和 fsync(1)
之后。输出结果几乎一样。
如果你运行程序多次。输出不同:
main thread:
new thread:
或
main thread:
new thread:
new thread:
或
main thread:
大多数 libc 库都会像您提到的那样缓冲输出。在程序结束时(当主线程退出时),它们刷新所有缓冲区并退出。
您的新线程有可能刷新了输出,但在更新缓冲区状态之前,主程序退出并且清理代码再次刷新了同一个缓冲区。由于这些缓冲区是线程本地的,我确信它们不会有并发机制。但是由于这种罕见的情况,它可能会搞砸。
你可以试试
err = pthread_create(&ntid, NULL, thr_fn, NULL);
printids("main thread:");
pthread_join(ntid, NULL);
main函数结束,查看问题是否解决
这将导致您的主函数等待新线程完成(包括它执行的刷新操作)。
双重输出 在基于 glibc 的 linux 系统上是可能的,因为 glibc 中的一个讨厌的错误:如果 FILE
锁已经在time exit
尝试刷新,锁被简单地忽略并且缓冲区访问在没有同步的情况下执行。如果你能可靠地重现它,这将是一个很好的测试用例,可以向 glibc 报告以迫使他们修复它。
这是我的代码:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
pthread_t ntid;void
printids(const char *s) {
printf("%s \n", s);
}
void *
thr_fn(void *arg) {
printids("new thread: ");
return((void *)0);
}
int
main(void) {
pthread_create(&ntid, NULL, thr_fn, NULL);
printids("main thread:");
}
我运行在 Red Hat Enterprise Linux 工作站版本 6.5 上安装它。
这是我的编译命令
gcc -ansi -g -std=c99 -Wall -DLINUX -D_GNU_SOURCE threadid.c -o threadid -pthread -lrt -lbsd
这是输出:
main thread:
new thread:
new thread:
为什么"new thread"被打印了两次?
我怀疑这可能与 Linux 中的缓冲机制有关。但是在我在每个函数的末尾添加 fflush(stdout)
和 fsync(1)
之后。输出结果几乎一样。
如果你运行程序多次。输出不同:
main thread:
new thread:
或
main thread:
new thread:
new thread:
或
main thread:
大多数 libc 库都会像您提到的那样缓冲输出。在程序结束时(当主线程退出时),它们刷新所有缓冲区并退出。
您的新线程有可能刷新了输出,但在更新缓冲区状态之前,主程序退出并且清理代码再次刷新了同一个缓冲区。由于这些缓冲区是线程本地的,我确信它们不会有并发机制。但是由于这种罕见的情况,它可能会搞砸。
你可以试试
err = pthread_create(&ntid, NULL, thr_fn, NULL);
printids("main thread:");
pthread_join(ntid, NULL);
main函数结束,查看问题是否解决
这将导致您的主函数等待新线程完成(包括它执行的刷新操作)。
双重输出 在基于 glibc 的 linux 系统上是可能的,因为 glibc 中的一个讨厌的错误:如果 FILE
锁已经在time exit
尝试刷新,锁被简单地忽略并且缓冲区访问在没有同步的情况下执行。如果你能可靠地重现它,这将是一个很好的测试用例,可以向 glibc 报告以迫使他们修复它。