0

私は、80 以上のクライアントから読み取り、o/p を継続的にファイルに書き込み、別のタスクのためにこれらの新しいデータを読み取る必要がある 1 つのプロジェクトに取り組んでいます。私の質問は、選択またはマルチスレッドを使用する必要がありますか?

また、read/fgets および write/fputs 呼び出しを使用してマルチスレッドを使用しようとしましたが、これらは呼び出しをブロックしていて、一度に 1 つの操作を実行できるため、実行できません。どんなアイデアでも大歓迎です。

更新 1: 条件変数を使用して同じものを実装しようとしました。私はこれを達成できましたが、一度に1つずつ書き込みと読み取りを行っています.別のクライアントが書き込みを試みたとき、最初のスレッドから終了しない限り、書き込みできません. ぜんぜんわかりません。これで動作するはずです。私がしている間違いは何ですか?

更新 2: ありがとうございます。mutex 条件変数を使用してこのモデルを実装することに成功しました。

更新されたコードは次のとおりです。

        **header file*******
         char    *mailbox ;
    pthread_mutex_t  lock  = PTHREAD_MUTEX_INITIALIZER ;
    pthread_cond_t   writer = PTHREAD_COND_INITIALIZER;

    int main(int argc,char *argv[])
    {
      pthread_t          t1 , t2;
      pthread_attr_t     attr;
      int            fd, sock , *newfd;
      struct sockaddr_in cliaddr;
      socklen_t      clilen;
      void          *read_file();
      void          *update_file();

      //making a server socket
      if((fd=make_server(atoi(argv[1])))==-1)
        oops("Unable to make server",1)


      //detaching threads
      pthread_attr_init(&attr);
      pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);

      ///opening thread for reading
      pthread_create(&t2,&attr,read_file,NULL);

      while(1)
      {
        clilen = sizeof(cliaddr);
        //accepting request
        sock=accept(fd,(struct sockaddr *)&cliaddr,&clilen);

        //error comparison against failire of request and INT
        if(sock==-1 && errno != EINTR)
                oops("accept",2)
        else if ( sock ==-1 && errno == EINTR)
            oops("Pressed INT",3)

        newfd = (int *)malloc(sizeof(int));
        *newfd = sock;
        //creating thread per request
        pthread_create(&t1,&attr,update_file,(void *)newfd);
      } 
     free(newfd);
     return 0;
    }

    void *read_file(void *m)
    {
        pthread_mutex_lock(&lock);
        while(1)
        {
            printf("Waiting for lock.\n");
        pthread_cond_wait(&writer,&lock);
            printf("I am reading here.\n");
            printf("%s",mailbox);
            mailbox = NULL ;
        pthread_cond_signal(&writer);
        }
    }


    void *update_file(int *m)
    {
       int  sock = *m;
       int  fs ; 
       int  nread;
       char buffer[BUFSIZ] ;

       if((fs=open("database.txt",O_RDWR))==-1)
          oops("Unable to open file",4)

       while(1)
       {
        pthread_mutex_lock(&lock);
        write(1,"Waiting to get writer lock.\n",29);

        if(mailbox != NULL)
           pthread_cond_wait(&writer,&lock);

            lseek(fs,0,SEEK_END);
            printf("Reading from socket.\n");
            nread=read(sock,buffer,BUFSIZ);
            printf("Writing in file.\n");
            write(fs,buffer,nread);
            mailbox = buffer ;
          pthread_cond_signal(&writer);
          pthread_mutex_unlock(&lock);
       }
        close(fs);
    }
4

3 に答える 3

1

物事のネットワーク部分については、クライアントごとのスレッドまたは多重化されたシングルスレッドのいずれかがうまくいくと思います。

ディスク I/O に関しては、ディスク I/O 操作が操作をブロックしていることは間違いありません。データ スループットが十分に高い (および/またはハード ドライブが十分に遅い) 場合、ネットワーク操作が遅くなる可能性があります。ディスク I/O は同期的に行われます。

それがあなたにとって実際の問題である場合(そして、それが本当に問題であることを確認するために最初に測定する必要があります。必要がなければ、物事を複雑にする意味はありません)、問題を改善するために私が最初に試みることは、setbufferを呼び出して、ファイルの出力バッファを大きくします。バッファが十分に大きい場合、C ランタイム ライブラリは、ディスク アクセスによって発生する遅延を隠すことができる場合があります。

より大きなバッファーが十分でない場合、次に試みることは、データの読み取りおよび/または書き込み専用のスレッドを 1 つ以上作成することです。つまり、ネットワーク スレッドがデータをディスクに保存したい場合、fputs()/write() を直接呼び出すのではなく、書き込みたいデータを含むバッファーを割り当て、(ミューテックス保護またはロックレス) FIFO キュー。次に、I/O スレッドはそのバッファーをキューから取り出し、データをディスクに書き込み、バッファーを解放します。I/O スレッドは、他のスレッドが書き込みの完了を待ってブロックされないため、書き込みが遅くなる場合があります。ディスクからのスレッド化された読み取りはもう少し複雑ですが、基本的に IO 読み取りスレッドは、ネットワーク スレッドがドレインするメモリ内データの 1 つ以上のバッファーをいっぱいにします。そして、ネットワーク スレッドがバッファからデータの一部を排出するたびに、IO 読み取りスレッドに信号を送り、バッファを再び先頭まで補充するように指示します。そうすれば(理想的には)、ネットワーク スレッドがクライアントにデータを送信する必要があるときはいつでも、すでに大量の入力データが RAM に存在します。

上記のマルチスレッド方式は、スレッド間の同期と通信を伴うため、正しく理解するのが少し難しいことに注意してください。十分な単純な代替手段がない限り、そうしないでください。

于 2013-10-16T06:34:14.697 に答える
0

プログラムで問題を解決する場合は、選択/ポーリングまたはマルチスレッドのいずれかで問題ありません。

ディスクの読み取り/書き込みが頻繁に行われるため、クライアントの数が増えるにつれて、プログラムは io バウンドになると思います。したがって、複数のスレッドで io 操作を実行しても速度は上がりません。ポーリングはより良い選択かもしれません

于 2013-10-16T05:19:25.983 に答える