C++ 在c+中实现pipe命令+;
我正在尝试制作一个本机支持管道命令的终端。C++ 在c+中实现pipe命令+;,c++,terminal,pipe,C++,Terminal,Pipe,我正在尝试制作一个本机支持管道命令的终端。 我曾经尝试过实现这一点,但每当我尝试执行管道命令时,它就会一次又一次地执行,直到我的电脑崩溃——可能是一些内存,但我无法回溯到底是什么导致了它 这个问题是学术作业的一部分 在展示此命令的实现之前,我将解释在管道实现中使用的函数: \u parseCommandLine-接收一个命令char*和一些空数组args-对于每个参数,它在args数组中动态地为其分配空间,最后函数返回参数的数量 \u isBackgroundComamnd和\u removeB
我曾经尝试过实现这一点,但每当我尝试执行管道命令时,它就会一次又一次地执行,直到我的电脑崩溃——可能是一些内存,但我无法回溯到底是什么导致了它 这个问题是学术作业的一部分 在展示此命令的实现之前,我将解释在管道实现中使用的函数:
\u parseCommandLine
-接收一个命令char*和一些空数组args-对于每个参数,它在args数组中动态地为其分配空间,最后函数返回参数的数量
\u isBackgroundComamnd
和\u removeBackgroundSign
似乎是不言自明的
\u clear\u命令
仅释放参数数组和命令本身
如果你需要澄清更多的功能,让我知道
这是我的实现
void PipeCommand::execute(){
char* args1[COMMAND_ARGS_MAX_LENGTH];
char* args2[COMMAND_ARGS_MAX_LENGTH];
char* command1 = (char*)malloc(COMMAND_ARGS_MAX_LENGTH);
char* command2 = (char*)malloc(COMMAND_ARGS_MAX_LENGTH);
char* command1_print = (char*)malloc(COMMAND_ARGS_MAX_LENGTH);
char* command2_print = (char*)malloc(COMMAND_ARGS_MAX_LENGTH);
unsigned int cmd_sep_out = string(this->command).find("|");
unsigned int cmd_sep_err = string(this->command).find("|&");
strcpy(command1, string(this->command).substr(0, cmd_sep_out).c_str());
if(cmd_sep_err != string::npos){
strcpy(command2, string(this->command).substr(cmd_sep_err + 1).c_str());
} else{
strcpy(command2, string(this->command).substr(cmd_sep_out + 1).c_str());
}
strcpy(command1_print, string(this->command).substr(0, cmd_sep_out).c_str());
if(cmd_sep_err != string::npos){
strcpy(command2_print, string(this->command).substr(cmd_sep_err + 1).c_str());
} else{
strcpy(command2_print, string(this->command).substr(cmd_sep_out + 1).c_str());
}
int args_count1 = _parseCommandLine(command1, args1);
int args_count2 = _parseCommandLine(command2, args2);
if (_isBackgroundComamnd(command1)){
_removeBackgroundSign(command1);
}
bool is_bg = false;
if (_isBackgroundComamnd(command2)){
_removeBackgroundSign(command2);
is_bg = true;
}
SmallShell& smash = SmallShell::getInstance();
int smash_pid = getpid();
int first_fork = fork();
if(first_fork == -1){
perror("smash error: fork failed");
_clear_command(command1, args1, args_count1);
_clear_command(command2, args2, args_count2);
free(command1_print);
free(command2_print);
}
if(first_fork == 0){
if(this->getIsPipe()){
setpgrp();
}
int fd[2];
if(pipe(fd) == -1){
perror("smash error: pipe failed");
_clear_command(command1, args1, args_count1);
_clear_command(command2, args2, args_count2);
free(command1_print);
free(command2_print);
}
int second_fork = fork();
if(second_fork == -1){
perror("smash error: fork failed");
_clear_command(command1, args1, args_count1);
_clear_command(command2, args2, args_count2);
free(command1_print);
free(command2_print);
}
else if(second_fork == 0){
setpgrp();
if(cmd_sep_err != string::npos){
dup2(fd[1], STDERR_FILENO);
} else{
dup2(fd[1], STDOUT_FILENO);
}
close(fd[1]);
close(fd[0]);
Command* command_obj1 = smash.CreateCommand(command1);
if(strcmp(args1[0], "showpid") == 0){
std::cout << "smash pid is " << smash_pid << std::endl;
} else{
command_obj1->execute();
}
_clear_command(command1, args1, args_count1);
_clear_command(command2, args2, args_count2);
free(command1_print);
free(command2_print);
delete command_obj1;
smash.setQuitShell(true);
return;
}
int third_fork = fork();
if(third_fork == -1){
perror("smash error: fork failed");
_clear_command(command1, args1, args_count1);
_clear_command(command2, args2, args_count2);
free(command1_print);
free(command2_print);
} else if(third_fork == 0){
setpgrp();
dup2(fd[0], STDIN_FILENO);
close(fd[1]);
close(fd[0]);
Command* command_obj2 = smash.CreateCommand(command2);
if(strcmp(args2[0], "showpid") == 0){
std::cout << "smash pid is " << smash_pid << std::endl;
} else{
command_obj2->execute();
}
_clear_command(command1, args1, args_count1);
_clear_command(command2, args2, args_count2);
free(command1_print);
free(command2_print);
delete command_obj2;
smash.setQuitShell(true);
return;
}
close(fd[1]);
close(fd[0]);
waitpid(first_fork, NULL, 0);
waitpid(second_fork, NULL, 0);
_clear_command(command1, args1, args_count1);
_clear_command(command2, args2, args_count2);
smash.setQuitShell(true);
return;
} else{
this->pid = first_fork;
if(is_bg){
smash.getJobs()->addJob(this->command, this->pid, command2_print, false, -1, is_bg);
} else{
smash.setForeGroundPID(this->pid);
smash.setForegroundJID(-1);
smash.setForegroundCommand(this->command);
waitpid(this->pid, NULL, WUNTRACED);
smash.setForeGroundPID(-1);
}
}
_clear_command(command1, args1, args_count1);
_clear_command(command2, args2, args_count2);
free(command1_print);
free(command2_print);
}
执行我的终端并键入cat file | less
我预计产出:
a
b
c
但不是只得到一次输出,而是
a
b
c
一次又一次直到我的机器崩溃@YSC可能正确的术语应该只是一个管道,但我的意思是像这样的命令
cat file | less
可能是管道的创建。这可能不太实际,但这是一个学术作业的一部分。编辑我的问题以提及这一切:)@YSC可能正确的术语只是一个管道,但我的意思是像这样的命令cat file | less
可能创建管道。这可能不太实际,但这是一项学术作业的一部分。编辑我的问题以提及所有内容:)
a
b
c