【问题标题】:Implementing Pipes in a C shell (Unix)在 C shell (Unix) 中实现管道
【发布时间】:2011-04-25 05:25:37
【问题描述】:

基本上我已经使用标准 POSIX 命令创建了一个 shell,我也希望能够实现管道。现在它可以正确处理命令,并且可以使用 & 进行后台处理。但我需要能够使用 | 进行管道传输和 >> 也是如此。 例如这样的: 猫文件1 文件2 >> 文件3 猫文件1 文件2 |更多的 更多文件1 | grep 的东西

这是我目前拥有的代码。我也想避免“系统”调用。我知道你需要使用 dup2,但是我编写代码的方式有点奇怪,所以我希望有人能告诉我在这段代码中实现管道是否可行?谢谢!我知道使用了 dup2,但我也知道。对如何实现 >> as WELL as |

感到困惑
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <string>
#include <iostream>
#include <stdlib.h> 
#include <stdio.h>

using namespace std;


void Execute(char* command[],bool BG)
{
//Int Status is Used Purely for the waitpid, fork() is set up like normal.
    int status;
    pid_t pid = fork();


    switch(pid)
    {
        case  0:
            execvp(command[0], command);

            if(execvp(command[0], command) == -1)
            {
                cout << "Command Not Found" << endl;
                exit(0);
            }

          default:
            if(BG == 0)
            {
                    waitpid(pid, &status, 0);
//Debug             cout << "DEBUG:Child Finished" << endl;
            }


    }

}


bool ParseArg(char* prompt, char* command[], char Readin[],bool BG)
{

    fprintf(stderr, "myshell>");
        cin.getline(Readin,50);
    prompt = strtok(Readin, " ");
    int i = 0;

    while(prompt != NULL)
    {
        command[i] = prompt;
        if(strcmp(command[i], "&") == 0){
//Debug        cout << "& found";
        command[i] = NULL;
        return true;
    }
//Debug        cout << command[i] << " ";
        i++;
        prompt = strtok(NULL, " ");

    }
    return false;
}

void Clean(char* command[])
{
//Clean Array
        for(int a=0; a < 50; a++)
        {
             command[a] = NULL;
        }
}



int main()
{
   char* prompt;
   char* command[50];
   char Readin[50]; 
   bool BG = false;



   while(command[0] != NULL)
   {

        Clean(command);
       BG = ParseArg(prompt, command, Readin, BG);
       if(strcmp(command[0], "exit") == 0 || strcmp(command[0], "quit") == 0 )
       {
             break;
       }

    else
    {
            Execute(command,BG);
    }

   }

   return 1;

}

【问题讨论】:

  • 你为什么要避免系统调用?可移植性?您可以尽可能地坚持使用 POSIX 指定的系统调用。此外,您的 shell 是 C 和 C++ 的奇怪组合。

标签: c unix shell pipe


【解决方案1】:

实际上,管道和重定向是不同的。要实现重定向(例如&gt;&gt;),您确实必须使用dup2。首先,使用适当的标志打开所需的文件(对于&gt;&gt;,它们将是O_WRONLY|O_CREAT|O_APPEND)。其次,使用dup2,使stdout(文件描述符1)成为这个新打开的fd的副本。最后关闭新打开的fd。

要创建管道,您需要一个 pipe 系统调用。阅读它的手册页,它包含示例代码。然后你还需要dup2pipe 返回的文件描述符分别作为一个进程的标准输入和另一个进程的标准输出。

【讨论】:

  • 你认为我做外壳的方式“可能”还是我应该重新设计外壳?
【解决方案2】:

你应该能够用你的 shell 实现管道和输出重定向,但是我注意到了一些事情:

  • 您用于读取输入、解析和输出的代码混合在一起,您可能希望分离此功能。
  • strtok 不能很好地用作 shell 命令的解析器。它适用于非常简单的命令,但您可能想研究创建或寻找更好的解析器。 echo "hello world" 之类的命令将与您当前的解析方法有问题。
  • 您可能想要创建一个简单的结构来保存已解析的命令。

这里有一些伪代码可以帮助您入门:

#define MAX_LINE 10000
#define MAX_COMMANDS 100
#define MAX_ARGS 100

// Struct to contain parsed input
struct command
{
    // Change these with IO redirection
    FILE *input; // Should default to STDIN
    FILE *output; // Should default to STDOUT

    int num_commands;
    int num_args[MAX_COMMANDS]; // Number of args for each command
    char* command_list[MAX_COMMANDS]; // Contains the programs to be run
    char* args_list[MAX_COMMANDS][MAX_ARGS]; // The args for each command
    boolean background_task;
    boolean append;
}

int main()
{
    char input[MAX_LINE];

    while (1)
    {
        struct command cmd;

        print_prompt();
        read_input(input);
        parse_input(input, &cmd);
        execute(&cmd);
    }
}

祝这个项目好运!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-11
    • 1970-01-01
    • 1970-01-01
    • 2013-03-21
    • 1970-01-01
    • 2012-12-06
    相关资源
    最近更新 更多