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()
。所以,
开关是执行两次还是一次?
如果孩子先执行,那么如果在切换中两次怎么办?它会破坏还是转到其他陈述?
如果父母执行了什么?主要程序将被终止,孩子会继续吗?
修改 因此,开关也将与父母一起运行两次,而与孩子一起运行一次。并在返回值上行事。
最后一点是,守护进程是一个预定义的函数,它已被重新定义并像用户创建的守护进程一样使用。它将如何创建守护进程以及
`if (!nochdir)
{
chdir("/");
}`
和
if (!noclose)
{
dup(0);
dup(1);
}
我这样称呼这个函数。
if (daemon(0, 0) < 0)
{
printf("Starting %s [ Failed ]\n",AGENT_NAME);
exit(2);
}
答案 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()怎么办?然后是的,父母将终止,孩子将自己做。父进程和子进程都拥有相同的代码段,但彼此独立执行(除非您添加了一些同步)。
答案 1 :(得分:2)
是的,当父项执行时,它将继续使用默认值:case,因为交换机将返回子进程ID。
说fork()是一个被调用一次并返回两次的函数的常见惯例有点混淆,因为它只在每个进程空间中返回一次。问题是是否创建了一个孩子,它决定了父母返回的两种方式中的哪一种。父对象从不从fork()得到'0'的结果,只有-1或&gt; 0。孩子总是(如果有的话)得零。
如果未创建子级,则fork()永远不会在其进程空间中返回。
答案 2 :(得分:2)
除非出现错误,否则fork
将返回两次:一次在父进程中,一次在子进程中。 fork
创建当前进程的副本,然后在两个进程中继续执行,您可以通过返回值来确定。请注意,副本(孩子)不是&#34;完美的&#34; copy:例如,在子节点中,除了执行fork
的线程之外,所有线程都被终止。 The exact behavior is a bit complex.
未指定父进程或子进程是否先继续执行。这取决于您的操作系统,甚至可能在您的操作系统上完全随机。由于它们是两个独立的进程(碰巧运行相同的代码),因此顺序并不重要。父进程将获得返回值> 0(或出错时为-1),从而执行default:
标签。子进程的返回值为0,从而执行case 0:
标签。 fork的返回值是父进程如何知道父进程和子进程知道它是一个子进程(子进程可以使用getpid(2)
查询自己的PID,并使用{{1}查询其父进程的PID }})。
是的,父进入getppid(2)
标签并执行default:
,从而终止。孩子将继续跑(注意这里_exit
非常重要;没有它,如果你父家的shell会话退出,孩子就不会继续跑。)这是创建守护程序的常用模式:当您运行程序时,它会通过分叉生成实际的主程序(守护程序),然后退出。例如,在shell中,您将看到程序快速退出,但是当您输入setsid()
时,您可以看到具有相同名称的进程(您的守护程序)。