【问题标题】:Chain of fork() outputfork() 输出链
【发布时间】:2013-11-27 11:19:20
【问题描述】:

我在 Unix 环境中完全是新手,我在罗宾斯的 Unix 系统编程书中的简单示例中遇到了一些问题。

这是一个简单的进程链,每个进程都会打印一些信息到日志文件和标准错误

#define BUFSIZE 1024
#define CREATE_FLAGS (O_WRONLY | O_CREAT | O_APPEND)
#define CREATE_PERMS (S_IRUSR | S_IWUSR| S_IRGRP | S_IROTH)

int main  (int argc, char *argv[]) {
   char buf[BUFSIZE];
   pid_t childpid = 0;
   int i, n;
   if (argc != 3){       /* check for valid number of command-line arguments */
      fprintf (stderr, "Usage: %s processes filename\n", argv[0]);
      return 1;
   }
                                        /* open the log file before the fork */

   n = atoi(argv[1]);                              /* create a process chain */
   for (i = 1; i < n; i++)
       if (childpid = fork())
          break;
   if (childpid == -1) {
      fprintf(stderr, "Failed to fork");
      return 1;
   }

   auto fd = open(argv[2], CREATE_FLAGS, CREATE_PERMS);
   if (fd < 0) {
      fprintf(stderr,"Failed to open file");
      return 1;
   }

   sprintf(buf, "i:%d process:%ld parent:%ld child:%ld\n", 
           i, (long)getpid(), (long)getppid(), (long)childpid);
   fprintf(stderr, buf);
   write(fd, buf, strlen(buf));
   return 0;
}

它是在 Netbeans 7.1 上使用 g++ 4.7 编译的,运行命令是 "${OUTPUT_PATH}" 10 /home/maxim/testlog.log

所以问题是:

  1. 当我运行或调试项目时,它只会在控制台和文件中打印出 2 或 3 行信息。但是,如果我通过 childpid = fork() 遍历“Step Over”,它会打印有关所有 10 个进程的信息。这是一些编译器优化还是我的错?

  2. 即使它打印所有行,输出看起来像

    i:2 process:6571 parent:6566 child:6572
    i:3 process:6572 parent:1 child:6573
    i:4 process:6573 parent:6572 child:6574
    ...
    i:9 process:6578 parent:1 child:6579
    i:10 process:6579 parent:6578 child:0
    

    某些进程的父 pid 值为 1,这似乎是错误的

【问题讨论】:

    标签: c++ unix fork netbeans-7 g++-4.7


    【解决方案1】:
    1. 如果每个进程都打开相同的输出文件,则会出现导致进程相互覆盖的竞争条件。这就是为什么它只有在你全速奔跑时才会发生。

    2. 当父进程结束时,任何仍然活着的子进程要么被杀死,要么得到一个新的父进程,具体取决于 Linux 中的设置。在你的情况下,他们似乎有了一个新的父母。新的父进程是进程 1。

    【讨论】:

    • 感谢您的回答,现在我理解了这段代码的问题,但您能否再请我一点:当我将 open() 放在 fork() 之前时,我得到相同的结果(2 或输出中的 3 个字符串),但 O_Append 标志应该使 write() 原子。所以我不明白如何正确使用带有附加标志的原子写入。
    • 问题还在于当另一个进程写入文件时文件指针没有正确更新。如果您想要绝对确定性,那么您需要某种锁定机制(例如文件锁定或信号量)或为每个进程使用单独的文件。如果“几乎总是有效”足够好(通常是用于日志文件),那么在每个日志事件之后关闭文件通常就可以解决问题,尤其是在日志量不太高的情况下。
    猜你喜欢
    • 2012-03-10
    • 2012-01-12
    • 2012-10-04
    • 2019-07-17
    • 1970-01-01
    • 2016-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多