一、信号量的作用:
![]()
信号量有时被称为信号灯,是在多线程环境下使用的一种设施,用来保证两个或者多个代码段不会被并发的调用。
主要用途是用来保护临界资源(进程互斥),进程可以根据它判断是否可以访问某些共享资源。
二、信号量的分类:
二值信号灯:信号灯的值只能取0或者1;
计数信号灯:信号灯的值可以去任意非负整数
信号量的实质:就是一个数字
操作:获取信号量
释放信号量
三、信号量的操作函数:
1.打开或者创建信号量
semget(key_t key,int nsems, int semflag) //功能 获取信号量的标识符 当key所指定的信号量不存在时,并且semflag包含了IPC_CREAT就会创建信号量集合
//
nsems 创建的这个信号量集合里面包含的信号量的数目,返回semid
key:键值
semflag:标识
IPC_CREAT;
2.操作信号量
;
semop(int semid ,struct smbuf *sops,unsigned nsops)
semid:要操作的信号量的标识符
nsops:要操作的信号量的个数
sops:对信号量执行什么样的操作(正代表释放,负代表获取)
四、什么是键值,键值的性质以及作用:
1.可以通过键值(数字)来找到所需的信号量
2.指定键值
1.任意指定一个
缺点:这个数已经被IPC对象(消息队列、共享内存)所使用,再与新创建的信号量关联就会失败,
2.构造一个尽量不会被别的IPC对象用的的数
方法:key_t ftok(char* fname,int id);
键值的组成:
二、“公示栏”问题的程序化:
同学1
#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>
#include<fcntl.h>
#include<sys/stat.h>
void main()
{
int fd;
//打开文件
fd=open("./board.txt",O_RDWR | O_APPEND);
//1.向公告板文件里写入“数学课
write(fd,"class match",11);
//2.暂停休息
sleep(5);
//3.向公告板文件里写入"取消"
write(fd,"is cancle",11);
close(fd);
}
同学2
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
void main()
{
int fd;
//0.打开公告板
fd=open("./board.txt",O_RDWR | O_APPEND);
//1.写入“英语课考试”
write(fd,"English exam",20);
//关闭公告板
close(fd);
}
步骤:
先运行同学1再快速的运行同学2,则输出的结果为
class matchEnglish exam^@^@^@^@^A^[^C;is cancle^@^@
需要的结果为
class match is cancle
English exam
使用信号量之后的代码
student1.c
#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/ipc.h>
#include<sys/sem.h>
void main()
{
int fd=0;
key_t key;
int semid;
struct sembuf sops;
//创建键值
key = ftok("/home/part3/lesson38",1);
//创建并打开信号量集合
semid = semget(key,1,IPC_CREAT);
semctl(semid,0,SETVAL);
//打开文件
fd=open("./board.txt",O_RDWR | O_APPEND);
//1.1操作信号量
sops.sem_num=0; //只操作第一个信号量
sops.sem_op=-1; //负数 获取这个信号量
semop(semid,&sops,1);
//1.向公告板文件里写入“数学课
write(fd,"class match",11);
//2.暂停休息
sleep(10);
3.向公告板文件里写入"取消"
write(fd,"is cancle",11);
//释放信号量
sops.sem_num=0; //只操作第一个信号量
sops.sem_op=+1; // 正数 释放这个信号量
semop(semid,&sops,1);
close(fd);
}
student2.c
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/sem.h>
#include<sys/ipc.h>
void main()
{
int fd;
key_t key;
int semid;
int ret;
struct sembuf sops;
//创建键值
key=ftok("/home/part3/lesson38",1);
//打开信号量集合
semid=semget(key,1,IPC_CREAT);//只会打开存在的信号量,以为这个信号量已经存在
//0.打开公告板
fd=open("./board.txt",O_RDWR | O_APPEND);
ret= semctl(semid,0,GETVAL);
printf("ret is %d\n",ret);
//1.1操作信号量
sops.sem_num=0; //只操作第一个信号量
sops.sem_op=-1; //负数 获取这个信号量
semop(semid,&sops,1); //如果获取不到这个信号量,该进程会在这等待
//1.写入“英语课考试”
write(fd,"English exam",20);
//释放信号量
sops.sem_num=0; //只操作第一个信号量
sops.sem_op=+1; //负数 释放这个信号量
semop(semid,&sops,1);
//关闭公告板
close(fd);
}