要求:
1、不能重复读取内容,就像管道一样,读过的内容不能再读取。
2、不能覆盖未读取的内容,就像管道一样,未读取的内容不会因为再次写入而遭受破坏。
3、用信号来协调两个程序。
本程序需要用到共享内存和信号完成,通过writer写数据到共享内存,利用信号告诉reader可以读取数据等操作。利用信号告诉对方可以读取数据。
注意:共享内存不能重复创建,防止读写操作由于上一次的操作造成的紊乱,每一次操作完都需要删除再重新
int shmget(key_t key, size_t size, int shmflg);
功能:创建或者打开一个共享内存对象
参数:
key:由 ftok( ) 产生的唯一标识。
size:共享内存的大小,要求是偶数。
shmflg:可选项
IPC_CREAT:创建
IPC_EXCL:如果存在就报错
八进制权限,他们以位或的形式组合起来。
返回值:代表该共享内存的ID
注意:创建的共享内存是物理内存,必须要映射到本进程的内存空间才能使用。
writer.c
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <dirent.h>
#include <time.h>
int main()
{
//1.搞个key:key是ipc的唯一标识
key_t key = ftok("/mnt/hgfs/share/home/",1);
// 2,试图新建共享内存
int id = shmget(key, 100, IPC_CREAT|IPC_EXCL|0666);
// 如果成功了,要是代表对方还没启动,那么我要负责初始化
char *addr1;
if(id == -1 && errno == EEXIST)
{
id = shmget(key,100,0666);//初始化
//将共享内存映射到进程的内存空间
addr1 = shmat(id,NULL,0);
if(addr1 == (void *)-1)
{
perror("映射内存失败");
exit(0);
}
}
// 如果成功了,那么代表对方还没启动,那么我要负责初始化
else if( id > 0)
{
printf("对方没启动,我来初始化!\n");
// 3,将共享内存映射到本进程的内存空间
addr1 = shmat(id, NULL, 0);
if(addr1 == (void *)-1)
{
perror("映射内存失败");
exit(0);
}
bzero(addr1, 100);
}
//不断检测判断对方是否已经启动
while(*(pid_t *)addr1 == 0)
sleep(1);
pid_t pids;
memcpy(&pids , addr1,sizeof (pid_t));
//收到对方的pid
printf("reader is pid:%d\n",pids);
while(1)
{
//将要发送的数据放在共享内存中
fgets(addr1+sizeof(pid_t),100-sizeof(pid_t),stdin);
//通知对方要可以读数据
kill(pids,SIGUSR1);
}
//解除映射
shmdt(addr1);
return 0;
}
reader.c
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <dirent.h>
#include <time.h>
char *addr2;
void recv(int sig)
{
printf("收到的数据:%s",addr2+sizeof (pid_t));
}
int main()
{
//接受信号,当信号来临时响应recv的函数
signal(SIGUSR1,recv);
//1.搞个key
key_t key = ftok("/mnt/hgfs/share/home/sysprocess/homework/4-1",1);
// 2,试图新建共享内存
int id = shmget(key, 100, IPC_CREAT|IPC_EXCL|0666);
char *addr2;
// 如果失败了,那么代表对方已经建立了
if(id == -1 && errno == EEXIST)
{
printf("对方已经建立\n");
id = shmget(key, 100, 0666);
// 3,将共享内存映射到本进程的内存空间
addr2 = shmat(id, NULL, 0);
if(addr2 == (void *)-1)
{
perror("映射内存失败");
exit(0);
}
}
// 如果成功了,那么代表对方还没启动,那么我要负责初始化
else if(id > 0)
{
printf("对方没启动,我来初始化!\n");
// 3,将共享内存映射到本进程的内存空间
addr2 = shmat(id, NULL, 0);
if(addr2 == (void *)-1)
{
perror("映射内存失败");
exit(0);
}
bzero(addr2, 100);
}
pid_t pid = getpid();
//把pid以二进制的形式映射到共享内存中
memcpy(addr2,&pid,sizeof(pid_t));
printf("reader id pid:%d",pid);
while(1)
pause();
// 5,解除映射
shmdt(addr2);
return 0;
}