当前位置: 技术问答>linux和unix
关于fork(),有一段程序不理解。
来源: 互联网 发布时间:2015-06-16
本文导语: 刚接触fork(),在看一个程序,是一个ftp的server。刚开始有一段这样的程序: if (fork()) exit(0); /* Exit from parent process */ setsid(); if (fork()) return 0; 我能理解第一个fork,是退出父进程,留下子进...
刚接触fork(),在看一个程序,是一个ftp的server。刚开始有一段这样的程序:
if (fork())
exit(0); /* Exit from parent process */
setsid();
if (fork())
return 0;
我能理解第一个fork,是退出父进程,留下子进程。目的是使程序作为一个后台服务进程。但为什么之后还要用一个fork呢?目的是什么?
if (fork())
exit(0); /* Exit from parent process */
setsid();
if (fork())
return 0;
我能理解第一个fork,是退出父进程,留下子进程。目的是使程序作为一个后台服务进程。但为什么之后还要用一个fork呢?目的是什么?
|
这样的目的在于把程序设置为init进程,失去控制台,可以在用户退出控制台后继续运行。
|
呵呵,我想使这样的:当fork以后,子进程和父进程从fork处同时执行,在父进程中调用exit(第一个),父进程退出,而子进程中调用setsid()。子进程接着执行,然后又在子进程中创建另一个子进程,还是一样,第一个子进程返回。下边执行第二个创建的子进程
|
正如楼上所说
不过至于为什么要这样写,就要看看前后的代码,或者注释说明le
不过至于为什么要这样写,就要看看前后的代码,或者注释说明le
|
yaxii(笑影) 说得对
|
yaxii(笑影) 说的不对~~
因为在第一个父进程终止的时候,当前进程的父进程已经是init了,而setsid是让它变成daemon而失去控制台。
实际上fork两次最可能的原因是要避免zombie的产生,但是那是在父进程没有exit的情况下才需要这样做,而对于上面这个例子,由于父进程已经终止了,所以子进程再fork一次也不是为了这个原因。
如果是因为程序不能判断是第2行的exit(0)先执行,还是setsid后面的程序先执行,那么它同样不能断定是第5行的return先执行还是更后面的statement先执行。
实际上,说道这里,原因已经出来了。第2行终止用的是exit(0),而第5行用的是return 0。第2个fock的父进程并没有结束,结束的是当前运行的函数而已。
因为在第一个父进程终止的时候,当前进程的父进程已经是init了,而setsid是让它变成daemon而失去控制台。
实际上fork两次最可能的原因是要避免zombie的产生,但是那是在父进程没有exit的情况下才需要这样做,而对于上面这个例子,由于父进程已经终止了,所以子进程再fork一次也不是为了这个原因。
如果是因为程序不能判断是第2行的exit(0)先执行,还是setsid后面的程序先执行,那么它同样不能断定是第5行的return先执行还是更后面的statement先执行。
实际上,说道这里,原因已经出来了。第2行终止用的是exit(0),而第5行用的是return 0。第2个fock的父进程并没有结束,结束的是当前运行的函数而已。
|
如果这段代码是在main函数里面的话,我认为第二个fork没有任何意义~~
|
同意passingguy(贝多芬作品13号第二乐章)的看法
进程调用setsid是为了建立一个新的session(对话期),如果调用该函数的进程已经是一个进程组的组长,则setsid会返回错误,为了保证不出现这种情况,通常都会先调用fork,然后终止父进程,而子进程继承了父进程的进程组ID,而它的进程ID又是新分配的,从而保证了子进程不是进程组组长。也就是说,第一个fork既让当前进程成为init进程,同时也确保了setsid的正确执行,至于为什么又要做第二个fork创建子子进程,我估计是程序作者误解了对话期首进程和控制终端间的联系,其实在调用setsid时,该进程就已经和控制终端解除联系了,总之我认为第二个fork是没有意义的。
至于return和exit,这段代码在我看来觉得只是程序作者无心的混用,因为:
在main中使用return而不是exit的话,可以避免某些编译器或是lint(C程序验证器)程序产生不必要的警告信息,因为有些编译器不能正确判断main中exit和return起到的是相同的作用,这样做的不好之处在于不方便完整找到程序中的所有exit调用,尤其是程序做大之后。
进程调用setsid是为了建立一个新的session(对话期),如果调用该函数的进程已经是一个进程组的组长,则setsid会返回错误,为了保证不出现这种情况,通常都会先调用fork,然后终止父进程,而子进程继承了父进程的进程组ID,而它的进程ID又是新分配的,从而保证了子进程不是进程组组长。也就是说,第一个fork既让当前进程成为init进程,同时也确保了setsid的正确执行,至于为什么又要做第二个fork创建子子进程,我估计是程序作者误解了对话期首进程和控制终端间的联系,其实在调用setsid时,该进程就已经和控制终端解除联系了,总之我认为第二个fork是没有意义的。
至于return和exit,这段代码在我看来觉得只是程序作者无心的混用,因为:
在main中使用return而不是exit的话,可以避免某些编译器或是lint(C程序验证器)程序产生不必要的警告信息,因为有些编译器不能正确判断main中exit和return起到的是相同的作用,这样做的不好之处在于不方便完整找到程序中的所有exit调用,尤其是程序做大之后。
|
我手头也有这样的代码,有部分注释
void Init_daemon(void)
{
struct sigaction act;
int error, in, out;
int pid;
int i;
if(pid = fork())
exit(0);//是父进程,结束父进程
else if(pid
void Init_daemon(void)
{
struct sigaction act;
int error, in, out;
int pid;
int i;
if(pid = fork())
exit(0);//是父进程,结束父进程
else if(pid