信号量实现进程间访问互斥的资源测试例子。
主要涉及到的函数及原型如下
(加粗、颜色表示要重点关心的上下文相关变量)
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;
-
}
阅读(2188) | 评论(0) | 转发(0) |