IPC: 信号量

###################################################

信号量

信号量:在多线程环境下,用来保证多个关键代码不被并发调用,一次只能有个一个线程访问关键代码。

信号量有两组函数接口:

1.posix信号量

2.system v信号量

信号量的两种形式:

1.二进制信号量:用来保护一段代码,使其每次只能被一个执行线程运行,初始值一般为1.

2.计数信号量:有限数目的线程执行一段指定的代码,初始值一般大于1.

-----------------------------------------------------------

posix信号量:

posix信号量分两种:

1.posix有名信号量,一般用在无亲缘关系的进程间。

2.posix基于内存的信号量(无名信号量),一般用在不需要使用与有名信号量关联的名字。

gcc - lpthread

#include <semaphore.h>

#include <fcntl.h>

#include <sys/stat.h>

sem_t *sem_open(const char*name, int oflag);

打开一个已存在的有名信号量。

sem_t *sem_open(const char*name, int oflag, mode_t mode, unsigned int value);

创建一个有名信号量。

value:信号量初始值。

int
sem_close
(sem_t *sem);

关闭有名信号量

int
sem_unlink
(const char*name);

删除有名信号量

int
sem_init
(sem_t *sem, int pshared, unsigned int value);

初始化无名(基于内存)信号量;

pshared:

0:信号量在同一个进程间的线程间共享

非0:在进程间共享信号量

value:信号量的初始值

int
sem_destroy
(sem_t *sem);

销毁无名(基于内存)信号量

信号量等待操作,在使用信号量之前调用:

int
sem_wait
(sem_t *sem);

如果信号量值大于0,就减去1然后返回,如果信号量值等于0,就阻塞。

int sem_trywait(sem_t *sem);

等待操作的非阻塞版本,如果信号量值等于0,立即返回错误。

int sem_timedwait(sem_t *sem, conststruct timespec *abs_timeout);

阻塞指定的时间。

信号量挂出操作,在使用信号量之后调用

int
sem_post
(sem_t *sem);

将信号量的值加1.

获取信号量的值

int
sem_getvalue
(sem_t *sem,int *sval);

返回信号量的当前值放入sval中,如果信号量已上锁返回0或某个负数,负数的绝对值表示等待该信号量解锁的进程数。

SEM_NSEMS_MAX:一个进程可以同时打开的最大信号量数目。

SME_VALUE_MAX:一个信号量的最大值。

-----------------------------------------------------------

system v信号量:

#include <sys/ipc.h>

#include <sys/sem.h>

#include <sys/types.h>

内核位system V维护一个信号量结构:

struct semid_ds {

struct ipc_permsem_perm;

struct sem*sem_base;//指向信号量集

ushort sem_nsems;//初始化为nsems

time_t sem_otime;//初始化为0

time_t sem_ctime;//初始化为当前时间

}

struct sem {

ushort_t semval; //信号量的值

short sempid; //对semval值进行最后一次操作的进程ID

ushort_t semncnt;//等待semval变为大于其当前值的线程数。

ushort_t semzcnt;//等待semval变为0的线程数。

}

int semget(key_t key, int nsems, int semflg);

创建一个信号量集或访问一个已存在的信号量集,返回信号量标识符。

key:既可以是ftok的返回值,也可以是IPC_PRIVATE.

nsems:

指定集合中的信号量数,访问一个已存在信号量就置0.

semflg:

semflg: 可以用读写权限 或 其它可选权限。

0:打开已存在的

属主:SEM_R        SEM_A

属组:SEM_R >> 3   SEM_A >> 3

其它:SEM_R >> 6   SEM_A >> 6

IPC_CREAT:不存在就创建,存在就返回已存在的。

IPC_CREAT | IPC_EXCL:不存在就创建,存在就返回错误。

int semop(int semid, struct sembuf *sops, unsignednsops);

对信号量的操作,sops指向一个结构数组,nsops是数组元素个数。

struct sembuf {

unsigned shortsem_num; //0-nsems 指定某个信号量

short sem_op;

short sem_flg;

};

sem_op: 决定做什么操作

0:等待semval变为0

1(正数):将该值加到semval上,如果semval已经为0,就返回。

-1(负数):等待semval变为大于或等于该值的绝对值。

sem_flg:

IPC_NOWAIT:给定信号量非阻塞

SEM_UNDO:指定该标识,semadj才会更新,

int semctl(int semid, int semnum, int cmd, (union semunarg …);

对一个信号量执行各种控制操作,semnum为0-nsems 为指定的某个信号量。

第四个参数由第三个参数决定,这个结构需要自己定义

union semun {

int val;//SETVAL

struct semid_ds*buf;//IPC_SET IPC_STAT

ushort*array;//GETALL SETALL

} arg;

cmd:命令执行成功函数返回0,失败函数返回-1:

GETVAL:获取semval的值返回

GETPID:把sempid的当前值作为函数返回值

GETNCNT:把semncnt的当前值作为函数返回值

GETZCNT:把semzcnt的当前值作为函数返回值

IPC_RMID:把semid指定的信号量集从系统中删除

cmd取下列值才有第四个参数arg:

GETALL:通过arg.array返回指定信号量集内每个成员的semval。

SETALL:将arg.array中的值赋给信号量集中的每个semval。

SETVAL:将arg.val的值赋给semval。

IPC_STAT:通过arg.buf获取指定信号量集中当前semid_ds结构。

IPC_SET:用arg.buf设置指定信号集中semid_ds结构中的ipc_perm结构的三个成员。

时间: 2024-11-06 13:26:04

IPC: 信号量的相关文章

linux进程间通讯-System V IPC 信号量

进程间通信的机制--信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信--使用信号.下面就进入信号量的讲解. 一.什么是信号量 为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域.临界区域是指执行数据更新的代码需要独占式地执行.而信号量就可以提供这样的一种访问机制,让一个临界区同一时间只有一个线程在

IPC——信号量

这篇文章将讲述别一种进程间通信的机制——信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信——使用信号.下面就进入信号量的讲解. 一.什么是信号量 为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域.临界区域是指执行数据更新的代码需要独占式地执行.而信号量就可以提供这样的一种访问机制,让一个临界区同

Linux中IPC信号量的使用

信号量是用来解决进程间的同步与互斥问题的一种进程间通信机制,包括一个称为信号量的变量和在该信号量下等待资源的进程等待队列,以及对信号量进行的两个原子操作(P/V操作).其中,信号量对应于某一种资源,取一个非负的整形值.信号量值(常用sem_id表示)指的是当前可用的该资源的数量,若等于0则意味着目前没有可用的资源. PV原子操作(很重要的) PV原子操作的具体定义如下:(好好理解,很重要的啊) ●  P操作:如果有可用的资源(信号量值>0),则此操作所在的进程占用一个资源(此时信号量值减1,进入

从并发处理谈PHP进程间通信(二)System V IPC

.container { margin-right: auto; margin-left: auto; padding-left: 15px; padding-right: 15px } .container::before,.container::after { content: " "; display: table } .container::after { clear: both } .container::before,.container::after { content:

Linux多线程编程-信号量

在Linux中,信号量API有两组,一组是多进程编程中的System V IPC信号量:另外一组是我们要讨论的POSIX信号量.这两组接口类似,但不保证互换.POSIX信号量函数都已sem_开头,并不像大多数线程函数那样以pthread_开头,常用的有以下5个: #include <semaphore.h> int sem_init(sem_t* sem, int pshared, unsigned int value); int sem_destroy(sem_t *sem); int se

信号量&amp;读写信号量&amp;完成变量

Linux提供两种信号量: 1.内核信号量,由内核控制路径使用 2.System V IPC信号量,由用户态进程使用 从本质上说,它们实现了一个加锁原语,即让等待者睡眠,直到等待的资源变为空闲. 信号量 内核信号量类似于自旋锁,因为当锁关闭着的时候,它不允许内核控制路径继续运行.然而,当内核内核控制路径试图获取内核信号量所保护的忙资源时,相应的进程被挂起.只有在资源被释放时,进程才再次变为可运行的. 因此,只有可以睡眠的函数才能获取内核信号量:中断处理程序和可延迟处理函数都不能使用内核信号量.

itop-4412开发板使用第一篇-信号量的学习使用(未完待续)

1. 本次基于itop-4412研究下Linux信号量的使用方法. 2. 创建信号量的函数,信号量的头文件在那个路径?编译应用程序的话,头文件有3个路径,内核源码头文件,交叉编译器头文件,ubuntu的头文件,不是很理解为啥交叉编译器也需要头文件,全用内核源码不行吗?书上说内核信号量和用户空间信号量(也叫IPC信号量)有区别的,前者用于内核同步,后者用于用户进程间同步.下面的函数是创建或者寻找信号量,在IPC信号量是一组的,内核信号量是一个的. sem_id = semget((key_t)12

【转】高通平台android 环境配置编译及开发经验总结

原文网址:http://blog.csdn.net/dongwuming/article/details/12784535 1.高通平台android开发总结 1.1 搭建高通平台环境开发环境 在高通开发板上烧录文件系统 建立高通平台开发环境 高通平台,android和 modem 编译流程分析 高通平台 7620 启动流程分析 qcril 流程分析,设置sim卡锁 python scons 语法学习 Python 语言之 scons 工具流程分析: 1.2 搭建高通平台环境开发环境 高通and

Linux工具参考篇(网摘)

Linux工具参考篇 原文出处:[Linux Tools Quick Tutorial] 1. gdb 调试利器 2. ldd 查看程序依赖库 3. lsof 一切皆文件 4. ps 进程查看器 5. pstack 跟踪进程栈 6. strace 跟踪进程中的系统调用 7. ipcs 查询进程间通信状态 8. top linux下的任务管理器 9. free 查询可用内存 10. vmstat 监视内存使用情况 11. iostat 监视I/O子系统 12. sar 找出系统瓶颈的利器 13.

内核同步

1.内核如何为不同的请求提供服务 (1)内核抢占:如果一个进程还在处理一个异常的时候,分配给它的时间片到期了,会发生什么事情呢?这取决于有没有启用内核抢占(Kernel Preemption),如果没有启用,进程就继续处理异常,如果启用了,进程可能会立即被抢占,异常的处理也就暂停了,直到schedule()再度选择原先那个进程(注意:内核处理中断的时候,必然会禁用内核抢占,所以这里才说是异常). 内核抢占的目的是减少用户态进程的分派延迟. 2.同步原语 3.每CPU变量: 4.原子操作 5.优化