1

名前のないパイプを介して親と通信するN 個の子プロセスを生成するプロセス マスターがあります。私はできる必要があります:

  • 父親にファイルを開かせてから、最小行から最大行まで読み取る必要があることを伝える構造体を各子に送信します。
  • これは同時に起こるので、私にはわかりません:
  • 最初の N マップの total_lines の分割方法と
  • 2番目に、各子供に本来あるべき行だけを読ませるにはどうすればよいですか?

私の問題はOSの概念には関係なく、ファイル操作のみに関係しています:S

おそらくfseek?ログ ファイルを mmap できません (1 GB を超えるものもあります)。

いくつかのアイデアをいただければ幸いです。前もって感謝します

編集: fseek とチャンクの値を使用せずに、子供たちにそれぞれの行を読ませようとしているので、これが有効かどうか教えてもらえますか? :

//somewhere in the parent process:

    FILE* logFile = fopen(filename, "r");
                while (fgets(line, 1024, logFile) != NULL) {
                    num_lines++;
                }
                rewind(logFile);
                int prev = 0;
                for (i = 0; i < maps_nr; i++) {
                    struct send_to_Map request;
                    request.fp = logFile;
                    request.lower = lowLimit;
                    request.upper = highLimit;

                    if (i == 0)
                        request.minLine = 0;
                    else
                        request.minLine = 1 + prev;
                    if(i!=maps_nr-1)
                        request.maxLine = (request.minLine + num_lines / maps_nr) - 1;
                    else
                       request.maxLine = (request.minLine + num_lines / maps_nr)+(num_lines%maps_nr);
                    prev = request.maxLine;

                }
                //write this structure to respective pipe


//child process:

while(1) {
      ...
      //reads the structure to pipe (and knows which lines to read)
      int n=0, counter=0;
      while (fgets(line, 1024, logFile) != NULL){
         if (n>=minLine and n<=maxLine)
              counter+= process(Line);//returns 1 if IP was found, in that line, between the low and high limit
         n++; 
      }
     //(...) 
}

うまくいくかどうかはわかりませんが、うまくいくようにするだけです!このように、ファイル全体を読み取り、ログ ファイルで見つかった ips の総数を出力する単一のプロセスよりも優れたパフォーマンスを発揮できますか?

4

3 に答える 3

1

私はそれがあなたを助けることができると思います:テキストファイルから特定の範囲の行を読む

于 2010-10-15T12:37:32.880 に答える
1
/* get an array with line-startpositions (file-offsets) */
fpos_t readLineBegins(FILE *f,fpos_t **begins)
{
  fpos_t ch=0, mark=0, num=0;
  *begins = 0;
  do {
    if( ch=='\n' )
    {
       *begins = realloc( *begins, ++num * sizeof(fpos_t) );
      (*begins)[num-1] = mark;
        mark = ftell(f);
    }
  } while( (ch=fgetc(f))!=EOF );

  if( mark<ftell(f) )
  {
    *begins = realloc( *begins, ++num * sizeof(fpos_t) );
    (*begins)[num-1]=mark;
  }

  return num;
}

/* output linenumber beg...end */
void workLineBlocks(FILE *f,fpos_t *begins,fpos_t beg,fpos_t end)
{
  while( beg<=end )
  {
    int ch;
    fsetpos( f, &begins[beg] ); /* set linestart-position */
    printf("%ld:", ++beg );
    while( (ch=fgetc(f))!=EOF && ch!='\n' && ch!='\r' )
      putchar(ch);
    puts("");
  }
}

main()
{
  FILE *f=fopen("file.txt","rb");
  fpos_t *lineBegins, /* Array with line-startpositions */
  lb = readLineBegins(f,&lineBegins); /* get number of lines */

  workLineBlocks(f,lineBegins,lb-2,lb-1); /* out last two lines */
  workLineBlocks(f,lineBegins,0,1); /* out first two lines */

  fclose(f);
  free(lineBegins);
}
于 2010-10-13T15:43:42.737 に答える
1

ファイルを正確に均等に分割することを気にせず、行の長さの分布がファイル全体である程度均等である場合は、親でファイル全体を一度に読み取ることを避けることができます。

  1. ファイルサイズを取得します。
  2. chunk_size = file_size / number_of_children
  3. 各子をスポーンするときは、親で次のことを行います。
    • (child_num+1) * chunk_size にシーク
    • 改行が見つかるまで読み進めます。
    • 子を生成し、前のチャンクの最後 (または最初の子の場合は 0) から開始するように指示し、チャンクの実際の長さを指定します。
  4. 各子は、バイトをシークしstartて読み取ります。chunk_size

作戦の大まかな図です。

物事を少し単純化するために編集されました。

編集: 以下は、ステップ 3 とステップ 4 のテストされていないコードです。これはすべてテストされておらず、off-by-one エラーには注意を払っていませんでしたが、探しているように聞こえるfseekandの使用法のアイデアが得られます。ftell

// Assume FILE* f is open to the file, chunk_size is the average expected size,
// child_num is the id of the current child, spawn_child() is a function that
// handles the logic of spawning a child and telling it where to start reading,
// and how much to read. child_chunks[] is an array of structs to keep track of
// where the chunks start and how big they are.
if(fseek(f, child_num * chunk_size, SEEK_SET) < 0) { handle_error(); }
int ch;
while((ch = fgetc(f)) != FEOF && ch != '\n')
{/*empty*/}

// FIXME: needs to handle EOF properly.
child_chunks[child_num].end = ftell(f); // FIXME: needs error check.
child_chunks[child_num+1].start = child_chunks[child_num].end + 1;
spawn_child(child_num);

次に、あなたの子供 (ステップ 4) で、子供がアクセスできると仮定し、次のchild_chunks[]ことを知っていますchild_num

void this_is_the_child(int child_num)
{
    /* ... */

    fseek(f, child_chunks[child_num].start, SEEK_SET); // FIXME: handle error
    while(fgets(...) && ftell(f) < child_chunks[child_num].end)
    {
    }
}
于 2010-10-13T12:10:24.707 に答える