заморозить процесс с помощью exec (), fork () и pipe () - PullRequest
0 голосов
/ 21 мая 2018

Моя цель - написать программу, которая выполняет канал bash с использованием анонимных каналов в C.

Пока я тестирую свою функцию с помощью этой команды: ls -l | wc [EDIT], но цельобъединить несколько каналов или просто выполнить программу без них.

Я использую основную программу, которая вызывает функцию, определенную в заголовке routines.h, которая выполняет fork и exec:

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;
}

executeCommand в 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()и затем процесс (дочерний процесс) зависает и, по-видимому, находится в спящем режиме.

Удаление оператора ожидания помогает, но вывод неправильный .... может ли это быть проблемой ожидания?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...