2014-02-28 24 views
1

我想學習如何使用信號量和我從here添加了一些新取自here的shmat()失敗,「標識符去掉」

/* 
** semdemo.c -- demonstrates semaphore use as a file locking mechanism 
*/ 

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 
#include <sys/types.h> 
#include <sys/ipc.h> 
#include <sys/sem.h> 
#include "parameter.h" 

#define MAX_RETRIES 10 

union semun { 
    int val; 
    struct semid_ds *buf; 
    ushort *array; 
}; 

/* 
** initsem() -- more-than-inspired by W. Richard Stevens' UNIX Network 
** Programming 2nd edition, volume 2, lockvsem.c, page 295. 
*/ 
char *shm; 

int initsem(key_t key, int nsems) /* key from ftok() */ { 
    int i; 
    union semun arg; 
    struct semid_ds buf; 
    struct sembuf sb; 
    int semid; 

semid = semget(key, nsems, IPC_CREAT | IPC_EXCL | 0666); 

if (semid >= 0) { /* we got it first */ 
    sb.sem_op = 1; 
    sb.sem_flg = 0; 
    arg.val = 1; 

    printf("press return\n"); 
    getchar(); 

    for (sb.sem_num = 0; sb.sem_num < nsems; sb.sem_num++) { 
     /* do a semop() to "free" the semaphores. */ 
     /* this sets the sem_otime field, as needed below. */ 
     if (semop(semid, &sb, 1) == -1) { 
      int e = errno; 
      semctl(semid, 0, IPC_RMID); /* clean up */ 
      errno = e; 
      return -1; /* error, check errno */ 
     } 
    } 
    if ((shm = (char*) shmat(semid, NULL, 0)) == (char *) -1) { 
     perror("shmat"); 
     exit(1); 
    } 
} else if (errno == EEXIST) { /* someone else got it first */ 
    int ready = 0; 

    semid = semget(key, nsems, 0); /* get the id */ 
    if (semid < 0) return semid; /* error, check errno */ 

    /* wait for other process to initialize the semaphore: */ 
    arg.buf = &buf; 
    for (i = 0; i < MAX_RETRIES && !ready; i++) { 
     semctl(semid, nsems - 1, IPC_STAT, arg); 
     if (arg.buf->sem_otime != 0) { 
      ready = 1; 
     } else { 
      sleep(1); 
     } 
    } 
    if (!ready) { 
     errno = ETIME; 
     return -1; 
    } 
    if ((shm = shmat(semid, NULL, 0)) < 0) { 
     perror("shmat"); 
     exit(1); 
    } 
} else { 
    return semid; /* error, check errno */ 
} 

return semid; 
} 

int main(void) { 
key_t key; 
int semid; 
struct sembuf sb; 

sb.sem_num = 0; 
sb.sem_op = -1; /* set to allocate resource */ 
sb.sem_flg = SEM_UNDO; 

key = KEY; 

/* grab the semaphore set created by seminit.c: */ 
if ((semid = initsem(key, 1)) == -1) { 
    perror("initsem"); 
    exit(1); 
} 

printf("Press return to lock: "); 
getchar(); 
printf("Trying to lock...\n"); 

if (semop(semid, &sb, 1) == -1) { 
    perror("semop"); 
    exit(1); 
} 

printf("Locked.\n"); 
printf("Press return to unlock: "); 
getchar(); 

sb.sem_op = 1; /* free resource */ 
if (semop(semid, &sb, 1) == -1) { 
    perror("semop"); 
    exit(1); 
} 

printf("Unlocked\n"); 

return 0; 
} 

parameter.h下面的代碼

#ifndef PARAMETER_H 
#define PARAMETER_H 

#define KEY 91234567 
#define SHM_SIZE 1024 

#endif /* PARAMETER_H */ 

當我嘗試使用shmat時,我收到「標識已移除」錯誤。我究竟做錯了什麼?我該如何解決它。請幫忙。

回答

1

此呼叫

if (-1 == semctl(semid, 0, IPC_RMID)) /* clean up */ 

去除信號標識,以通過下面的呼叫給予shmat()誤差是可以預料的。


而且代碼似乎缺少

#include <sys/shm.h> 

最後這個調用

if ((shm = shmat(semid, NULL, 0)) < 0) { 

應該

if ((shm = shmat(semid, NULL, 0)) == (char*) -1) { 
+0

不,我小號直到得到相同的錯誤... –

+0

@SpyrosNonServiam:你在哪個平臺上觀察這個,使用哪個編譯器? – alk

+0

@SpyrosNonServiam:請參閱我更新的答案。 – alk