【问题标题】:Bus error with semaphore func semctl() in this code running on Solaris在 Solaris 上运行的此代码中,信号量 func semctl() 出现总线错误
【发布时间】:2011-01-16 14:53:22
【问题描述】:

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

  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};

感谢大家的帮助和耐心。

【问题讨论】:

  • 注意:我想得到我的最终输出为 abc
  • @Carl:我使用的是 Solaris 机器。我在 linux 机器上尝试了同样的方法,得到了同样的“总线错误”。
  • 我尝试添加以下行: union semun s_u; s_u.val=1; rc = semctl(semId, 0, SETVAL, s_u);我收到以下错误:sem.c:42: error: storage size of 's_u' is not known
  • 注意:我在 Linux 机器上尝试了相同的代码。 semctl() 失败并以 printf("\n Unable to set val to 1\n"); 退出

标签: c multithreading unix semaphore


【解决方案1】:

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

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

也许传递int 会导致对齐问题。

【讨论】:

  • @Alex:我尝试添加以下行: union semun s_u; s_u.val=1; rc = semctl(semId, 0, SETVAL, s_u);我收到以下错误:sem.c:42: error: storage size of 's_u' is not known
  • @tomkaith,那个错误信息告诉你你没有阅读(或理解)手册页,见docs.sun.com/app/docs/doc/816-5167/semctl-2?a=view:"""type union semun,必须由应用程序显式声明.""" -- 应用显式声明,明白了吗?
  • @Alex:谢谢。我现在定义了联合......但我的 semctl() 仍然失败,并显示“无法将 val 设置为 1”消息。关于为什么我无法将其设置为 sem val 的任何想法?
  • 另见 POSIX 标准 (opengroup.org/onlinepubs/9699919799/toc.htm),它说了同样的话。这是原始 System V IPC 实现中的怪异强加给 POSIX 的怪异。我想不出用户必须使用但也必须定义的 POSIX 中的任何其他类型。
  • 产生错误信息时'rc'的值是多少。如果它失败了,它应该是 -1 并且 errno 应该告诉你更多。
【解决方案2】:

在您执行任何其他操作之前,请更正您的错误处理代码。这是错误的:

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,否则返回错误号。很容易让他们混淆,所以要小心。

【讨论】:

  • @Duck:感谢您的建议.. 我适当地更改了我的代码。下次会记住的。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-31
    • 2017-10-16
    • 2013-02-05
    • 2020-07-29
    • 1970-01-01
    • 1970-01-01
    • 2021-04-14
    相关资源
    最近更新 更多