簡體   English   中英

使用execvp時輸入重定向問題?

[英]Input redirection problem while using execvp?

我已經實現了一個模擬$ls -l | wc -c的簡單程序 使用簡單管道和execvp調用執行$ls -l | wc -c命令。

現在重定向stdin和stdout后,執行程序時,shell提示符消失,等待按下回車鍵。

任何解決這個問題的方法。 Plz批評我的代碼也..

謝謝

 /* Create pipe */
  ret_val=pipe(pipe_fd);
  /*Error check */
   if(ERROR==ret_val)
   {
    perror("Pipe creation error \n");
    _exit(FAILURE);
   }

/*Fork First Child */
pid_one = fork() ;

if( 0 == pid_one ) /*child process block */
{


    /* First sub process */
    /*printf("First sub process is %d \n",getpid());*/

    /* redirect stdout to pipe's write end  for sub process one*/
    dup2(pipe_fd[1],1);


    /*close pipe read end */
    close(pipe_fd[0]);

    execvp(cmd_one_tokens[0],cmd_one_tokens);   

    /* if execvp returns then if must have failed */
    printf("Unknown Command \n ");
    //exit(10);
}
else /*main process block */
{
    /*printf(" Main  process is %d \n",getpid());*/

    /*Wait for first sub process to finish */
    //wait(&status);

    /*printf("Exit status of first child is %d \n ", WEXITSTATUS(status) );*/

    /*Fork second subprocess */
    pid_two = fork();

    if( 0 == pid_two ) /*second child process block */
    {
        /* redirect stdin  to pipe's read end  for sub process two */
        dup2(pipe_fd[0],0);

    //  close(0);       /* close normal stdin */
        //  dup(pipe_fd[0]);   /* make stdib same as pfds[0] */


        /*close pipe write end */
        close(pipe_fd[1]);

        /* Second  sub process */
        /*printf("Second sub process is %d \n",getpid()); */

        execvp(cmd_two_tokens[0] , cmd_two_tokens); 
        /* if execvp returns then if must have failed */
        printf("Unknown Command \n ");

    }
    else        /*main process block */
    {
        /* printf(" Main  process is %d \n",getpid()); */
        status=-1; /*reset status */

        /*Waiting for the second sub process to finish in No hang fashion */
            waitpid ( -1 , &status ,WNOHANG);
        /*printf("Exit status of second  child is %d \n ", WEXITSTATUS(status) ); */

    }
}

在分叉后,您必須在主進程中關閉管道文件描述符。 在關閉它們之前,子進程( wc )將等待主進程仍然打開的管道上的輸入。 您必須非常小心地關閉管道的所有不需要的端部。

您的代碼沒有按照您的描述執行您想要執行的操作:

你創建一個管道,分叉一個新進程,將它的stdout重定向到管道並讓它執行一些程序(到目前為止一直很好),然后在父進程中等待你的孩子完成,然后只分叉第二個進程,重定向它stdin到管道的另一端,讓它執行另一個程序。

這不是“ls | wc”所做的 - 在shell中它們同時運行。 刪除第一個wait()。

 pid_one = fork() ; if( 0 == pid_one ) /*child process block */ 

你沒有檢查fork(2)的錯誤返回,這是一個非常現實的可能性。 (用戶可能會kernel.threads-max他們的RLIMIT_NPROC限制, kernel.threads-max ,用於保存任務結構的內存不足等)

更慣用的fork(2)使用如下所示:

if(-1 == (pid = fork()) {
    perror("fork");
    exit(1); /* or return -1 or similar */
} else if (0 == pid) {
    /* executing as child */
} else {
    /* parent, pid is child */
}
 execvp(cmd_two_tokens[0] , cmd_two_tokens); /* if execvp returns then if must have failed */ printf("Unknown Command \\n "); 

請注意, execvp(3)失敗的原因有很多 ; 簡單地打印“未知命令”可能會讓您的用戶在將來感到非常困惑。 調用perror("execvp");會更好perror("execvp"); 並讓您的用戶有機會發現他們的execvp(3)調用失敗的真正原因。

  waitpid ( -1 , &status ,WNOHANG); 

在這里使用WNOHANG可能很危險; 如果系統“正常”運行,您的父母可能會在孩子甚至有機會開始執行之前獲得此代碼。 因為如果沒有孩子退出,你已經要求它立即返回,孩子可能會在最終退出時變成僵屍 - 你的代碼沒有機會再次等待孩子。

我不確定最佳解決方案是什么:如果您使用SA_NOCLDWAIT進行sigaction(2)以避免完全創建僵屍,您將沒有機會收集孩子的退出狀態。 安裝SIGCHLD信號處理程序可能會干擾進程的其余部分; 您的客戶可能有理由自行設置。 使用阻塞waitpid(2)可能會停止其他地方的處理。 並且使用非阻塞waitpid(2)意味着您仍然必須在某個時間收集孩子的狀態,可能通過輪詢。 (但是在這種情況下你不能使用-1作為pid ,因為你可能會意外地收獲另一個子進程。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM