一,基本概念
XSI的api是对信号量集合的创建和操作,一个信号量集合包含一个或多个信号量,
二.api
1. int semget(key_t key, int nsems, int flag)
根据key获取或者创建一个信号集
key:IPC关键字, nsems:创建时表示信号量的个数,flag: 可以是IPC_CREAT | IPC_EXCL | 0660
返回值是信号量的标识符
2.int semctl(int semid, int semnum, int cmd, .../* union semun arg */)
设置或者获取此信号量集合的信息
3.int semop(int semid, struct sembuf semoparray[], size_t nops)
释放或者获取信号量,semid:标识信号, struct sembuf 的结构定义如下:
struct sembuf
{
unsigned short int sem_num; /* semaphore number */
short int sem_op; /* semaphore operation */
short int sem_flg; /* operation flag */
};
sem_num表示此信号集中几个信号量,
sem_op 为正表示释放,为负标识获取,为0表示等到此信号量变成0,
sem_flg 可以是IPC_NOWAIT,UNDO; IPC_NOWAIT表示此信号量不阻塞,注意此处,semoparray是一个数组,flag起作用是有顺序的,
如何根据数组的第一个元素,判断需要等待或者条件不满足返回,第二个元素就不其作用了,如果第一个满足条件,会继续判断第二个元素,...类推
UNDO表示,进程终止时,会把此次操作导致的信号量变化调整过来,注意信号量的值不能为负,所以当需要调整到负时,会调整为0
如果一个进程重新设置了此信号量,所有进程中对于此信号量的调整都会设置为0;
三,一个例子
sem_require.c:
#include<stdlib.h>
#include<stdio.h>
#include<sys/sem.h>
#include<sys/ipc.h>
//#include<linux/sem.h>
//#include<linux/ipc.h>
#include<errno.h>
#include<unistd.h>
#define SEMFILEPATH "/tmp/sem4.txt"
union semun{
int val;
struct semid_ds *buf;
unsigned short *array;
};
int main()
{
key_t key = ftok(SEMFILEPATH, 1);
union semun initval;
initval.array = (unsigned short *)malloc(2*sizeof(unsigned short));
int count = 0;
struct sembuf aqrval[2];
int ret;
int semid = semget(key, 2, IPC_CREAT | IPC_EXCL | 0660);
if(semid < 0 && EEXIST == errno)
{
printf("sem exist ! \n");
semid = semget(key, 2, 0);
if(semid < 0)
{
printf("get sem failed !");
return 0;
}
}
else
{
initval.array[0]=3;
initval.array[1]=3;
ret = semctl(semid, 0, SETALL, initval);
if(ret < 0)
{
printf("semctl failed !");
free(initval.array);
return 0;
}
}
printf("in aquire: semid, %d\n", semid);
initval.array[0] = 0;
initval.array[1] = 0;
if(semctl(semid, 0, GETALL, initval) >= 0)
{
printf("in aquire:sem 1 res %d,sem 2 res %d \n", initval.array[0], initval.array[1]);
}
else
{
printf("errorno: %d \n", errno);
}
while(count++ < 1)
{
aqrval[0].sem_num = 0;
aqrval[0].sem_op = -4;
aqrval[0].sem_flg = 0;
aqrval[1].sem_num = 1;
aqrval[1].sem_op = -4;
aqrval[1].sem_flg = IPC_NOWAIT;
ret = semop(semid, aqrval, 2);
if(ret < 0)
{
printf("in aquire:sem_op error ! errno:%d\n", errno);
}
if(semctl(semid, 0, GETALL, initval) >= 0)
{
printf("in aquire:sem 1 res %d,sem 2 res %d \n", initval.array[0], initval.array[1]);
}
}
return 0;
}
sem_release.c:
#include<stdlib.h>
#include<stdio.h>
#include<sys/sem.h>
#include<sys/ipc.h>
//#include<linux/sem.h>
//#include<linux/ipc.h>
#include<errno.h>
#include<unistd.h>
#define SEMFILEPATH "/tmp/sem4.txt"
union semun{
int val;
struct semid_ds *buf;
unsigned short *array;
};
int main()
{
key_t key = ftok(SEMFILEPATH, 1);
union semun initval;
initval.array = (unsigned short *)malloc(2*sizeof(unsigned short));
struct sembuf aqrval[2];
int ret = 0;
int count = 0;
int semid = semget(key, 2, IPC_CREAT | IPC_EXCL | 0660);
if(semid < 0 && EEXIST == errno)
{
printf("sem exist ! \n");
semid = semget(key, 2, 0);
if(semid < 0)
{
printf("get sem failed !");
return 0;
}
}
else
{
initval.array[0]=3;
initval.array[1]=3;
ret = semctl(semid, 0, SETALL, initval);
if(ret < 0)
{
printf("semctl failed !");
free(initval.array);
return 0;
}
}
printf("sem exist ! out\n");
printf("semid: %d\n", semid);
initval.array[0] = 0;
initval.array[1] = 0;
while(count < 2)
{
aqrval[count].sem_num = 0;
aqrval[count].sem_op = 3 + count;
aqrval[count].sem_flg = 0;
ret = semop(semid, aqrval, 1);
printf("in relase: realease result:%d\n", ret);
sleep(5);
count++;
}
return 0;
}
sem_aquire.c 编译成sem_aquired, sem_release.c编译成 sem_released
执行结果如下:
[read_ng@wukong workspace]$ ./sem_aquired &
[1] 14774
[read_ng@wukong workspace]$ in aquire: semid, 196614
in aquire:sem 1 res 3,sem 2 res 3
[read_ng@wukong workspace]$ ./sem_released &
[2] 14776
[read_ng@wukong workspace]$ sem exist !
sem exist ! out
semid: 196614
in relase: realease result:0
in aquire:sem_op error ! errno:11
in aquire:sem 1 res 6,sem 2 res 3
in relase: realease result:0
[1]- Done ./sem_aquired
[2]+ Done ./sem_released
[read_ng@wukong workspace]$