自学Linux--semaphore

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) */
           };

cmd :
GETVAL        返回旗语的值
SETVAL        设置旗语的值
GETPID        返回对旗语进行上一次操作(semop)的进程的ID
GETNCNT       返回正在等待这个旗语的值增加的进程个数
GETZCNT       返回正在等待这个旗语的值变成零的进程的个数
GETALL        返回旗语数组中每个旗语的值
SETALL        设置旗语数组中每个旗语的值
IPC_STAT      返回有效用户,用户组以及旗语的权限
IPC_SET       设置有效用户,用户组以及旗语的权限
IPC_RMID      移除旗语或旗语数组

semop : 获取或释放旗语
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 */
}


semaphore实例:
#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 ..

和Message queue一样,Semaphore也可以使用ipcs命令行工具,只是选项变成 -s 这里就不介绍了,详情可参考Message queue相关内容。


你可能感兴趣的:(自学Linux--semaphore)