linux进程间通信之管道

         linux中fork中一个子进程,这个子进程需长期运行,而父进程又不想使用wait来等待子进程结束;为了避免产生僵死进程,于是想到了两次fork的方法,让那个进程作为孙进程。但是,如果想在父进程中获得孙进程的pid,该如何做呢?因为子进程知道孙进程的pid,于是想到了使用管道把孙进程的pid由子进程传递给父进程。下面是代码片段。

/**Function:start a tor process.we call fork twice to aviod zombie process
 *Parameter:none
 *Retval:succeed-pid of the started tor process;failed-'-1'
 */
pid_t start_tor()
{
    pid_t pid;
    int fd[2];
    char line[8];
    if(pipe(fd)<0){
        perror("pipe failed");
        return -1;
    }

    if((pid=fork())<0){
         perror("fork failed");
         return -1;
    }else if(pid==0){           //first child
        close(fd[0]);            //close read end
        if((pid=fork())<0){
            perror("fork failed");
        }else if(pid>0){
            sprintf(line,"%d/0",pid);
            write(fd[1],line,sizeof(line));      //write tor pid to pipe
            exit(0);
        }
        //we are the second child;our parent becomes init as soon as our real parent calls exit() in that statement above.
        //change work directory
        char *home_dir;
        if((home_dir=getenv("HOME"))==NULL){
            perror("get $HOME failed");
            exit(1);
        }
        char work_dir[64];
        sprintf(work_dir,"%s/tor/tor/bin/",home_dir);
        if(chdir(work_dir)==-1){
            perror("chdir failed");
            exit(1);
        }
        //redirect tor stdout to log file
        int filedes;
        umask(0);
        if((filedes=open("tor_log",O_RDWR|O_CREAT|O_TRUNC,RWRWRW))<0){
                perror("open tor_log failed");
                exit(1);
        }
        if(dup2(filedes,1)<0){
                perror("dup2 failed");
                exit(1);
        }
        if(execlp("/home/hyh/tor/tor/bin/tor","tor",(char *)0)==-1){
            perror("execlp failed");
            exit(1);
        }
        if(DEBUG){
            printf("exit from tor,you should not see this tip/n");
        }
        exit(1);
    }
    close(fd[1]);               //close write end
    read(fd[0],line,8);         //read tor pid from pipe

    if(waitpid(pid,NULL,0)!=pid){
        perror("waitpid failed");
        return -1;
    }
    if(DEBUG){
        sleep(60);
    }
    return atoi(line);
}

 

APUE 2 Edtion 对管道的介绍如下:

管道是UNIX系统IPC的最古老形式,并且所有UNIX系统都提供此种通信机制。管道有以下两方面局限性:

(1)它们是半双工的,即数据只能在一个方向上流动。现在,某些系统提供全双工管道,但是为了最佳的可移植性,我们决不应预先假定系统提供此特性。

(2)它们只能在具有公共祖先的进程之间使用。通常,一个管道由一个进程创建,然后该进程调用fork,此后父、子进程之间就可应用该管道。

另外UNIX中父子进程之所以可以通过管道进程通信,我猜是由于fork的子进程继承了父进程的文件描述符表的缘故。

 

参考:APUE 2 Edition 183 Page

            APUE 2 Edition 398 Page

你可能感兴趣的:(linux进程间通信之管道)