繁体   English   中英

C ++微外壳,输入命令,然后使用fork(),dup(),pipe()将其通过管道传递给进程。 只是我没有得到想要的结果

[英]C++ microshell, input a command and pipe it to a process using fork(), dup(), pipe(). Is just I don't get the results I want

#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()执行该微外壳,并将其通过管道传递到另一个进程,然后“排序”或“ grep U”或任何其他进程。

只是我的进程不能正确运行或什么都不显示。 我到处都已关闭管道,什么也没发生。

由OP解决。

这是适用于微外壳的代码。

最后,我在原始的父流程中创建了两个流程。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM