【问题标题】:C/C++ linux fork() and exec()C/C++ linux fork() 和 exec()
【发布时间】:2014-03-12 12:06:25
【问题描述】:

我使用 fork() 创建子进程。从子进程我使用 exec() 启动新进程。我的代码如下:

   ......
   pid = fork();
   if (pid > 0) {
       WriteLog("Parent Process");
       //Do something
   } else if (pid == 0) {
       WriteLog("Child process");
       int return = execl(ShellScript);
       if ( return == -1 ) 
          WriteLog("Launch process fail");
   } else {
       WriteLog("Can't create child process");
   }
   ......

注意:WriteLog 函数将是打开文件、写入日志和关闭文件。 (它被冲洗了) ShellScript 将启动新进程 c/c++。

我长期运行我的程序,上面的代码被多次调用。有时(很少)会发生新进程无法成功启动的问题,尽管子进程创建成功(我已经仔细检查过)。有一点是非常误解的,当这个问题发生时,虽然子进程创建成功,但“子进程”日志却无法打印。

在正常情况下(不发生错误)“子进程”和“父进程”日志的打印次数是相同的。

在异常情况下,虽然子进程总是创建成功,但它们并不相同。这种情况下不会打印“启动进程失败”和“无法创建子进程”日志。 请帮我咨询。

【问题讨论】:

    标签: c++ c linux multiprocessing


    【解决方案1】:

    请记住,stdio(3) 已被缓冲。在fork 之前,请始终致电fflush(NULL);(有关更多信息,请参阅fflush(3))。在每个printf(3) 格式字符串的末尾添加一个\n(换行符)(或者,在它们后面加上fflush(NULL); ...)。

    函数execl(3)(也许你想要execlp?)可能会失败(所以设置errno失败)。

    } else if (pid == 0) {
       printf("Child process\n");
       fflush(NULL);
       execl("/bin/foo", "foo", "arg1", NULL);
       // if we are here execl has failed 
       perror("Launch process fail");
    }
    

    出错时,fork(2) 失败并返回 -1 并设置 errno(3)(另请参阅 perror(3)strerror(3))。所以你最后一个else应该是

    } else {
        perror("Can't create child process");
        fflush(NULL);
    }
    

    您可能想使用strace(1)(特别是strace -f yourprog ...)来了解所涉及的syscalls(请参阅syscalls(2)...)

    您的WriteLog 可能应该使用strerror(在WriteLog开头 保存的errno 值......)。我建议像

     void WriteLog(const char* msg) {
       int e = errno;
       if (e) 
         syslog (LOG_ERR, "%s [%s]", msg, strerrno(e));
       else
         syslog (LOG_ERR, "%s", msg);
     }
    

    syslog(3)

    fork-ed 进程的数量有限制,请参阅 setrlimit(2)RLIMIT_NPROC 和 bash ulimit 内置。

    另请阅读Advanced Linux Programming

    【讨论】:

    • 很抱歉我的代码不清楚。我刚刚更新了。每次写日志时我都考虑过 fflush 我也刷新。所以我用文件来写日志。并且当子进程创建成功时启动进程失败时仍然不会打印日志。 (我根据 kill(childid) 函数检查这个东西
    • 我会尝试使用strerror和errno。目前我的系统也使用系统日志和日志文件来打印日志。我会尝试使用它。谢谢你的好主意。
    • 同时fork的进程总是小于7,所以我认为没有超过限制
    • 声明if ( return == -1 ) 似乎没有必要:execl 除非失败,否则不会返回。
    • 虽然子进程启动成功,但当 excel 启动新进程失败时,系统日志仍未打印。 syslog 中的 errno 总是成功的。这似乎是系统资源不足以做更多的事情:(。我认为:)。
    猜你喜欢
    • 1970-01-01
    • 2013-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多