【发布时间】:2017-04-23 07:05:59
【问题描述】:
以下函数成功执行任何不包含管道的命令,所以不要担心奇怪的函数。这些工作。我遇到的问题是,每当我执行如下任何命令时:
cat file.txt | grep string
该命令已成功执行,但它仍处于空闲状态,因此不知何故卡住了,无法执行其他命令。为什么会这样?我认为这与我使用 pipe、dup 和 fork 的方式有关,所以尝试从这些函数中解决问题。我知道您可能会争辩说此代码不适用于其他带有管道的命令,但我只想让这个特定示例正常工作,为此我只需在第一次迭代中将 STDIN 重定向到打开的文件。
int myshell_execute(struct processNode* list, int a)
{
struct processNode* myList = list; // next node to be handled
int pipefd[2];
int in=0;
if (pipe(pipefd) == -1) {
perror("pipe");
myshell_exit(-1);
}
while(myList != NULL)
{
char* program = myList->program; // Get the program to be executed
char ** program_args = myList->program_arguments; // get the programs and arguments to be executed
char ** redirection_string = myList->redirection; //get the part of the command that contains redirection
int *status;
int* stdout;
int stdout_num = 1;
stdout = &stdout_num;
int fileDescriptor;
pid_t pid;
if(strcmp(program,"cd") == 0)
{
return myshell_cd(program_args);
}
else if (strcmp(program,"exit") == 0)
{
return myshell_exit(0);
}
pid = fork();
if(pid == 0)
{
if(in == 1)
{
close(pipefd[1]);
dup2(pipefd[0],0);
close(pipefd[0]);
}
if(sizeOfLine(redirection_string) != 0)
{
redirectionHandler(redirection_string,stdout); // This works. This just handles redirection properly
}
if(*stdout == 1 && myList->next !=NULL)
{
close(pipefd[0]);
dup2(pipefd[1],STDOUT_FILENO); // with this
close(pipefd[1]);
}
if(execvp(program,program_args) !=-1)
{
perror("myshell:");
myshell_exit(-1);
}
else{
myshell_exit(0);
}
}
else if (pid <0)
{
perror("myshell: ");
myshell_exit(-1);
}
else
{
wait(status);
}
in = 1;
myList = myList->next;
}
}
新解决方案:
int helper_execute(int in, int out, char* program, char ** program_args, char *redirection)
{
pid_t pid;
if ((pid = fork ()) == 0)
{
if (in != 0)
{
dup2 (in, 0);
close (in);
}
if (out != 1)
{
dup2 (out, 1);
close (out);
}
redirectionHandler(redirection);
return execvp (program, program_args);
}
return pid;
}
int myshell_execute(struct processNode* list, int a)
{
int i;
pid_t pid;
int in, fd [2];
struct processNode*new_list = list;
char ** newProgram = new_list->program_arguments;
char ** redirection = new_list->redirection;
char * program = new_list->program;
/* The first process should get its input from the original file descriptor 0. */
in = 0;
/* Note the loop bound, we spawn here all, but the last stage of the pipeline. */
while(new_list->next != NULL)
{
pipe (fd);
/* f [1] is the write end of the pipe, we carry `in` from the prev iteration. */
helper_execute (in, fd [1],program,newProgram,redirection);
/* No need for the write end of the pipe, the child will write here. */
close (fd [1]);
/* Keep the read end of the pipe, the next child will read from there. */
in = fd [0];
new_list = new_list->next;
}
/* Last stage of the pipeline - set stdin be the read end of the previous pipe
and output to the original file descriptor 1. */
if (in != 0)
dup2 (in, 0);
/* Execute the last stage with the current process. */
char* lastProgram = new_list->program;
char ** lastRedirection = new_list->redirection;
char * lastPrArguments = new_list->program_arguments;
redirectionHandler(redirection);
return execvp (lastProgram, lastPrArguments);
}
int main() {
int i=0;
char **input;
struct processNode* list;
int tracker = 0;
while ((input = getline()) != EOF) {
list = create_list(input);
myshell_execute(list,0);
}
return 0;
}
这个解决方案唯一的问题是,一旦执行了一个命令,main就立即检测到文件的结尾,所以它退出了shell。
【问题讨论】: