共享内存实现原理

/*
创建一个共享内存区
key值可以由ftok()函数生成,是唯一的进程资源
*/
int main()
{
    int shmid;
    char *addr;
   
    
    shmid = shmget(1002, 128, IPC_CREAT|IPC_EXCL|0666);
    addr = (char* )shmat(shmid, NULL, 0); 
    strcpy(addr,"hello world");
    return 0;
}

在这里插入图片描述

/*
IPC_CREAT  创建一个新的片段。如果没有,检查其权限
IPC_EXCL 这个标志位可以|一起使用
其他几个标志位可以 用命令:man 2  查看
*/
int ret = shmget(1001,4096,IPC_CREAT|IPC_EXCL|0666);

$ ipcs

在这里插入图片描述

前段时间被一家公司问到了,一个是内存映射的原理,一个是共享内存的原理,图片来源:人人都是极客。

struct shmid_kernel 用来管理共享内存的结构体

里面记录了创建的PID,以及操作的时间戳,已使用空间和未使用空间

共享内存最多能有128个

shmget函数,首先要查看

  • findkey,查找key值得共享内存是否被创建
  • findkey(),返回共享内存在shm_segs的数组索引
  • 找到了就直接返回标识符,没找到就newseg()创建
  • 创建一个新的struct shmid_kernel结构体出来

在这里插入图片描述

在这里插入图片描述

shmat() 函数用于将共享内存映射到本地虚拟内存地址。

这时一个问题就出来了,共享内存是需要经历一道手续的,内存映射。

共享内存和内存映射的区别。

找到一个可用的虚拟内存地址,如果在调用 shmat() 函数时没有指定了虚拟内存地址,那么就通过 get_unmapped_area() 函数来获取一个可用的虚拟内存地址。

共享内存需要找到虚拟内存地址,然后再进行映射。

如果没有找到,就会引发缺页异常,再度令Mmap去映射一块物理地址实现共享内存。

简而言之,就是不同虚拟地址的进程映射到了同一片内存空间,也减少了磁盘IO的次数。最常见的就是epoll,底层有红黑树

key管理文件描述符,value管理注册的事件

双向链表管理就绪的文件描述符,用于给用户返回轮询

mmap用于传递文件描述符,避免在内核态陷入时间过久,而且每次轮询和就绪都无需再向红黑树重新注册,又避免了频繁陷入用户态和内核态的上下文切换,是支撑服务器百万并发的关键。

只是共享内存也有缺点,毕竟会造成物理地址空间对运行内存的占用,如果系统觉得不够用,会将一部分不常用的运行内存的地址迁移到物理地址,又会涉及到地址交换技术。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值