目录
int semget(key_t key, int nsems, int semflg);
int semctl(int semid, int semnum, int cmd, union semun arg);
int semop(int semid, struct sembuf *sops, size_t nsops);
一、简介:
信号量的本质就是一个计数器,它的作用是保护共享资源,用来负责数据操作过程中的同步、互斥等功能,当它的值大于0时,表示当前可用资源的数量;当它的值小于0时,其绝对值表示等待使用该资源的进程。
二、相关函数:
int semget(key_t key, int nsems, int semflg);
- key:信号量的键值
- nsems:信号量的数量
- semflg:
- IPC_CREAT:信号量不存在则创建
- mode:信号量的权限int semctl(int semid, int semnum, int cmd, union semun arg);
- semid:信号量ID
- semnum:信号量编号,如果只有一个信号量,一般为0
- cmd:
- IPC_STAT:获取信号量的属性信息
- IPC_SET:设置信号量的属性
- IPC_RMID:删除信号量
- SETVAL:设置信号量的值- arg:
/*/usr/include/linux/ipc.h 中有定义,但是 /usr/include/sys/ipc.h 中没有
一般包含<sys/ipc.h>,所以需要自己定义*/
- union semun {
int val;//设置信号量的值(等待进程的数量)
struct semid_ds *buf;//设置属性
};int semop(int semid, struct sembuf *sops, size_t nsops);
- semid:信号量的id
- sops:
- struct sembuf
{
short sem_num;//信号量编号
short sem_op;//信号量P/V操作
short sem_flg;信号量的行为,一般设置为SEM_UNDO(如果进程结束前没有释放则自动释放信号量)
}- nsops:信号量的数量
三、信号量的用法:
- 创建一个信号量(semget)
- 初始化信号量(semctl IPC_SETVAL)
- P/V操作(semop)
- 删除信号量(semctl IPC_RMID)
四、信号量编程中的应用(让父进程运行在子进程后):
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <unistd.h>
#define SEM "/tmp"
union semun
{
int val;//设置信号量的值
struct semid_ds *buf;//设置属性
};
/*初始化信号量*/
int sem_init(int semid,int semnum,int val)
{
union semun sem_semun;
sem_semun.val = val;
if(semctl(semid,semnum,SETVAL,sem_semun) == -1)
{
printf("semctl error!\r\n");
return -1;
}
return 0;
}
/*删除信号量*/
int sem_del(int semid,int semnum)
{
union semun sem_semun;
if(semctl(semid,semnum,IPC_RMID,NULL) == -1)
{
printf("sem_del error!!\r\n");
return -1;
}
return 0;
}
/*P/V操作*/
int sem_op(int semid,int semnum,int sem_op,size_t nsops)
{
struct sembuf sops;
sops.sem_num = semnum;
sops.sem_op = sem_op;
sops.sem_flg = SEM_UNDO;
if(semop(semid,&sops,nsops) == -1)
{
printf("sem_op error!\r\n");
return -1;
}
return 0;
}
int main(void)
{
pid_t fd;
int sem_id;
key_t key;
key = ftok(SEM,0);
sem_id = semget(key,1,IPC_CREAT | 0666);//创建一个信号量
sem_init(sem_id,0,0);//初始化信号量
fd = fork();//创建子进程
if(-1 == fd)
{
printf("fork error!\r\n");
return -1;
}
else if(0 == fd)
{
printf("sleep start\r\n");
sleep(3);
printf("sleep end\r\n");
sem_op(sem_id,0,1,1);//进行P操作,此时由-1变为0,父进程可以往下运行
}
else
{
sem_op(sem_id,0,-1,1);进行V操作,信号量的值变为-1,父进程等待
printf("father fork run\r\n");
}
}