C 中的睡眠函数 (POSIX) 破坏了我的程序
Sleep function in C (POSIX) breaks my program
这是我的程序代码:
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <sys/types.h>
void function() {
srand(time(NULL));
while(1) {
int n = rand();
printf("%d ", n);
//sleep(1);
}
}
int main() {
pid_t pid;
pid = fork();
if (pid == 0) {
function();
}
}
随着睡眠线被注释掉(如上面的代码)程序工作正常(即它打印一堆随机数太快甚至看不到它们是否真的是随机的),但是如果我删除注释程序不打印任何内容并退出(甚至不是第一次,在它进入睡眠状态之前),即使它编译时没有警告或错误,有或没有评论。
我相信你需要打电话给 fflush(3) from time to time. See also setvbuf(3) and stdio(3) and sysconf(3)。
我猜如果你编码:
while(1) {
int n = rand();
printf("%d ", n);
if (n % 4 == 0)
fflush(NULL);
sleep(1);
}
您的程序的行为可能对用户更友好。 stdout
的缓冲区可能至少有几十千字节。
顺便说一句,我可能是错的。通过阅读最近的 C 草案标准进行检查(可能 n2176)。
至少,看到this C reference website then syscalls(2), fork(2) and sleep(3)。
您需要致电waitpid(2) or a similar function for every successful fork(2)。
如果在 Linux 上,另请阅读 Advanced Linux Programming and use both strace(1) and gdb(1) to understand the behavior of your program. With GCC 不要忘记将其编译为 gcc -Wall -Wextra -g
以获取所有警告和调试信息。
也考虑使用 Clang static analyzer。
but if I remove the comment the program doesn't print anything and exits
它不打印,但也不真正退出。它仍然是 运行 后台进程。该过程运行您的无限 while 循环。
在 p.c
中使用您的代码:
$ gcc p.c
$ ./a.out
$ ps -A | grep a.out
267282 pts/0 00:00:00 a.out
$ killall a.out
$ killall a.out
a.out: no process found
问题是 printf
并没有真正打印出来。它只将数据发送到输出缓冲区。为了强制打印输出缓冲区,调用 fflush(stdout)
如果您不刷新,那么您只需依赖您正在使用的终端的行为。当您将换行符写入输出流时,终端刷新是很常见的。这就是为什么最好使用 printf("data\n")
而不是 printf("\ndata")
的原因之一。有关详细信息,请参阅此问题:https://softwareengineering.stackexchange.com/q/381711/283695
我怀疑如果您只是离开您的程序 运行,它最终会打印出来。它有一个有限的缓冲区并且在缓冲区满时刷新是有道理的。但这只是一个(有根据的)猜测,这取决于您的终端。
it prints a bunch of random numbers too fast to even see if they are actually random
如何判断数字序列是否随机? (打鬼子)
这是我的程序代码:
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <sys/types.h>
void function() {
srand(time(NULL));
while(1) {
int n = rand();
printf("%d ", n);
//sleep(1);
}
}
int main() {
pid_t pid;
pid = fork();
if (pid == 0) {
function();
}
}
随着睡眠线被注释掉(如上面的代码)程序工作正常(即它打印一堆随机数太快甚至看不到它们是否真的是随机的),但是如果我删除注释程序不打印任何内容并退出(甚至不是第一次,在它进入睡眠状态之前),即使它编译时没有警告或错误,有或没有评论。
我相信你需要打电话给 fflush(3) from time to time. See also setvbuf(3) and stdio(3) and sysconf(3)。
我猜如果你编码:
while(1) {
int n = rand();
printf("%d ", n);
if (n % 4 == 0)
fflush(NULL);
sleep(1);
}
您的程序的行为可能对用户更友好。 stdout
的缓冲区可能至少有几十千字节。
顺便说一句,我可能是错的。通过阅读最近的 C 草案标准进行检查(可能 n2176)。
至少,看到this C reference website then syscalls(2), fork(2) and sleep(3)。
您需要致电waitpid(2) or a similar function for every successful fork(2)。
如果在 Linux 上,另请阅读 Advanced Linux Programming and use both strace(1) and gdb(1) to understand the behavior of your program. With GCC 不要忘记将其编译为 gcc -Wall -Wextra -g
以获取所有警告和调试信息。
也考虑使用 Clang static analyzer。
but if I remove the comment the program doesn't print anything and exits
它不打印,但也不真正退出。它仍然是 运行 后台进程。该过程运行您的无限 while 循环。
在 p.c
中使用您的代码:
$ gcc p.c
$ ./a.out
$ ps -A | grep a.out
267282 pts/0 00:00:00 a.out
$ killall a.out
$ killall a.out
a.out: no process found
问题是 printf
并没有真正打印出来。它只将数据发送到输出缓冲区。为了强制打印输出缓冲区,调用 fflush(stdout)
如果您不刷新,那么您只需依赖您正在使用的终端的行为。当您将换行符写入输出流时,终端刷新是很常见的。这就是为什么最好使用 printf("data\n")
而不是 printf("\ndata")
的原因之一。有关详细信息,请参阅此问题:https://softwareengineering.stackexchange.com/q/381711/283695
我怀疑如果您只是离开您的程序 运行,它最终会打印出来。它有一个有限的缓冲区并且在缓冲区满时刷新是有道理的。但这只是一个(有根据的)猜测,这取决于您的终端。
it prints a bunch of random numbers too fast to even see if they are actually random
如何判断数字序列是否随机? (打鬼子)