gpt4 book ai didi

C++ microshell,输入命令并使用 fork()、dup()、pipe() 将其通过管道传输到进程。只是我没有得到我想要的结果

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:19:00 31 4
gpt4 key购买 nike

#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <sys/utsname.h>
#include <unistd.h>


using namespace std;

//first comannd to execute
void first(int pipeA[], char * command[]){

//redirect STDOUT to pipe[1] and close the pipe[0] we are not using
dup2(pipeA[1], 1);
close(pipeA[0]);

execvp(command[0], command);
printf(" first error ");
exit(127);
}

void second(int pipeA[], char * command2[]){

//redirect STDIN to pipe[0] and close the pipe[1] that we are not using
dup2(pipeA[0], 0);
close(pipeA[1]);

//This doesnt seem to be doing anything at times
execvp(command2[0], command2);
perror(" second error ");
exit(127);

}


int main(void)
{
char buf[1024];
char * command[1024];// this one is the first input usually 'cat file.txt'

//Use only one or the other, sort never works and 'grep U' works sometimes
char * command2[] = {(char *)"sort", (char *) NULL};// this is wants to sort the above 'command[1024]' and its use in the second function
//char * command2[] = {(char *)"grep",(char *)"U",(char *) NULL};// this is wants to grep the above 'command[1024]' and its use in the second function

//variables for forks and waits
pid_t pid;
pid_t pid2;
int status;
int status2;

//see if || exists not in use currently
bool pipeExists = false;

//create pipe
int pipeA[2];
pipe(pipeA);

//first line and ask for input,
cout<< "command: ";

while (fgets(buf,1024,stdin) != NULL)
{
buf[strlen(buf) -1] = 0;

//Save input into buf and tokenized? it
//NOT YET CATCHING ||, im only debugging and usually use use 'cat file.txt'
int number =0;
char * ptr;
ptr = strtok(buf, " ");
while(ptr != NULL){
command[number] = ptr;
ptr = strtok(NULL, " ");
number++;
}

//***************************************************************
//1. do the pipes go here or after the children?
//They seem to be working here but im not really sure where they should be
close(pipeA[0]);
close(pipeA[1]);

//create first child
if ((pid = fork()) <0)
printf("fork error");
else if (pid == 0)
{ /* child */

//create second child INSIDE ORIGINAL CHILD
//2. Is this correct? or is there not supposed to be grandchildren?
if ((pid2 = fork()) <0)
printf("fork 2 error");
else if (pid == 0)
{ /* child */
second(pipeA, command2);
printf("couldn't execute: %s");
exit(127);
}


//first command from buf
first(pipeA, command);
printf("couldn't execute: %s");
exit(127);


//3. Do I wait for this child aswell?
if ( (pid2 = waitpid(pid2, &status2, 0)) < 0)
printf("waitpid error");
}


/* parent */
if ( (pid = waitpid(pid, &status, 0)) < 0)
printf("waitpid error");
printf("Command :");
//***************************************************************

//***************************************************************
//SECOND WAY OF DOING IT
// THIS WAY IT TRIGGERS WAITPID ERRORS.
/*
close(pipeA[0]);
close(pipeA[1]);

//create first child
if ((pid = fork()) <0)
printf("fork error");
else if (pid == 0)
{
first(pipeA, command);
printf("couldn't execute: %s");
exit(127);
}
//create second child INSIDE ORIGINAL CHILD
if ((pid2 = fork()) <0)
printf("fork 2 error");
else if (pid == 0)
{
second(pipeA, command2);
printf("couldn't execute: %s");
exit(127);
}

//3. Do I wait for this child aswell?
if ( (pid2 = waitpid(pid2, &status2, 0)) < 0)
printf("waitpid error");


if ( (pid = waitpid(pid, &status, 0)) < 0)
printf("waitpid error");
printf("Command :");
*/
//***************************************************************
}

exit(0);
}

这里的代码几乎就是其中的问题。

我需要创建一个 microshell,它接受一个命令(“cat file.txt”)并使用 execvp() 执行它,并将其通过管道传递给另一个进程,“sort”或“grep U”或任何其他进程。

只是我的进程无法正常运行或无法显示任何内容。我关闭了所有地方的管道,但没有任何反应。

最佳答案

OP 的解决方案。

这是适用于 microshell 的代码。

我最终在原始父进程中创建了两个进程。

在 while 循环中移动一些变量并重置它们以再次工作。每次代码运行时也创建管道并关闭管道。

为两个进程创建了一个 waitpid(),而不仅仅是一个。

#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <sys/utsname.h>
#include <unistd.h>
using namespace std;


//This function will execute the users first command.
//It takes in a pipe the command array and a boolean to check for piping
//If a pipe exists then the boolean is true and will dup() the STDOUT into the write part of the pipe
//We close unecessary parts of the pipe and execvp() the command in the command array
//there it some error checkink in case the command doesn't execute
void first_command(int pipeA[], char * command[], bool pipeExists){

if(pipeExists){
dup2(pipeA[1], 1);
close(pipeA[0]);
}

execvp(command[0], command);
printf("can not execute first command. \n");
exit(127);
}

//This function is only called in the main is a piping exists
//It takes in a pipe and a command array
//It dup() the STDIN from the read end of the pipe and closes the unsued end
//It will execute the command accorind to what was provided in the the pipe
void second_command(int pipeA[], char * command2[]){

dup2(pipeA[0], 0);
close(pipeA[1]);

execvp(command2[0], command2);
printf("can not execute second command. \n");
exit(127);

}


int main(void)
{
//this variable will take in the line of input submitted by the user
char buf[1024];

//PIDs for the two child processes
pid_t pid;
pid_t pid2;

//these will be use to check the status of each child in the parent process
int status;
int status2;

//initializes the pipe
int pipeA[2];

//out put the first line to ask user for input
cout<< "480shel> ";

//stay inside the loop and keep asking the user for input until the user quits the program
while (fgets(buf,1024,stdin) != NULL){

//initialize a boolean to check if user wants to pipe something, set to false by default until we check with user
bool pipeExists = false;

//initialize this arrays to NULL so anything that store in them gets cleared out.
//these arrays will hold the commands that the user wants to carry out.

char * command[1024] = {NULL, NULL, NULL};
char * command2[1024] = {NULL, NULL, NULL};

//Important to delete mark the last byte as 0 in our input
buf[strlen(buf) -1] = 0;

//initialize this number to zero to start save the tokens at this index
int index = 0;

//a char * to hold the token saved by strtok
char * ptr;
ptr = strtok(buf, " ");

//Loop through 'buf' and save tokens accordingly
while(ptr != NULL){

//If ptr is equal to q or quit then user want to exit program
if(strcmp( ptr, "q" ) == 0){
exit(0);
}
if(strcmp( ptr, "quit" ) == 0){
exit(0);
}

//if ptr is equal to || user wants to pipe something and we change pipeExists to true
if(strcmp( ptr, "||" ) == 0){
pipeExists = true;
index= 0;
ptr = strtok(NULL, " ");
}

//enter here while user doesnt want to user pipes
if(!pipeExists){
command[index] = ptr;
ptr = strtok(NULL, " ");
index++;
}

//enter here if user want to use pipes
if(pipeExists){
command2[index] = ptr;
ptr = strtok(NULL, " ");
index++;
}
}

//if pipes exists then initialize it
if(pipeExists){
pipe(pipeA);
}

//create first child
if ((pid = fork()) == 0) {
//pass in the pipe, commands and pipe to function to execute
first_command(pipeA, command, pipeExists);
}
else if(pid < 0){
//error with child
cerr<<"error forking first child"<<endl;
}

// if pipe exists create a second process to execute the second part of the command
if(pipeExists){

//create second child
if ((pid2 = fork()) == 0) {
second_command(pipeA, command2);
}
else if(pid2 < 0){
//error with second child
cerr<<"error forking second child"<<endl;
}
}

//if the pipe was created then we close its ends
if(pipeExists){
close(pipeA[0]);
close(pipeA[1]);
}

//wait for the first child that ALWAYS executes
if ( (pid = waitpid(pid, &status, 0)) < 0)
cerr<<"error waiting for first child"<<endl;

//wait for the second child bu only if user wanted to created to use piping
if(pipeExists){
if ( (pid2 = waitpid(pid2, &status2, 0)) < 0)
cerr<<"error waiting for second child"<<endl;
}


cerr<<"480shell> ";

}//endwhile
exit(0);
}

关于C++ microshell,输入命令并使用 fork()、dup()、pipe() 将其通过管道传输到进程。只是我没有得到我想要的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46515080/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com