2

これは、セマフォとスレッドに対する私の最初の試みです。このコードは、例とネットで見つけた man ページから作成しました。このコードには 2 つの疑問があります。

  1. semctl を試すたびに Bus エラーが発生するのはなぜですか (デバッグ行 3 が出力されないため、これが問題の原因であることはわかっています)。また、それを防ぐ方法を教えてください。

  2. semctl() を削除したにもかかわらず、クリティカル セクションのロックを取得できないのはなぜですか?

次のコードを実行しようとしています。

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

#define NUM 3
char c='a';
int semId=-1;
struct sembuf lockOperation = { 0, -1, 0};
struct sembuf unlockOperation = { 0, -1, 0};

void* PrintLetter()
{
  int rc;

  rc=semop(semId, &lockOperation, 1);

  if(rc)
    {
      printf("\n Unable to lock\n");
      exit(1);
    }
  printf("%c",c);    //CRITICAL SECTION
  c=c+1;             //CRITICAL SECTION  
  rc = semop(semId, &unlockOperation, 1);
  if(rc)
    {
      printf("\n Unable to unlock\n");
      exit(1);
    }

  pthread_exit(NULL);

}
int main()
{
  pthread_t threads[NUM];

  int rc=1;
  long t;
   printf("debug line 1\n");
  semId = semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL);
  if( semId == -1)
    {
      printf("\n Error in making the sem\n");
      exit(1);
    }
  printf("debug line 2\n");
  rc = semctl(semId, 0, SETVAL, (int)1); // Comment from here

  if(rc)
    {
      printf("\n Unable to set val to 1\n");
      exit(1);
      }    ////////////////////////////////// till here
   printf("debug line 3\n");


  for(t=0; t<NUM; t++){
    printf("In main: creating thread %ld\n", t);
    rc = pthread_create(&threads[t], NULL, PrintLetter, NULL);
    if (rc){
      printf("ERROR; return code from pthread_create() is %d\n", rc);
      exit(-1);
    }
    sleep(3);
  }
  pthread_exit(NULL);
}

注:提案後にコードに次を追加しました:

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) */
};

また、以下を追加しました。

union semun s_u;
s_u.val=1;

semctl 行を次のように変更しました

rc = semctl(semId, 0, SETVAL, s_u);

すべての rc チェックを次のように行いました。

if(rc == -1)

semctl() 行はまだ正常に実行されません。errno は次のように表示されます: Permission Denied

更新:次の変更を使用して、「アクセス許可が拒否されました」エラーを取り除くことができます。

semId = semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL|0660);

さて、新しい問題は、コンソールに「abc」を出力できないことです。プログラムは単に "a" を出力してハングします。理由がわからない。

最終更新: ロック解除コードを台無しにしました: 1 の代わりに -1 を使用しました 新しいコードは次のとおりです:

struct sembuf unlockOperation = { 0, 1, 0};

皆さんの助けと忍耐に感謝します。

4

3 に答える 3

4

への 4 番目の引数semctl(存在する場合) は、次の型である必要がありますunion semun

union semun {
            int val;
            struct semid_ds *buf;
            unsigned short  *array;
} arg;

代わりに thereを渡すと、intアライメントの問題が発生する可能性があります。

于 2010-02-14T01:59:50.470 に答える
1

他のことを行う前に、エラー処理コードを修正してください。これは間違っています:

rc = semop(semId, &lockOperation, 1);

if (rc)
{
    printf("\n Unable to lock\n");
    exit(1);
}

Semop() と semctl() はエラー時に -1 を返すので、次のようになります。

rc = semctl(semId, 0, SETVAL, (int)1); // Comment from here

if (rc == -1)
{
    perror("SETVAL");
    exit(1);
}

pthread API は成功すると 0 を返し、それ以外の場合はエラー番号を返すため、これは混乱を招きます。混同しやすいので注意が必要です。

于 2010-02-14T02:41:25.420 に答える
0

右辺値 1 ではなく、明示的な semun union を semctl に渡すようにしてください。おそらく問題にはならないはずですが、誰にもわかりません。

于 2010-02-14T01:58:35.910 に答える