C 了解系统如何调用pipe()、fork和dup

C 了解系统如何调用pipe()、fork和dup,c,shell,C,Shell,我正在用C编写一个shell来处理重定向操作符和管道。以下想法适用于处理管道吗?。因此,我以以下方式创建管道: int pipefd[2]; if (pipe(pipefd) == -1) { perror("pipe"); myshell_exit(-1); } 然后我分叉一个新进程,在新进程中,我将标准输出重定向到管道的一端,如下所示: dup2(STDOUT_FILENO,pipefd[1]); 因此,父进程现在可以从管道中读取,并将st

我正在用C编写一个shell来处理重定向操作符和管道。以下想法适用于处理管道吗?。因此,我以以下方式创建管道:

  int pipefd[2];
  if (pipe(pipefd) == -1) {
        perror("pipe");
        myshell_exit(-1);
    }
然后我分叉一个新进程,在新进程中,我将标准输出重定向到管道的一端,如下所示:

dup2(STDOUT_FILENO,pipefd[1]);
因此,父进程现在可以从管道中读取,并将stdin重定向到要读取的管道末端。像这样

dup2(STDIN_FILENO,pipefd[0]);
然后我派生一个新的进程,因此执行下一个命令或程序时,输入
pipefd[0]

示例:cat file.txt | grep字符串

总之,我在父进程中分叉了两个进程。一个用于执行当前程序,另一个用于执行下一个程序。这项任务是归纳性的

这个想法对吗

这是主函数的代码。假设所有奇怪的函数都能工作

int myshell_execute(struct processNode* list)
{
  int i;
  char* program = list->program;  // Get the program to be executed
  char ** program_args = list->program_arguments; // get the programs and arguments to be executed
  char ** redirection_string = list->redirection; //get the part of the command that contains redirection
  int *status;
  int* stdout;
  int stdout_num = 1;
  stdout = &stdout_num;
  int fileDescriptor;
  pid_t pid;
  struct processNode* next_node  = (*list).next; // next node to be handled



    if(strcmp(program,"cd") == 0)
    {
      return myshell_cd(program_args);
    }
    else if (strcmp(program,"exit") == 0)
    {
      return myshell_exit(0);
    }


  int pipefd[2];
  if (pipe(pipefd) == -1) {
        perror("pipe");
        myshell_exit(-1);
    }


// Execute the current program
  pid = fork();
  if(pid == 0)
  {  
    if(sizeOfLine(redirection_string) != 0)
    {
    redirectionHandler(redirection_string,stdout); // This works. This just handles redirection properly
    }

    if(*stdout == 1 && list->next !=NULL)
    {
       dup2(STDOUT_FILENO,pipefd[1]); // with this line of code, I intend to redirect the stdout to the file descriptor pipefd[1], so the next command can use it if there are pipes. The reason why I put it in an if is because 1) stdout may be handled by the function redirectionHandler, so we don't touch it or we are in the last node
    }
    if(execvp(program,program_args) !=-1)
    {
      perror("myshell:");
    }
     myshell_exit(-1);
  }
  else if (pid <0)
    {
      perror("myshell: ");
      myshell_exit(-1);
   }
  else
   {
     wait(status);
   }

  // Go to the next command to be executed
   if(list->next != NULL) // I parse the command line in a convenient mannner. Thar works too
   {
     dup2(STDIN_FILENO,pipefd[0]);

      pid = fork();
      if(pid == 0)
       {  
         return myshell_execute(next_node);
       }
      else if (pid <0)
      {
          perror("myshell: ");
          myshell_exit(-1);
      }
      else
      {
      wait(status);
      }

    }
   else
   {
     myshell_exit(0);
   }



} 
int myshell\u执行(结构进程节点*列表)
{
int i;
char*program=list->program;//获取要执行的程序
char**program\u args=list->program\u arguments;//获取要执行的程序和参数
char**redirection\u string=list->redirection;//获取命令中包含重定向的部分
国际*地位;
int*stdout;
int stdout_num=1;
标准输出=&stdout_num;
int文件描述符;
pid_t pid;
struct processNode*next_node=(*list).next;//要处理的下一个节点
如果(strcmp(程序,“cd”)==0)
{
返回myshell\u cd(程序参数);
}
否则如果(strcmp(程序,“退出”)==0)
{
返回myshell_出口(0);
}
int-pipefd[2];
如果(管道(管道FD)=-1){
佩罗(“管道”);
myshell_出口(-1);
}
//执行当前程序
pid=fork();
如果(pid==0)
{  
如果(sizeOfLine(重定向字符串)!=0)
{
redirectionHandler(redirection_string,stdout);//这可以正常工作。这只是正确地处理重定向
}
如果(*stdout==1&&list->next!=NULL)
{
dup2(STDOUT_FILENO,pipefd[1]);//通过这行代码,我打算将STDOUT重定向到文件描述符pipefd[1],以便下一个命令可以在有管道的情况下使用它。我将其放入if的原因是1)STDOUT可能由函数redirectionHandler处理,因此我们不接触它,或者我们处于最后一个节点
}
if(execvp(程序,程序参数)!=-1)
{
佩罗尔(“我的地狱”);
}
myshell_出口(-1);
}
else if(pid next!=NULL)//我用一种方便的方式解析命令行。塔尔也可以工作
{
dup2(标准文件号,pipefd[0]);
pid=fork();
如果(pid==0)
{  
返回myshell\u execute(下一个\u节点);
}

否则如果(pid总体思路是正确的。父进程和子进程具有相同的
stdout
stdin
。您将子进程的stdout重定向到管道的一端,并将父进程的
stdin
重定向到管道的另一端。因此,发送到子进程的
stdout
的内容现在将在管道中,直到父进程为止进程读取。然后,在您分叉另一个子进程后,它可以从管道接收其输入。一般的想法是正确的。父进程和子进程具有相同的
stdout
stdin
。您将子进程的stdout重定向到管道的一端,将父进程的
stdin
重定向到管道的另一端。那么,发生了什么r被发送到子进程的
stdout
现在将在管道中,直到父进程读取为止。然后在您派生另一个子进程后,它可以从管道接收其输入。