使用共享内存实现一个进程写文件,两个进程读文件
主要功能:读取任意的文件,大小不限(不超过共享内存设置的大小,一般为8k,但可手动重新设置,这已经很大了。),执行后两个或多个读进程可同时读取该文件并在终端打印。
要实现该功能,首先你得了解共享内存的搭建,有四个函数,分别为shmget,shmat,shmdt,shmctl,他们的作用如下:
- int shmget(key_t key, size_t size, int shmflg);
- void *shmat(int shm_id, const void *shm_addr, int shmflg);
- int shmdt(const void *shmaddr);
- int shmctl(int shm_id, int command, struct shmid_ds *buf);
- struct shmid_ds
- {
- uid_t shm_perm.uid;
- uid_t shm_perm.gid;
- mode_t shm_perm.mode;
- };
具体思路:先写后读,写进程先打开文件,然后往shmemory共享内存内写入文件,读进程直接从共享内存中读文件,并打印出来。
三个文件:shmwrite.c (写进程) shmread.c(读进程,可以有多个) sharemry.h(头文件)
先看头文件sharemry.h:
定义了flag是否可读的标志,size写入文件的大小,free_status是否最后一个读进程,text是一个可变数组,根据打开的文件大小开辟内存。无论是端还是写端,都必须先挂载到同一共享内存上。
可变数组:
text[0]结构
经常遇到的结构形状如下:
struct buffer
{
int text_len; //长度
char text[0]; //起始地址
};
在这个结构中,text是一个数组名;但该数组没有元素;该数组的真实地址紧随结构体buffer之后,而这个地址就是结构体后面数据的地址(如果给这个结构体分配的内容大于这个结构体实际大小,后面多余的部分就是这个text的内容);这种声明方法可以巧妙的实现C语言里的数组扩展。
下图是shmwrite.c写进程源码:
挂载到共享内存之后,开始读文件并写入共享内存
写入完成,将程序和共享内存卸载,也即脱离。
最后是shmread.c:
接上图
这里就会用到flag,有两个或多个进程同时读同一个共享内存时,每个读进程都会去挂载这块创建好的共享内存,但是有个隐藏的bug,共享内存是公用的一块,如果每个读进程都去shmctl共享内存的话,会出现错误,类似于内存泄露。所以标志flag保证最后一个读进程退出时才删除共享内存。