SYSTEM V IPC——信号量笔记
来源:互联网 发布:索尼自家应用商店软件 编辑:程序博客网 时间:2024/05/21 17:28
一、概念
system v的信号量实质是一个计数器,用于多进程对共享数据对象的访问。
二、工作流程
为了获得共享资源,进程需要执行下列操作:
1.测试控制该资源的信号量
2.若此信号的值为正,则进程可以使用该资源,并对该信号量的值减1,表示消耗了一个资源单位。至第三步。
若此信号量的值为0,则进入休眠状态,直至信号量大于0。进程被唤醒后,返回至第一步。
3.当进程使用完该资源以后,需要释放一个信号量,即对这个信号量的值加1操作。如果有进程正在休眠等待此信号量,则唤醒他们。
备注:为了正确的实现信号量,信号量值的测试、加1、减1操作是原子操作。所以,信号量通常是在内核实现的。
三、相关函数
1.semget
获得一个信号量集ID
#include <sys/sem.h>
int semget(key_t key, int nsems, int flag);
key是个什么东西?
nsems表示这个信号量集里面包含的信号量数
flag表示属性,第一次创建用IPC_CREAT
成功返回信号量ID,错误返回-1
2.semctl
设置初值或者删除等操作
int semctl(int semid, int semnum, int cmd, ...);
semid是信号量ID,就是semget的返回值;
semnum表示信号量集中的第几个信号量(0 <= semnum <= nsems )
cmd是控制指令:IPC_STAT、IPC_SET(设置初值)、IPC_RMID(删除信号量集)、GETVAL、SETVAL、GETALL……
...表示一个枚举,semun
返回值:除GETALL以外的GET命令的返回相应的值,其他成功0,失败-1
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
};
3.semop
加1或减1操作
int semop(int semid, struct sembuf semoparray[], size_t nops);
semid为信号量ID
semoparray[]为struct sembuf 型结构体指针
nops是要操作的信号量个数
返回值:成功0,失败-1
struct sembuf
{
unsigned short sem_num;//要操作的第几个信号量
short sem_op;//1 or -1
short sem_flg;//SEM_UNDO
}
四、例程(单个信号量)
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/sem.h>#include "semun.h"static int set_semvalue(void);static void del_semvalue(void);static int semaphore_p(void);static int semaphore_v(void);static int sem_id;int main(int argc, char *argv[]){ int i; int pause_time; char op_char = 'O'; srand((unsigned int)getpid ()); sem_id = semget((key_t)1234,1,0666|IPC_CREAT); if(argc >1 ) { if(!set_semvalue ()) { fprintf (stderr,"Failed to initialize semaphore\n"); exit(EXIT_FAILURE); } op_char ='X'; sleep(2); } for(i =0 ; i < 10; i++) { if(!semaphore_p ())exit(1); printf("%c",op_char);fflush(stdout); pause_time = rand() % 3; sleep(pause_time); printf("%c",op_char);fflush(stdout); if(!semaphore_v ())exit (1); pause_time = rand() % 2; sleep(pause_time); } printf("\n%d - finished\n",getpid()); if(argc >1) { sleep(10); del_semvalue (); } exit(0);}static int set_semvalue (void){ union semun sem_union; sem_union.val = 1;<span style="white-space:pre"></span>//初始值设为1个资源单位 if(semctl (sem_id, 0, SETVAL, sem_union)==-1)return (0); return (1);}static void del_semvalue (void){ union semun sem_union; if(semctl(sem_id, 0, IPC_RMID, sem_union)==-1) printf(stderr, "Failed to del semaphore.\n");}static int semaphore_p (void){ struct sembuf sem_b; sem_b.sem_num = 0; sem_b.sem_op = -1; sem_b.sem_flg = SEM_UNDO; if(semop(sem_id, &sem_b, 1)==-1) { fprintf(stderr, "semaphore_p failed.\n"); return 0; } return 1;}static int semaphore_v (void){ struct sembuf sem_b; sem_b.sem_num = 0; sem_b.sem_op = 1; sem_b.sem_flg = SEM_UNDO; if(semop(sem_id, &sem_b, 1)==-1) { fprintf(stderr, "semaphore_v failed.\n"); return 0; } return 1;}添加了一个自定义的头文件semun.h:
#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) /* union semun is defined by including <sys/sem.h> */#else /* according to X/OPEN we have to define it ourselves */ union semun { int val; /* value for SETVAL */ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ unsigned short int *array; /* array for GETALL, SETALL */ struct seminfo *__buf; /* buffer for IPC_INFO */ };#endif
运行程序:
#./sem 1 &
#./sem &
结果:XXXXOOXXXXXXOOOOOOXXOOXXOOXXXXXXOOO
解释:第一次执行sem程序,申请了一个信号量集,第二次运行的sem程序,直接访问该信号量集。二者交替打印,因为信号量的存在,而初始值设为1个资源单位,所以‘X’或‘O’必定是成对出现的。
- SYSTEM V IPC——信号量笔记
- IPC笔记之System V信号量
- 信号量/灯(system V IPC)
- Linux ipc------System V信号量
- 【记录】system v ipc(3) 信号量
- Linux IPC实践 --System V信号量(1)
- Linux IPC实践--System V信号量(2)
- Linux ——System V IPC
- IPC之System V 信号量(后续代码实现)
- [linux系统编程]System V IPC 信号量做进程间互斥
- linux进程间通讯-System V IPC 信号量
- Linux IPC实践(11) --System V信号量(1)
- Linux IPC实践(12) --System V信号量(2)
- linux IPC 通信 study 三:system v 信号量semphore
- Linux IPC实践(11) --System V信号量(1)
- Linux IPC实践(12) --System V信号量(2)
- 【C语言】【unix c】信号量集(system v ipc)
- XSI IPC——System V消息队列
- 段错误产生的原因
- 用C++打开指定文件夹,并选中文件
- JavaScript
- mysql交叉表,行列动态转换
- find_if和函数对象结合实现对自定义类型vector的查找
- SYSTEM V IPC——信号量笔记
- Vs2010调试技巧
- 自定义View步骤--来自GitHub组织android-training-course-in-chinese
- BCB图片按钮的实现
- Dagger - 快速依赖注入器(for android and java) (2)
- Ajax Drag and Drop
- Path Functions 学习
- 第一遍机房收费系统总结
- Android sdk 和 ndk 和 adt 和 ide