XSI信号量
概念:
- 实现进程间同步
- 表示系统可用资源的个数
对象:
struct semid_ds {
struct ipc_perm sem_perm; /* Ownership and permissions */
time_t sem_otime; /* Last semop time */
time_t sem_ctime; /* Last change time */
unsigned long sem_nsems; /* No. of semaphores in set */
struct sem * sem_base
};
struct sem{
int semval 信号量的值
int sempid 最近一个操作的进程号
}
struct ipc_perm
{
__kernel_key_t key;
__kernel_uid_t uid;
__kernel_gid_t gid;
__kernel_uid_t cuid;
__kernel_gid_t cgid;
__kernel_mode_t mode;
unsigned short seq;
};
对象操作
- 创建对象:
int semget(key_t k,int n,int semflag);
- 设置对象:
int semctl(int sid,int semnum,int cmd,union semun a);
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short* array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
cmd 如果对于整个信号量集合,则有如下设置方法
IPC_STAT ipc_perm
IPC_SET ipc_perm
IPC_RMID
IPC_INFO 信号量的系统信息
int semctl(int sid,int semnum,int cmd,…);
cmd 如果对于单个信号量集合,则有如下设置方法
GETPID 返回操作IPC的PID
GETVAL 返回操作IPC的VAL
GETALL返回操作IPC的所有值
SETVAL 设置操作IPC的VAL
SETALL 设置操作IPC的所有值
- 使用对象
int semop(int s,struct sembuf *sb,size _t n);
struct sembuf{
unsigned short int sem_num;
short int sem_op;
short int sem_flg;};
sem_op
+ 表示进行加
- 表示进行减
0 表示测试是否为0
- 如果当前信号量的操作后的值为负数,则进行阻塞,一直到满足条件为止
sem_flg:
IPC_NOWAIT 如果操作信号集合中任意一个失败,立即返回,并且不会对其他的信号量做操作
SEM_UNDO :进程退出后,该进程对sem进行的操作将被撤销
struct sembuf sops[4]
sops[0].sem_num =1
sops[0].sem_op =-1 / P操作/
sops[0].sem_flag = 0
sops[1].sem_num =2
sops[1].sem_op =1 / V操作/
sops[1].sem_flag =0
demo
生产者:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
int sem_id;
void init()
{
key_t key;
int ret;
unsigned short sem_array[2];
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
}arg;
key=ftok(".",'s');
sem_id=semget(key,2,IPC_CREAT|0644);
sem_array[0]=0; //identify the productor
sem_array[1]=100; //identify the space
//printf("set the productor init value is 0\nset the space init value is 100\n");
arg.array = sem_array;
ret = semctl(sem_id, 0, SETALL, arg);
if (ret == -1)
printf("SETALL failed (%d)\n", errno);
//printf("\nread the number\n");
printf("productor init is %d\n",semctl(sem_id,0,GETVAL));
printf("space init is %d\n\n",semctl(sem_id,1,GETVAL));
}
void del()
{
semctl(sem_id,IPC_RMID,0);
}
#define produce 1
#define customer 0
#define P 1
#define V 0
int main(int argc,char *argv[])
{
struct sembuf sops[2];
sops[0].sem_num = 0;
sops[0].sem_op = 1;
sops[0].sem_flg = 0;
sops[1].sem_num = 1;
sops[1].sem_op = -1;
sops[1].sem_flg = 0;
init();
printf("this is productor\n");
while(1)
{
printf("\n\nbefore produce:\n");
printf("productor number is %d\n",semctl(sem_id,0,GETVAL));
printf("space number is %d\n",semctl(sem_id,1,GETVAL));
//生产者的操作
semop(sem_id,(struct sembuf *)&sops[P],produce); //get the space to instore the productor
printf("now producing......\n");
semop(sem_id,(struct sembuf *)&sops[V],customer); //now tell the customer can bu cusume
printf("\nafter produce\n");
printf("spaces number is %d\n",semctl(sem_id,1,GETVAL));
printf("productor number is %d\n",semctl(sem_id,0,GETVAL));
sleep(4);
}
del();
}
消费者:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
int sem_id;
void init()
{
key_t key;
key=ftok(".",'s');
sem_id=semget(key,2,IPC_CREAT|0644);
//printf("sem id is %d\n",sem_id);
}
#define produce 1
#define customer 0
#define P 1
#define V 0
int main(int argc,char *argv[])
{
init();
struct sembuf sops[2];
sops[0].sem_num = 0;
sops[0].sem_op = 1;
sops[0].sem_flg = 0;
sops[1].sem_num = 1;
sops[1].sem_op = -1;
sops[1].sem_flg = 0;
printf("this is customer\n");
while(1)
{
printf("\n\nbefore consume:\n");
printf("productor is %d\n",semctl(sem_id,0,GETVAL));
printf("space is %d\n",semctl(sem_id,1,GETVAL));
semop(sem_id,(struct sembuf *)&sops[P],customer); //get the productor to cusume
printf("now consuming......\n");
semop(sem_id,(struct sembuf *)&sops[V],produce); //now tell the productor can bu produce
printf("\nafter consume\n");
printf("products number is %d\n",semctl(sem_id,0,GETVAL));
printf("space number is %d\n",semctl(sem_id,1,GETVAL));
sleep(3);
}
}