1 有一个全局的结构体数据,每次需要一块共享的内存时(shmget),从里面取一个结构体,记录相关的信息。

struct shmid_ds {

// 权限相关

struct ipc_perm shm_perm;/* operation perms */

// 共享内存的大小

intshm_segsz;/* size of segment (bytes) */

time_tshm_atime;/* last attach time */

time_tshm_dtime;/* last detach time */

time_tshm_ctime;/* last change time */

// 创建该结构体的进程

unsigned shortshm_cpid;/* pid of creator */

unsigned shortshm_lpid;/* pid of last operator */

// 当前使用该共享内存的进程数

shortshm_nattch;/* no. of current attaches */

/* the following are private */

// 共享内存的页数

unsigned short shm_npages;/* size of segment (pages) */

// 指向共享的物理内存的指针

unsigned long *shm_pages;/* array of ptrs to frames -> SHMMAX */

// 使用该共享内存的进程信息

struct vm_area_struct *attaches; /* descriptors for attaches */

}

2 调用shmat的时候传入shmget返回的id。shmat根据id找到对应的shmid_ds 结构体。新建一个vm_area_struct结构体。开始地址和结束地址根据shmid_ds 中的信息计算,也就是用户申请的大小。接着把vm_area_struct插入进程中管理vm_area_struct的avl树。并且把一些上下文信息保存到页表项。缺页中断的时候在shm_swap_in里使用。

shm_sgn = shmd->vm_pte + ((shmd->vm_offset >> PAGE_SHIFT) << SHM_IDX_SHIFT);

for (tmp = shmd->vm_start; tmp < shmd->vm_end; tmp += PAGE_SIZE,

shm_sgn += (1 << SHM_IDX_SHIFT)) {

page_dir = pgd_offset(shmd->vm_task,tmp);

page_middle = pmd_alloc(page_dir,tmp);

if (!page_middle)

return -ENOMEM;

page_table = pte_alloc(page_middle,tmp);

if (!page_table)

return -ENOMEM;

pte_val(*page_table) = shm_sgn;

}

3 进程访问共享内存范围中的地址时,触发缺页中断。

void do_no_page(struct vm_area_struct * vma, unsigned long address,

int write_access)

{

pte_t * page_table;

pte_t entry;

unsigned long page;

// 在进程页表里获取address对应的页表项地址

page_table = get_empty_pgtable(vma->vm_task,address);

// 分配失败则返回

if (!page_table)

return;

entry = *page_table;

// 已经建立了虚拟地址到物理地址的映射,返回

if (pte_present(entry))

return;

// 还没有建立映射

if (!pte_none(entry)) {

do_swap_page(vma, address, page_table, entry, write_access);

return;

}

......

}

在缺页中断中调用do_swap_page。

static inline void do_swap_page(struct vm_area_struct * vma, unsigned long address,

pte_t * page_table, pte_t entry, int write_access)

{

pte_t page;

if (!vma->vm_ops || !vma->vm_ops->swapin) {

swap_in(vma, page_table, pte_val(entry), write_access);

return;

}

page = vma->vm_ops->swapin(vma, address - vma->vm_start + vma->vm_offset, pte_val(entry));

if (pte_val(*page_table) != pte_val(entry)) {

free_page(pte_page(page));

return;

}

if (mem_map[MAP_NR(pte_page(page))] > 1 && !(vma->vm_flags & VM_SHARED))

page = pte_wrprotect(page);

++vma->vm_task->mm->rss;

++vma->vm_task->mm->maj_flt;

// 写入物理地址

*page_table = page;

return;

}

其中vma->vm_ops->swapin对应shm.c的shm_swap_in

pte_val(pte) = shp->shm_pages[idx];

// 还没有分配物理内存

if (!pte_present(pte)) {

// 分配物理内存

unsigned long page = get_free_page(GFP_KERNEL);

...

// 记录物理地址

shp->shm_pages[idx] = pte_val(pte);

}

mem_map[MAP_NR(pte_page(pte))]++;

return pte_modify(pte, shmd->vm_page_prot);

如果还没分配物理地址则分配,否则直接范围已经分配的地址。do_swap_page函数的最后一句会把物理地址写入进程的页表项。下次就不会缺页中断了。

同理,其他进程共享该块内存的时候,如果访问范围内的地址,处理过程是类似的。进程访问某一个地址,发生缺页中断,然后进入do_swap_page函数处理,再到shm_swap_in。发现这时候共享内存已经映射了物理地址。最后改写自己的页表项。因为各个进程都对应同一块内存,所以操作的时候会互相感知,实现通信。

linux 进程原理内存,linux进程通信之共享内存原理(基于linux 1.2.13)相关推荐

  1. linux进程间的通信(C): 共享内存

    一.共享内存介绍 共享内存是三个IPC(Inter-Process Communication)机制中的一个. 它允许两个不相关的进程访问同一个逻辑内存. 共享内存是在两个正在进行的进程之间传递数据的 ...

  2. Linux访问其他进程空间,Linux环境进程间通信系列(五):共享内存

    共享内存可以说是最有用的进程间通信方式,也是最快的 IPC 形式.两个不同进程 A . B 共享内存的意思是,同一块物理内存被映射到进程 A . B 各自的进程地址空间.进程 A 可以即时看到进程 B ...

  3. Linux 进程间通讯(IPC)方式 ------- 共享内存

    Linux 进程间通讯(IPC)方式有以下几种: 1->管道(pipe)和有名管道(fifo). 2->消息队列 3->共享内存 4->信号量 5->信号(signal) ...

  4. Linux环境进程间通信系列(五):共享内存

    共享内存(上) 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进程A可以即时看到进程B对共享内存 ...

  5. linux进程间通信快速入门【二】:共享内存编程(mmap、XSI、POSIX)

    文章目录 mmap内存共享映射 XSI共享内存 POSIX共享内存 参考 使用文件或管道进行进程间通信会有很多局限性,比如效率问题以及数据处理使用文件描述符而不如内存地址访问方便,于是多个进程以共享内 ...

  6. Linux 3.进程间通信(shmget shmat shmdt shmctl 共享内存、signal signaction sigqueue 信号、semget semctl semop 信号量)

    Linux 3.进程间通信(IPC) 共享内存 共享内存的接口指令 shmget 创建获取获取共享内存 shmat 映射:连接共享内存到当前进程的地址空间 shmdt 断开与共享内存的连接 shmct ...

  7. Linux的IPC机制(一):共享内存

    0. 共享内存 比喻 本质 多个进程访问同一个逻辑内存 直接访问内存,不用read()/write()非常方便 1. POSIX 共享内存 资料:unpv22e-ch13 查看: man shm_ov ...

  8. 共享内存 传一个类指针_大神是如何学习 Go 语言之为什么使用通信来共享内存...

    为什么这么设计(Why's THE Design)是一系列关于计算机领域中程序设计决策的文章,我们在这个系列的每一篇文章中都会提出一个具体的问题并从不同的角度讨论这种设计的优缺点.对具体实现造成的影响 ...

  9. 如何理解“不要通过共享内存来通信,而应该通过通信来共享内存”?

    不要通过共享内存来通信,而应该通过通信来共享内存 这是一句风靡golang社区的经典语,对于刚接触并发编程的人,该如何理解这句话? 如何理解"不要通过共享内存来通信,而应该通过通信来共享内存 ...

  10. mmap内存映射、system V共享内存和Posix共享内存

    linux内核支持多种共享内存方式,如mmap内存映射,Posix共享内存,以system V共享内存.当内核空间和用户空间存在大量数据交互时,共享内存映射就成了这种情况下的不二选择.它能够最大限度的 ...

最新文章

  1. 个人觉得非常好的B树,B+树的总结
  2. linux bash: sqlplus: command not found 错误处理
  3. 汇编语言程序如何转化成c语言,如何把汇编语言转换成C语言
  4. 《ODAY安全:软件漏洞分析技术》学习心得-----shellcode的一点小小的思考
  5. spring相关API
  6. fcntl函数之文件锁 F_SETLKW
  7. 容器编排技术 -- Kubernetes kubectl create poddisruptionbudget 命令详解
  8. 一般技术书籍出版版税多少_如何为您的技术书籍寻找出版商
  9. Android开发笔记(八十一)屏幕规格适配
  10. 老漏洞easy击:CVE-2012 0158占顶!
  11. 一切皆有可能——在iPod上安装Linux
  12. echarts按照时间显示柱状图_百度Echarts 柱状图 动态显示
  13. Tomcat 修改网站旁边的小图标
  14. wps word文字样式管理
  15. 南京毕业生租房补贴发票开具地点一览表
  16. 学习:SPWeb:Allusers、SiteUsers、Users和Sitegroups、Groups以及安全性编程
  17. 应用程序无法正常启动(oxc000007b):解决方案
  18. 记一次巨KD的中考维护历程
  19. 浙工商计算机学院教师,浙工商计算机与信息工程学院导师介绍:魏贵义
  20. Hbase安装~Hbase安装过程中常见的问题

热门文章

  1. 4.Verilog 基础语法
  2. nginx DNS 缓存问题
  3. PHP代码静态分析工具PHPStan
  4. 互联网与大数据将成为智能制造的基石
  5. 剑指offer23 从上往下打印二叉树
  6. 一些软件软件开发原则
  7. 上海奋斗记--从3500到700W(转)
  8. python绝技 — 侦听802.11 Probe请求
  9. 【Linux入门连载一】[Win10下安装Linux虚拟机]VMWare15运行CentOS7(亲测有效)
  10. spring boot2.3.1版本导入spring-boot-starter-web没有validation校验框架的解决办法