semaphore API:
semget : 创建一个新的旗语 or 取得一个已有的旗语的描述符
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
int semget(key_t key , int nsems ,int semflg) ;
semctl : 取得旗语的消息 or 释放旗语 or 移除旗语
int semctl(int semid ,int semnum ,int cmd , ...) ;
This function has three or four arguments, depending on cmd. When there are four, the fourth has the type union semun. The calling program must define this union as follows:
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) */
};
GETVAL 返回旗语的值
SETVAL 设置旗语的值
GETPID 返回对旗语进行上一次操作(semop)的进程的ID
GETNCNT 返回正在等待这个旗语的值增加的进程个数
GETZCNT 返回正在等待这个旗语的值变成零的进程的个数
GETALL 返回旗语数组中每个旗语的值
SETALL 设置旗语数组中每个旗语的值
IPC_STAT 返回有效用户,用户组以及旗语的权限
IPC_SET 设置有效用户,用户组以及旗语的权限
IPC_RMID 移除旗语或旗语数组
int semop(int semid ,struct sembuf *sops, unsigned nsops) ;
struct sembuf{
unsigned short semval; /* semaphore value */
unsigned short semzcnt; /* # waiting for zero */
unsigned short semncnt; /* # waiting for increase */
pid_t sempid; /* process that did last op */
}
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<errno.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#include<time.h>
#include<unistd.h>
#include<sys/wait.h>
#define MAX_SEMAPHORE 10
#define FILE_NAME "test.c"
union semun{
int val ;
struct semid_ds *buf ;
unsigned short *array ;
struct seminfo *_buf ;
}arg;
struct semid_ds sembuf;
int main()
{
key_t key ;
int semid ,ret,i;
unsigned short buf[MAX_SEMAPHORE] ;
struct sembuf sb[MAX_SEMAPHORE] ;
pid_t pid ;
pid = fork() ;
if(pid < 0)
{
/* Create process Error! */
fprintf(stderr,"Create Process Error!:%s\n",strerror(errno));
exit(1) ;
}
if(pid > 0)
{
/* in parent process !*/
key = ftok(FILE_NAME,'a') ;
if(key == -1)
{
/* in parent process*/
fprintf(stderr,"Error in ftok:%s!\n",strerror(errno));
exit(1) ;
}
semid = semget(key,MAX_SEMAPHORE,IPC_CREAT|0666);
if(semid == -1)
{
fprintf(stderr,"Error in semget:%s\n",strerror(errno));
exit(1) ;
}
printf("Semaphore have been initialed successfully in parent process,ID is :%d\n",semid);
sleep(2) ;
printf("parent wake up....\n");
/*父进程在子进程得到semaphore的时候请求semaphore,此时父进程将阻塞直至子进程释放掉semaphore*/
/* 此时父进程的阻塞是因为semaphore 1 不能申请,因而导致的进程阻塞*/
for(i=0;i<MAX_SEMAPHORE;++i)
{
sb[i].sem_num = i ;
sb[i].sem_op = -1 ; /*表示申请semaphore*/
sb[i].sem_flg = 0 ;
}
printf("parent is asking for resource...\n");
ret = semop(semid , sb ,10) ;
if(ret == 0)
{
printf("parent got the resource!\n");
}
/* 父进程等待子进程退出 */
waitpid(pid,NULL,0);
printf("parent exiting .. \n");
exit(0) ;
}
else
{
/* in child process! */
key = ftok(FILE_NAME,'a') ;
if(key == -1)
{
/* in child process*/
fprintf(stderr,"Error in ftok:%s!\n",strerror(errno));
exit(1) ;
}
semid = semget(key,MAX_SEMAPHORE,IPC_CREAT|0666);
if(semid == -1)
{
fprintf(stderr,"Error in semget:%s\n",strerror(errno));
exit(1) ;
}
printf("Semaphore have been initialed successfully in child process,ID is:%d\n",semid);
for(i=0;i<MAX_SEMAPHORE;++i)
{
/* Initial semaphore */
buf[i] = i + 1 ;
}
arg.array = buf ;
ret = semctl(semid , 0, SETALL,arg);
if(ret == -1)
{
fprintf(stderr,"Error in semctl in child:%s!\n",strerror(errno));
exit(1) ;
}
printf("In child , Semaphore Initailed!\n");
/*子进程在初始化了semaphore之后,就申请获得semaphore*/
for(i=0;i<MAX_SEMAPHORE;++i)
{
sb[i].sem_num = i ;
sb[i].sem_op = -1 ;
sb[i].sem_flg = 0 ;
}
ret = semop(semid , sb , 10) ;
if( ret == -1 )
{
fprintf(stderr,"子进程申请semaphore失败:%s\n",strerror(errno));
exit(1) ;
}
printf("child got semaphore,and start to sleep 3 seconds!\n");
sleep(3) ;
printf("child wake up .\n");
for(i=0;i < MAX_SEMAPHORE;++i)
{
sb[i].sem_num = i ;
sb[i].sem_op = +1 ;
sb[i].sem_flg = 0 ;
}
printf("child start to release the resource...\n");
ret = semop(semid, sb ,10) ;
if(ret == -1)
{
fprintf(stderr,"子进程释放semaphore失败:%s\n",strerror(errno));
exit(1) ;
}
ret = semctl(semid ,0 ,IPC_RMID);
if(ret == -1)
{
fprintf(stderr,"semaphore删除失败:%s!\n",strerror(errno));
exit(1) ;
}
printf("child exiting successfully!\n");
exit(0) ;
}
return 0;
}
运行结果:
root@ubuntu:~$ ./test
Semaphore have been initialed successfully in parent process,ID is :589825
Semaphore have been initialed successfully in child process,ID is:589825
In child , Semaphore Initailed!
child got semaphore,and start to sleep 3 seconds!
parent wake up....
parent is asking for resource...
child wake up .
child start to release the resource...
child exiting successfully!
parent got the resource!
parent exiting ..