Моя цель - написать программу, которая выполняет канал 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()
и затем процесс (дочерний процесс) зависает и, по-видимому, находится в спящем режиме.
Удаление оператора ожидания помогает, но вывод неправильный .... может ли это быть проблемой ожидания?