我经常听说,与在线程之间访问进程内存相比,在进程之间访问共享内存段没有性能损失。换句话说,多线程应用程序不会比使用共享内存的一组进程快(不包括锁定或其他同步问题)。
但我有我的怀疑:
1)shmat()将本地进程虚拟内存映射到共享段。这种转换必须为每个共享内存地址执行,并且可能表示一个很大的开销。在多线程应用程序中,不需要额外的转换:所有VM地址都转换为物理地址,就像在不访问共享内存的常规进程中一样。
2)内核必须以某种方式维护共享内存段。例如,当连接到shm的所有进程都被关闭时,shm段仍然是正常的,并且最终可以被新启动的进程重新访问。在shm段上可能会有一些与内核操作相关的开销。
多进程共享内存系统和多线程应用程序一样快吗?
1)shmat()将本地进程虚拟内存映射到共享段。这种转换必须针对每个共享内存地址执行,并且相对于shm访问的数量来说,它可能表示一个很大的开销。在多线程应用程序中,不需要额外的转换:所有VM地址都被转换为物理地址,就像在不访问共享内存的常规进程中一样。
与常规内存访问相比,除了在调用shmat()
的过程中填充页表的初始成本之外,没有任何开销--在大多数Linux中,每4KB共享内存为1页(4或8字节)。
无论页面是分配、共享还是在同一进程中,(与所有相关的比较)成本都是相同的。
2)共享内存段必须由内核以某种方式维护。我不知道“某种方式”在性能方面意味着什么,但例如,当连接到shm的所有进程都被关闭时,shm段仍然是正常的,并且最终可以被新启动的进程重新访问。在shm段的生存期内,内核需要检查的事情必须至少有一定程度的开销。
无论是否共享,内存的每一页都有一个“结构页”附加到它,其中包含一些关于该页的数据。其中一项是引用计数。当一个页面被发送给一个进程(无论是通过“SHMAT”还是其他机制)时,引用计数就会增加。当通过某种方式释放它时,引用计数就会递减。如果递减的计数为零,页面实际上被释放-否则“它不会发生更多的事情”。
与分配的任何其他内存相比,开销基本上为零。无论如何,同样的机制也用于页面的其他目的--例如,您有一个页面也被内核使用--如果进程死亡,内核需要知道在该页面被内核和用户进程释放之前不要释放该页面。
创建“fork”时也会发生同样的情况。当一个进程被分叉时,父进程的整个页表本质上被复制到子进程中,并且所有页都是只读的。每当发生写操作时,内核就会出现一个错误,从而导致该页被复制--所以现在该页有两个副本,执行写操作的进程可以修改它的页,而不会影响其他进程。一旦子进程(或父进程)死亡,当然,在两个进程都“死亡”之前,仍然由两个进程拥有的所有页面(例如从未写入的代码空间,以及可能从未触及的一堆公共数据,等等)显然无法释放。同样,引用计数的页面在这里也很有用,因为我们只对每个页面的引用计数进行计数,当引用计数为零时--也就是说,当使用该页面的所有进程都释放了它时--该页面实际上会作为“有用页面”返回。
共享库也发生了完全相同的情况。如果一个进程使用共享库,则该进程结束时将释放该库。但是,如果两个、三个或100个进程使用相同的共享库,代码显然必须留在内存中,直到不再需要页面为止。
所以,基本上,整个内核中的所有页面都已经被引用了。头顶上很少。
问题内容: 我经常听到与访问线程之间的进程内存相比,访问进程之间的共享内存段不会降低性能。换句话说,多线程应用程序不会比使用共享内存的一组进程更快(不包括锁定或其他同步问题)。 但我有疑问: 1)shmat()将本地进程虚拟内存映射到共享段。必须为每个共享内存地址执行此转换,并且转换可能会花费大量成本。在多线程应用程序中,不需要额外的转换:所有VM地址都转换为物理地址,就像在不访问共享内存的常规过
共享内存用于实现进程间大量的数据传输。 共享内存空间是在内存中单独开辟的一段内存空间。这段空间有自己特有的数据结构,包括访问权限、大小和最近访问时间等。 重要的数据结构 shmid_ds /*位于/usr/include/linux/shm.h*/ struct shmid_ds { struct ipc_perm shm_perm; /* 操作权限 */ in
在我的应用程序中,有一个进程将数据写入文件,然后响应接收到的请求,将通过网络将(一些)数据发送到请求进程。这个问题的基础是看看当两个进程碰巧在同一个主机上时,我们是否可以加快通信速度。(在我的例子中,进程是Java的,但我认为这个讨论可以更广泛地应用。) 有一些项目使用Java的FileChannel返回的MappedByteBuffer。map()作为在同一主机上的JVM之间共享内存IPC的一种
共享内存是两个或多个进程共享的内存。 但是,为什么我们需要共享内存或其他通信方式呢? 重申一下,每个进程都有自己的地址空间,如果任何进程想要将自己的地址空间的某些信息与其他进程进行通信,那么只能通过IPC(进程间通信)技术进行。 我们已经知道,通信可以在相关或不相关的进程之间进行。 通常,使用管道或命名管道来执行相互关联的进程通信。 可以使用命名管道或通过共享内存和消息队列的常用IPC技术执行无关
EasySwoole对Swoole table进行了基础的封装。 方法列表 getInstance() 该方法用于获取TableManager管理器实例 add($name,array $columns,$size = 1024) 该方法用于创建一个table get($name):?Table 该方法用于获取已经创建好的table 示例代码 TableManager::getInstance()
shmat是shared memory attach的缩写。而attach本意是贴的意思。 如果进程要使用一段共享内存,那么一定要将该共享内存与当前进程建立联系。即经该共享内存挂接(或称映射)到当前进程。 shmdt则是shmat的反操作,用于将共享内存和当前进程分离。在共享内存使用完毕后都要调用该函数。 函数原型 #include <sys/types.h> #include <sys/shm.