web-dev-qa-db-ja.com

セマフォの実装

次のプログラムでエラーが発生します。セマフォを使用して2つのプロセスが変数を共有する方法を示したいと思います。誰でも私を案内できますか?

エラーをデバッグできません...

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<semaphore.h>
int main()
{
  int pid,mutex=1;
  int semid;               /* semid of semaphore set */
  key_t key = 1234; /* key to pass to semget() */
  int nsems = 1; /* nsems to pass to semget() */
  semid=semget(key,nsems,IPC_CREAT|0666);
  if (semid<0) 
  { 
    perror("Semaphore creation failed ");
  }
  if ((pid = fork()) < 0) 
  {
    perror("fork");
    return 1;
  }
  else if(pid==0)
  {
    sem_wait(&semid);
    printf("IN CHILD PROCESS :\n");
    mutex++; 
    printf("value of shared variable =%d",mutex);
    sem_post(&semid);
    return 0;
  }
  sem_wait(&semid);
  printf("IN PARENT PROCESS :\n");
  mutex--;
  printf("value of shared variable =%d",mutex);
  sem_post(&semid);
  return 0;
} 
6
chinu

あなたの基礎は間違っている、プログラムは動作しませんので、基本を通過してプログラムを書き直してください。

修正する必要があるのは次のとおりです。

1)セマフォ型の変数を作成する必要があります

_sem_t semvar;
_

2)関数sem_wait()sem_post()はセマフォ変数を必要としますが、セマフォIDを渡しているため、意味がありません。

_sem_wait(&semvar);
   //your critical section code
sem_post(&semvar);
_

3)セマフォを初期化せずにsem_wait()およびsem_post()に渡します。使用する前に1に初期化する必要があります(そうでない場合)。そうしないと、デッドロックが発生します。

_ret = semctl( semid, 1, SETVAL, sem);
if (ret == 1)
     perror("Semaphore failed to initialize");
_

マニュアルページからセマフォAPIを調べて、これを確認してください

23

コードの基本的な問題は、2つのAPIを混在させることです。残念ながら、オンラインリソースはこれを指摘するのに優れていませんが、UNIXのようなシステムには2つのセマフォAPIがあります。

  • POSIX IPC API、これは標準APIです
  • System V API。古いUnixの世界から来ていますが、ほとんどすべてのUnixシステムで実際に利用可能です。

上記のコードを見て、System V APIのsemget()を使用し、POSIX APIのsem_post()を使用して投稿しようとしました。それらを混合することはできません。

必要なセマフォAPIを決定するには、それほど多くの優れたリソースはありません。最も簡単なのは、Stevensによる「Unix Network Programming」です。おそらく興味のあるセクションは第2巻です。

これら2つのAPIは驚くほど異なります。どちらも教科書スタイルのセマフォをサポートしていますが、言及する価値のあるSystem V APIにはいくつかの長所と短所があります。

  • セマフォセットに基づいて構築されるため、単一のセマフォではなくセマフォのセットであるsemget()を使用してオブジェクトを作成すると、
  • system V APIを使用すると、これらのセットでアトミック操作を実行できます。したがって、セット内の複数のセマフォを変更または待機できます
  • sysV APIを使用すると、セマフォがゼロ以外になるのではなく、しきい値に達するのを待つことができます。ゼロ以外のしきい値を待つこともサポートされていますが、前の文章は
  • セマフォリソースはすべてのUNIXでかなり制限されています。これらは「ipcs」コマンドで確認できます
  • system Vセマフォには元に戻す機能があるため、プログラムの異常終了によってセマフォが望ましくない状態にならないようにすることができます。
15
David Beck

コードの操作をよりよく理解するために、消費者レートと生産者レート(スリープを使用)を変更します。以下のコードは、消費者と生産者のシミュレーションです(コンテナの上限を超えています)。

参照用のコード:

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>

sem_t semP, semC;
int stock_count = 0;
const int stock_max_limit=5;

void *producer(void *arg) {
    int i, sum=0;
    for (i = 0; i < 10; i++) {

        while(stock_max_limit == stock_count){
            printf("stock overflow, production on wait..\n");
            sem_wait(&semC);
            printf("production operation continues..\n");
        }

        sleep(1);   //production decided here
        stock_count++;
        printf("P::stock-count : %d\n",stock_count);
        sem_post(&semP);
        printf("P::post signal..\n");
    }
 }

void *consumer(void *arg) {
    int i, sum=0;
    for (i = 0; i < 10; i++) {

        while(0 == stock_count){
            printf("stock empty, consumer on wait..\n");
            sem_wait(&semP);
            printf("consumer operation continues..\n");
        }

        sleep(2);   //consumer rate decided here
        stock_count--;
        printf("C::stock-count : %d\n", stock_count);
        sem_post(&semC);
        printf("C::post signal..\n");
        }
}

int main(void) {

    pthread_t tid0,tid1;
    sem_init(&semP, 0, 0);
    sem_init(&semC, 0, 0);

        pthread_create(&tid0, NULL, consumer, NULL);
        pthread_create(&tid1, NULL, producer, NULL);
        pthread_join(tid0, NULL);
        pthread_join(tid1, NULL);

    sem_destroy(&semC);
    sem_destroy(&semP);

    return 0;
}
3
parasrish

セマフォの実装(ロックおよびロック解除)のサンプルコードを以下で確認してください。

    #include<stdio.h>
    #include<stdlib.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include<string.h>
    #include<malloc.h>
    #include <sys/sem.h>
    int main()
    {
            int key,share_id,num;
            char *data;
            int semid;
            struct sembuf sb={0,-1,0};
            key=ftok(".",'a');
            if(key == -1 ) {
                    printf("\n\n Initialization Falied of shared memory \n\n");
                    return 1;
            }
            share_id=shmget(key,1024,IPC_CREAT|0744);
            if(share_id == -1 ) {
                    printf("\n\n Error captured while share memory allocation\n\n");
                    return 1;
            }
            data=(char *)shmat(share_id,(void *)0,0);
            strcpy(data,"Testing string\n");
            if(!fork()) { //Child Porcess
                 sb.sem_op=-1; //Lock
                 semop(share_id,(struct sembuf *)&sb,1);

                 strncat(data,"feeding form child\n",20);

                 sb.sem_op=1;//Unlock
                 semop(share_id,(struct sembuf *)&sb,1);
                 _Exit(0);
            } else {     //Parent Process
              sb.sem_op=-1; //Lock
              semop(share_id,(struct sembuf *)&sb,1);

               strncat(data,"feeding form parent\n",20);

              sb.sem_op=1;//Unlock
              semop(share_id,(struct sembuf *)&sb,1);

            }
            return 0;
    }
1
Gyan Prakash