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

Popular posts from this blog

commonjs - How to write a typescript definition file for a node module that exports a function? -

openid - Okta: Failed to get authorization code through API call -

ios - Change Storyboard View using Seague -