临界区
:访问临界资源的代码
临界资源
:同一时刻只允许一个进程访问的资源
p
:获取资源
v
:释放资源
前台只能执行一个进程,后台可以执行多个所以a和b程序必须得放在后台,结果还是在前台显示
a程序
#include<stdlib.h>
#include<stdio.h>
#include<assert.h>
#include<unistd.h>
#include<string.h>
#include<sys/sem.h>信号量头文件
static int semid=-1;
union semun
{
int val;
};
void sem_init()创建
{
semid=semget((key_t)1234,1,IPC_CREAT|IPC_EXCL|0600);
两个进程同一个key_t,代表一个信号量,1代表1个信号量
创建|确保第一个创建(创建的得初始化)| 访问权限
if(semid==-1)失败,说明已有人创建
{
semid=semget((key_t)1234,1,0600);获取
if(semid==-1)
{ printf("semid err\n");
return;
}
}else
{
全新创建成功,现在初始化
union semun a;
a.val=1;
if(semctl(semid,0,SETVAL,a)==-1)失败
{
0表示对第几个信号量初始化,SETVAL将a的值赋给信号量
printf("semctl err\n");
}
}
}
void sem_p()
{
struct sembuf buf;
buf.sem_num=0;对第0个信号量进行操作
buf.sem_op()=-1;值减1
buf.sem_flg=SEM_UNDO;当程序不小心结束后,帮忙释放信号量
if(semop(semid,&buf,1)==-1)1组信号量
{
printf("semop p err\n");
}
}
void sem_v()
{
struct sembuf buf;
buf.sem_num=0;对第0个信号量进行操作
buf.sem_op()=1;值加1
buf.sem_flg=SEM_UNDO;当程序不小心结束后,帮忙释放信号量
if(semop(semid,&buf,1)==-1)1个结构体变量
{
printf("semop v err\n");
}
}
void sem_destory()
{
if(semctl(semid,0,IPC_RMID)==-1)删除信号量
{
printf("semctl err destory\n");
}
}
int main()
{
sem_init();
for(int i=0;i<5;++i)
{
sem_p();p操作
printf("A");
fflush(stdout);
int n=rand()%3;
sleep(n);
printf("A");
fflush(stdout);
sem_v();v操作
n=rand()%3;
sleep(n);
}
sleep(10);
sem_destory();
}
b程序
#include<stdlib.h>
#include<stdio.h>
#include<assert.h>
#include<unistd.h>
#include<string.h>
int main()
{
for(int i=0;i>5;++i)
{
sem_init();
sem_p();
printf("A");
fflush(stdout);
int n=rand()%3;
sleep(n);
printf("A");
fflush(stdout);
sem_v();
n=rand()%3;
sleep(n);
}
}
结果为AABBAABBAABB或BBAABBAABBAA
让三个进程打印ABCABCABC,得设置三个信号量,s1(0),s2(1),s3(1)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/sem.h>
#define SEM_NUM 3共设置三个信号量
#define SEM1 0三个信号量名
#define SEN2 1
#define SEN3 2
static int semid=-1;
union semun
{
int val;
}
void sem_init()
{
semid=semget((key_t)1234,SEN_NUM,IPC_CREAT|IPC_EXCL|0600);
if(semid==-1)
{
semid=semget((key_t)1234,SEM_NUM,0600);
}else
{
int arr[SEM_NUM]={1,0,0};
for(int i=0;i<SEM_NUM;++i)
{
union semun a;
a.val=arr[i];
if(semctl(semid,i,SETVAL,a)==-1)
{
printf("semctl err\n");
return -1;
}
}
}
}
void sem_p(int index)
{
if(index<0||index>=SEM_NUM)
{
return;
}
struct sembuf buf;
buf.sem_num=index;
buf.sem_op=-1;
buf.sem_flg=SEM_UNDO;
if(semop(semid,&buf,1)==-1)
{
return ;
}
}
void sem_v(int index)
{
if(index<0||index>=SEM_NUM)
{
return;
}
struct sembuf buf;
buf.sem_num=index;
buf.sem_op=1;
buf.sem_flg=SEM_UNDO;
if(semop(semid,&buf,1)==-1)
{
return ;
}
}
void sem_destory()
{
if(semctl(semid,0,IPC_RMID)==-1)
{
return;
}
}
int main()
{
int res=sem_init();
if(res==-1)
{
return 0;
}
for(int i=0;i<5;++i)
{
sem_p(SEM1);
printf("A");
fflush(stdout);
sem_v(SEM2);
}
}
int main()
{
int res=sem_init();
if(res==-1)
{
return 0;
}
for(int i=0;i<5;++i)
{
sem_p(SEM1);
printf("B");
fflush(stdout);
sem_v(SEM2);
}
}
int main()
{
int res=sem_init();
if(res==-1)
{
return 0;
}
for(int i=0;i<5;++i)
{
sem_p(SEM2);
printf("C");
fflush(stdout);
sem_v(SEM0);
}
sem_destory();
}
ipcs:可以查看共享内存,消息队列,信号量
共享内存
共享内存:内存中有一块既可以被A进程使用,B也可以使用
1.创建共享内存
2.将共享内存映射到进程中
3.断开映射
4.删除映射
ipcs -m
只看共享内存
ipcs -q
只看消息队列
ipcs -s
只看信号量
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<sys/shm.h>
a程序写
int main()
{
int shmid=shmget((key_t)1234,128,IPC_CREAT|0600);
128共享内存的大小
assert(shmid!=-1);
char* s=(char*)shmat(shmid.NULL,0);NULL代表由操统自行分配空间,0默认读写都可
while(1)
{
printf("input:\n");
char buff[128]={0};
fgets(buff,128,stdin);
sem_p(SEM0);
strcpy(s,buff);像共享内存中写入hello
sem_v(SEM1);
if(strncmp(buff,"end",3)==0)
{
break;
}
}
shmdt(s);断开映射
}
b程序读
int main()
{
int shmid=shmget((key_t)1234,128,IPC_CREAT|0600);
128共享内存的大小
assert(shmid!=-1);
char* s=(char*)shmat(shmid,NULL,0);NULL代表由操统自行分配空间,0默认读写都可
while(1)
{
sem_p(SEM2);
if(strncmp(s,"end",3)==0)
{
break;
}
printf("read:%s\n",s);
sem_v(SEM1);
}
shmdt(s);断开映射
shmctl(shmid,IPC_RMID,NULL);删除共享内存
sem_destroy();
}
ipcrm -s +标识符
:删除信号量
ipcrm -m +标识符
:删除共享内存