问题描述
我不知道我为什么挂在这里。据我所知,我已经正确地进行了管道和分叉,当我检查数组中的数据时,它很好。然而,当我尝试运行“ls -l | grep total”之类的命令时,它会挂起。有人可以帮我吗?
当我运行一个不涉及管道的命令时,它很好。但是当我尝试实现管道部分时,它挂了。奇怪的是,在我将所有内容分解为单独的功能之前,这对我有用。我假设我在某个地方犯了错误,但我只是没有看到它是什么。在重构我的代码之前,我试图保持所有内容与我的状态相似。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <fcntl.h>
#define MAX_BUF_SZ 1024
#define MAX_ARGS 10
bool checkForPipe(const char *string);
bool checkForRedirect(const char *string);
void tokenizeInput(char * string,char ** l_array,char **m_array,char **r_array,bool pipey,bool redirect,int *status);
void createArguments(char *string,char **arg_array);
void executeCommand(int status,char **l_array,char **r_array);
int main()
{
char *ptr;
bool is_pipe = false;
bool is_redirect_out = false;
bool is_exit = false;
int exec_status = 0; //Will determine how to execute execvp()
char *l_args[MAX_ARGS] = {NULL};
char *m_args[MAX_ARGS] = {NULL};
char *r_args[MAX_ARGS] = {NULL};
ptr = (char*)malloc(MAX_BUF_SZ);
while(!is_exit)
{
// Diplay prompt
char cur_dir[MAX_BUF_SZ];
getcwd(cur_dir,MAX_BUF_SZ);
printf("SHELL:%s$ ",cur_dir);
fgets(ptr,MAX_BUF_SZ,stdin);
is_pipe = checkForPipe(ptr);
is_redirect_out = checkForRedirect(ptr);
if(strcmp(ptr,"exit\n") == 0)
{
is_exit = true;
}
tokenizeInput(ptr,l_args,m_args,r_args,is_pipe,is_redirect_out,&exec_status);
executeCommand(exec_status,r_args);
for(int i = 0; i < MAX_ARGS; i++)
{
l_args[i] = NULL;
m_args[i] = NULL;
r_args[i] = NULL;
}
}
return 0;
}
bool checkForPipe(const char *string)
{
return strchr(string,'|') != NULL;
}
bool checkForRedirect(const char *string)
{
return strchr(string,'>') != NULL;
}
void tokenizeInput(char *string,int *status)
{
// No pipes or redirects given by user
if(!pipey && !redirect)
{
char main_str[1024];
strcpy(main_str,string);
//initialize argument array
createArguments(main_str,l_array);
*status = 1;
}
//A single pipe given by user
else if(pipey && !redirect)
{
char main_str[1024];
char pipe_str[1024];
strcpy(main_str,string);
char *token = strchr(main_str,'|');
*token = '\0';
token++;
while(*token == ' ')
{
token++;
}
strcpy(pipe_str,token);
//initialize argument arrays
createArguments(main_str,l_array);
createArguments(pipe_str,r_array);
*status = 2;
}
// A single redirect given by user
else if(!pipey && redirect)
{
char main_str[1024];
char pipe_str[1024];
strcpy(main_str,string);
char *token = strchr(main_str,'>');
*token = '\0';
token++;
while(*token == ' ')
{
token++;
}
strcpy(pipe_str,token);
//Initialize argument arrays
createArguments(main_str,r_array);
*status = 3;
}
else if(pipey && redirect)
{
// declare some strings
char copy_str[MAX_BUF_SZ];
char main_str[MAX_BUF_SZ];
char pipe_str[MAX_BUF_SZ];
char redirect_str[MAX_BUF_SZ];
//make copy of the readonly string
strcpy(copy_str,string);
char *token = strtok(copy_str,"|>");
//create the main string
strcpy(main_str,copy_str);
//create pipe string
token = strtok(NULL,"|>");
while(*token == ' ')
{
token++;
}
strcpy(pipe_str,token);
//create redirect string
token = strtok(NULL,"|>");
while(*token == ' ')
{
token++;
}
strcpy(redirect_str,m_array);
createArguments(redirect_str,r_array);
*status = 4;
}
}
void createArguments(char *string,char **arg_array)
{
char *token;
char copy_str[MAX_BUF_SZ];
strcpy(copy_str,string);
int i = 0;
for(token = strtok(copy_str," \n"),i = 0; token; token = strtok(NULL," \n" ),++i)
{
arg_array[i] = token;
}
}
void executeCommand(int status,char **r_array)
{
int fd[2];
pid_t cpid_1;
pid_t cpid_2;
// No Pipes or Redirects
if(status == 1)
{
cpid_1 = fork();
if(cpid_1 < 0)
{
printf("Failed to fork");
exit(EXIT_FAILURE); //Error forking
}
if(cpid_1 == 0)
{
if(execvp(l_array[0],l_array) == -1)
{
printf("Failed to execute command");
exit(EXIT_FAILURE);
}
}
wait(NULL);
}
else if(status == 2)
{
if(pipe(fd) == -1)
{
printf("Failed to pipe");
exit(EXIT_FAILURE); // Failed to create pipe
}
cpid_1 = fork();
if(cpid_1 < 0)
{
printf("Failed to fork");
exit(EXIT_FAILURE); //Failed to fork
}
if(cpid_1 == 0)
{
dup2(fd[1],STDOUT_FILENO);
close(fd[0]);
close(fd[1]);
execvp(l_array[0],l_array);
}
cpid_2 = fork();
if(cpid_2 < 0)
{
printf("Failed to fork");
exit(EXIT_FAILURE); // Failed to fork
}
if(cpid_2 == 0)
{
dup2(fd[0],STDIN_FILENO);
close(fd[0]);
close(fd[1]);
execvp(r_array[0],r_array);
}
}
close(fd[0]);
close(fd[1]);
waitpid(cpid_1,NULL,0);
waitpid(cpid_2,0);
}
解决方法
在 tokenizeInput()
中,您将 *status
设置为 1
和 4
之间可能的整数值。但在 executeCommand()
中,您只处理 status
为 1
或 2
的情况。 “管道 + 重定向”的情况是 status=4
而您没有在 executeCommand()
中处理这种情况。因此,您在 waitpid()
中徘徊 - 没有分叉。