当前位置:网站首页>进程间通信-共享内存shmat
进程间通信-共享内存shmat
2022-06-12 23:47:00 【喵小林菌】
进程间通信-共享内存shmat
进程间通信三种方式
在linux系统中,每个进程都有独立的虚拟空间地址,通过MMU地址转换将虚拟地址与物理地址进行映射,每个进程相同的虚拟地址空间都会映射到不同的物理地址,每个进程在物理内存空间都是相互独立和隔离的。
不同的进程之间如果需要相互通信,该怎么办?因为不同的进程在物理内存上是相互隔离的,所以需要借助第三方工具来完成进程间通信。其实进程间通信的本质就是交换数据,进程间交换数据有三种方式:通过文件、通过内核、共享内存。
- 通过文件:AB进程通过访问同一个磁盘文件(I/O访问)进行数据交换
- 通过内核:进程间用户空间是相互独立,但是内核空间都是同一个, 因此可以通过内核这个中介去进行数据交换
- 共享内存:每个进程间的虚拟地址会映射到不同的物理地址,如果允许映射到同一块物理地址就可以进行数据交换

共享内存特点
- 共享内存 VS 通过文件:共享内存读写速度更快
- 共享内存VS通过内核:抛弃了内核“代理人”角色,让两个进程直接通过一块内存通信。减少了内存拷贝(从用户拷贝到内核、从内核拷贝到用户空间),减少了2次系统调用,提高系统性能
- 共享内存缺点:是共享内存并未提供同步机制,所以需要用其他机制来同步对共享内存的方位,这将由程序员来完成。一般可以通过信号量、互斥锁、文件锁等配合使用,防止数据的踩踏。
共享内存原理
共享内存是由IPC为进程创建的一个特殊的地址范围,出现在该进程的地址空间中,其他进程可以将同一段共享内存连接到他们自己的地址空间中。所有进程都可以访问共享内存中的地址,就好像他们是由malloc分配的一样。如果一个进程向共享内存中写了数据,那么其他进程将立刻能够看到。
共享内存使用

创建/获取共享内存shmget
该函数用来创建/获取共享内存
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
- key:IPC 对象的键值,一般为IPC_PRIVATE或ftok返回的key值
- size:共享内存的大学,一般为存物理页的整数倍
- shmflg:IPC_CREAT:如果不存在与制定的key对应的段,那么就创建一个新段;IPC_EXCL:若key制定的内存存在且制定了IPC_CREAT,返回EEXIST错误;
- 返回值:共享内存的标识符ID
映射共享内存shmat
该函数将shmid标识的共享内存引入到当前进程的虚拟地址空间
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
- shmid:共享内存的IPC对象ID
- shmaddr:若为NULL:共享内存会被attach到一个合适的虚拟地址空间,建议使用NULL;不为NULL:系统会根据参数及地址边界对齐等分配一个合适的地址
- shmflg:IPC_RDONLY:附加只读权限,不指定的话默认是读写权限;IPC_REMAP:替换位于shmaddr处的任意既有映射:共享内存段或内存映射;
- 返回值:共享内存段的地址
共享内存读写
共享内存的读写就要注意共享内存多进程访问同步,一般可以通过信号量、互斥锁、文件锁等配合使用,防止数据的踩踏。
解除内存映射shmdt
该函数解除内存映射,将共享内存分离出当前进程的地址空间
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);
- shmaddr:共享内存地址
注意,函数shmdt仅仅是使进程和共享内存脱离关系,将共享内存的引用计数减1,并为删除共享内存。通过#ipc -m就可查看某个IPC对象的状态,其中“连接数”就是表示该共享内存对象被引用的计数。
删除共享内存
上面看到,shmdt仅仅是使进程和共享内存脱离关系,并未删除共享内存。当共享内存的引用次数未0,可以调用shmctl的IPC_RMID命令才会删除共享内存。或者进程结束后,也会被删除掉。
shmctl获取/设置共享内存对象属性
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
- shmid:共享内存的对象ID
- cmd:IPC_RMID:删除共享内存段及关联的shmid_ds数据结构
- buf:指向包含共享模式和访问权限的结构
- 返回值:成功返回0,失败返回-1
更多的cmd可以通过man shmct去查看。
生产者-消费者代码示例
下面是一个简单的生产者-消费者模型,生产者producer进程负责将用户输入的数据写到共享内存中,消费者customer进程负责将共享内存中的读出来并打印出来。下面的程序示例通过共享内存中的变量written_by_you标记进行一个读写的同步,保证读写操作是互斥的。
//share.h
#define TEXT_SZ 2048
struct shared_use_st
{
int written_by_you;
char some_text[TEXT_SZ];
};
//customer.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "share.h"
int main()
{
int running = 1;
void *shared_memory = (void *)0;
struct shared_use_st *shared_stuff;
int shmid;
srand((unsigned int)getpid());
shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666 | IPC_CREAT);
if (shmid == -1)
{
fprintf(stderr, "shmget failed\n");
exit(EXIT_FAILURE);
}
shared_memory = shmat(shmid, (void *)0, 0);
if (shared_memory == (void *)-1) {
fprintf(stderr, "shmat failed\n");
exit(EXIT_FAILURE);
}
printf("Memory attached at %X\n", (int)shared_memory);
shared_stuff = (struct shared_use_st *)shared_memory;
shared_stuff->written_by_you = 0;
while(running)
{
if (shared_stuff->written_by_you)
{
printf("You wrote: %s", shared_stuff->some_text);
sleep( rand() % 4 );
shared_stuff->written_by_you = 0;
if (strncmp(shared_stuff->some_text, "end", 3) == 0)
{
running = 0;
}
}
}
if (shmdt(shared_memory) == -1)
{
fprintf(stderr, "shmdt failed\n");
exit(EXIT_FAILURE);
}
if (shmctl(shmid, IPC_RMID, 0) == -1)
{
fprintf(stderr, "shmctl(IPC_RMID) failed\n");
exit(EXIT_FAILURE);
}
printf("customer exit.\n");
exit(EXIT_SUCCESS);
}
//producer.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "share.h"
int main()
{
int running = 1;
void *shared_memory = (void *)0;
struct shared_use_st *shared_stuff;
char buffer[BUFSIZ];
int shmid;
shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666 | IPC_CREAT);
if (shmid == -1)
{
fprintf(stderr, "shmget failed\n");
exit(EXIT_FAILURE);
}
shared_memory = shmat(shmid, (void *)0, 0);
if (shared_memory == (void *)-1)
{
fprintf(stderr, "shmat failed\n");
exit(EXIT_FAILURE);
}
printf("Memory attached at %X\n", (int)shared_memory);
shared_stuff = (struct shared_use_st *)shared_memory;
while(running)
{
while(shared_stuff->written_by_you == 1)
{
sleep(1);
printf("waiting for client...\n");
}
printf("Enter some text: ");
fgets(buffer, BUFSIZ, stdin);
strncpy(shared_stuff->some_text, buffer, TEXT_SZ);
shared_stuff->written_by_you = 1;
if (strncmp(buffer, "end", 3) == 0)
{
running = 0;
}
}
if (shmdt(shared_memory) == -1)
{
fprintf(stderr, "shmdt failed\n");
exit(EXIT_FAILURE);
}
printf("producer exit.\n");
exit(EXIT_SUCCESS);
}
参考资料
[1]嵌入式C语音自我修养,王立涛
[2]大连理工大学《嵌入式软件设计》慕课
边栏推荐
- Start of u-boot S analysis (IV)
- Comprehensive analysis of C array
- Using baserecyclerviewadapterhelper to implement tree structure
- CV - baseline summary (development history from alexnet to senet)
- Memory address mapping of u-boot
- 设计消息队列存储信息数据的MySQL表结构
- leaflet如何加载10万条数据
- 实战 | UI 自动化测试框架设计与 PageObject 改造
- 2022年R2移动式压力容器充装考试题及在线模拟考试
- cookie
猜你喜欢

Accelerating with Dali modules

36 krypton's debut | "osogena" won nearly ten million angel rounds of financing. The original DLR scientists of German Aerospace Research and development system modeling and simulation CAE software PA

如何让矢量瓦片配图神器maputnik支持 geoserver

数组

array

2022年危险化学品经营单位安全管理人员考试试题及在线模拟考试

Unprecedented analysis of Milvus source code architecture
![[opencv learning] use the Tesseract OCR movement to recognize numbers](/img/ed/92e5261c9abda4e79d58e9404d3aee.jpg)
[opencv learning] use the Tesseract OCR movement to recognize numbers

QT actual combat case (38) -- using qpprocess class to realize the function of starting process

Alien skin exposure X7 color filter plug-in, raw post-processing tool
随机推荐
CS for mobile security [nethunter]
CST learning: four element array design of circular patch antenna (II) array formation and combination results
Introduction to business rules service on SAP Business Technology Platform (BTP)
2202-簡曆制作
[matlab] two dimensional curve
Hongmeng starts 2
Enterprise wechat H5_ Authentication, H5 application web page authorization login to obtain identity
Online examination questions for September examination of financial management
Theory + practice will help you master the dynamic programming method
2022年6月11日记:王老师的春天,混入
2022 electrician (elementary) operation certificate examination question bank and online simulation examination
Software development tools [3] theoretical basis of software development tools
C # graphic tutorial (Fourth Edition) chapter7-7.6.1 virtual and override
妙才周刊 - 5
OSM map local publishing - how to generate vector maps of provinces and cities
如何利用华为云容灾解决方案替代灾备一体机
RT thread quick start - experience RT thread
利率降低导致债券价格上涨
Common message oriented middleware selection
Huawei cloud elastic ECS use [Huawei cloud to jianzhiyuan]