文章目录
一,利用信号量三个进程打印ABC
思想:
1,代码sem.h
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/sem.h>
#include<string.h>
#define SEMNUM 3
#define SEM1 0
#define SEM2 1
#define SEM3 2
union semun
{
int val;
}
int sem_init();
void sem_p(int index);
void sem_v(int index);
void sem_destroy();
2,代码sem.c
#include"sem.h"
int static semid=-1;
int sem_init()
{
semid=semget((key_t)1234,SEMNUM,IPC_CREAT|IPC_EXCL|0600)
if(semid==-1)
{
semid=semget((key_t)1234,SEMNUM,0600);
if(semid==-1)
{
printf("semget err\n");
return -1;
}
}
else
{
int b[SEMNUM]={1,0,0};
union semun a;
for(int i=0;i<SEMNUM;i++)
{
a.val=b[i];
if(semctl(semid,i,SETVAL,a)==-1)
{
printf("sem_init err\n");
return -1;
}
}
}
}
//注意这里只需要三个信号量中的一个来执行P操作;
void sem_p(int index)
{
if(index<0||index>=SEMNUM)
{
printf("index err\n");
return;
}
struct sembuf buf;
buf.sem_num=index;
buf.sem_op=-1;
buf.sem_flg=SEM_UNDO;
if(semop(semid,&buf,1)==-1)
{
printf("sem_p err\n");
return;
}
}
//如果需要三个信号量都执行P操作(这种情况很少见)
/*
void sem_p()
{
struct sembuf buf[SEMNUM];
for(int i=-0;i<SEMNUM;i++)
{
buf[i].sem_num=i;
buf[i].sem_op=-1;
buf[i].sem_flg==SEM_UNDO;
if(semop(semid,&buf[i],1)==-1)
{
printf("sem_p err\n");
return;
}
}
}
*/
void sem_v(int index)
{
printf("index err\n");
return;
}
struct sembuf buf;
buf.sem_num=index;
buf.sem_op=-1;
buf.sem_flg=SEM_UNDO;
if(semop(semid,&buf,1)==-1)
{
printf("sem_p err\n");
return;
}
}
void sem_destroy()
{
if(semctl(semid,0,IPC_RMID)==-1)
{
printf("sem_destroy erro\n");
return;
}
}
3,代码a.c
#include"sem.h"
int main()
{int flag=sem_init();
if(flag==--1)
{
printf("获取信号量失败\n");
}
for(int i=0;i<3;i++)
{
sem_p(SEM1);
printf("A");
fflush(stdout);
sem_v(SEM2);
}
}
4,代码b.c
#include"sem.h"
int main()
{int flag=sem_init();
if(flag==--1)
{
printf("获取信号量失败\n");
}
for(int i=0;i<3;i++)
{
sem_p(SEM2);
printf("B");
fflush(stdout);
sem_v(SEM3);
}
}
5,代码c.c
#include"sem.h"
int main()
{int flag=sem_init();
if(flag==--1)
{
printf("获取信号量失败\n");
}
for(int i=0;i<3;i++)
{
sem_p(SEM3);
printf("A");
fflush(stdout);
sem_v(SEM!);
}
}
二,共享内存
1,共享内存的原理(同时共享方式)
shmget函数
shmat函数
shmdt函数
如果一个进程结束了没有使用该函数断开映射也会自动断开映射;
shmctl函数
1.函数shma.c代码
刚开始的a.c代码
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<sys/shm.h>
#include<unistd.h>
#include<string.h>
int main()
{
int shmid=shmget((key_t)1234,128,IPC_CREAT|0600)
assert(shmid!=-1);
char*s=(char*)shmat(shmid,NULL,0);
//sleep(10);//这里是为了让我们看到共享内存的连接数不然程序一下结束就减一看不到连接数的变化;
strcpy(s,"hello");
shmdt(s);//注意如果这里没有断开映射,进程结束后会自动断开映射
}
2,函数shmb.c的代码
刚开始的shmb.c的代码
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<sys/shm.h>
#include<unistd.h>
#include<string.h>
int main()
{
int shmid=shmget((key_t)1234,128,IPC_CREAT|0600)
assert(shmid!=-1);
char*s=(char*)shmat(shmid,NULL,0);
printf("read: %s\n",s);
shmdt(s);
}
三,利用信号量实现共享内存的输入一次才能打印一次
1,改进后的shma.c的代码
1 #include<stdlib.h>
2 #include<stdio.h>
3 #include<assert.h>
4 #include<unistd.h>
5 #include<sys/shm.h>
6 #include<string.h>
7 #include"sema.h"
8 int main()
9 {
10 int shmid=shmget((key_t)1234,128,IPC_CREAT|0600);
11 assert(shmid!=-1);
12 char*s=(char*)shmat(shmid,NULL,0);
13 //sleep(10);
14 sem_init();
15 while(1)
16 {
17 printf("write: \n");
18 char buff[128]={};
19 fgets(buff,128,stdin);
20 sem_p(SEM1);
21 strcpy(s,buff);
22 sem_v(SEM2);
23 if(strncmp(buff,"end",3)==0)
24 {
25 break;
26 }
27 }
28 shmdt(s);
2,改进后的代码shmb.c
1 #include<stdlib.h>
2 #include<stdio.h>
3 #include<assert.h>
4 #include<unistd.h>
5 #include<sys/shm.h>
6 #include<string.h>
7 #include"sema.h"
8 int main()
9 {
10 int shmid=shmget((key_t)1234,128,IPC_CREAT|0600);
11 assert(shmid!=-1);
12 char*s=(char*)shmat(shmid,NULL,0);
13 sem_init();
14 while(1)
15 {sem_p(SEM2);
16 if(strncmp(s,"end",3)==0)
17 {
18 break;
19 }
20 printf("read: %s\n",s);
21 sem_v(SEM1);
22 //sleep(1);
23 }
24 shmdt(s);
25 shmctl(shmid,IPC_RMID,NULL);
26 sem_destroy();
27 }