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

如何判断数字序列是否随机? (打鬼子)