简体   繁体   English

无法从匿名管道读取

[英]Cannot read from anonymous pipe

I began to study the anonymous pipe in windows and ran into a problem. 我开始研究Windows中的匿名管道,并遇到了问题。

The program should create a child process that will handle the commands given ones to enter. 该程序应创建一个子进程,该子进程将处理给定输入的命令。 But I can not read from the pipe until the child process works. 但是,直到子进程正常工作,我才能从管道中读取内容。

Here is the programm 这是程序

#define _CRT_SECURE_NO_DEPRECATE
#include "windows.h"
#include "cstdio"
#include "tchar.h"
#include "io.h"
#include "conio.h" 
#include "cstring"

static const int bufSize = 20;

int main() {
    STARTUPINFO si;
    PROCESS_INFORMATION  pi;
    LPTSTR szCmdline = _tcsdup(TEXT("Project2\\Release\\command_handler.exe"));
    HANDLE writePipe, readPipe, writePipeInput, readPipeInput;
    SECURITY_ATTRIBUTES sa;
    ZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;
    if(!CreatePipe(&readPipe, &writePipe, &sa, 0) || !CreatePipe(&readPipeInput, &writePipeInput, &sa, 0))
    {
        printf("ERROR: cannot create pipe\n");
        system("pause");
        exit(1);
    }
    si.dwFlags = STARTF_USESTDHANDLES;
    si.hStdOutput = writePipe;
    si.hStdInput = readPipeInput;
    DWORD dwByteRead, dwByteWrite;
    if(!CreateProcess(0, szCmdline, 0, 0, TRUE, CREATE_NO_WINDOW, 0, 0, &si, &pi)) {
        printf("ERROR: cannot create process\n");
        system("pause");
        exit(2);
    }
    CloseHandle(writePipe);
    CloseHandle(readPipeInput);
    printf("Procces ready!\n");

    TQueue <int> q;
    TQueue <int> tmp;
    char c;
    char s[bufSize];
    int value;
    for ( ; ; ) {
        int i;
        for(i = 0;i < bufSize && (s[i] = getchar()) != '\n';++i);
        WriteFile(writePipeInput,s,i + 1,&dwByteWrite,NULL);

        ReadFile(readPipe, &c, (int)1, &dwByteRead, NULL);
        printf("Get : '%c'\n",c);
        switch (c) {
            case '+':
                ReadFile(readPipe, &value, sizeof(int), &dwByteRead, NULL);
                printf("%d\n",value);
                q.push(value);
                printf("OK\n");
                break;
            case '-':
                if (!q.empty()) {
                    q.pop();
                }
                printf("OK\n");
                break;
            case 'f':
                if (!q.empty()) {
                    printf("%d\nOK\n",q.firstEl());
                } else {
                    printf("Queue is empty\nOK\n");
                }
                break;
            case 'p':
                if (q.empty()) {
                    printf("empty");
                }
                while (!q.empty()) {
                    tmp.push(q.firstEl());
                    printf("%d ",q.firstEl());
                    q.pop();
                }
                printf("\nOK\n");
                while (!tmp.empty()) {
                    q.push(tmp.firstEl());
                    tmp.pop();
                }
                break;
            case 'e':
                printf("%s\nOK\n",q.empty()?"yes!":"no");
                break;
            case 'q':
                break;
            case '?':
                printf("ERROR: undefined command\n");
                break;
            default:
                printf("Fatal error: wrong symbol from hadeler '%c'\n",c);
                //system("pause");
                //exit(3);
        }
        if (c == 'q') break;
    }
    CloseHandle(readPipe);
    CloseHandle(writePipeInput);
    printf("Exited normaly\n");
    system("pause");
}

And this is handler 这是处理程序

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <string.h>

static const int sz = 10;

char read_cmd(char *s) {
    char c = getchar();
    int i;
    for (i = 0;(i < sz) && (c != ' ') && (c != '\n');i++) {
        s[i] = c;
        c = getchar();
//      printf("%c",s[i]);
    }
    s[i] = '\0';
    return c;
}

char correct(char res) {
    if (res != '\n') {
        while (getchar() != '\n');
        return 0;
    }
    return 1;
}

int main() {
    char s[sz + 1];
    char c, res;
    int val = 0;
    for ( ; ; ) {
        res = read_cmd(s);
        if (strcmp(s,"add") == 0) {
            val = 0;
            while ((c = getchar()) >= '0' && c <= '9') {
                val = val * 10 + c - '0';
            }
            res = c;
            c = '+';
        }else if (strcmp(s,"pop") == 0) {
            c = '-';
        }else if (strcmp(s,"first") == 0) {
            c = 'f';
        }else if (strcmp(s,"print") == 0) {
            c = 'p';
        }else if (strcmp(s,"empty") == 0) {
            c = 'e';
        }else if (strcmp(s,"help") == 0) {
            c = 'h';
        }else if (strcmp(s,"quit") == 0) {
            c = 'q';
        }else {
            c = '?';
        }
        if (!correct(res)) c = '?';
        printf("%c",c);
        if (c == 'q') break;
        if (c == '+') printf("%d",val);
    }
    return 0;
}

So if I run it and immediately type "quit" it works, otherwise it stop when trying get result from output pipe. 因此,如果我运行它并立即键入“ quit”,它将起作用,否则,当尝试从输出管道获取结果时它将停止。

Why is this happening? 为什么会这样呢?

Thanks in advance for your reply. 预先感谢您的答复。

I rewrote the program again and it worked. 我再次重写了程序,它成功了。 Honestly, I do not know that there was not correct. 老实说,我不知道那里是不正确的。 Here is a working version: 这是一个工作版本:

#define _CRT_SECURE_NO_DEPRECATE

#include <windows.h> 
#include <stdio.h> 

#define BUFSIZE 256

template <class T> class TQueue {
private:
    class TQueEl {
    public:
        T value;
        TQueEl *next, *prev;
    };
    TQueEl *first, *last;
    int size;
public:
    int& operator = (TQueue <T>& b){
        while (!empty ()) {
            pop ();
        }
        while (!b.empty ()) {
            push(b.firstEl ());
            b.pop ();
        }
    }
    TQueue () {
        size = 0;
        first = last = nullptr;
    }
    void push (T val) {
        if (size == 0) {
            first = last = new TQueEl;
            first -> next = first -> prev = nullptr;
            first -> value = val;
        } else {
            last -> next = new TQueEl;
            last -> next -> prev = last;
            last = last -> next;
            last -> next = nullptr;
            last -> value = val;
        }
        size++;
    }
    T firstEl () {
        return first -> value;
    }
    void pop () {
        TQueEl *tmp=first;
        if (size == 1) {
            first = last = nullptr;
        } 
        else if ( empty() ) {
            // error("pop of empty queue");
        }
        else {
            first = first -> next;
            first -> prev = nullptr;
        }
        size--;
        delete tmp;
    }
    bool empty () {
        return !size;
    }
    ~TQueue () {
        TQueEl *tmp;
        while (first != nullptr) {
            tmp = first;
            first = first -> next;
            delete tmp;
        }
    }
};

DWORD WINAPI rerout(LPVOID params) {
    DWORD dwByteWrite, dwByteRead;
    char buffer[BUFSIZE];
    HANDLE hParentStdIn = GetStdHandle(STD_INPUT_HANDLE);
    HANDLE childInput = (HANDLE) params;
    for ( ; ; ) {
        ReadFile(hParentStdIn, buffer, BUFSIZE, &dwByteRead, NULL);
        WriteFile(childInput, buffer, dwByteRead, &dwByteWrite, NULL);
    }
    return 0;
}

int main() { 
    HANDLE childInputRd = NULL;
    HANDLE childInputWr = NULL;
    HANDLE childOutputRd = NULL;
    HANDLE childOutputWr = NULL;
    SECURITY_ATTRIBUTES sa; 

    sa.nLength = sizeof(SECURITY_ATTRIBUTES); 
    sa.bInheritHandle = TRUE; 
    sa.lpSecurityDescriptor = NULL; 

    if ( ! CreatePipe(&childOutputRd, &childOutputWr, &sa, 0) ) {
        printf("Fatal error: cannot create child output pipe\n");
        system("pause");
        exit(1);
    }
    if (! CreatePipe(&childInputRd, &childInputWr, &sa, 0)) {
        printf("Fatal error: cannot create child input pipe\n");
        system("pause");
        exit(2);
    }
    TCHAR szCmdline[]=TEXT("Project2\\Release\\command_handler.exe");
    PROCESS_INFORMATION pi; 
    STARTUPINFO si;

    ZeroMemory( &pi, sizeof(PROCESS_INFORMATION) );

    ZeroMemory( &si, sizeof(STARTUPINFO) );
    si.cb = sizeof(STARTUPINFO); 
    si.hStdError = childOutputWr;
    si.hStdOutput = childOutputWr;
    si.hStdInput = childInputRd;
    si.dwFlags = STARTF_USESTDHANDLES;

    if ( !CreateProcess(NULL, szCmdline, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi) ) {
        printf("Fatal error: cannot create child process\n");
        system("pause");
        exit(3);
    }
    else {
        CloseHandle(childInputRd);
        CloseHandle(childOutputWr);
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    }

    DWORD reroutThreadID;
    HANDLE inputRerouting = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)rerout,(LPVOID) childInputWr,0 , &reroutThreadID);
    if (inputRerouting == NULL) {
        printf("Fatal error: cannot create thread\n");
        system("pause");
        exit (4);
    }

    TQueue <int> q;
    TQueue <int> tmp; 
    DWORD dwRead; 
    CHAR c;
    HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    for (;;) {
        ReadFile( childOutputRd, &c, sizeof(char), &dwRead, NULL);
        switch (c) {
            case '+':
                int value;
                ReadFile( childOutputRd, &value, sizeof(int), &dwRead, NULL);
                q.push(value);
                printf("OK\n");
                break;
            case '-':
                if (!q.empty()) {
                    q.pop();
                    printf("OK\n");
                }
                else {
                    printf("Queue is empty!\n");
                }
                break;
            case 'f':
                if (!q.empty()) {
                    printf("%d\n",q.firstEl());
                } else {
                    printf("Queue is empty!\n");
                }
                break;
            case 'p':
                printf("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n");
                if (q.empty()) {
                    printf("empty");
                }
                while (!q.empty()) {
                    tmp.push(q.firstEl());
                    printf("%d ",q.firstEl());
                    q.pop();
                }
                while (!tmp.empty()) {
                    q.push(tmp.firstEl());
                    tmp.pop();
                }
                printf("\n\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n\nOK\n");
                break;
            case 'e':
                printf("%s\n",q.empty()?"YES":"NO");
                break;
            case 'q':
                break;
            case '?':
                printf("ERROR: undefined command\n");
                break;
            default:
                printf("Fatal error: wrong symbol from hadeler '%c'\n",c);
                system("pause");
                exit(5);
        }
        if (c == 'q') break;
    }
    CloseHandle(inputRerouting);
    CloseHandle(childInputWr);
    CloseHandle(childOutputRd);
    system("pause");
    return 0; 
}

And the handler: 和处理程序:

#define _CRT_SECURE_NO_DEPRECATE
#include <windows.h>
#include <stdio.h>

#define BUFSIZE 5 

HANDLE hStdin, hStdout;
DWORD dwRead, dwWritten; 

void readCmd(char* s) {
    ReadFile(hStdin, s, 1, &dwRead, NULL);
    int i;
    for (i = 0;(i < BUFSIZE) && (s[i] != ' ') && (s[i] != '\n') && (s[i] != '\r');i++) {
        ReadFile(hStdin, s + i + 1, 1, &dwRead, NULL);
    }
    s[i] = '\0';
}

bool correct() {
    char c;
    ReadFile(hStdin, &c, sizeof(char), &dwRead, NULL);
    if (c != '\n') {
        while (c != '\n') ReadFile(hStdin, &c, sizeof(char), &dwRead, NULL);
        return 0;
    }
    return 1;
}

int main() { 
    hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
    hStdin = GetStdHandle(STD_INPUT_HANDLE); 
    if ( (hStdout == INVALID_HANDLE_VALUE) || (hStdin == INVALID_HANDLE_VALUE) ) {
        ExitProcess(1); 
    } 
    int val;
    char s[BUFSIZE + 1];
    char c,digit;
    for (;;) { 
        readCmd(s);
        if (strcmp(s,"add") == 0) {
            val = 0;
            ReadFile(hStdin, &digit, 1, &dwRead, NULL);
            if (digit == '\n') {
                c = '?';
                WriteFile(hStdout,&c,sizeof(char),&dwRead,NULL);
                continue;
            }
            else if (digit < '0' || digit > '9') {
                c = '?';
            }
            else {
                c = '+';
            }
            while (digit >= '0' && digit <= '9') {
                val = val * 10 + digit - '0';
                ReadFile(hStdin, &digit, 1, &dwRead, NULL);
            }
        }else if (strcmp(s,"pop") == 0) {
            c = '-';
        }else if (strcmp(s,"first") == 0) {
            c = 'f';
        }else if (strcmp(s,"print") == 0) {
            c = 'p';
        }else if (strcmp(s,"empty") == 0) {
            c = 'e';
        }else if (strcmp(s,"help") == 0) {
            c = 'h';
        }else if (strcmp(s,"quit") == 0) {
            c = 'q';
        }else {
            c = '?';
        }
        if (!correct()) c = '?';
        WriteFile(hStdout, &c, 1, &dwRead, NULL);
        if (c == 'q') break;
        if (c == '+') WriteFile(hStdout, &val, sizeof(int), &dwRead, NULL);
    }
    return 0;
}

Thank you all for your help! 谢谢大家的帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM