之前学习过信号量但是只知道怎么使用但是对于其使用和核心没有进行了解过因此重新写这篇文章
在头文件下<sys/sem.h>
信号量的几个函数api
主要的函数时这三个具体如下解析
int semget(key_t key,int num_sems,int sem_flgs)//
第一个参数key标识信号量集的唯一性,第二个参数是标识该信号量集的个数第三个设置信号量的属性的 flage一般是CREATE | IPC_EXCL
确保唯一性和新的
int semctl(int semid,int sem_num,int command ......)
这是第二个函数具体第一个返回信号量的标识,第二个参数要操作的信号量集中的信号量的标识(一个信号量集可能有多个信号),第三个参数具体使用如下一般设置为SETVAL 具体含义将val设置到semun.val,并且更新内核中的semid_ds.sem_ctime
第四个参数一般传的是个union semun sem_un 联合体 具体是用来初始化的这个函数具体的意思是对信号量集中特定的信号量进行初始因为参数信号量参数多所以采用联合体的形式减少内存
具体分析这个联合体
union semun
{
int val;用于设置信号量的val值得
struct semid_ds *buff;将信号量集中的部分成员关联到内核函数中同时被更新
unsigned short int *array;//也是对信号量集的操作
struct seminfo *__buf;//获取信号集的想信息
}
具体使用的时候一般情况下只需要val属性就可以了
int semop(int sem_id,struct sembuf *sem_ops,size_t num_sem_ops)第一个参数是信号量集第二个是结构体具体下方
这个函数就是就是pv函数的系统调用了具体分析如下
为什么自己要写pv操作 因为pv操作是要对信号量集中的信号量进行操作的 并且信号量也有自己的属性要设置所以必须自己实现
struct sembuf
{
unsigned short int sem_num;信号量的编号在该信号量集中
short int sem_op;传入对应的op进行操作val的值如果op的大于0进行加一等于0阻塞,小于0阻塞或者错误或者等待
short int sem_flg;设置完进行更新
};
所以分析完了具体状况如下图所示
例1
sem.h
- #include <stdio.h>
- #include <signal.h>
- #include <fcntl.h>
- #include <stdlib.h>
- #include <sys/sem.h>
- union semun
- {
- int val;
- };
- void sem_init();
- void sem_p();
- void sem_v();
- void del_sem();
sem.c
- #include "sem.h"
- static int semid=-1;
- void sem_init()
- {
- semid =semget((key_t)1234,1,IPC_CREAT | IPC_EXCL | 0600);
- if(semid==-1)
- {
- semid=semget((key_t)1234,1,0600);
-
- if(semid==-1)
- {
- perror("erro");
- }
- }
- else
- {
- union semun a;
- a.val=1;
- if(semctl(semid,0,SETVAL,a)==-1)
- {
- printf("semctl erro");
- }
- }
- }
- void sem_p()
- {
- struct sembuf a;
- a.sem_num=0;
- a.sem_op=-1;
- a.sem_flg=SEM_UNDO;
- if(semop(semid,&a,1)==-1)
- {
- perror("erro");
- }
- }
- void sem_v()
- {
- struct sembuf a;
- a.sem_num=0;
- a.sem_op=1;
- a.sem_flg=SEM_UNDO;
- if(semop(semid,&a,1)==-1)
- {
- perror("erro");
- }
- }
- void del_sem()
- {
- union semun sem_union;
- if(semctl(semid,0,IPC_RMID)==-1)
- {
- perror("erro");
- }
- }
b.c
- #include <stdio.h>
- #include "sem.h"
- int main()
- {
- int i=0;
- sem_init();
- int n;
- for(;i<10;i++)
- {
- sem_p();
- printf("b");
- fflush(stdout);
- n=rand()%3;
- sleep(n);
- printf("b");
- fflush(stdout);
- n=rand()%3;
- sleep(n);
- sem_v();
- }
- sleep(8);
- del_sem();
- exit(0);
-
- }
a.c
- #include <stdio.h>
- #include "sem.h"
- int main()
- {
- int i=0;
- sem_init();
- int n;
- for(;i<10;i++)
- {
- sem_p();
- printf("A");
- fflush(stdout);
- n=rand()%3;
- sleep(n);
- printf("A");
- fflush(stdout);
- n=rand()%3;
- sleep(n);
- sem_v();
- }
- exit(0);
- }