日期:2014-05-16  浏览次数:20763 次

fork()函数入门级问题:fork()与进程数
这样一段代码:
最后还剩2个进程?为什么呢?
我的意见是 初始父进程 在第一次fork()后终止;第一子进程在第二次fork()后终止,然后就只剩下第二子进程了???
C/C++ code

if ( (pid=fork())<0 ){
        printf("error fork()\n");
        exit(1) ;
    }

    else if (pid!=0) {
            exit(0);
         }

// ...............................................................some other  ,but have no fork() 

    if ( (pid=fork()<0) ){
        fputs("error fork()\n",stdout);
        exit(1) ;
    }
    else if (pid!=0) {
            exit(0);
         }



这是完整的源码:
C/C++ code

void daemonize(const char *cmd)
{
    int                 i,fd0,fd1,fd2;
    pid_t                 pid;
    struct rlimit        rl;
    struct sigaction     sa;

    umask(0);

    if ( getrlimit(RLIMIT_NOFILE,&rl)<0 ){
        printf("%s can't get file limit.\n",cmd);
        exit(1) ;
    }

    if ( (pid=fork())<0 ){
        printf("error fork()\n");
        exit(1) ;
    }

    else if (pid!=0) {
            exit(0);
         }

    setsid();//creates a session and sets the process group ID.

    sa.sa_handler = SIG_IGN;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags=0;
    if (sigaction(SIGHUP,&sa,NULL)<0){
        printf("error sigaction()");
        exit(1) ;
    }

    if ( (pid=fork()<0) ){
        fputs("error fork()\n",stdout);
        exit(1) ;
    }
    else if (pid!=0) {
            exit(0);
         }
/*
    if ( chdir("/tmp")<0 ){
        FILE *fp=fopen("err","w");
        fprintf(fp,"%d",errno);
        fprintf(fp,"woj");

        printf("error chdir()\n");
        exit(1) ;
    }
*/

    if (rl.rlim_max == RLIM_INFINITY){
        rl.rlim_max = 1024;
    }
    for(i=0;i<rl.rlim_max;i++){
        close(i);
    }

    fd0=open("/dev/null",O_RDWR);
    fd1=dup(0);
    fd2=dup(0);

    openlog(cmd,LOG_CONS,LOG_DAEMON);
/*
    if(fd0!=0||fd1!=0||fd2!=0){
        syslog(LOG_ERR,"unexpected file descriptors %d %d %d\n",fd0,fd1,fd2);
        exit(1);
    }
*/

}



------解决方案--------------------
建守护进程, 最后就一个孩子的孩子。

第一个孩子是为了获取一个全新的进程ID以便创建新的会话和新的进程组并成为进程组长与会话组长,这样就断开了之间关联的终端,SIGHUP是发不过来的了。

第二个孩子是怕第一个孩子重新获得终端,因为会话组长有权重新关联终端,所以再fork一个孩子,这个孩子是在一个没有关联终端的会话里,而且不会会话组长,就OK了。
------解决方案--------------------
亲自调试,找出了bug。在第二次fork()时,
if ( (pid=fork()<0) ) // ERROR!!!
if ( (pid=fork())<0 ) // RIGHT!!!