关于信号量的定义和系统调用,可以查看这篇博文:点击打开链接
其中,注意一点就是:在编译信号量程序时,semctl 函数,其中一个参数是union semun 联合体。但是在编译时,union semun _semval; 这段声明联合体的代码却报错:storage size of '_semval' isn't known. 查看semctl手册,在Notes中可以看到这么一段:In some earlier versions og glibc,the semun union was defined in <sys/sem.h>,but POSIX.1-2001 requires that the caller define this union.On versions of glibc where this union is not defined, the macro _SEM_SEMUN_UNDEFINED is defined in <sys/sem.h>。因此,该问题的解决方案就是测试宏,如果定义了该宏,则自己在程序中定义union semun 结构体。
下面是自己写的示例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
void my_err(char *);
int semphore_p(int);
int semphore_v(int);
#ifdef _SEM_SEMUN_UNDEFINED
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
#endif
int main(void)
{
printf("start\n");
key_t key;
int semid;
pid_t pid;
if((key=ftok("/tmp/test_sem.c",0))==-1)
my_err("ftok error");
if((semid=semget(key,1,IPC_CREAT))==-1)
my_err("semget error");
union semun semun_val;
semun_val.val=1;
if(semctl(semid,0,SETVAL,semun_val)==-1)
my_err("semctl set error");
if((pid=fork())==-1)
my_err("fork error");
else if(pid==0)
{
sleep(1);
if(semphore_p(semid)==-1)
my_err("child semphore_p error");
printf("child\n");
if(semphore_v(semid)==-1)
perror("semor child error.....");
printf("child will exit\n");
exit(0);
}
else
{
if(semphore_p(semid)==-1)
my_err("parent semphore_p error");
printf("parent\n");
sleep(3);
if(semphore_v(semid)==-1)
my_err("parent semphore_v error");
}
printf("parent will sleep,after wake,sem will be removed\n");
sleep(2);
if(semctl(semid,0,IPC_RMID,NULL)==-1)
my_err("semctl rm error");
printf("end\n");
exit(0);
}
//P操作,申请一个资源单位
int semphore_p(int semid)
{
struct sembuf _sembuf;
_sembuf.sem_num=0;
_sembuf.sem_op=-1;
_sembuf.sem_flg=SEM_UNDO;
if(semop(semid,&_sembuf,1)==-1)
return -1;
return 0;
}
//V操作,释放一个资源单位
int semphore_v(int semid)
{
struct sembuf _sembuf;
_sembuf.sem_num=0;
_sembuf.sem_op=1;
_sembuf.sem_flg=IPC_NOWAIT;
if(semop(semid,&_sembuf,1)==-1)
return -1;
return 0;
}
void my_err(char *str)
{
printf("Line:%d,",__LINE__);
perror(str);
exit(1);
}