模型

#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 信号量的更多相关文章

  1. Linux IPC System V 共享内存

    模型 #include<sys/types.h> #include<sys/ipc.h> #include<sys/shm.h> ftok() //获取key值 s ...

  2. Linux IPC System V 消息队列

    模型 #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> ftok() //获取key ...

  3. Linux进程间通信(System V) --- 信号量

    信号量 IPC 原理 信号量通信机制主要用来实现进程间同步,避免并发访问共享资源.信号量可以标识系统可用资源的个数.最简单的信号量为二元信号量 下图为 Linux 信号量通信机制的概念图.在实际应用中 ...

  4. Linux IPC实践(11) --System V信号量(1)

    信号量API #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semget ...

  5. linux网络编程之system v信号量(一)

    今天起,学习信号量相关的知识,下面开始: 关于信号量,在前面已经介绍过了,这里回顾一下: 通过上面的描述,很容易就能想到信号量的一上数据结构: 下面再来回顾一下P.V原语: 所谓的原语就是指这段代码是 ...

  6. Linux中的System V信号量

    在进程同步,并发运行时,保证按序地访问共享资源是十分重要的.因此引入了临界区的概念,一次只能有一个线程进入临界区完成他的指令.而信号量(semaphore)的作用,类似于一个交通信号灯,它负责进程协作 ...

  7. linux网络编程之system v信号量(二)

    今天迎来元旦假期的最后一天了,过得好快~昨天跟小伙伴们在军都滑雪陪儿爽,虽说上了两回中级道都摔得异常的惨烈,但是在初级道上学习"s"转弯还是有一些小心得,可以在要往高手迈进的前提, ...

  8. system V信号量和Posix信号量

    一.函数上的区别 信号量有两种实现:传统的System V信号量和新的POSIX信号量.它们所提供的函数很容易被区分:对于所有System V信号量函数,在它们的名字里面没有下划线.例如,应该是sem ...

  9. System V信号量

    信号量对比 二值信号量:其值要么0要么1,比如互斥锁就是这种类型 计数信号量:其值为0或某个正整数,比如POSIX 信号量 计数信号量:一个或多个信号量构成一个集合,每个都是计数信号量,比如Syste ...

随机推荐

  1. 框架SpringMVC笔记系列 一 基础

    主题:SpringMVC 学习资料参考网址: 1.http://www.icoolxue.com 2.http://aokunsang.iteye.com/blog/1279322 1.SpringM ...

  2. 《Java4Android》视频学习笔记——为什么用抽象类?

    我们来举个例子,然后引出这个问题的答案: 市面上有 喷墨式打印机 和 针式打印机 这两种形式的打印机,我们需要编程来实现他们的 开机,关机以及打印. 构建父类Printer class Printer ...

  3. pm2 配置

    ---恢复内容开始--- 1. ecosystem.json { "apps": [ { "name": "name", // 项目名 &q ...

  4. Windows Git中文文件名乱码

    在Windows下使用git,安装包如下: https://git-for-windows.github.io/ 在使用git bash时git 默认中文文件名是 xx% 是因为 对0x80以上的字符 ...

  5. toastr 自定义提示

    在线实例 实例演示 使用方法 <button type="button" class="btn btn-primary" id="showtoa ...

  6. 15款最佳的MySQL管理工具和应用程序

    工欲善其事,必先利其器.几乎每个开发人员都有最钟爱的 MySQL 管理工具,它帮助开发人员在许多方面支持包括 PostgreSQL,MySQL,SQLite,Redis,MongoDB 等在内的多种数 ...

  7. 【HTML】字符(Glyphs)收集

    Special Characters " " " quotation mark u+0022 ISOnum p:before { content:"\0022& ...

  8. iOS音频开发之`AudioStreamBasicDescription`

    这个类提供了对于音频文件的描述 An audio stream is a continuous series of data that represents a sound, such as a so ...

  9. AS下NDK开发(一)

    捣鼓了一天的NDK,总结下. Eclipse下开发ndk好像挺麻烦的样子,看书上要下载Cygwin,eclipse还要下载插件CDT..而在AS上就方便多啦.下载android ndk.安装,配置环境 ...

  10. Android studio git 本地仓库和远程仓库节点对比

    1.初始状态 2.本地修改文件,然后commit 3.本地再次修改文件,然后commit 4.本地push 从上图可以看出,push完成后,本地仓库的节点和远程仓库的节点是一样的.