プログラミングは生産者と消費者の問題(linuxでC実現)を実現します.

6458 ワード

  • シリーズのブログの参考:http://blog.csdn.net/zy416548283/article/category/1108400
  • コードは、Githubに番号で対応付けられています.https://github.com/zy416548283/networkProgramming
  •    -       :             ,                 。                   ,             N         ,                        ,                       。
  • テーマ解読:
  • その名の通り、生産者は製品を生産し、消費者は商品を消費し、両者の間に協力の関係がある.製品が消費者に消費されたら、生産者はまた製品を生産していないので、消費者は待たなければなりません.同じように、倉庫に製品がいっぱい置いてありますが、消費者はまだ消耗していません.生産者が生産した製品は置くところがありません.両者の間にはもう一つの制約がある.だから生産者は製品を生産する前に、まず時間のあるところを見て、浪費しないようにします.消費者は消費する前に、商品があるかどうか確認して、むだ足を踏まないようにします.
    次のプログラムの実装では、倉庫を一つの配列(循環列)で表し、製品を格納し、生産者が生産する製品は、文字'1'であり、消費者が'1'を消費した後、スペースを0にします.倉庫が空か倉庫が満杯かどうかを確認して、信号量を使用する方法があります.もちろん生産者と消費者は互いに反発して公共資源を使うしかないです.
  • テーマ実現
  • 以下はいくつかの関連する一般的な関数です.
    信号量(マルチタスク同期):参照http://blog.163.com/kmustchenb@126/blog/static/1109057652071840555/
    semuut empty,full.,二つの信号量(長整形)を宣言する.
    どの変数も使用前の初期化がベストで、信号量も例外ではなく、extern int semuinitを使用します. ,を使用して、最初の値を信号量に割り当てます.最初のときは、配列がすべて空(0)であると仮定します.つまり、empy=配列サイズ、full=0です.
    生産者は列を占有する前に、空いているところがあるかどうか(逆に操作すれば、デッドロックになります)を確認し、関数semuwaitを使って、信号量が0より大きいかどうかを確認します.
    製品を生産し終わったら、倉庫の占有権を釈放して、またいっぱいの空間があると宣言して、関数semupostを使って、信号の量を+1させます.ここはfull+1です.
    信号量もリリースし、関数semudestryを使ってリリースします.
    相互反発ロック(マルチタスク相互反発):臨界リソースを制御するためのもの、参照:http://blog.163.com/yangfan_407/blog/static/12795065420099220218815/
    pth read mutexut muttex,声明の相互反発量
    pthread mutexuinit(pthread mutexut*muttex、const pth readmutext traut*matr)は、相互反発量を初期化し、属性がNULLの場合は、デフォルト属性として設定されます.
    pthreadmutexcuulock(pthreadmutexut*muttex)は、相互反発ロックを申請し、資源を占用します.これは閉塞用法です.非閉塞:pthread mutexturylock(pthread mutext*muttex);
    pthreadmutexunlock(pthreadmutexut*muttex)は、相互反発ロックを解除し、占有された資源を解放する.
    pth readmutexudesttoryは、相互反発ロックを破壊します.
    スレッド関連、参照:http://blog.csdn.net/zhhxidian2005/article/details/5605404
    pth readaut idは、スレッドのidを宣言します.
    要点 pth read create(pth readaut) *resticttidp コンサート pthreadaut *restictattr void *(*starturtn)(void)、 void *restict arg);スレッドを作成し、最初のパラメータはスレッドIDに戻り、2番目のパラメータはスレッドの属性(NULLの場合はデフォルト属性)を設定し、3番目のパラメータはスレッド実行関数の名前であり、4番目のパラメータは実行関数のパラメータ(1つ以上のパラメータの場合は構造体で表しても良い)である.
    pth readaujoin(pth readaut tid、void**status)は、スレッドが終了するのを待って、スレッドの終了状態値を保存します.pthreadauexitを使ってスレッドを終了することもできます.
    pth readauselfは、自分のスレッドIDを知ることができます.
    プログラム全体参照:http://hi.baidu.com/shazi129/item/4d2a054626be7d17896d1088いくつかの小さな修正を行いました.
    /*
    * author   
    * 2012/05/21
    */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <pthread.h>
    #include <semaphore.h>
    
    #define BUFFSIZE 9 //       
    
    struct queue_type     //      
    {
    	int buff[BUFFSIZE];
    	int front;	//  ,        "  ” 
    	int rear;	//  ,        "  “ 
    }Q={{0},0,0};		
    
    sem_t empty; //         ,         。 
    sem_t full;   //       ,           。 
    pthread_mutex_t mutex; //      ,             
    
    int producer_id = 0;   //     ,   0 
    int consumer_id = 0;   //     ,   0 
    
    /*        */
    void print()
    {
         int i;
         for(i = 0; i < BUFFSIZE; i++)
         printf("%d ", Q.buff[i]);
         printf("
    "); } /* */ void *producer() { int id=++producer_id; while(1) { sleep(1); // sem_wait(&empty); // pthread_mutex_lock(&mutex); // Q.buff[Q.rear] = 1; // rear printf("producer number<%d> thread idetifier:%u put into buffer[%d].The buffer is like: \t", id, ((unsigned int)pthread_self()),Q.rear+1); print(); Q.rear = (Q.rear+1) % BUFFSIZE; pthread_mutex_unlock(&mutex); // sem_post(&full); // } } /* */ void *consumer() { int id=++consumer_id; while(1) { sleep(1); sem_wait(&full); // pthread_mutex_lock(&mutex); // Q.buff[Q.front] = 0; // front printf("consumer number<%d> thread idetifier:%u get from buffer[%d].The buffer is like: \t", id,((unsigned int)pthread_self()), Q.front+1); print(); Q.front = (Q.front+1) % BUFFSIZE; pthread_mutex_unlock(&mutex); // sem_post(&empty); // } } int main() { int M,N; //M ,N printf("please input the producers number: "); scanf("%d",&M); printf("please input the consumers number: "); scanf("%d",&N); pthread_t id1[M]; // ID pthread_t id2[N]; // ID int i; int ret1[M],ret2[N]; // 。 /* empty full */ int ini1 = sem_init(&empty, 0, BUFFSIZE);// empty , Buffersize , , -1 int ini2 = sem_init(&full, 0, 0); // full , 0 if((ini1 || ini2)!=0) // { printf("sem init failed
    "); exit(1); } /* mutex*/ int ini3 = pthread_mutex_init(&mutex, NULL); // ( ) , , 0 if(ini3 != 0) { printf("mutex init failed
    "); exit(1); } /* */ for(i = 0; i < M; i++) { ret1[i] = pthread_create(&id1[i], NULL, producer, (void *)(&i)); // , 0 if(ret1[i] != 0) { printf("producer%d creation failed
    ", i); exit(1); } } /* */ for(i = 0; i < N; i++) { ret2[i] = pthread_create(&id2[i], NULL, consumer, NULL); // , 0 if(ret2[i] != 0) { printf("consumer%d creation failed
    ", i); exit(1); } } /* */ for(i = 0; i < M; i++) { pthread_join(id1[i],NULL); // } for(i = 0; i < N; i++) { pthread_join(id2[i],NULL); // } exit(0); }
    運転方式:
    gcc mutex.c -o mutex -lpthread  <span style="font-family: Arial, Helvetica, sans-serif;">#       </span>
    ./mutex   
    興味があるなら、このプログラムも見られます.
    http://www.cnblogs.com/lycheng/archive/2011/11/23/2260656.html