关于信号量的定义和系统调用,可以查看这篇博文:点击打开链接
其中,注意一点就是:在编译信号量程序时,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); }