2017-04-21 13 views
1

例を通してセマフォを数える概念を理解しようとしています。しかし、私はこれをLinuxのSysVを使って実装したいと思っています。
私はバイナリセマフォとカウントセマフォの理論的な部分に精通しています。
私はこれを参照しましたlinkSysVを使ってセマフォを数える

概念的には、セマフォーはあるプロセスから別のプロセスへのシグナル伝達メカニズムとして使用されるため、私は単純なプログラムを作成しようとしていました。以下のプログラムで

は、私はそれが thread_2からの信号を取得していないまで待つ thread_1をしたいし、それが thread_3からの信号を取得していないまでも同様 thread_2待つ必要があります。

出力はこのようなものになるよう: Hello From thread 3 Hello from thread 2 Hello from thread 1

私はそれが適切pthread_join()を使用して達成することができます知っているが、私は、セマフォを使用して、それを達成したいです。

コード:

#include <stdio.h> 
#include <unistd.h> 
#include <pthread.h> 
#include <sys/types.h> 
#include <sys/ipc.h> 
#include <sys/sem.h> 
#include <errno.h> 

int sem_id; 
struct sembuf sops[3]; 
void thread_1(void) 
{ 
    sops[0].sem_num = 0; 
    sops[0].sem_op = 0; 
    sops[0].sem_flg = 0; 

    if(semop(sem_id, sops, 1) < 0) 
     perror("Semop In thread 3"); 
    else 
     printf("Hello From thread 1\n"); 
} 

void thread_2(void) 
{ 
    sops[0].sem_num = 0; 
    sops[0].sem_op = -1; 
    sops[0].sem_flg = 0; 

    if(semop(sem_id, sops, 1) < 0) 
     perror("Semop In thread 2"); 
    else 
     printf("Hello from thread 2\n"); 
} 

void thread_3(void) 
{ 

    sops[0].sem_num = 0; 
    sops[0].sem_op = -1; 
    sops[0].sem_flg = 0; 

    if(semop(sem_id, sops, 1) < 0) 
     perror("Semop In thread 3"); 
    else 
     printf("Hello from thread 3\n"); 
} 

int main(void) 
{ 
    void (*funct[]) = {thread_1, thread_2, thread_3}; 

    key_t semkey; 
    char i; 
    union semun { 
       int    val; /* Value for SETVAL */ 
       struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ 
       unsigned short *array; /* Array for GETALL, SETALL */ 
       struct seminfo *__buf; /* Buffer for IPC_INFO 
              (Linux-specific) */ 
      }arg; 
    pthread_t thread_id[3]; 

    semkey = ftok("/tmp", 'a'); 

    if(semkey < 0) 
     perror("Cannot Create Semaphore Key"); 
    else 
    { 
     sem_id = semget(semkey, 1, (IPC_CREAT|IPC_EXCL|0666)); 
     if(sem_id < 0) 
      perror("Cannot create semaphore\n"); 
     else 
     { 
      arg.val = 3; 
      if (semctl(sem_id, 0, SETVAL, arg) == -1) { 
       perror("semctl"); 
       exit(1); 
      } 
     } 
    } 

    for(i = 0; i < 3; i++) 
    { 
     if(pthread_create(&thread_id[i], NULL, funct[i], NULL) < 0) 
      perror("Cannot Create thread\n"); 
    } 

    for(i = 0; i < 3; i++) 
     pthread_join(thread_id[i], NULL); 

    if(semctl(sem_id, 0, IPC_RMID, NULL) == -1) 
     perror("semctl"); 

    return 0; 
} 

私は私が何をしようとしています何を達成するために、複数のセマフォセットを使用する必要がありますか?

+0

pthread_wait、btwはありません。あなたはおそらくpthread_joinを意味します。 – PSkocik

+0

はい、ありがとうございます。訂正済! – Gaurav

答えて

1

は、あなたのスレッドがt0,t1,t2と呼ばれ、その後、あなたのセマフォsem0sem1t0自由に実行され、刻みsem0sem0インクリメントsem1t1待ち、sem1t2待機していると仮定すると、カウント1 を持つ2つのミューテックス/セマフォを必要としています。私は逆の順序でスレッドを実行すると、1秒でセマフォが仕事を表示するにはt0t1、およびt1t2の間で待機してい

#include <stdio.h> 
#include <unistd.h> 
#include <pthread.h> 
#include <sys/types.h> 
#include <sys/ipc.h> 
#include <sys/sem.h> 
#include <errno.h> 

static int sem0, sem1; 
#define POST1(Sem) semop(Sem, &(struct sembuf){0,1,0}, 1) 
#define WAIT1(Sem) semop(Sem, &(struct sembuf){0,-1,0}, 1) 

static void* t0(void *unused) { puts("hello from t0"); POST1(sem0); return 0; } 
static void* t1(void *unused) { WAIT1(sem0); puts("hello from t1"); POST1(sem1); return 0; } 
static void* t2(void *unused) { WAIT1(sem1); puts("hello from t2"); return 0; } 

int main(void) 
{ 
    key_t sem0_k, sem1_k; 
    sem0_k = ftok("/tmp", '0'); 
    sem1_k = ftok("/tmp", '1'); 

    sem0 = semget(sem0_k, 1, (IPC_CREAT|IPC_EXCL|0666)); 
    sem1 = semget(sem1_k, 1, (IPC_CREAT|IPC_EXCL|0666)); 

    pthread_t tids[3]; 
    pthread_create(tids+2, NULL, t2, NULL); 
    sleep(1); 
    pthread_create(tids+1, NULL, t1, NULL); 
    sleep(1); 
    pthread_create(tids+0, NULL, t0, NULL); 

    for(int i = 0; i < 3; i++) 
     pthread_join(tids[i], NULL); 

    semctl(sem0, 0, IPC_RMID, NULL); 
    semctl(sem1, 0, IPC_RMID, NULL); 

    return 0; 
} 

はここでエラーチェックなしの完全な案ですスレッドをt0からt2に注文する。

+0

ありがとうございました。 – Gaurav

1

@ PSkocikあなたの答えに基づいて、2つのセマフォーのセットを使用するようにコードを修正しました。コードは次のとおりです。

#include <stdio.h> 
#include <unistd.h> 
#include <pthread.h> 
#include <sys/types.h> 
#include <sys/ipc.h> 
#include <sys/sem.h> 
#include <errno.h> 

int sem_id; 

struct sembuf sops; 
void thread_1(void) 
{ 
    /*Wait on Set1 of Semaphore*/ 
    sops.sem_num = 1; 
    sops.sem_op = -1; 
    sops.sem_flg = 0; 

    if(semop(sem_id, &sops, 1) < 0) 
     perror("Semop Wait In thread 3"); 
    else 
     printf("Hello From thread 1\n"); 
} 


void thread_2(void) 
{ 
    /*Wait on Set0 of Semaphore*/ 
    sops.sem_num = 0; 
    sops.sem_op = -1; 
    sops.sem_flg = 0; 

    if(semop(sem_id, &sops, 1) < 0) 
     perror("Semop Wait In thread 2"); 
    else 
     printf("Hello from thread 2\n"); 

    /*Post on Set1 of Semaphore*/   
    sops.sem_num = 1; 
    sops.sem_op = 1; 
    sops.sem_flg = 0; 

    if(semop(sem_id, &sops, 1) < 0) 
     perror("Semop Post In thread 2"); 
} 

void thread_3(void) 
{ 
    printf("Hello from thread 3\n"); 

    /*Post operation on Set0 of semaphore*/ 
    sops.sem_num = 0; 
    sops.sem_op = 1; 
    sops.sem_flg = 0; 

    if(semop(sem_id, &sops, 1) < 0) 
     perror("Semop In thread 3"); 
    else 
    { ; } 
} 

int main(void) 
{ 
    void (*funct[]) = {thread_1, thread_2, thread_3}; 

    key_t semkey; 
    char i; 
    union semun { 
       int    val; /* Value for SETVAL */ 
       struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ 
       unsigned short *array; /* Array for GETALL, SETALL */ 
       struct seminfo *__buf; /* Buffer for IPC_INFO 
              (Linux-specific) */ 
      }arg; 
    pthread_t thread_id[3]; 

    semkey = ftok("/tmp", 'a'); 

    if(semkey < 0) 
     perror("Cannot Create Semaphore Key"); 
    else 
    { 
     sem_id = semget(semkey, 2, (IPC_CREAT|IPC_EXCL|0666)); 
     if(sem_id < 0) 
      perror("Cannot create semaphore\n"); 
     else 
     { 
      /*arg.val = 3; 
      if (semctl(sem_id, 0, SETVAL, arg) == -1) { 
       perror("semctl"); 
       exit(1); 
      }*/ 
     } 
    } 

    for(i = 0; i < 3; i++) 
    { 
     if(pthread_create(&thread_id[i], NULL, funct[i], NULL) < 0) 
      perror("Cannot Create thread\n"); 
    } 

    for(i = 0; i < 3; i++) 
     pthread_join(thread_id[i], NULL); 

    if(semctl(sem_id, 0, IPC_RMID, NULL) == -1) 
     perror("semctl"); 

    return 0; 
} 

ご参考までに、ありがとうございます。

+0

SysVセマフォは、1つのセマフォの2つのスタンドアロンセマフォセットより優れたアプローチです(しかし、問題がこれより複雑ではない場合は、pthread mutexまたはposixセマフォを使用する必要があります。これはsysvセマフォと比較してはるかに軽いためです)。 – PSkocik

+0

はい、私はSysVセマフォがカーネルレベルで動作することを勉強しましたが、確かにそうは思いません。 – Gaurav

関連する問題