C ++进程和管道

时间:2012-02-15 04:39:49

标签: c++ operating-system fork pipe

我通过C ++和操作系统书籍,我开始了一项需要创建,编写和读取管道的任务。但是我的程序在从第二个管道读取时停止。我的程序是接受输入并将空格分隔的字符串解析为标记并相应地对这些标记进行分类。我的代码与我标记的问题区域相似。任何帮助都是非常感激的。

编辑:这应该有两个孩子。一个用于处理空格分隔的标记,另一个用于确定分隔标记的类型。就调试而言,我只能访问cout作为调试器。所以我在读取之前插入了一个cout,在读取之前插入了一个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 个答案:

答案 0 :(得分:4)

一个明显的问题是:

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

这将分叉3个新进程。初始fork将为您提供两个进程,每个进程继续分叉一个新进程。

编辑:

正确分叉:

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
}

我实际上并不十分清楚数据如何通过您的程序,因此我将留给您添加等待。我实际上更改了value和value2的名称,但那只是我。另外,我只是解决了这里的分叉问题,所以你的代码可能还有其他问题(因为你有两个管道,我有点怀疑)。

编辑2:

我看到的另一个问题是你没有关闭你不使用的管道的末端。如果您从未关闭管道的写入端,则读取将阻塞,直到管道有数据(或者管道没有更多的写入器,即写入端未打开)。这意味着当您不使用或完成管道时,应在所有进程中关闭管道的写入端。