linux的ipc信号量简单实例
2015-07-14 12:57
477 查看
信号量实现进程间访问互斥的资源测试例子。
主要涉及到的函数及原型如下(加粗、颜色表示要重点关心的上下文相关变量)
1: key_tftok(char *fileName, int id);//目的获取key值
2: intsemget(key_t key, int nsems, int semflg)//目的获取id
3:int semctl(int semid, int semnum, int cmd, union semunarg)//目的设置信号量的值,获取信号量的值等等,功能通过cmd变量控制
//其中semunarg必须由用户自身定义,格式如下
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
//other linux specific
};
4: int semop(int semid, struct sembuf *sops, unsign ednsops)//目的改变信号量的值,在sembuf中。
可通过每个函数大体功能,man手册中查找一些说明,进行研究测试。
以下测试代码非常简单,仅仅是为了熟悉api的基本功能,如果有错误和需要说明的地方,欢迎指正。
#include <sys/types.h>
#include <sys/sem.h>
#include <stdio.h>
#include <errno.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <unistd.h>
union semun {//semctl函数的第三个参数结构定义,现只关心设置val,其它成员可忽视,起到初始化资源数目的作用
int val;
// struct semid_ds *buf;
// unsigned short *array;
// struct seminfo *__buf;
};
int sem_init(int semid, int initval)//初始化信号量 init val
{
union semun arg;
arg.val = initval;
semctl(semid, 0, SETVAL, arg);//SETVAL 是semctl的cmd参数,意思是设置信号量为arg.val的值,0是信号量中第1个资源的下标
//fixme if some error
return 0;
}
int creat_sem(char *fileName)//创建一个信号灯,信号量默认写了1个,如果没有该信号量,创建,如果有,获取id
{
int id;
key_t key;
key = ftok(fileName, 1);
if (key < 0) {
perror("ftok()");
key = 5;//any number just for test
}
if ((id = semget(key, 1, IPC_CREAT | IPC_EXCL |0660)) < 0) {//1个信号量 creat? or exist?
if ((id = semget(key, 1, IPC_CREAT | 0660)) < 0) {//1个信号量 if exist,only get the id
printf("semget error: id = %d\n", id);
}
printf("sem allready exist: id = %d\n", id);
} else {//init the number when first use
sem_init(id, 0);
}
return id;
}
void P(int semid)//申请资源,资源数sembuf中的sem_op - 1
{
int ret = 0;
struct sembuf sb;
sb.sem_num = 0;
sb.sem_op = -1;
sb.sem_flg = 0;
ret = semop(semid, &sb, 1);
if (ret < 0) {
printf("error in p(s)\n");
}
}
void V(int semid)//释放资源,资源数sembuf中的sem_op - 1
{
int ret = 0;
struct sembuf sb;
sb.sem_num = 0;
sb.sem_op = 1;
sb.sem_flg = 0;
ret = semop(semid, &sb, 1);
if (ret < 0) {
printf("error in v(s)\n");
}
}
void showStat(int semid)
{
int ret = semctl(semid, 0, GETVAL, 0);
printf("now %d val is %d\n", semid, ret);
}
int main(int argc, char **argv)
{
int sem_id0, sem_id1;
if (fork() == 0) {//子进程 进程1
sem_id0 = creat_sem("/tmp/2");
sem_id1 = creat_sem("/tmp/3");
V(sem_id1);
while (1) {
P(sem_id0);
printf("working : process11111\n");
showStat(sem_id0);
showStat(sem_id1);
sleep(1);
V(sem_id1);
}
} else {//父进程 进程2
sem_id0 = creat_sem("/tmp/2");
sem_id1 = creat_sem("/tmp/3");
sleep(2);
while (1) {
P(sem_id1);
printf("working : process2222222222\n");
showStat(sem_id0);
showStat(sem_id1);
sleep(2);
V(sem_id0);
}
}
return 0;
}
主要涉及到的函数及原型如下(加粗、颜色表示要重点关心的上下文相关变量)
1: key_tftok(char *fileName, int id);//目的获取key值
2: intsemget(key_t key, int nsems, int semflg)//目的获取id
3:int semctl(int semid, int semnum, int cmd, union semunarg)//目的设置信号量的值,获取信号量的值等等,功能通过cmd变量控制
//其中semunarg必须由用户自身定义,格式如下
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
//other linux specific
};
4: int semop(int semid, struct sembuf *sops, unsign ednsops)//目的改变信号量的值,在sembuf中。
可通过每个函数大体功能,man手册中查找一些说明,进行研究测试。
以下测试代码非常简单,仅仅是为了熟悉api的基本功能,如果有错误和需要说明的地方,欢迎指正。
#include <sys/types.h>
#include <sys/sem.h>
#include <stdio.h>
#include <errno.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <unistd.h>
union semun {//semctl函数的第三个参数结构定义,现只关心设置val,其它成员可忽视,起到初始化资源数目的作用
int val;
// struct semid_ds *buf;
// unsigned short *array;
// struct seminfo *__buf;
};
int sem_init(int semid, int initval)//初始化信号量 init val
{
union semun arg;
arg.val = initval;
semctl(semid, 0, SETVAL, arg);//SETVAL 是semctl的cmd参数,意思是设置信号量为arg.val的值,0是信号量中第1个资源的下标
//fixme if some error
return 0;
}
int creat_sem(char *fileName)//创建一个信号灯,信号量默认写了1个,如果没有该信号量,创建,如果有,获取id
{
int id;
key_t key;
key = ftok(fileName, 1);
if (key < 0) {
perror("ftok()");
key = 5;//any number just for test
}
if ((id = semget(key, 1, IPC_CREAT | IPC_EXCL |0660)) < 0) {//1个信号量 creat? or exist?
if ((id = semget(key, 1, IPC_CREAT | 0660)) < 0) {//1个信号量 if exist,only get the id
printf("semget error: id = %d\n", id);
}
printf("sem allready exist: id = %d\n", id);
} else {//init the number when first use
sem_init(id, 0);
}
return id;
}
void P(int semid)//申请资源,资源数sembuf中的sem_op - 1
{
int ret = 0;
struct sembuf sb;
sb.sem_num = 0;
sb.sem_op = -1;
sb.sem_flg = 0;
ret = semop(semid, &sb, 1);
if (ret < 0) {
printf("error in p(s)\n");
}
}
void V(int semid)//释放资源,资源数sembuf中的sem_op - 1
{
int ret = 0;
struct sembuf sb;
sb.sem_num = 0;
sb.sem_op = 1;
sb.sem_flg = 0;
ret = semop(semid, &sb, 1);
if (ret < 0) {
printf("error in v(s)\n");
}
}
void showStat(int semid)
{
int ret = semctl(semid, 0, GETVAL, 0);
printf("now %d val is %d\n", semid, ret);
}
int main(int argc, char **argv)
{
int sem_id0, sem_id1;
if (fork() == 0) {//子进程 进程1
sem_id0 = creat_sem("/tmp/2");
sem_id1 = creat_sem("/tmp/3");
V(sem_id1);
while (1) {
P(sem_id0);
printf("working : process11111\n");
showStat(sem_id0);
showStat(sem_id1);
sleep(1);
V(sem_id1);
}
} else {//父进程 进程2
sem_id0 = creat_sem("/tmp/2");
sem_id1 = creat_sem("/tmp/3");
sleep(2);
while (1) {
P(sem_id1);
printf("working : process2222222222\n");
showStat(sem_id0);
showStat(sem_id1);
sleep(2);
V(sem_id0);
}
}
return 0;
}
相关文章推荐
- Linux下firefox安装flash player插件
- SELinux角色的用途
- linux动态链接相关
- linux系统下查看图片尺寸的命令
- Centos 7 安装jdk1.7
- Linux下安装php扩展
- Linux中解决SSH连接慢问题
- 安装centos 7 体验安装过程
- 安装centos 7 体验安装过程
- 如何在win 7/8 中制作一个Ubuntu 14.04 的USB随身碟
- linux grep命令 More命令 Less命令 基本使用
- Linux 编写ls -l 命令
- Linux 编写ls -l 命令
- Linux 编写ls -l 命令
- Linux 编写ls -l 命令
- cmd&Linux 下使用mysql全记录
- Linux中iptables设置详细
- linux 内存文件系统
- linux 驱动学习笔记03--Linux 内核的引导
- [Linux]vbox 虚拟机添加新磁盘