0

我有两个子进程从文件中读取并将结果发送给父进程,但是当孩子们发送字符串时,父亲收到字符串加上一些其他奇怪的字符......我如何 null 终止接收到的字符串以及如何我是否让父亲在发送一些结果后等待所有可能有更多工作要做的儿子...因为儿子可能稍后会发送其他结果...谢谢您的帮助...

#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <stdio.h>
#include <strings.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>

    #define max_chars_string 1000
    #define n_childs 2

    pid_t childs[n_childs];
    int channel[n_childs][2];

    void read_lines(char * filename, char (*pointer)[max_chars_string],int init_read,int n_lines);
    void get_strings_hash(char (*pointer_strings)[max_chars_string],char (*pointer_hashes)[max_chars_string],int total_lines);

    void worker(int mypipe,char filename[],int n_lines){ // meter as funcoes de ler passwords no filho
        int resources[2];// numero de linhas que cada processo tem de ler
        int i = 0;

        //definicao arrays
        char strings_hashes[n_lines][max_chars_string];//aray de string com as strings lidas do ficheiro
            char * pointer_strings = &strings_hashes[0][0];//ponteiro para o inicio do array das hashes

        read_lines(filename,strings_hashes,0,n_lines); // le as strings do ficheiro e passa para o array

        for(i = 0;i<n_lines;i++){
            printf("%s \n",strings_hashes[i]);
        }
        printf("[%d] My parent is: %d\n", getpid(), getppid());

        //open pipe to write and close pipe to read

        close(channel[mypipe][0]);
        i = 0;
        int incr = 0;
        while (i<n_lines) {
            printf("[Son] Password sent e  %s: \n",strings_hashes[incr]);
             write(channel[mypipe][1], strings_hashes[incr], strlen(strings_hashes[incr]));
             incr++;
             i++;
        }
        exit(0);
    }

    int main(int argc, char **argv)
    {
        char *filename;
        int status;//status do processos filho
        int resources[2];// numero de linhas que cada processo tem de ler
        int n_lines; //numero de linhas do ficheiro
        int i = 0;

          // Create a pipe
        filename = (char*)malloc(strlen(argv[1])*sizeof(char)+1);

        if(argc !=3){
            fprintf(stderr, "Usage : %s [text_file] [cores]",argv[0]);
            exit(0);
        }

        strcpy(filename,argv[1]);

        char get_file [strlen(filename)];
        strcpy(get_file,filename);

     // start the processes
       for(i = 0; i <atoi(argv[2]);i++){
            pipe(channel[i]);
            childs[i] = fork();

            if(childs[i] == -1){
               perror("Failed to fork");
               return 1;
           }
           if (childs[i] == 0)
           {
              worker(i,get_file,n_lines);
           }
           close(channel[i][1]);
       }

               i = 0;
               int k = 0;
               int fd;
               fd_set read_set;
               FD_ZERO(&read_set);
               char string_lida [30];

               // working father
               printf("[%d] I'm the father!\n", getpid());
               printf("[Father]orking ...\n");

                //unammed_pipes connection
                while(k<n_childs){

                    FD_SET(channel[0][0], &read_set);
                    for(i=0;i<n_childs;i++){
                            FD_SET(channel[i][0], &read_set);
                            if(fd<channel[i][0]){      fd=channel[i][0];
                            }
                        }

                    if(select(fd+1,&read_set,NULL,NULL,NULL)>0){
                        for(i=0;i<n_childs;i++){
                            if(FD_ISSET(channel[i][0], &read_set)){                    
                                read(channel[i][0],string_lida,sizeof(string_lida));
                                printf("[Father]pipe %d - string lida:%s\n",i,string_lida);

                                k++;                 
                            }
                        }
                    }
                    fd=1;
                }
              //
              //waiting for childs ...
            for(i=0;i<n_childs;i++){
                wait(&status);
                printf("waiting for childs \n");
              }

      return 0;
    }  


    void get_strings_hash(char (*pointer_strings)[max_chars_string],char (*pointer_hashes)[max_chars_string],int total_lines)//vai ao array de strings e corta a parte de hash e mete num array
    {
        int i = 0;
        char *strings;
        char *hash;

        for(i = 0;i<total_lines;i++){
                strings = (char*)malloc(strlen(pointer_strings)*sizeof(char)+1);
                strcpy(strings,*pointer_strings);
                hash = (char*)malloc(strlen(pointer_strings)*sizeof(char)+1);
                find_hash(strings,hash);
                strcpy(*pointer_hashes,hash);
            pointer_hashes++;
            pointer_strings++;
        }

    }


    void read_lines(char * filename, char (*pointer)[max_chars_string],int init_read,int n_lines){ 
        FILE *fp;
        char str[max_chars_string];
        int i =0;

        if((fp = fopen(filename, "r"))==NULL) {
          printf("Cannot open file.\n");
          exit(1);
        }

        if(init_read>0 && init_read<=n_lines){
         for(i = 0;i<init_read;i++){
             fgets(str, sizeof str, fp);
           for(i = init_read;i<n_lines;i++){
               fgets(str, sizeof str, fp);
               strcpy(*pointer, str); //copia para a posicao actula do ponteiro
               pointer++;
           }
         }
        }
        if(init_read<=n_lines && init_read==0){
           for(i = init_read;i<n_lines;i++){
                fgets(str, sizeof str, fp);
               strcpy(*pointer, str); //copia para a posicao actula do ponteiro
               pointer++;
           }
         }


      fclose(fp);
    }
4

1 回答 1

0

When the child does

write(channel[mypipe][1], strings_hashes[incr], strlen(strings_hashes[incr]));

strlen() doesn't count the null terminator of the string. So when the parent reads from the pipe, it doesn't receive a null-terminated string. Then when it does:

printf("[Father]pipe %d - string lida:%s\n",i,string_lida);

It keeps printing past the end of what was written, because there's no string terminator.

Also, there's no guarantee that the amount read by read() will match up with the amount written each time write() was called. If the child writes two strings before the parent reads from the pipe, it may get all or parts of both, or it could get even less than was written.

You need to implement a way to indicate where the string boundaries are. You could send the size of the string first as one or two bytes, or you could use a null terminator. When the parent is reading, it needs to do this in a loop until it gets a whole string, and if it goes past the end it may need to save it in a buffer.

于 2012-10-13T01:09:40.457 回答