C ++ процессы и каналы - PullRequest
       19

C ++ процессы и каналы

1 голос
/ 15 февраля 2012

Я пробираюсь через книгу по C ++ и операционным системам, и я наткнулся на задание, которое требует создания, записи и чтения из каналов. Однако моя программа зависает при чтении из второго канала. Моя программа заключается в приеме ввода и разборе строки с пробелом в токены и соответствующей классификации этих токенов. Мой код ниже с моей проблемной зоной. Любая помощь, как всегда, очень ценится.

edit: Предполагается, что у него двое детей. Один для обработки маркеров с разделителями, а другой для определения типа маркеров с разделителями. Что касается отладки, у меня есть доступ только к cout как к отладчику. Поэтому я вставил cout перед чтением и после того, как появилось чтение, но после не сделал.

#include <iostream>
#include <fstream>
#include <string>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

using namespace std;

//declaring the pipes
int pipeOne[2];
int pipeTwo[2];

struct inputStruct {
char str[256]; /* one extra spot for \n */
int  len;      /* length of str         */
int  flag;     /*  0 for normal input, 1 to indicate “done” */
};

struct tokenStruct {
char token[256]; /* tokens can be 255 max */
int  flag;       /* same as inputStruct   */
int  tokenType;  /* a code value          */
};

void dataProcess(){

//new input struct to contain the the input from the parent
inputStruct input;

//the intial read from the pipe to populate the input stuct
read( pipeOne[0], (char*)&input, sizeof(inputStruct));

//set the flag
int flag = input.flag;

while (flag != 1){

    int size = 0;

    //get the size of the array up until the null character
    while (input.str[size] != '\0'){
        size++;
    }

    //Here's the parsing of each token
    for (int i=0; i<size; i++) {

        int tokenLength;

        tokenStruct token;

        //while the char isn't white space or null increment through it
        while (input.str[i] != ' ' && input.str[i] != '\0') {

            //a is the index of the string token 
            int a = 0;

            //write the parsed string
            token.token[a] = input.str[i];

            a++;
            i++;

        }

        //write to process 2
        write(pipeTwo[1], (char*)&token, sizeof(tokenStruct));

    }

    //read again and store the results
    read(pipeOne[0], (char*)&input, sizeof(inputStruct));
    flag = input.flag;

}

tokenStruct token;

token.flag = flag;

//final write to the second child to tell it to commit suicide
write(pipeTwo[1], (char*)&token, sizeof(tokenStruct));

exit(0);
}

void tokenClassifer(){

tokenStruct token;

//Problem area is here on ****************************************************

//the initial read
read(pipeTwo[0], (char*)&token, sizeof(tokenStruct));

while (token.flag != 1){

    int size = 0;

    //get the size of the array up until the null character
    while (token.token[size] != '\0'){
        size++;
    }

    if (size == 1) {
        //check for the one char things first
        switch (token.token[0])
        {
            case '(':
                token.tokenType = 0;
                break;
            case ')':
                token.tokenType = 0;
                break;
            case ';':
                token.tokenType = 0;
                break;
            case '+':
                token.tokenType = 1;
                break;
            case '-':
                token.tokenType = 1;
                break;
            case '/':
                token.tokenType = 1;
                break;
            case '*':
                token.tokenType = 1;
                break;
            default:
                if (isdigit(token.token[0])) {
                    token.tokenType = 2;
                } else {
                    token.tokenType = 3;
                }
                break;
        }

    } else {

        bool isStr;

        int i = 0;
        //check for the more than one character
        while (token.token[i] != '\0'){

            //check if it's a string or digits
            if (isdigit(token.token[0])) {
                isStr=false;
            } else{
                //set up the bools to show it is a string
                isStr=true;
                break;
            }
        }

        //if it is a string token type 3
        if (isStr) {
            token.tokenType = 3;
        } else {
            //if not then it's digits and token type 2
            token.tokenType = 2;
        }

    }

    //print out the token and token type
    cout << "Token type is: " << token.tokenType << "Token value is: " << token.token << "\n";

    //read the pipe again and start the process all over
    read(pipeTwo[0], (char*)&token, sizeof(tokenStruct));
}

exit(0);
}

int main()
{

//create the pipes for reading and writing between processes
pipe(pipeOne);
pipe(pipeTwo);

//fork off both processes
int value = fork();
int value2 = fork();

//do the process for the first fork
if(value == 0){

    //fork one
    dataProcess();

} else {

    wait(0);

}

//do the process for the second fork
if (value2 == 0) {
    //fork two

    //the token classifer function for the second fork
    tokenClassifer();

} else {
    cout << "Type some tokens (or just press enter to quit) \n";
    //this is all of the parent functions        
    for (string line; getline(cin, line); )
    {

        inputStruct input;
        if (line.empty())
        {
            // if the line is empty, that means the user didn't
            // press anything before hitting the enter key
            input.flag = 1;
            write( pipeOne[1], (char*)&input, sizeof(inputStruct));
            break;
        } else {

            //else copy the string into an array
            strcpy(input.str, line.c_str());

            //set the flag to zero to show everthing is ok
            input.flag = 0;
        }

        //write the stuct to the pipe
        write( pipeOne[1], (char*)&input, sizeof(inputStruct));

        cout << "Type some tokens (or just press enter to quit) \n";
    }

    wait(0);
}
}

1 Ответ

4 голосов
/ 15 февраля 2012

Одна очевидная проблема:

//fork off both processes
int value = fork();
int value2 = fork();

Это будет форком 3 новых процесса. Первоначальный разветвитель оставит вам два процесса, каждый из которых будет разветвлять новый процесс.

EDIT:

Правильное разветвление:

int value = fork();
if (value == 0) {
    // do child stuff
    exit(0);
} else if (value == -1) {
    //fork failed
}

int value2 = fork();
if (value2 == 0) {
    //do child stuff
    exit(0);
} else if (value2 == -1) {
    //fork failed
}

На самом деле я не совсем понимаю, как данные проходят через вашу программу, поэтому я оставлю это вам, чтобы добавить ожидания. Я бы на самом деле изменил имена значений и значений2, но это только я. Кроме того, я рассматриваю здесь только проблему разветвления, поэтому могут возникнуть другие проблемы с вашим кодом (что я подозреваю, поскольку у вас два канала).

РЕДАКТИРОВАТЬ 2:

Другая проблема, которую я вижу, заключается в том, что вы не закрываете концы труб, которые вы не используете. Если вы никогда не закроете конец записи канала, ваши чтения будут блокироваться до тех пор, пока в канале не появятся данные (или больше не будет записывающих в канал, то есть конец записи не будет открыт). Это означает, что конец записи канала должен быть закрыт во всех процессах, когда вы его не используете или закончили с ним.

...