我经常听到与访问线程之间的进程内存相比,访问进程之间的共享内存段不会降低性能。换句话说,多线程应用程序不会比使用共享内存的一组进程更快(不包括锁定或其他同步问题)。
但我有疑问:
1)shmat()将本地进程虚拟内存映射到共享段。必须为每个共享内存地址执行此转换,并且转换可能会花费大量成本。在多线程应用程序中,不需要额外的转换:所有VM地址都转换为物理地址,就像在不访问共享内存的常规过程中一样。
2)共享内存段必须由内核 以某种方式
维护。例如,关闭与shm关联的所有进程时,shm段仍处于启动状态,并且最终可以由新启动的进程重新访问。在shm段上可能有一些与内核操作有关的开销。
多进程共享内存系统是否与多线程应用程序一样快?
1)shmat()将本地进程虚拟内存映射到共享段。必须对每个共享内存地址执行此转换,并且相对于shm访问的数量而言,这种转换可能会花费大量成本。在多线程应用程序中,不需要额外的转换:所有VM地址都转换为物理地址,就像不访问共享内存的常规过程一样。
除了建立共享页的初始成本外,与常规内存访问相比,没有任何开销shmat()
-在调用过程中填充页表-
在大多数类型的Linux中,每4KB共享内存为1页(4或8字节) 。
无论是共享页面分配还是在同一流程中分配,(所有相关比较)成本都相同。
2)共享内存段必须由内核以某种方式维护。我不知道“某种程度上”在性能方面意味着什么,但是例如,当拆除了与shm相连的所有进程时,shm段仍处于启动状态,并且最终可以由新启动的进程重新访问。在shm段的生存期内,内核必须至少检查某种程度的开销。
无论是否共享,内存的每个页面都具有一个“结构页面”,并带有有关该页面的一些数据。其中一项是参考计数。当将页面分配给进程时(无论是通过“
shmat”还是其他机制),引用计数都会增加。通过某种方式释放它时,引用计数将减少。如果减少的计数为零,则实际上释放了页面-否则“此后再也没有发生”。
与分配的任何其他内存相比,开销基本上为零。无论如何,相同的机制也用于页面的其他目的-例如,您有一个页面也被内核使用-
并且您的进程终止了,内核需要知道在释放该页面之前,不释放该页面,因为以及用户流程。
创建“叉子”时会发生同样的事情。派生一个进程时,父进程的整个页表实际上都将复制到子进程中,并且所有页都变为只读状态。每当发生写操作时,内核都会发生错误,从而导致该页面被复制-
因此该页面现在有两个副本,执行写操作的进程可以修改该页面,而不会影响其他进程。一旦子进程(或父进程)死亡,则当然这两个进程仍然拥有所有页面(例如,从未写入的代码空间,以及可能从未接触过的一堆公共数据,等等)显然无法释放,直到两个进程都“死”为止。同样,引用计数的页面在这里很有用,因为我们只对每个页面上的引用计数进行计数,
共享库确实发生了同样的事情。如果一个进程使用共享库,则该进程结束时将释放它。但是,如果两个,三个或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的一种
在Java中,对于两个JVM(运行在同一台物理机器上),是否有办法使用/共享相同的内存地址空间?假设JVM-1中的生产者将消息放在特定的预定义内存位置,如果JVM-2上的消费者知道要查看哪个内存位置,那么它是否可以检索消息?
共享内存是两个或多个进程共享的内存。 但是,为什么我们需要共享内存或其他通信方式呢? 重申一下,每个进程都有自己的地址空间,如果任何进程想要将自己的地址空间的某些信息与其他进程进行通信,那么只能通过IPC(进程间通信)技术进行。 我们已经知道,通信可以在相关或不相关的进程之间进行。 通常,使用管道或命名管道来执行相互关联的进程通信。 可以使用命名管道或通过共享内存和消息队列的常用IPC技术执行无关
EasySwoole对Swoole table进行了基础的封装。 方法列表 getInstance() 该方法用于获取TableManager管理器实例 add($name,array $columns,$size = 1024) 该方法用于创建一个table get($name):?Table 该方法用于获取已经创建好的table 示例代码 TableManager::getInstance()