信号量
英文名字:semaphore
这里的进程信号量
会为下列的信号量打基础
- Ucos系统的信号量
- c线程的信号量
- java进程和线程的信号量
信号量作用
当多个进程/线程进行共享操作时,用于资源保护,以防止出现相互干扰的情况
信号量用于“资源的保护“
(1)进程信号量---实现的是进程所操作资源的保护。
(2)线程信号量---实现的是线程所操作资源的保护。
什么是进程的资源保护
1.多个进程同时向共享内存
里面写数据
时,可能会出现数据相互干扰的情况
-
某个进程写数据操作还没有写完时,进程的时间片就到了
-
然后被切换到另一个"共享内存"的写进程上运行
-
这个进程会接着往共享内存里面写数据,此时显然就把第一个进程写的数据给干扰了
这就形成了数据相互干扰。
2.当多个进程同时共享向文件
里面写数据时,同样会出现和共享写“共享内存”相同的情况
避免出现相互干扰
,需要加入资源保护
的措施
保护的目的就是:
保证每个进程在没有把数据读、写完整之前,其它进程不能进行读、写操作,以防止干扰别人
资源保护中资源指的就是操作的数据
保护的目的就是不要出现相互干扰,导致紊乱和错误数据的产生。
资源保护的种类:同步或互斥
信号量在资源保护中:即可以实现互斥又可以实现同步
但是文件锁只能实现互斥不同实现同步
互斥
对于互斥
操作来说,多进程共享操作时:
-
多个进程间不关心谁先操作、谁后操作的先后顺序
问题
-
它们只关心一件事,那就是我在操作时别人不能操作
---就算当前正在操作的进程它的时间片到了,切换到了其它进程上;
---但是当该进程检测到上一个进程还没有操作完时,该进程在当前的时间片内会休眠;
---直到再次切换会上一个进程,将操作完成后再切换回来,此时才能进行操作。
跟上厕所时把门关起来是一样的:
我在蹲坑时你不能蹲,你在蹲坑时我不能蹲,这就是互斥
至于蹲坑先后顺序并没有要求。
同步
同步其实本身就包含了互斥,不过同步不仅仅只互斥
同步对于谁先操作、谁后操作的先后顺序
有要求
规定A进程先写,然后是B进程写,然后是C进程写,绝对不能出现这操作顺序以外的顺序
很像:银行办理业务,又注重互斥还注重顺序
互斥和同步的实现本质–加锁
信号量就是一个加锁机制,通过加锁来实现同步和互斥
同步和互斥的目的其实就是为了实现“资源”的保护,不要让数据出现紊乱
信号量是什么
信号量从代码上就是:结构体,链表,数组等数据结构写的锁。
通过数据结构可以标记
这个进程的执行情况
,实现加锁
功能
信号量是加锁机制,为什么会被归到了进程间通信里面
资源保护时,某个进程的操作没有完全完成之前,别人是不能操作的
那么进程间必须相互知道对方的操作状态
,也就是一定会涉及通信过程
信号量实现资源保护的本质
通过通信让各个进程了解到操作状态
,然后查看自己能不能操作
信号量实现互斥的原理
进程信号量既能实现进程的互斥,也能实现进程的同步
父子进程同时写文件(不加信号量)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void print_err(char *str){
perror(str);
exit(-1);
}
int main(void){
int ret =0;
int fd=-1;
fd=open("./share_file",O_RDWR|O_CREAT|O_TRUNC,0664);
if(fd==-1) print_err("open fails\n");
ret=fork();
if(ret>0){
while(1){
write(fd,"aaaaaaaaa ",10);
write(fd,"bbbbbbbbb\n",10);
}
}
else if(ret==0){
while(1){
write(fd,"ccccccccc ",10);
write(fd,"ddddddddd\n",10);
}
}
return 0;
}
父子进程这两个相同的“文件描述符”指向的是相同的“文件表”,文件表的指针位置是同一个不会覆盖
如果父子进程各自打开文件,各自会有自己的文件表,那么虽然通过索引得到同样的文件,但是各自文件表中的指针位置不同步,那么读写会覆盖
不能保证互斥,因为会切换进程
进程信号量实现互斥的原理
什么是进程信号量
简单理解的话:
----信号量其实是OS创建的一个共享变量
--------进程在进行操作之前,会先检查这个变量的值,这变量的值就是一个标记
--------通过这个标记就可以知道可不可以操作,以实现互斥
信号量是共享变量,这个变量的值就是操作标记
二值信号量
- 同步和互斥时使用的都是二值信号量
- 二值信号量的值就两个:0和1,0表示不可以操作,1表示可以操作
比如父进程写之前将共享变量值设为0,进行加锁,两个写语句设为加锁代码段;如果没写完就切换,那么切换后的进程发现变量值为0,就阻塞等待,不进行操作;直到两个write结束了,就解锁,也就是把共享变量值设为1。如此循环
多值信号量
- 信号量的最大值>1,比如为3的话,信号量允许的值为0、1、2、3
多值信号量用的不是很多
信号量集合
信号量其实是一个OS创建的,供相关进程共享
的int变量,只不过在调用相关API创建信号量时,创建的都是一个信号量集合
所谓集合就是可能会包含好多个信号量
- 用于互斥时,集合中只包含一个信号量
- 用于同步时,集合中会包含多个信号量,至于多少个,需要看情况。
信号量的使用
使用步骤
-
进程调用semget函数
创建新的信号量
集合,或者获取已有的信号量集合
-
调用semctl函数
给集合中的每个信号量
设置初始值
-
调用semop函数
,对集合中的信号量进行pv操作
-
调用semctl
删除信号量集合
创建或获取->设初值->pv操作->删除
PV操作
pv操作其实说白了就是加锁、解锁操作
P操作(加锁)
:对信号量的值进行-1,如果信号量的值为0,p操作就会阻塞V操作(解锁)
:对信号量的值进行+1,V操作不存在阻塞的问题
通过pv操作(加锁、解锁),就能够实现互斥,以防止出现干扰
信号量的API
semget()
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
-
key:设置同消息队列和共享内存。
一般都使用ftok获取key值
-
nsems:指定集合中信号量的个数
- 用于
互斥
时,数量都指定为1
,因为只需要一个信号量 - 如果是
同步
的话就需要至多为多个
-
semflg:设置同消息队列和共享内存
一般都设置为0664|IPC_CREAT
成功
返回信号量集合的标识符,失败
返回-1
semctl()
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semctl(int semid, int semnum, int cmd, ...);
...
表示它是一个变参函数
,如果第四个参数用不到的话,可以省略不写
-
semid
:信号量标识符
-
semnum
:集合中某个
信号量的编号
通过信号量编号就能找到集合中
对应信号量
-
cmd
:控制选项
-
IPC_STAT
:将信号量的属性信息从内核读到第四个参数所以指定的struct semid_ds缓存中
-
IPC_SET
:修改属性信息,此时也会用到struct semid_ds结构体变量
-
IPC_RMID
:删除信号量
当集合中所有的信号量都被删除后,信号量集合也就被删除了
删除操作时第四个参数用不到,比如:semctl(semid, 0, IPC_RMID);
-
SETVAL
:通过第四个
参数,给集合中semnu编号的信号量设置一个int初始值
如果是二值信号量的话,设置初始值要么是0,要么是1
如果信号量的目的是互斥
的话,基本都是设置为1
当设置为1后,多几个进程互斥操作时,那就是谁先运行就谁先操作
…
第四个参数具体设置依赖于“cmd”
- cmd为
IPC_STAT
:第四个参数应为struct semid_ds类型的缓存 - cmd为
SETVAL
:第四个参数应该设置为一个int的值,用于初始化信号量
第四个参数对应内容是变着的,为了应对这种变化就用到了一个联合体
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
指定struct semid_ds缓存时
union semun sem_un;
struct semid_ds buff;
sem_un.buf = &buff;
semctl(semid, 0, IPC_STAT, sem_un);
定信号量的int初始值
union semun sem_un;
sem_un.val = 1;
semctl(semid, 0, IPC_STAT, sem_un);
删除信号量
int semctl(int semid, int semnum, int cmd, …);
删除信号量集合时,并不需要把所有的信号量都删除掉后才能删除
---------只需要指定semid和IPC_RMID就可以不把整个信号量集合删除,其中第二个参数semnum没有被用到,所以semnum的值可以随便写,不过我们一般都是把它写为0。
所以删除整个信号量集合时,删除的写法可以统一的为:
semctl(semid, 0, IPC_RMID);
semop()
op是operate操作的意思
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid, struct sembuf *sops, size_t nsops);
- p操作:将信号量的值-1
- v操作:将信号量的值+1
对于二值信号量来说
v操作后,值就从0变为了1
这就表示我操作完了,其它进程运行时就可以进行p操作了
参数
semid
:信号量集合的标识符sops
:这个参数更好理解的写法是struct sembuf sops[]
nsops
:用于指定数组元素个数的
1. 每一个数组成员对应一个信号量
2. 每一个元素都是一个struct sembuf结构体变量
内部成员
的决定着:
- 你要对集合中哪一个信号量进行操作
- 要进行的是p操作呢,还是v操作
struct sembuf{
unsigned short sem_num;
short sem_op;
short sem_flg;
}
以二值信号量为例:
当进程在v操作之前就结束时,信号量的值就会一直保持为0,那么其它进程将永远无法p操作成功,会使得进程永远休眠下去,这造成就是死锁。
互斥完整程序
信号量封装程序
#ifndef mm
#define mm
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/sem.h>
void print_err(char* str){
perror(str);
exit(-1);
}
union semun {
int val;
struct semid_ds *buf;
};
int create_or_get_sem(int nsems){
int semid=0;
int fd=open("./semaFile",O_CREAT|O_RDWR,0664);
if(fd==-1) print_err("open fails\n");
key_t key=0;
key=ftok("./semaFile",'a');
if(key==-1) print_err("ftok fails\n");
semid=semget(key,nsems,0664|IPC_CREAT);
if(semid==-1) print_err("semget fails\n");
return semid;
}
void init_sema(int semid,int semnum,int val){
int ret=-1;
union semun sem_un;
sem_un.val=val;
ret=semctl(semid,semnum,SETVAL,sem_un);
if(ret==-1) print_err("semctl fails\n");
}
void del_sema(int semid,int nsems){
int i=0;
for(;i<nsems;i++)
semctl(semid,i,IPC_RMID);
}
void p_sema(int semid,int sembuf[],int n){
struct sembuf sem_buf[n];
int i=0;
for(;i<n;i++){
sem_buf[i].sem_num=sembuf[i];
sem_buf[i].sem_op=-1;
sem_buf[i].sem_flg=SEM_UNDO;
}
semop(semid,sem_buf,n);
}
void v_sema(int semid,int sembuf[],int n){
struct sembuf sem_buf[n];
int i=0;
for(;i<n;i++){
sem_buf[i].sem_num=sembuf[i];
sem_buf[i].sem_op=1;
sem_buf[i].sem_flg=SEM_UNDO;
}
semop(semid,sem_buf,n);
}
#endif
父子进程通信程序
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "semaphore.h"
#include <signal.h>
#define NSEMS 1
int semID = -1;
void signal_fun(int signo)
{
del_sema(semID, NSEMS);
exit(-1);
}
int main(void)
{
int ret = 0;
int fd = -1;
fd = open("./share_file", O_RDWR | O_CREAT | O_TRUNC, 0664);
if (fd == -1)
print_err("open fails\n");
semID = create_or_get_sem(NSEMS);
int i;
for (i = 0; i < NSEMS; i++)
init_sema(semID, i, 1);
ret = fork();
if (ret > 0)
{
signal(SIGINT, signal_fun);
int sem_op[1] = {0};
while (1)
{
sem_op[0] = 0;
p_sema(semID, sem_op, 1);
write(fd, "aaaaaaaaa ", 10);
write(fd, "bbbbbbbbb\n", 10);
sem_op[0] = 0;
v_sema(semID, sem_op, 1);
}
}
else if (ret == 0)
{
int sem_op[1] = {0};
while (1)
{
sem_op[0] = 0;
p_sema(semID, sem_op, 1);
write(fd, "ccccccccc ", 10);
write(fd, "ddddddddd\n", 10);
sem_op[0] = 0;
v_sema(semID, sem_op, 1);
}
}
return 0;
}
程序复习
#ifndef MY_SEMA
#define MY_SEMA
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
//创建或得到一个信号量的semId
//semget(key,信号量集合个数,0664|IPC_CREAT);
int create_get_sema(int numSema){
int fd=-1;
key_t key=0;
int semId=0;
fd=open("./share_file",O_CREAT|O_RDWR,0664);
key=ftok("./share_file",'a');
semId=semget(key,numSema,0664|IPC_CREAT);
}
//联合:cmd的第四个可变参数
union semun {
int val;
struct semid_ds *buf;
};
//初始化信号量
//semctl(semId,信号量集合个数,SETVAL,初值)
void init_sema(int semId,int numSema,int val){
union semun ss;
ss.val=val;
semctl(semId,numSema,SETVAL,ss);
}
//删除信号量
//semctl(semId,信号量的集合个数,IPC_RMID)
void del_sema(int semId,int n){
int i;
for(i=0;i<n;i++)
semctl(semId,i,IPC_RMID);
}
//P操作,加锁,资源-1
//sembuf成员:信号量编号;pv(+1,-1);IPC_NOWAIT//SEM_UNDO
//semop(semid,sembuf数组地址,数组个数)
void p_sema_plus(int semId,int semaSet[],int n){
struct sembuf semBuf[n];
int i;
for(i=0;i<n;i++){
semBuf[i].sem_num=i;
semBuf[i].sem_op=-1;
semBuf[i].sem_flg=SEM_UNDO;
}
semop(semId,semBuf,n);
}
//v操作,释放锁,资源+1
void v_sema_minus(int semId,int semaSet[],int n){
struct sembuf semBuf[n];
int i;
for(i=0;i<n;i++){
semBuf[i].sem_num=i;
semBuf[i].sem_op=1;//v+1
semBuf[i].sem_flg=SEM_UNDO;
}
semop(semId,semBuf,n);
}
#endif
#include"semaphore.h"
#include<signal.h>
#include<stdlib.h>
#define SEMA 1
int semId=-1;
void signal_fun(int signo){
del_sema(semId,SEMA);
exit(-1);
}
int main(){
int fd=-1;
fd=open("./share_file",O_CREAT|O_RDWR|O_TRUNC,0664);
semId=create_get_sema(SEMA);
/*信号量初始化*/
int i;
for(i=0;i<SEMA;i++)
init_sema(semId,i,1);
int ret=fork();
if(ret>0){//父进程写,一定别加等号
signal(SIGINT,signal_fun);//父进程调用捕获
int semaSET[1]={0};
while(1){
//p,v操作前必须定义信号量集合
semaSET[0]=0;
p_sema_plus(semId,semaSET,1);
write(fd,"hello\t",6);
write(fd,"world\n",6);
semaSET[0]=0;//只有一个信号量,编号为0
v_sema_minus(semId,semaSET,1);
}
}
else if(ret==0){
int semaSET[1]={0};
while(1){
semaSET[0]=0;
p_sema_plus(semId,semaSET,1);
write(fd,"learn\t",6);
write(fd,"happy\n",6);
semaSET[0]=0;//只有一个信号量,编号为0
v_sema_minus(semId,semaSET,1);
}
}
return 0;
}
信号量实现同步
什么是同步
同步本身就是互斥
的,让多个进程按照固定的步调
做事(多了顺序)
让三个进程按照顺序打印:11111,22222,33333
#ifndef MY_SEMA
#define MY_SEMA
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
void print_err(char* str){
perror(str);
exit(-1);
}
int create_get_sema(int numSema){
int fd=-1;
key_t key=0;
int semId=0;
fd=open("./share_file",O_RDWR|O_CREAT|O_TRUNC,0664);
if(fd==-1) print_err("open fails\n");
key=ftok("./share_file",'a');
if(key==-1) print_err("ftok fails\n");
semId=semget(key,numSema,IPC_CREAT|0664);
if(semId==-1) print_err("semget fails\n");
return semId;
}
union semun{
int val;
struct semid_ds* buf;
};
void init_sema(int semId,int numSema,int val){
union semun sema;
sema.val=val;
semctl(semId,numSema,SETVAL,sema);
}
void del_sema(int semId,int numSema){
semctl(semId,0,IPC_RMID);
remove("./share_file");
}
void p_sema_minus(int semId,int bufop[],int n){
int i;
struct sembuf sem_op[n];
for(i=0;i<n;i++){
sem_op[i].sem_num=bufop[i];
sem_op[i].sem_op=-1;
sem_op[i].sem_flg=SEM_UNDO;
}
semop(semId,sem_op,n);
}
void v_sema_plus(int semId,int bufop[],int n){
int i;
struct sembuf sem_op[n];
for(i=0;i<n;i++){
sem_op[i].sem_num=bufop[i];
sem_op[i].sem_op=1;
sem_op[i].sem_flg=SEM_UNDO;
}
semop(semId,sem_op,n);
}
#endif
#include"semaphore.h"
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#define SEMA 3
int semId=-1;
void signal_fun(int signo){
del_sema(semId,SEMA);
exit(-1);
}
int main(void){
int buf_sema[1]={0};
int ret=0;
/*创建信号量集合*/
semId=create_get_sema(SEMA);
/*初始化信号量集合*/
int i;
for(i=0;i<SEMA;i++){
if(i==0) init_sema(semId,i,1);
else init_sema(semId,i,0);
}
/*三个亲缘进程*/
//信号量数组,每次pv只针对一个信号量
ret=fork();
if(ret>0){
//父进程再次fork()
ret=fork();
if(ret>0){//父进程
while(1){
buf_sema[0]=2;
p_sema_minus(semId,buf_sema,1);
printf("33333\n");
sleep(1);
buf_sema[0]=0;
v_sema_plus(semId,buf_sema,1);
}
}
else if(ret==0){//子进程2
while(1){
buf_sema[0]=1;
p_sema_minus(semId,buf_sema,1);
printf("22222\n");
sleep(1);
buf_sema[0]=2;
v_sema_plus(semId,buf_sema,1);
}
}
}
else if(ret==0){//子进程1
//负责删除信号量
signal(SIGINT,signal_fun);
while(1){
buf_sema[0]=0;
p_sema_minus(semId,buf_sema,1);
printf("11111\n");
sleep(1);
buf_sema[0]=1;
v_sema_plus(semId,buf_sema,1);
}
}
return 0;
}
易错点
int i;
for(i=0;i<SEMA;i++){
if(i==0) init_sema(semId,i,1);
else init_sema(semId,i,0);
}
int i;
for(i=0;i<SEMA;i++){
if(i==0) {init_sema(semId,i,1);
break;}
init_sema(semId,i,0);
}
回顾共享内存实现通信
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHMSIZE 2046
int shmId=-1;
void* shmAddr=NULL;
char buf[100]={"aaaaaaaaabbbbbbbbbbbcccccccccccccccc"};
void create_get_shmId(){
open("./sharefile",O_RDWR|O_CREAT,0664);
key_t key=ftok("./sharefile",'a');
shmId=shmget(key,SHMSIZE,IPC_CREAT|0664);
}
void signal_fun(int signo){
shmdt(shmAddr);
shmctl(shmId,IPC_RMID,NULL);
remove("./sharefile");
exit(-1);
}
int main(){
signal(SIGINT,signal_fun);
create_get_shmId();
shmAddr=shmat(shmId,NULL,SHM_RND);
if(shmAddr==(void*)-1){
perror("shmat fails\n");
exit(-1);
}
while(1){
memcpy(shmAddr,buf,sizeof(buf));
sleep(2);
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHMSIZE 2046
int shmId=-1;
void* shmAddr=NULL;
void create_get_shmId(){
open("./sharefile",O_RDWR|O_CREAT,0664);
key_t key=ftok("./sharefile",'a');
shmId=shmget(key,SHMSIZE,IPC_CREAT|0664);
}
void signal_fun(int signo){
shmdt(shmAddr);
shmctl(shmId,IPC_RMID,NULL);
remove("./sharefile");
exit(-1);
}
int main(){
signal(SIGINT,signal_fun);
create_get_shmId();
shmAddr=shmat(shmId,NULL,SHM_RND);
if(shmAddr==(void*)-1){
perror("shmat fails\n");
exit(-1);
}
while(1){
if(strlen((char *)shmAddr)!=0){
printf("%s\n",(char*)shmAddr);
bzero(shmAddr,sizeof(shmAddr));
}
}
return 0;
}
- 共享内存中:shmat()返回的(void*)shmAddr十分重要
不管是读还是写都需要这个地址,如果读,强转:(char*)
也就是所有程序都需要shmdt(shmAddr)
后才能删了共享内存
即:shmctl(shmId,IPC_RMID,NULL)
用信号量解决程序等待问题
读进程如果优先写进程执行,共享内存没数据,会一直循环等待,从而浪费CPU
必须:写进程先写,读进程后读,读写进程有顺序,需要用信号量同步
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "semaphore.h"
#define SHMSIZE 2046
int shmId=-1;
int semaId=-1;
void* shmAddr=NULL;
char buf[100]={"aaaaaaaaabbbbbbbbbbbcccccccccccccccc"};
void create_get_shmId(){
open("./sharefile",O_RDWR|O_CREAT,0664);
key_t key=ftok("./sharefile",'a');
shmId=shmget(key,SHMSIZE,IPC_CREAT|0664);
}
void signal_fun(int signo){
shmdt(shmAddr);
shmctl(shmId,IPC_RMID,NULL);
remove("./sharefile");
exit(-1);
}
int main(){
signal(SIGINT,signal_fun);
semaId=create_get_sema(2);
init_sema(semaId,0,1);
init_sema(semaId,1,0);
int semaSet[1]={0};
create_get_shmId();
shmAddr=shmat(shmId,NULL,SHM_RND);
if(shmAddr==(void*)-1){
perror("shmat fails\n");
exit(-1);
}
while(1){
semaSet[0]=0;
p_sema_plus(semaId,semaSet,1);
memcpy(shmAddr,buf,sizeof(buf));
sleep(2);
semaSet[0]=1;
v_sema_minus(semaId,semaSet,1);
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "semaphore.h"
#define SHMSIZE 2046
int shmId=-1;
void* shmAddr=NULL;
int semaId=-1;
void create_get_shmId(){
open("./sharefile",O_RDWR|O_CREAT,0664);
key_t key=ftok("./sharefile",'a');
shmId=shmget(key,SHMSIZE,IPC_CREAT|0664);
}
void signal_fun(int signo){
shmdt(shmAddr);
shmctl(shmId,IPC_RMID,NULL);
del_sema(semaId);
remove("./sharefile");
exit(-1);
}
int main(){
signal(SIGINT,signal_fun);
semaId=create_get_sema(2);
create_get_shmId();
int semaSet[1]={0};
shmAddr=shmat(shmId,NULL,SHM_RND);
if(shmAddr==(void*)-1){
perror("shmat fails\n");
exit(-1);
}
while(1){
semaSet[0]=1;
p_sema_plus(semaId,semaSet,1);
printf("%s\n",(char*)shmAddr);
bzero(shmAddr,sizeof(shmAddr));
semaSet[0]=0;
v_sema_minus(semaId,semaSet,1);
}
return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)