2

这是我对信号量和线程的第一次尝试。我根据示例和网上找到的手册页构建了这段代码。我对这段代码有两个疑问。

  1. 为什么每次尝试 semctl 时都会出现总线错误(我知道这是问题的根源,因为没有打印调试行 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 现在状态:权限被拒绝

更新:我可以使用以下更改摆脱“权限被拒绝”错误:

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

现在,新问题是,我无法在控制台上打印“abc”。该程序只打印“a”并挂起。不知道为什么。

最终更新:我在解锁代码中搞砸了:我使用 -1 而不是 1 这是新代码:

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

我感谢大家的帮助和耐心。

4

3 回答 3

4

(如果存在)的第四个参数semctl应该是类型union semun

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

也许通过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

尝试将显式 semun union 传递给 semctl,而不是 rvalue 1。可能无关紧要,但谁知道呢。

于 2010-02-14T01:58:35.910 回答