Working with pipes in Unix C

I am having serious problems working with channels in C. I have to accept arguments from the command line (example: ./ myprogram 123 45 67), read the arguments one character at a time to the buffer, send the character for the child process to be counted, and then return the total number of characters read into the parent process. My code is as follows (note: comments are what I have to do):

// Characters from command line arguments are sent to child process
// from parent process one at a time through pipe.
// Child process counts number of characters sent through pipe.
// Child process returns number of characters counted to parent process.
// Parent process prints number of characters counted by child process.

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>

static int toChild[2];
static int fromChild[2];
static char buffer;

int main(int argc, char **argv)
{
    int status;
    int nChars = 0;
    pid_t   pid;

    pipe(toChild);
    pipe(fromChild);

    if ((pid = fork()) == -1) {
        printf("fork error %d\n", pid);
        return -1;
    }
    else if (pid == 0) {
        close(toChild[1]);
        close(fromChild[0]);
        // Receive characters from parent process via pipe
        // one at a time, and count them.

        int count = 0;
        printf("child about to read\n");
        while(read(toChild[0], &buffer, 1)){
            count++;
        }
        // Return number of characters counted to parent process.

        write(fromChild[1], &count, sizeof(count));
        close(toChild[0]);
        close(fromChild[1]);
        printf("child exits\n");
    }
    else {
        close(toChild[0]);
        close(fromChild[1]);
        // -- running in parent process --
        printf("CS201 - Assignment 3 - Chris Gavette\n");

        write(toChild[1], &argv[1], 1); 

        // Send characters from command line arguments starting with
        // argv[1] one at a time through pipe to child process.

        read(fromChild[0], &nChars, 1);

        // Wait for child process to return. Reap child process.
        // Receive number of characters counted via the value
        // returned when the child process is reaped.
        close(toChild[1]);
        close(fromChild[0]);
        waitpid(pid, &status, 0);

        printf("child counted %d chars\n", nChars);
        printf("parent exits\n");
        return 0;
    }
}

The child process seems to be hanging, although I closed both ends of both pipes.

+4
source share
1 answer

For starters, this is not true.

write(toChild[1], &count, 1) 

. count - int, char unsigned char. sizeof(count). , EOF, , . :

while(read(toChild[0], &buffer, 1) == 1)

, argv[], strlen.

, , . , , , , #define, , . , , , :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>

// P0_READ   - parent read source
// P0_WRITE  - parent write target
// P1_READ   - child read source
// P1_WRITE  - child write target

#define P0_READ     0
#define P1_WRITE    1
#define P1_READ     2
#define P0_WRITE    3
#define N_PIPES     4

int main(int argc, char **argv)
{
    int fd[N_PIPES], count = 0, i;
    pid_t pid;
    char c;

    if (pipe(fd) || pipe(fd+2))
    {
        perror("Failed to open pipe(s)");
        return EXIT_FAILURE;
    }

    // fork child process
    if ((pid = fork()) == -1)
    {
        perror("Failed to fork child process");
        return EXIT_FAILURE;
    }

    // child process
    if (pid == 0)
    {
        // close non P1 descriptors
        close(fd[P0_READ]);
        close(fd[P0_WRITE]);

        // get chars from input pipe, counting each one.
        while(read(fd[P1_READ], &c, 1) == 1)
            count++;

        printf("Child: count = %d\n", count);
        write(fd[P1_WRITE], &count, sizeof(count));

        // close remaining descriptors
        close(fd[P1_READ]);
        close(fd[P1_WRITE]);
        return EXIT_SUCCESS;
    }

    // parent process. start by closing unused descriptors
    close(fd[P1_READ]);
    close(fd[P1_WRITE]);

    // send each arg
    for (i=1; i<argc; ++i)
        write(fd[P0_WRITE], argv[i], strlen(argv[i]));

    // finished sending args
    close(fd[P0_WRITE]);

    // Wait for child process to return.
    wait(NULL);

    // wait for total count
    if (read(fd[P0_READ], &count, sizeof(count)) == sizeof(count))
        printf("Parent: count = %d\n", count);

    // close last descriptor
    close(fd[P0_READ]);

    return 0;
}

./progname argOne argTwo

Child: count = 12
Parent: count = 12

:

, , . pipe. , :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>

// P0_WRITE  - parent write target
// P1_READ   - child read source

#define P1_READ     0
#define P0_WRITE    1
#define N_PIPES     2

int main(int argc, char **argv)
{
    int fd[N_PIPES], count = 0;
    pid_t pid;
    char c;

    if (pipe(fd))
    {
        perror("Failed to open pipe(s)");
        return EXIT_FAILURE;
    }

    // fork child process
    pid = fork();
    if (pid == -1)
    {
        perror("Failed to fork child process");
        return EXIT_FAILURE;
    }

    if (pid == 0)
    {
        // close non P1 descriptors
        close(fd[P0_WRITE]);

        // Return number of characters counted to parent process.
        while(read(fd[P1_READ], &c, 1) == 1)
            ++count;

        close(fd[P1_READ]);
        printf("Child: count = %d\n", count);
        return count;
    }

    // parent process. start by closing unused descriptors
    close(fd[P1_READ]);

    // eacn each arg entirely
    for (int i=1; i<argc; ++i)
        write(fd[P0_WRITE], argv[i], strlen(argv[i]));

    // finished sending args
    close(fd[P0_WRITE]);

    // Wait for child process to return.
    if (wait(&count) == -1)
    {
        perror("Failed to wait for child process");
        return EXIT_FAILURE;
    }

    printf("Parent: count = %d\n", WEXITSTATUS(count));

    return 0;
}

, , , . , Mac Xcode:

Failed to wait for child process: Interrupted system call

:

Child: count = 12
Parent: count = 12

, .

+3

Source: https://habr.com/ru/post/1542873/


All Articles