简体   繁体   中英

How to read a character string from a pipe instead of a keyboard entry

I have the following two C files from my textbook.

The first file is the parent process that is writing to the child process

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

#define BUFFER_SIZE 25

int main(void) {
    HANDLE ReadHandle, WriteHandle;
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    char message[25] = "Hello";
    DWORD written;

    /* set up security attributes allowing pipes to be inherited */
    SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };

    /* allocate memory */
    ZeroMemory(&pi, sizeof(pi));

    /* create the pipe */

    if (!CreatePipe(&ReadHandle, &WriteHandle, &sa, 0)) {
        fprintf(stderr, "Create Pipe Failed");
        return 1;
    }

    /* establish the START INFO structure for the child process */
    GetStartupInfo(&si);
    si.dwFlags = STARTF_USESTDHANDLES;
    si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);

    /* redirect standard input to the read end of the pipe */
    si.hStdInput = ReadHandle;


    /* don’t allow the child to inherit the write end of pipe */
    SetHandleInformation(WriteHandle, HANDLE_FLAG_INHERIT, 0);

    /* create the child process */
    CreateProcess(NULL, filter(), NULL, NULL, TRUE,
        /* inherit handles */ 0, NULL, NULL, &si, &pi);

    /* close the unused end of the pipe */
    CloseHandle(ReadHandle);

    /* the parent writes to the pipe */
    if (!WriteFile(WriteHandle, message, BUFFER_SIZE, &written, NULL))
        fprintf(stderr, "\nError writing to pipe abc .\n");

    /* close the write end of the pipe */
    CloseHandle(WriteHandle);

    /* wait for the child to exit */
    WaitForSingleObject(pi.hProcess, INFINITE);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    return 0;
} 

And then for the child process:

#include <Windows.h>
#include <stdio.h>
#include <Stdlib.h>

#define BUFFER_SIZE 25

int filter() {
    HANDLE ReadHandle;
    char buffer[BUFFER_SIZE];
    //char* buffer = malloc(sizeof(char)* (BUFFER_SIZE + 1));
    //buffer[BUFFER_SIZE] = '\0'; 
    DWORD read;

    /* get the read handle of the pipe */
    //ReadHandle = GetStdHandle(STD_INPUT_HANDLE);

    //SetHandleInformation(ReadHandle, HANDLE_FLAG_INHERIT, 0);
    ReadHandle = GetStdHandle(STD_INPUT_HANDLE);
    printf("Please work!!");

    /* the child reads from the pipe */
    if (ReadFile(ReadHandle, buffer, BUFFER_SIZE, &read, NULL)) {
        //return buffer;
        printf("child read %s", buffer);
    }
    else
        fprintf(stderr, "Error reading from pipe");
    system("Pause");
    return 0;

}

When I run the parent process, I get child read (whatever I enter into the prompt) followed by a bunch of weird symbols (kind of looks like a row of [][][][][] ). However, it seems like I should be receiving the message defined in the parent process instead. I have set si.dwflags to STARTF_USESTDHANDLES , which should allow my si.hStdOutput and si.hStdInput to not use the console, however it seems like it is still using the console input buffer for STD_INPUT_HANDLE .

Can anyone tell me why this is? How can I have a message sent through the pipe to my child process instead of a console input buffer?

When ReadFile() exits, the buffer is not guaranteed to be null-terminated. You need to either:

  1. add a null terminator before printing buffer :

     char buffer[BUFFER_SIZE+1]; // <-- add space for null terminator ... if (ReadFile(ReadHandle, buffer, BUFFER_SIZE, &read, NULL)) { buffer[read] = 0; // <-- add the null terminator printf("child read %s", buffer); } 
  2. take the read value outputted by ReadFile() into account when printing buffer :

     char buffer[BUFFER_SIZE]; // <-- null terminator not needed ... if (ReadFile(ReadHandle, buffer, BUFFER_SIZE, &read, NULL)) { printf("child read %.*s", read, buffer); } 

Also note that you are closing the parent's pipe handles without waiting to make sure the child process actually finishes reading everything. That might cause ReadFile() to fail, or at least return fewer bytes than requested. So make sure you take that into account. Either wait for the child process to exit before closing the parent's pipe handles, or make sure the child process handles partial data reads by calling ReadFile() in a loop until all expected bytes have been received.

Raymond Chen's MSDN blog also has some important information about reading/writing pipes across processes:

Be careful when redirecting both a process's stdin and stdout to pipes, for you can easily deadlock

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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