linux — C ++ microshell, введите команду и передайте ее процессу, используя fork (), dup (), pipe (). Просто я не получаю желаемых результатов

#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);
}

Почти то, что код показывает здесь со своими вопросами.

Мне нужно создать микрооболочку, которая принимает команду («cat file.txt») и выполняет ее с помощью execvp () и передает ее другому процессу и либо «sort», либо «grep U», либо anyother.

Просто мои процессы не будут работать правильно во время или не будут отображать что-либо. Я закрыл трубы повсюду, и ничего не произошло.

1

Решение

Решение по ОП.

Это код, который работает для 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);
}
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]