How to execute child processes in order in C

南楼画角 提交于 2019-12-11 09:10:18

问题


I have written a code in C to count lines words and characters in a file. Like the wc command. The code is below and works fine.

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

char* concat(char *s1, char *s2)
{
char *result = malloc(strlen(s1)+strlen(s2)+1);
strcpy(result, s1);
strcat(result, s2);
return result;
} 

int countLines(char *f){
 FILE *file = fopen(f, "r");
int count = 0;
char ch;
while ((ch = fgetc(file)) != EOF){
   if (ch == '\n')
       count++;
}
return count;
}

int countWords(char *f){
char buffer[1];
FILE *file = fopen(f, "r");
  int countW = 0;
  enum states { WSP, WRD };
  int state = WSP;
char last = ' '; 
 while (read(fileno(file),buffer,1) == 1 )
 {
 if ( buffer[0]== ' ' || buffer[0] == '\t' || buffer[0]=='\n' )
 {
    state = WSP;
 }
 else 
 {
    if ( state == WSP )
    {
       countW++;
    }
    state = WRD;
 }
  last = buffer[0];
}
return countW;
}

int countChars(char *f){
 FILE *file = fopen(f, "r");
int chars = 0;
char ch;
while ((ch = fgetc(file))){
     if (ch == EOF) break;
  chars++;
}
return chars;
}

int main(int argc, char** argv)
{
 int lineCount = 0;
 int wordCount = 0;
 int charCount = 0;
 int n = 3;
 int i,status;
 int pids[3];
 char *theprogram = argv[0];
 char *thefile = argv[1];
 if ( argc !=2 )
 {
     printf( "Help: %s filename\n", argv[0]);
 }
 else{
     FILE *file = fopen( argv[1], "r");

   if(file == 0){
         char *sub = concat(theprogram, ": ");
         char *middle = concat(sub, thefile); 
         perror(middle);
   }
   else{
         for (i = 0; i < n; i++) {
             pids[i] = fork();
             if ( pids[i] < 0) { 
                perror("fork"); 
                exit(-1); 
            } else if (pids[i] == 0) { 
                if (i==0){
                        lineCount = countLines(argv[1]);
                        printf("This is child proccess %d, and the number of lines is %d\n", i+1, lineCount);
                        exit(0);
                    }
                    else if (i==1){ 
                        wordCount = countWords(argv[1]);
                        printf("This is child proccess %d, and the number of words is %d\n", i+1, wordCount);
                        exit(0);
                    }
                    else if (i==2){
                        charCount += countChars(argv[1]);
                        printf("This is child proccess %d, and the number of characters is %d\n", i+1, charCount);
                        exit(0);
                    }
            } 
          }
            for(i = 0; i < n; i++){
                wait(NULL);
            }
            return 0;      
            }
 } 
}

The problem i have is this:

The output is not always in order, like this:

//GOOD
This is child proccess 1, and the number of lines is 5
This is child proccess 2, and the number of words is 5
This is child proccess 3, and the number of characters is 159

//BAD
This is child proccess 1, and the number of lines is 5
This is child proccess 3, and the number of characters is 159
This is child proccess 2, and the number of words is 5

The third process ends before the second sometimes. How can i prevent this?


回答1:


Quick and dirty method:

        } else if (pids[i] == 0) { 
            usleep(i*1000);  /* wait 1ms for child 1, 2ms for child 2,... */
            if (i==0){
                    lineCount = countLines(argv[1]);
                    printf("This is child proccess %d, and the number of lines is %d\n", i+1, lineCount);
                    exit(0);
                }
                else if (i==1){ 
                    wordCount = countWords(argv[1]);
                    printf("This is child proccess %d, and the number of words is %d\n", i+1, wordCount);
                    exit(0);
                }
                else if (i==2){
                    charCount += countChars(argv[1]);
                    printf("This is child proccess %d, and the number of characters is %d\n", i+1, charCount);
                    exit(0);
                }
        } 

Another way would be by having the parent process to create three UNIX sockets and listen to all of them using select() or something like that. Childs would connect and write to the socket, exit, and then, parent process would print the information received in proper order.




回答2:


The forked processes will execute asynchronously to the main line code, so if you wanted them to happen in order, you need to use some kind of flag. This could be a semaphore, mutex, or set a boolean value inside the if conditionals.

You would need to use a semaphore or mutex to protect susceptible data from asynchronous writes, but that's not an issue in this context.




回答3:


i think u can use thread but not process, initializing some global variables and assign the variables value in the child thread. control the output in parent thread.



来源:https://stackoverflow.com/questions/20449276/how-to-execute-child-processes-in-order-in-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!