linux共享内存的设计

简介:

posix的共享内存是通过用户空间挂在的tmpfs文件系统实现的,而system V的共享内存是由内核本身的tmpfs实现的,这里可以看出,二者其实是用同一种机制实现的,不同的是用户接口不同,posix旨在提供一套统一的可用接口而不是实现,因此posix的上层根本就不会在意其机制是内核实现的还是用户空间实现的,因此用文件系统实现再好不过了,在linux上它实际上是通过用户空间挂载的tmpfs实现,system v的共享内存就不一样,它严格由操作系统内核提供接口和实现,因此linux中有关于共享内存的shmget/at等系统调用,虽然它们的底层实现一致,但是system v的共享内存作为内核提供的ipc之一,由内核直接支持,而posix就不一定了,在某些系统上由内核直接实现,而在另一些系统比如linux上由用户空间实现,posix的共享内存严格依赖用户空间tmpfs的挂载,在shm_open中有判断:

int shm_open (const char *name, int oflag, mode_t mode)

{

size_t namelen;

char *fname;

int fd;

__libc_once (once, where_is_shmfs); //找到tmpfs的挂载点

if (mountpoint.dir == NULL)

{

__set_errno (ENOSYS); //如果没有挂载tmpfs,那么就说明它还有被实现,返回错误码

return -1;

}

while (name[0] == '/')

++name;

if (name[0] == '/0')

{

__set_errno (EINVAL);

return -1;

}

namelen = strlen (name);

fname = (char *) alloca (mountpoint.dirlen + namelen + 1);

__mempcpy (__mempcpy (fname, mountpoint.dir, mountpoint.dirlen), name, namelen + 1);

fd = open (fname, oflag | O_NOFOLLOW, mode);

...

return fd;

}

posix的共享内存机制实际上在库过程中以及用户空间的其他部分被展示为完全的文件系统的调用过程,在调用完shm_open之后,需要调用mmap来将tmpfs的文件映射到地址空间,接着就可以操作这个文件了,需要注意的是,别的进程也可以操作这个文件,因此这个文件其实就是共享内存。反观system v的共享内存,内核直接实现了shmget/at系统调用,虽然最终也是靠tmpfs来实现的,但是接口设计上和posix完全不同,posix旨在提供所有系统都一致的接口,而system v只在于实现自己的逻辑,共享内存其实只是sysv中ipc的一部分,最终的管理数据结构也是ipc的而不是共享内存的,比如newseg(ipc/shm.c文件中)函数中的shm_addid函数调用的是ipc_addid(在文件ipc/util.c中),我们看一下这个newseg函数:

static int newseg (key_t key, int shmflg, size_t size)

{

...

} else {

sprintf (name, "SYSV%08x", key);

file = shmem_file_setup(name, size, VM_ACCOUNT); //最终落实到tmpfs

}

...

id = shm_addid(shp); //加入到ipc统一的管理数据结构中

...//设置shp的各个字段的值

return shp->id;

}

注意shmem_file_setup这个调用只是使用了tmpfs的一个实例,从它的实现可以看出有这样一句:file->f_vfsmnt = mntget(shm_mnt);使用了shm_mnt,那么这个shm_mnt是什么时候初始化的呢?在init_tmpfs中有:

shm_mnt = do_kern_mount(tmpfs_fs_type.name, MS_NOUSER, tmpfs_fs_type.name, NULL);

从linux的Document中可以看出,内核中起码要有一个tmpfs的实例,就是shm_mnt,这就是专门为system v的共享内存准备的,和是否编译TMPFS无关,虽然posix也使用了tpfs,但是却不是和内核实现的system v共享内存使用的一样的实例,后者的mnt实例是在用户执行mount tmpfs时创建的,实例虽然不一样但操作还是一样的,就像类实例虽不同,但是类是同一个类,数据不同但是代码相同。具体的tmpfs的file_operations等等就不赘述了。所以可以看出,不管是sysyem v的还是posix的共享内存,在计算机重新启动之后都会不复存在,因为数据室存在物理存储器或者交换分区的,它们不同的是,posix是以用户空间文件实现的,并且用户空间操作的是文件描述符,文件描述符是属于task_struct的,因此进程退出之后共享内存将递减共享计数,如果为0则销毁,因此posix的共享内存虽然使用open来创建或打开共享内存并没有用close而是用unlink来关闭的,作用就是在计数为0的时候销毁它,看看system v的共享内存,虽然也是由文件实现的,但是文件并没有加入到进程的打开文件表,而是作为进程的一种内禀属性被使用的,因此在进程退出时并不关闭文件,只要机器不重启或者该共享内存不显式销毁,那么共享内存将一直存在,进程和文件其实是互不相关的两个概念,只是进程打开的文件才和进程相关,在进程结束的时候只是能保证与之相关的文件被关闭,而别的文件比如sysv的共享内存使用的文件结构没有和进程关联,因此不会被关闭。其实close并不操作什么,而是仅仅刷新缓冲区,然后递减文件的使用者计数:

int filp_close(struct file *filp, fl_owner_t id)

{

int retval = 0;

if (!file_count(filp)) {

printk(KERN_ERR "VFS: Close: file count is 0/n");

return 0;

}

if (filp->f_op && filp->f_op->flush)

retval = filp->f_op->flush(filp);

dnotify_flush(filp, id);

locks_remove_posix(filp, id);

fput(filp); //linux的懒惰特性决定了这个fput操作才是最重要的。

return retval;

}


 本文转自 dog250 51CTO博客,原文链接:http://blog.51cto.com/dog250/1273333


相关文章
|
18天前
|
Linux
Linux rsyslog占用内存CPU过高解决办法
该文档描述了`rsyslog`占用内存过高的问题及其解决方案。
41 4
|
23天前
|
机器学习/深度学习 缓存 监控
linux查看CPU、内存、网络、磁盘IO命令
`Linux`系统中,使用`top`命令查看CPU状态,要查看CPU详细信息,可利用`cat /proc/cpuinfo`相关命令。`free`命令用于查看内存使用情况。网络相关命令包括`ifconfig`(查看网卡状态)、`ifdown/ifup`(禁用/启用网卡)、`netstat`(列出网络连接,如`-tuln`组合)以及`nslookup`、`ping`、`telnet`、`traceroute`等。磁盘IO方面,`iostat`(如`-k -p ALL`)显示磁盘IO统计,`iotop`(如`-o -d 1`)则用于查看磁盘IO瓶颈。
|
4天前
|
消息中间件 算法 Linux
【Linux】详解如何利用共享内存实现进程间通信
【Linux】详解如何利用共享内存实现进程间通信
|
3天前
|
Java Linux Arthas
linux上如何排查JVM内存过高?
linux上如何排查JVM内存过高?
20 0
|
6天前
|
消息中间件 存储 Unix
【探索Linux】P.15(进程间通信 —— system V共享内存)
【探索Linux】P.15(进程间通信 —— system V共享内存)
17 0
|
7天前
|
安全 Linux Python
Volatility3内存取证工具安装及入门在Linux下的安装教程
Volatility3内存取证工具安装及入门在Linux下的安装教程
Volatility3内存取证工具安装及入门在Linux下的安装教程
|
7天前
|
安全 Python Linux
Kali Linux下Volatility2.6常见问题疑难杂症-内存取证信息安全管理与评估
Kali Linux下Volatility2.6常见问题疑难杂症-内存取证信息安全管理与评估
Kali Linux下Volatility2.6常见问题疑难杂症-内存取证信息安全管理与评估
|
7天前
|
缓存 运维 算法
深入理解Linux内核的虚拟内存管理
【5月更文挑战第6天】 在现代操作系统中,尤其是类Unix系统如Linux中,虚拟内存管理是一项核心功能,它不仅支持了多任务环境,还提供了内存保护和抽象。本文将深入探讨Linux操作系统的虚拟内存子系统,包括分页机制、虚拟地址空间布局、页面置换算法以及内存分配策略。通过对这些概念的剖析,我们旨在为读者揭示Linux如何有效地管理和优化物理内存资源,并确保系统的稳定运行与高效性能。
|
消息中间件 Unix Linux
[Linux打怪升级之路]-system V共享内存
[Linux打怪升级之路]-system V共享内存
[Linux打怪升级之路]-system V共享内存