Ошибка шины с семафором func semctl () в этом коде, работающем на Solaris - PullRequest
1 голос
/ 14 февраля 2010

Это моя первая попытка семафоров и потоков. Я построил этот код из примеров и страниц руководства, найденных в сети. У меня есть два сомнения с этим кодом.

  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» на консоли. Программа просто печатает "а" и зависает. Не уверен почему.

Окончательное обновление : Я запутался в коде разблокировки: я использовал -1 вместо 1 Вот новый код:

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

Благодарю всех за помощь и терпение.

Ответы [ 3 ]

3 голосов
/ 14 февраля 2010

Четвертый аргумент semctl (если имеется) должен иметь тип union semun:

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

Возможно, пропуск int вызывает проблемы с выравниванием.

1 голос
/ 14 февраля 2010

Прежде чем что-либо делать, исправьте свой код обработки ошибок. Это неправильно:

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 в случае успеха и номер ошибки в противном случае. Их легко запутать, поэтому будьте осторожны.

0 голосов
/ 14 февраля 2010

Попробуйте передать явное semun union в semctl, а не в rvalue 1. Возможно, это не имеет значения, но кто знает.

...