C-使用fork和sleep函数的结果出乎意料

时间:2018-08-08 13:17:52

标签: c fork sleep

我找到了这篇Redirect ouput to another instance terminal window帖子,并尝试使用类似的代码替代方法,但是在将sleep函数或类似函数与fork函数结合使用时,得到了意外的结果。

我从(“父”)终端窗口运行以下代码。该程序应该打开另一个(子)终端窗口,并在无限循环中向父终端和子终端打印一些文本。

问题在于,每个窗口中的打印频率都不相同,实际上可能会非常不同。

我尝试了4个替代循环(一个仅需要同时注释掉4个替代循环中的1个)。 Alternative-1太快了,看不到太多,并且两个窗口的打印频率 look 相似。

在替代方法2,-3和-4中,当我尝试通过睡眠功能或较长的辅助循环(*)减慢循环速度时,就会出现问题。在那里,可以看到文本输出的时序在两个终端之间变得不同步,并且消息(似乎)以所需的周期性在父窗口中打印,例如在sleep(1)上有1秒的延迟,子窗口中的周期性似乎是随机且滞后的(例如,在我的机器上,子窗口中的第一条输出之前需要约200秒的时间)。替代方案4与替代方案2类似,但用fwrite代替fprintf。

我的问题:为什么两个窗口之间有这样的滞后?这种滞后是“确定性的”还是随机的?使两个终端以相同的常规频率打印的方式是什么?

我在Linux上。 gcc logwindow.c -o logwindow应该足以编译代码。

(*)我知道使用长循环(在替代3中)代替睡眠功能是不好的做法。我只是想看看它是否会从睡眠功能中得到不同的结果。

#include <stdlib.h>                 // system
#include <stdio.h>                  // tempnam, sprintf
#include <unistd.h>                 // sleep
#include <sys/types.h>          // pid_t

FILE *logwindow(){
  char *fp = tmpnam(NULL); //generate a random filepath/name
  char cmd[256];
  pid_t pid;

  mkfifo(fp, 0777);
  pid = fork();

  if (pid==0) {
      sprintf(cmd, "xterm -e \"cat %s\"", fp);
      system(cmd);
      return(NULL);
    }
  return fopen(fp, "w");
}


int main(){
    FILE *log = logwindow();

    if (log == NULL) {
        printf("child process, exiting\n"); 
        exit(0);
    }

    else {
        printf("parent process, keep going\n"); 
        int i=0;


        /* comment out only 1 alternative out of the 4 */

        // alternative-1 

        for(;;){
            fprintf(log, "i=%d, Child Terminal here\n", i); // print to child terminal
            printf("i=%d,  Parent Terminal here\n", i);     // print to parent terminal
            i++;
        }


        // alternative-2
        /*
        for(;;){
            fprintf(log, "i=%d, Child Terminal here\n", i); // print to child terminal
            printf("i=%d,  Parent Terminal here\n", i);     // print to parent terminal
            sleep(1);
            i++;
        }
        */

        // alternative-3
        /*
        int j=0;
        for(i=0;i<100000;i++){
            fprintf(log, "i=%d, Child Terminal here\n", i); // print to child terminal
            printf("i=%d,  Parent Terminal here\n", i);     // print to parent terminal
            for(j=0;j<5000000;j++){}                        // simulate the sleep function
        }
        */      

        // alternative-4
        /*
        char alt4text[] = "Child Terminal here\n";          
        for(;;){
            fwrite(alt4text, 1, sizeof(alt4text),log);          // print to child terminal
            printf("i=%d,  Parent Terminal here\n", i);     // print to parent terminal
            sleep(1);
            i++;
        }
        */


    }
}

1 个答案:

答案 0 :(得分:0)

您可能在缓冲方面遇到了问题。

在致电fprintf()后尝试致电fflush()

fprintf(log, "i=%d, Child Terminal here\n", i); // print to child terminal
fflush(log)

或者,您可以使用setbuf() / setvbuf()

查看行缓冲或完全禁用缓冲

还请注意,for(j=0;j<5000000;j++){}不是一个好主意-曾经。这被称为“ <忙>忙循环”,它将占用处理器时间-增加电源使用量,温度,并使其他资源进程枯竭。

即使在微控制器上工作,这也是一个坏主意,应尽可能避免使用。

另外,根据编译器的优化设置,这可能根本不产生指令,从而使alternative-3等效于alternative-1