Linux IPC System V 信号量
模型
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
ftok()              //获取key
semget()            //创建/获取信号量集
semctl()            //初始化信号量集
semop()             //操作信号量集
semctl()            //删除信号量集
ftok()
//获取key值, key值是System V IPC的标识符,成功返回key,失败返回-1设errno
//同pathname+同 proj_id==>同key_t;
key_t ftok(const char *pathname, int proj_id);
pathname :文件名
proj_id: 1~255的一个数,表示project_id
key_t key=ftok(".",100);	//“.”就是一个存在且可访问的路径, 100是假设的proj_id
	if(-1==key)
		perror("ftok"),exit(-1);
semget():
//创建/获取一个信号量集,成功返回semid,失败返回-1
int semget(key_t key, int nsems, int semflg);
nsems:	信号量集的大小/信号量的个数,0表示获取已经存在的信号量集
semflg
- IPC_CREAT :若不存在则创建, 需要在msgflg中"|权限信息"; 若存在则打开
 - IPC_EXCL :若存在则创建失败
 - 0 :获取已经存在的信号量集
 
//create sem
semid=semget(key,1,IPC_CREAT|IPC_EXCL|0664);
if(-1==semid)
	perror("semid"),exit(-1);
semctl()
//主要用于对指定的信号量集/信号量执行指定的操作,成功返回0,失败返回-1设errno
int semctl(int semid, int semnum, int cmd, ...);
semid:	信号量集的编号(哪个信号量集)
semnum:	信号量集的下标(这个信号量集里的哪个信号量)
cmd:具体的操作命令
- IPC_STAT 将内核中与semid相关的信息拷贝到arg.buf指向的结构体中
 - IPC_SET将buf指向的semid_ds结构体的部分内容写入到内核中的相关数据结构中,同时更新sem_ctime成员
 - IPC_RMID 立即销毁指定的信号量集,调用的进程的的effective UID必须和信号量集的创建者或所有者相匹配,或者这个进程有足够的特权级别,此时第四个参数会被忽略
 - IPC_INFO(Linux-specific)返回系统对信号量集的限制到__buf指向的结构体seminfo中
 
//_GNU_SOURCE
struct  seminfo {
	int 	semmap;  	/* Number of entries in semaphore map; unused within kernel */
	int 	semmni;  	/* Maximum number of semaphore sets */
	int 	semmns; 	/* Maximum number of semaphores in all semaphore sets */
	int 	semmnu;  	/* System-wide maximum number of undo structures; unused within kernel */
	int 	semmsl;  	/* Maximum number of semaphores in a set */
   	int 	semopm;  	/* Maximum number of operations for  semop(2) */
	int 	semume;  	/* Maximum number of undo entries per process; unused within kernel */
 	int 	semusz;  	/* Size of struct sem_undo */
        int 	semvmx;  	/* Maximum semaphore value */
	int 	semaem;  	/* Max. value that can be recorded for semaphore adjustment (SEM_UNDO) */
};
//semmsl, semmns, semopm, semmni可以通过/proc/sys/kernel/sem来设置
- SEM_INFO (Linux-specific)返回和IPC_INFO一样的信息,除了以下方面:semusz成员返回当前系统中存在的信号量集的数目,semaem返回系统中所有信号量集中的信号量总数
 - SEM_STAT(Linux-specific)返回semid_ds结构,类似与IPC_STAT
 - GETALL 返回所有信号量的semval到arg.array中,忽略semnum
 - GETNCNT 返回信号量集第semnum个信号量的semcnt值
 - GETPID 返回信号量集第semnum个信号量的sempid值
 - GETVAL 返回信号量集第semnum个信号量的semval值
 - GETZCNT 返回信号量集第semnum个信号量的semzcnt值
 - SETALL 使用arg.array设置信号量集里的所有的信号量的semval值,同时更新信号量集的semid_ds结构体的sem_ctime成员的值
 - SETVAL返回信号量集第semnum个信号量的semval的值到arg.val中,同时更新信号量集的semid_ds结构体的sem_ctime成员的值
 
the fourth argument:
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) */
};
//<sys/sem.h>
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 short	sem_nsems; 	/* No. of semaphores in set */
};
//<sys/ipc.h>
struct ipc_perm {
	key_t  			__key; 	/* Key supplied to semget(2) */
	uid_t   		uid;   	/* Effective UID of owner */
	gid_t  		 	gid;   	/* Effective GID of owner */
	uid_t   		cuid;  	/* Effective UID of creator */
	gid_t			cgid;  	/* Effective GID of creator */
 	unsigned short 	mode;  	/* Permissions */
   	unsigned short 	__seq; 	/* Sequence number */
};
int res=semctl(semid,0,SETVAL,5);
if(-1==res)
	perror("semctl"),exit(-1);
int res=semctl(semid,0,IPC_RMID);
if(-1==res)
	perror("semctl"),exit(-1);
semop():
//操作指定的信号量集,成功返回0,失败返回-1设errno
int semop(int semid, struct sembuf *sops, unsigned nsops);
semid:信号集的ID(returned by semget())
sops:结构体指针, 既可以指向结构体变量, 也可以指向结构体数组信号量集本质上是若干个信号量的集合, 可以实现对信号量的批处理
struct sembuf{
	unsigned short 	sem_num;	//信号量集的下标
	short          	sem_op; 	//正数表示增加, 0表示不变, 负数表示减小
	short          	sem_flg;	//操作标志,默认给0
}
nsops:结构体指针指向的元素个数, 也就是数组的大小
例子
Sys V IPC sem
#include<unistd.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
int main(){
	//get key
	key_t key=ftok(".",200);
	if(-1==key)
		perror("ftok"),exit(-1);
	printf("key=%d\n",key);
	//create sem
	int semid=semget(key,0,0);
	if(-1==semid)
		perror("semget"),exit(-1);
	printf("semid=%d\n",semid);
	//creat 10 children to take the shared resource
	int i=0;
	for(i=0;i<10;i++){		//创建10个进程, 当然,需要只给parent或child单独fork(), 否则就是2^10个进程
		pid_t pid=fork();
		if(-1==pid)
			perror("fork"),exit(-1);
		if(0==pid){
			struct sembuf buf;		//准备占用资源, sem_op-1
			buf.sem_num=0;		//信号量集下标
			buf.sem_op=-1;		//信号量-1
			buf.sem_flg=0;		//操作标志
			int res=semop(semid,&buf,1/*结构体变量的个数*/);
			if(-1==res)
				perror("semop"),exit(-1);
			sleep(20);			//模拟正在占用共享资源
			buf.sem_op=1;		//占用完了, sem_op+1
			res=semop(semid,&buf,1);
			if(-1==res)
				perror("semop"),exit(-1);
			exit(0);				//终止子进程, 自然也就跳出了循环,防止再fork()
		//	break;
		}
	}
	return 0;
}
//出现抢占的效果, 还没有全部释放完毕的时候就有进程抢到了已经释放的进程
												
											Linux IPC System V 信号量的更多相关文章
- Linux  IPC System V 共享内存
		
模型 #include<sys/types.h> #include<sys/ipc.h> #include<sys/shm.h> ftok() //获取key值 s ...
 - Linux IPC System V  消息队列
		
模型 #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> ftok() //获取key ...
 - Linux进程间通信(System V) --- 信号量
		
信号量 IPC 原理 信号量通信机制主要用来实现进程间同步,避免并发访问共享资源.信号量可以标识系统可用资源的个数.最简单的信号量为二元信号量 下图为 Linux 信号量通信机制的概念图.在实际应用中 ...
 - Linux IPC实践(11) --System V信号量(1)
		
信号量API #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semget ...
 - linux网络编程之system v信号量(一)
		
今天起,学习信号量相关的知识,下面开始: 关于信号量,在前面已经介绍过了,这里回顾一下: 通过上面的描述,很容易就能想到信号量的一上数据结构: 下面再来回顾一下P.V原语: 所谓的原语就是指这段代码是 ...
 - Linux中的System V信号量
		
在进程同步,并发运行时,保证按序地访问共享资源是十分重要的.因此引入了临界区的概念,一次只能有一个线程进入临界区完成他的指令.而信号量(semaphore)的作用,类似于一个交通信号灯,它负责进程协作 ...
 - linux网络编程之system v信号量(二)
		
今天迎来元旦假期的最后一天了,过得好快~昨天跟小伙伴们在军都滑雪陪儿爽,虽说上了两回中级道都摔得异常的惨烈,但是在初级道上学习"s"转弯还是有一些小心得,可以在要往高手迈进的前提, ...
 - system V信号量和Posix信号量
		
一.函数上的区别 信号量有两种实现:传统的System V信号量和新的POSIX信号量.它们所提供的函数很容易被区分:对于所有System V信号量函数,在它们的名字里面没有下划线.例如,应该是sem ...
 - System V信号量
		
信号量对比 二值信号量:其值要么0要么1,比如互斥锁就是这种类型 计数信号量:其值为0或某个正整数,比如POSIX 信号量 计数信号量:一个或多个信号量构成一个集合,每个都是计数信号量,比如Syste ...
 
随机推荐
- [javaEE] 反射-通过反射了解集合泛型本质
			
java中的泛型是防止错误输入的,只在编译时刻起作用 package com.tsh.reflect; import java.lang.reflect.Method; import java.uti ...
 - python队列Queue
			
Queue Queue是python标准库中的线程安全的队列(FIFO)实现,提供了一个适用于多线程编程的先进先出的数据结构,即队列,用来在生产者和消费者线程之间的信息传递 基本FIFO队列 clas ...
 - Linux学习笔记16--Linux扩展权限
			
默认权限: 每一个终端都有一个umask属性,用于确定新建文件.新文件夹的默认权限. umask使用数字权限方式表示,如:022 一般来说,普通用户的默认umask是002,root用户的默认um ...
 - 成为 Web 开发大师你必须知道的 7 件事情
			
曾经是这样的,懂点编码,并可以偶尔耍点酷,那么你就会被认为是一个Web开发大师.但是现在,情况再也不是这样的了.Web开发已经朝着主流方向发展,开发人员数量显著增加.这意味着,如果你想成为这个领域的大 ...
 - C#如何在DataGridViewCell中自定义脚本编辑器
			
上一篇博文探讨了如何自定义DataGridViewColumn实现一个TreeViewColumn来在DataGridView控件中显示TreeView控件,其实我们还可以继续发挥想象,自定义其他的列 ...
 - ESLint – 可扩展的 JavaScript & JSX 校验工具
			
ESLint 是一个开源的 JavaScript 代码校验工具,最初是由 Nicholas C. Zakas 在2013年创建的.经常被用来发现问题的模式或代码,不符合特定的风格准则. ESLint ...
 - Git正确的协作方式(很简单)
			
最近部门有人书写了一篇很好的Git协作方式,操作也简单,分支能以保持一条干净的线进行协作开发.这里做个笔记,方便之后查看. PS:本文非原创. 原则 不过分相信自己,自己的修改,可能影响所有人 不过分 ...
 - 马旭飞:共探H3 BPM社区发展战略
			
近日,以"让天下没有难用的流程"为主题,H3 BPM10.0在北京金隅喜来登酒店正式发布. H3 BPM全新的业务流程管理系统是颠覆BPM行业的巨作,拥有众多独创技术,近200个业 ...
 - Snort - manual 笔记(四)
			
1.7 Basic Output Snort可以做很多任务, 并且在任务完成后输出很多有用的统计信息. 一些不用说明就可以看懂, 其他的总结在这里, 不过只是一些基本的 1.7.1 Timing St ...
 - [SQL] SQL Server 触发器
			
触发器是一种特殊类型的存储过程,它不同于之前的我们介绍的存储过程.触发器主要是通过事件进行触发被自动调用执行的.而存储过程可以通过存储过程的名称被调用. Ø 什么是触发器 触发器对表进行插入.更新.删 ...