使用_exit()在守护进程内进行fork()系统调用

时间:2014-06-26 07:20:39

标签: c++ c fork

fork()上有很多问题,但我对这段代码感到有些困惑。我正在用c ++分析代码,因为我有这个函数。

int daemon(int nochdir, int noclose) 
{

  switch (fork()) 
  {
    case 0:  break;
    case -1: return -1;
    default: _exit(0);          /* exit the original process */
  }

  if (setsid() < 0)               /* shoudn't fail */
    return -1;

/* dyke out this switch if you want to acquire a control tty in */
/* the future -- not normally advisable for daemons */
  printf("Starting %s                [ OK ]\n",AGENT_NAME);

  switch (fork()) 
  {
    case 0:  break;
    case -1: return -1;
    default: _exit(0);
  }

  if (!nochdir)    
  {
    chdir("/");
  }

  if (!noclose) 
  {
    dup(0); 
    dup(1);
  }

return 0;
}

因此fork将创建一个精确的代码副本,从中调用fork()。所以,

  1. 开关是执行两次还是一次?

  2. 如果孩子先执行,那么如果在切换中两次怎么办?它会破坏还是转到其他陈述?

  3. 如果父母执行了什么?主要程序将被终止,孩子会继续吗?

  4. 修改 因此,开关也将与父母一起运行两次,而与孩子一起运行一次。并在返回值上行事。

    最后一点是,守护进程是一个预定义的函数,它已被重新定义并像用户创建的守护进程一样使用。它将如何创建守护进程以及

    `if (!nochdir)    
    {
        chdir("/");
    }`
    

    if (!noclose) 
    {
        dup(0); 
        dup(1);
    }
    

    我这样称呼这个函数。

    if (daemon(0, 0) < 0) 
    {
        printf("Starting %s                [ Failed ]\n",AGENT_NAME);
        exit(2);
    }
    

3 个答案:

答案 0 :(得分:3)

  

开关是执行两次还是一次?

据说fork是一次调用的函数,但返回两次,即每次进程一次:一次在父级,一次在子级。

男:

  

成功时,子进程的PID在父进程中返回,   在孩子身上返回0。失败时,返回-1   parent,没有创建子进程,并且正确设置了errno

它可能只返回一次(-1):仅在父项中如果没有创建孩子。它总是在父级返回(错误时为-1,成功时为> 0)。

  

如果孩子先执行,那么如果在开关中两次怎么办?会吗   只是打破或转到其他陈述?

未知儿童或父母是否先退回。在fork()之后,所有内存段都被复制到child中,但它继续从fork()返回正确的值 0 。家长继续孩子的 pid 。您可以在代码中使用fork的返回值来确定您是子级还是父级。如果以这种方式编写代码,这可能会更清楚

int daemon( int nochdir, int noclose) 
{

  pid_t pid;                /* to drive logic in the code */ 

  if ( ( pid = Fork()) < 0) /* fork and remember actual value returned to pid */
      return -1;

  if( pid > 0)
    _exit(0);               /* exit the original process */

  // here pid is 0, i.e. the child
  

如果父母执行了什么?将主要过程终止并且   孩子会继续吗?

如果在任何子指令之前调用父exit()怎么办?然后是的,父母将终止,孩子将自己做。父进程和子进程都拥有相同的代码段,但彼此独立执行(除非您添加了一些同步)。

http://linux.die.net/man/2/fork

答案 1 :(得分:2)

是的,当父项执行时,它将继续使用默认值:case,因为交换机将返回子进程ID。

说fork()是一个被调用一次并返回两次的函数的常见惯例有点混淆,因为它只在每个进程空间中返回一次。问题是是否创建了一个孩子,它决定了父母返回的两种方式中的哪一种。父对象从不从fork()得到'0'的结果,只有-1或&gt; 0。孩子总是(如果有的话)得零。

如果未创建子级,则fork()永远不会在其进程空间中返回。

答案 2 :(得分:2)

  1. 除非出现错误,否则fork将返回两次:一次在父进程中,一次在子进程中。 fork创建当前进程的副本,然后在两个进程中继续执行,您可以通过返回值来确定。请注意,副本(孩子)不是&#34;完美的&#34; copy:例如,在子节点中,除了执行fork的线程之外,所有线程都被终止。 The exact behavior is a bit complex.

  2. 未指定父进程或子进程是否先继续执行。这取决于您的操作系统,甚至可能在您的操作系统上完全随机。由于它们是两个独立的进程(碰巧运行相同的代码),因此顺序并不重要。父进程将获得返回值> 0(或出错时为-1),从而执行default:标签。子进程的返回值为0,从而执行case 0:标签。 fork的返回值是父进程如何知道父进程和子进程知道它是一个子进程(子进程可以使用getpid(2)查询自己的PID,并使用{{1}查询其父进程的PID }})。

  3. 是的,父进入getppid(2)标签并执行default:,从而终止。孩子将继续跑(注意这里_exit非常重要;没有它,如果你父家的shell会话退出,孩子就不会继续跑。)这是创建守护程序的常用模式:当您运行程序时,它会通过分叉生成实际的主程序(守护程序),然后退出。例如,在shell中,您将看到程序快速退出,但是当您输入setsid()时,您可以看到具有相同名称的进程(您的守护程序)。