使用exec(),fork()和pipe()冻结进程

时间:2018-05-20 22:02:57

标签: c bash pipe fork exec

我的目标是编写一个程序,使用C中的匿名管道执行bash管道。

现在我用这个命令测试我的函数:ls -l | wc [编辑],但目标是连接多个管道或只是在没有它们的情况下执行程序。

我使用的主程序调用了执行fork和exec的routines.h头文件中定义的函数:

MAIN.C

#include <stdlib.h> 
#include <stdio.h>
#include <string.h>
#include "routines.h"

#define READ 0 // for file descriptor index
#define WRITE 1 // for file descriptor index

typedef enum eMode{ // typedef of exec modes
    LEFT_PIPE=0,    // cmd1|... start pipe
    CENTER_PIPE=1,  // cmd1|cmd2|... center pipes
    RIGHT_PIPE=2,   // ...|cmd2  end of the pipe
    NORMAL_COMMAND=3// normal cmd
} Mode; 

int main()
{
    char * commandTest1[]={"ls","-l",NULL};
    char * commandTest2[]={"wc",NULL};

    int pipeFileDesc[2];
    pipe(pipeFileDesc);

    executeCommand(commandTest1,pipeFileDesc[READ],pipeFileDesc[WRITE],LEFT_PIPE);
    executeCommand(commandTest2,pipeFileDesc[READ],pipeFileDesc[WRITE],RIGHT_PIPE);

return 0;
}

在Routines.c中执行命令

int executeCommand(char** args,int inputDataFD,int outputDataFD,int mode){  //inputDataFD is READ PIPE BUFFER
                                                                        //outputDATA is WRITE PIPE BUFFER
    int pid,retCode,status;


    pid=fork(); // fork MONOLITIC: monolitic (father) remains unchanged the son will be transformed in exec of args 


    if(pid==-1){
        perror("Fork Error, for command: ");
        return 1; // TODO: in main read strerror(errno)
    }else{
        if(pid==0){ //son process
            printf("Child process: pid %i, father pid %i , pid fork %i \n",getpid(),getppid(),pid);
        ////////////////////// SETTING OF STDOUT/IN REDIRECTS //////////////////////

            if(mode==LEFT_PIPE){ // nothing to read for the process-> left side of the pipe -> PIPE has NO contet and another pipe is found
                close(inputDataFD);     //close the READ id/channel of the pipe Buffer: !!!! for a process the read side is input !!!!
                dup2(outputDataFD,1);   // redirects stdout on pipe write: fd 1 for every process is STDOUT, dup2 closes the file linked previously by stdout (closes stdout file)
                                        // and assign fd=1 to the file linked by outputDataFD (pipeFileDesc[WRITE]), beacuse of that outputDataFD (pipeFileDesc[WRITE]) 
                                        // is a duplicate and it can be unlinked with close()
                close(outputDataFD);
            }       
            if(mode==CENTER_PIPE){ //repiping: PIPE has contet and another pipe is found
                dup2(inputDataFD,0);    // redirects stdin on pipe READ: fd0 for every process is STDIN, dup2 closes the file linked previously by stdin (closes stdin file)
                                        // and assign the file linked by inputDataFD (pipeFileDesc[READ]) to fd id=0 (where processes get data for input (exstdin)
                                        // beacuse of that inputDataFD (pipeFileDesc[READ]) is a duplicate and it can be unlinked with close()
                close(inputDataFD);

                dup2(outputDataFD,1);   // redirects stdout on pipe write: fd 1 for every process is STDOUT, dup2 closes the file linked previously by stdout (closes stdout file)
                                        // and assign fd=1 to the file linked by outputDataFD (pipeFileDesc[WRITE]), beacuse of that outputDataFD (pipeFileDesc[WRITE]) 
                                        // is a duplicate and it can be unlinked with close()
                close(outputDataFD);                         
            }
            if(mode==RIGHT_PIPE){ //nothing to write for the process-> right side of pipe ->PIPE has contet and NO other pipe is found
                close(outputDataFD); // close the WRITE id/channel of the pipe Buffer: !!! for a process the write side is output !!!!
                dup2(inputDataFD,0);    // redirects stdin on pipe READ: fd0 for every process is STDIN, dup2 closes the file linked previously by stdin (closes stdin file)
                                        // and assign the file linked by inputDataFD (pipeFileDesc[READ]) to fd id=0 (where processes get data for input (exstdin)
                                        // beacuse of that inputDataFD (pipeFileDesc[READ]) is a duplicate and it can be unlinked with close()
                close(inputDataFD);

            }
            if(mode==NORMAL_COMMAND){ // non pipes-> no STDOUT/IN redirections -> PIPE has NO contet and NO other pipe is found

            }


            retCode=execvp(args[0],args); // exec command arg[0] with process name arg[0] and arg[1->i] parameters
                                          // stdout of process is redirected onto outputDataFD that is pipeBuffer WRITE side
            if(mode==RIGHT_PIPE) printf("error TWO %s",strerror(errno));


            if(retCode == -1){

                perror("Exec error, unable to execute:");
                return 1; //smthing went wrong same TODO in main read output strerror(errno)

            }

        }else{ //father process
            printf("Parent process: pid %i, pid fork %i \n",getpid(), pid );

            waitpid(pid,&status,0);    // The wait system-call puts the process to sleep and waits for a child-process to end. 
                                       // It then fills in the argument with the exit code of the child-process (if the argument is not NULL).
            perror("\n");
            printf("\nout of wait\n");
            if(WIFEXITED(status)==1){//this macro translate the value int of status in TRUE if child ends normaly and FALSE otherwise
                return WEXITSTATUS(status); //returns to the main the status of the call
            }else{
                printf("wait error\n");
            } 

        }

    }//end else pid==0

}//end executeCommand

所以我的问题是,当执行这个文件时,它一直运行到execvp()的第二次调用的executeCommand(),并且过程(孩子一个)冻结并且似乎处于睡眠状态模式。

删除等待语句有帮助,但输出错误......可能是等待问题吗?

0 个答案:

没有答案