Реализация Pipes в оболочке C (Unix) - PullRequest
5 голосов
/ 14 октября 2010

По сути, я создал оболочку, используя стандартные команды POSIX, и я хочу иметь возможность реализовать конвейеризацию. Сейчас он правильно обрабатывает команды и может выполнять фоновую обработку с помощью &. Но я должен быть в состоянии использовать трубу | и >> также. Например что-то вроде этого: cat file1 file2 >> file3 кошка file1 file2 | Больше больше file1 | grep вещи

Вот код, который у меня есть в настоящее время. Я также хочу ИЗБЕЖАТЬ «СИСТЕМНЫХ» звонков. Я знаю, что вам нужно использовать dup2, но способ, которым я сделал свой код, немного странный, так что я надеюсь, что кто-то может сказать мне, возможно ли реализовать каналы в этом коде? Спасибо! Я знаю, что используется dup2, но я также и def. запутался в том, как реализовать >> как ХОРОШО, как |

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

}

Ответы [ 2 ]

5 голосов
/ 15 октября 2010

Вы должны иметь возможность реализовать каналы и перенаправление вывода с помощью вашей оболочки, но я заметил несколько вещей:

  • Ваш код для чтения ввода, анализа и вывода смешан вместе, вы можете разделить эту функцию.
  • strtok не очень хорошо работает в качестве парсера для команд оболочки. Это будет работать для очень простых команд, но вы можете захотеть посмотреть на создание или поиск лучшего парсера. Такая команда, как 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);
    }
}

Удачи в этом проекте!

5 голосов
/ 14 октября 2010

Трубы и перенаправления разные, на самом деле.Чтобы реализовать перенаправление (например, >>), вы должны использовать dup2.Сначала откройте нужный файл с соответствующими флагами (для >> они будут O_WRONLY|O_CREAT|O_APPEND).Во-вторых, используя dup2, сделайте stdout (дескриптор файла 1) копией этого недавно открытого fd.Наконец, закройте вновь открытый fd.

Чтобы создать канал, вам понадобится системный вызов pipe.Прочтите его справочную страницу, она содержит пример кода.Тогда вам также потребуется dup2, чтобы дескрипторы файлов, возвращаемые pipe, были бы stdin для одного процесса и stdout для другого соответственно.

...