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

查看:55
本文介绍了C ++微外壳,输入命令,然后使用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);
} 

几乎所有的代码及其问题在这里显示.

Pretty much what the code shows here with its questions.

我需要创建一个接受命令("cat file.txt")的微外壳,并使用execvp()将其执行,然后将其通过管道传递给另一个进程,然后进行排序"或"grep U"或任何其他操作.

I need to create a microshell that takes in a command ("cat file.txt") and execute it with execvp() and pipe it to another process and either "sort" or "grep U" or anyother.

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

It's just that my processes won't run correctly at time or wont display anything. I have closed pipes all over the place and nothing has happen.

推荐答案

OP解决方案.

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

This is the code that works for microshell.

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

I ended up with creating two processes in the original parents process.

在while循环内移动一些变量,然后将其重置以再次工作.每次代码运行时也要创建管道并关闭管道.

Moving some variables inside the while loop and resetting them to work again. Also create the pipe everytime the code runs and close the pipes.

不仅为两个进程创建了一个waitpid().

Created a waitpid() for both processes not just one.

#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 ++微外壳,输入命令,然后使用fork(),dup(),pipe()将其通过管道传递给进程.只是我没有得到想要的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆