linux - Working with pipes in Unix C -
i having serious trouble working pipes in c. i'm supposed take in arguments command line (example: ./myprogram 123 45 67), read arguments 1 character @ time buffer, send character child process counted, , return total number of characters read parent process. code follows(note: comments i'm supposed doing):
// characters command line arguments sent child process // parent process 1 @ time through pipe. // child process counts number of characters sent through pipe. // child process returns number of characters counted parent process. // parent process prints number of characters counted 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 parent process via pipe // 1 @ time, , count them. int count = 0; printf("child read\n"); while(read(tochild[0], &buffer, 1)){ count++; } // return number of characters counted 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 command line arguments starting // argv[1] 1 @ time through pipe child process. read(fromchild[0], &nchars, 1); // wait child process return. reap child process. // receive number of characters counted via value // returned when child process 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 hang though i've closed both ends of both pipes.
for starters, wrong.
write(tochild[1], &count, 1)
it contribute problem. count
int
, not char
or unsigned char
. need send sizeof(count)
. also, read-function upon hitting error return eof, non-zero, child exit condition not appropriate. should this:
while(read(tochild[0], &buffer, 1) == 1)
finally, parent process should cycle through each argument in argv[]
sending each strlen
sized buffer.
i'm you're trying do. note in order maintain sanity in knowing descriptor used specific purpose, prefer using #define
note each process uses reading , writing. can extended number of processes, btw, i'm sure not far down line next assignment:
#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 open pipe(s)"); return exit_failure; } // fork child process if ((pid = fork()) == -1) { perror("failed fork child process"); return exit_failure; } // child process if (pid == 0) { // close non p1 descriptors close(fd[p0_read]); close(fd[p0_write]); // chars 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 closing unused descriptors close(fd[p1_read]); close(fd[p1_write]); // send each arg (i=1; i<argc; ++i) write(fd[p0_write], argv[i], strlen(argv[i])); // finished sending args close(fd[p0_write]); // wait child process return. wait(null); // wait 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; }
input
./progname argone argtwo
output
child: count = 12 parent: count = 12
edit: single pipe child return status
it seems comments of original question assignment may call reaping return status of child process result count rather returning in pipe. in doing so, can single pipe-descriptor pair. prefer first method, works well:
#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 open pipe(s)"); return exit_failure; } // fork child process pid = fork(); if (pid == -1) { perror("failed fork child process"); return exit_failure; } if (pid == 0) { // close non p1 descriptors close(fd[p0_write]); // return number of characters counted 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 closing unused descriptors close(fd[p1_read]); // eacn each arg entirely (int i=1; i<argc; ++i) write(fd[p0_write], argv[i], strlen(argv[i])); // finished sending args close(fd[p0_write]); // wait child process return. if (wait(&count) == -1) { perror("failed wait child process"); return exit_failure; } printf("parent: count = %d\n", wexitstatus(count)); return 0; }
the results same, note biach to debug debuggers signal-trip on child process , real exit status lost. on mac, example, running under xcode trips:
failed wait child process: interrupted system call
while running command line gives:
child: count = 12 parent: count = 12
one of many reasons prefer two-pipe methodology.
Comments
Post a Comment