API
int semget(key_t key, int nsems, int semflg);创建或者获取已经存在的信号量
semget()成功返回信号量的ID,失败返回-1
key:两个进程使用相同的key值,就可以使用同一个信号量
nsems:内核维护的是一个信号量集,在新建信号量时,其指定信号量集中信号量的个数
semflg 可选:IPC_CREAT IPC_EXCL
IPC_CREAT|IPC_EXCL,如果内核中不存在这样的信号量,则新建,否则,则报错,semfg使用时要与IPC对象权限进行|运算来设定权限
int semop(int semid, struct sembuf*sops, unsigned nsops);
semop(对信号量进行改变,做Р操作或者V操作
成功返回0,失败返回-1
struct sembuf{
unsigned short sem_num;//指定信号量集中的信号量下标
sem_op;//其值为-1,代表Р操作,其值为1,代表V操作
short sem_flg;//标志位SEM_UNDO,如果程序执行P操作后,程序奔了,不能执行V操作,SEM_UNDO可以记住程序进行了P操作,就算程序奔溃也可以帮助进行V操作,并不会因为程序奔溃而无法进行V操作,一直阻塞其它进程。
};
int semctl(int semid, int semnum, int cmd,...);控制信号量
成功返回0,失败返回-1
cmd选项:SETVAL (赋初值)IPC_RMID(删除)删除时semnum只需要填0就可以了,0只是占参数位置,填0就可以删除所有信号量。
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *_buf;
}
此联合体需要用户自己定义
案例:交替打印AB
sem.h
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/sem.h>
#define NUM 2
union semun
{
int val;
struct semid_ds * buf;
unsigned short *array;
struct seminfo *__buf;
};
void sem_init();
void sem_p(int index);
void sem_v(int index);
void sem_destory();
sem.c
#include"sem.h"
#include<sys/sem.h>
static int semid =-1;
void sem_init()
{
semid = semget((key_t)1234,NUM,IPC_CREAT|IPC_EXCL|0600);
if(semid == -1)
{
semid = semget((key_t)1234,NUM,0600);
if(semid == -1)
{
printf("semget erro\n");
}
}else//
{
union semun a;
int arr [2]={1,0};
for(int i=0;i<NUM;++i)
{
a.val =arr[i];
if(semctl(semid,i,SETVAL,a) ==-1)
{
printf("semctl init erro\n");
}
}
}
}
void sem_p(int index)
{
if(index <0 || index >=NUM)
{
exit(1);
}
struct sembuf buf;
buf.sem_num=index;
buf.sem_op=-1;
buf.sem_flg = SEM_UNDO;//yichang zhong duan hou gei xing hao liang v cao zuo
if(semop(semid,&buf,1) == -1)
{
printf("semop p erro\n");
}
}
void sem_v(int index)
{
if(index <0 || index >=NUM)
{
exit(1);
}
struct sembuf buf;
buf.sem_num=index;
buf.sem_op=1;
buf.sem_flg = SEM_UNDO;//yichang zhong duan hou gei xing hao liang v cao zuo
if(semop(semid,&buf,1) == -1)
{
printf("semop v erro\n");
}
}
void sem_destory()
{
if(semctl(semid,0,IPC_RMID) == -1)
{
printf("semctl destory err\n");
}
}
a.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include"sem.h"
int main()
{
sem_init();
for(int i=0;i<5;++i)
{
sem_p();
printf("A");
fflush(stdout);
int n = rand()%3;
sleep(n);
printf("A");
fflush(stdout);
sem_v();
n = rand()%3;
sleep(3);
}
sleep(10);
sem_destory();
exit(0);
}
b.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include"sem.h"
int main()
{
sem_init();
for(int i=0;i<5;++i)
{
sem_p();
printf("B");
fflush(stdout);
int n = rand()%3;
sleep(n);
printf("B");
fflush(stdout);
sem_v();
n = rand()%3;
sleep(3);
}
sleep(10);
exit(0);
}
ipcs 查看系统的消息队列,共享内存,信号量
0x4d2 为16进制,转换为10进制为1234
ipcrm -s 信号量id 删除信号量