linux进程间通信之信号量

XSI信号量

概念:

  • 实现进程间同步
  • 表示系统可用资源的个数

对象:

struct semid_ds {
	struct ipc_perm sem_perm;  /* Ownership and permissions */
	time_t          sem_otime; /* Last semop time */
	time_t          sem_ctime; /* Last change time */
	unsigned long   sem_nsems; /* No. of semaphores in set */
	struct   sem *	sem_base 
};
struct sem{
	int semval  信号量的值
	int sempid  最近一个操作的进程号
}
struct ipc_perm
{
	__kernel_key_t	key;   
	__kernel_uid_t	uid;
	__kernel_gid_t	gid;
	__kernel_uid_t	cuid;
	__kernel_gid_t	cgid;
	__kernel_mode_t	 mode; 
	unsigned short	seq;
};

对象操作

  • 创建对象:
 int semget(key_t k,int n,int semflag);
  • 设置对象:
 int semctl(int sid,int semnum,int cmd,union semun a);

	
	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 如果对于整个信号量集合,则有如下设置方法
IPC_STAT ipc_perm
IPC_SET ipc_perm
IPC_RMID
IPC_INFO 信号量的系统信息

int semctl(int sid,int semnum,int cmd,…);

cmd 如果对于单个信号量集合,则有如下设置方法
GETPID 返回操作IPC的PID
GETVAL 返回操作IPC的VAL
GETALL返回操作IPC的所有值
SETVAL 设置操作IPC的VAL
SETALL 设置操作IPC的所有值

  • 使用对象
int semop(int s,struct sembuf *sb,size _t n);

struct sembuf{
unsigned short int sem_num; 
short int sem_op; 
short int sem_flg;};

sem_op

+ 表示进行加
- 表示进行减

0 表示测试是否为0

  • 如果当前信号量的操作后的值为负数,则进行阻塞,一直到满足条件为止

sem_flg:

IPC_NOWAIT 如果操作信号集合中任意一个失败,立即返回,并且不会对其他的信号量做操作
SEM_UNDO :进程退出后,该进程对sem进行的操作将被撤销


struct sembuf sops[4]
sops[0].sem_num  =1
sops[0].sem_op   =-1			/ P操作/
sops[0].sem_flag  = 0
sops[1].sem_num   =2
sops[1].sem_op    =1		/ V操作/
sops[1].sem_flag  =0

demo

生产者:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
int sem_id;

void init()
{
	key_t key;
	int ret;
	unsigned short sem_array[2];
	union semun 
	{
		int val;
		struct semid_ds *buf;
		unsigned short *array;
	}arg;

	key=ftok(".",'s');

	sem_id=semget(key,2,IPC_CREAT|0644);

	sem_array[0]=0;				//identify the productor
	sem_array[1]=100;			//identify the space
	//printf("set the productor init value is 0\nset the space init value is 100\n");
	arg.array = sem_array;
	ret = semctl(sem_id, 0, SETALL, arg);	
	if (ret == -1) 
		printf("SETALL failed (%d)\n", errno); 
	//printf("\nread the number\n");
	printf("productor init is %d\n",semctl(sem_id,0,GETVAL));
	printf("space init is %d\n\n",semctl(sem_id,1,GETVAL));

}
void del()
{
	semctl(sem_id,IPC_RMID,0);
}
#define produce   1 
#define customer  0
#define P   1 
#define V   0
int main(int argc,char *argv[])
{
	struct sembuf sops[2];
	
	sops[0].sem_num = 0;
	sops[0].sem_op = 1;
	sops[0].sem_flg = 0;

	sops[1].sem_num = 1;
	sops[1].sem_op = -1;
	sops[1].sem_flg = 0;

	init();
	

	printf("this is productor\n");
	while(1)
	{
		printf("\n\nbefore produce:\n");
		printf("productor number is %d\n",semctl(sem_id,0,GETVAL));
		printf("space number is %d\n",semctl(sem_id,1,GETVAL));
		
		//生产者的操作
		semop(sem_id,(struct sembuf *)&sops[P],produce);		//get the space to instore the productor
		printf("now producing......\n");
		semop(sem_id,(struct sembuf *)&sops[V],customer);		//now tell the customer can bu cusume
		printf("\nafter produce\n");
		printf("spaces number is %d\n",semctl(sem_id,1,GETVAL));
		printf("productor number is %d\n",semctl(sem_id,0,GETVAL));
		sleep(4);
	}
	del();
}

消费者:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
int sem_id;

void init()
{
	key_t key;

	key=ftok(".",'s');
	sem_id=semget(key,2,IPC_CREAT|0644);
	//printf("sem id is %d\n",sem_id);
}
#define produce   1 
#define customer  0
#define P   1 
#define V   0
int main(int argc,char *argv[])
{

	init();

	struct sembuf sops[2];
	
	sops[0].sem_num = 0;
	sops[0].sem_op = 1;
	sops[0].sem_flg = 0;

	sops[1].sem_num = 1;
	sops[1].sem_op = -1;
	sops[1].sem_flg = 0;


	printf("this is customer\n");
	while(1)
	{
		printf("\n\nbefore consume:\n");
		printf("productor is %d\n",semctl(sem_id,0,GETVAL));
		printf("space  is %d\n",semctl(sem_id,1,GETVAL));
		
		semop(sem_id,(struct sembuf *)&sops[P],customer);		//get the productor to cusume
		printf("now consuming......\n");
		semop(sem_id,(struct sembuf *)&sops[V],produce);		//now tell the productor can bu produce
		
		printf("\nafter consume\n");
		printf("products number is %d\n",semctl(sem_id,0,GETVAL));
		printf("space number is %d\n",semctl(sem_id,1,GETVAL));
		sleep(3);
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_45309916/article/details/107743027