一.共享内存知识
共享内存是指多个进程之间共同使用同一物理内存空间,通过将同一物理内存映射到不同进程的虚拟空间来实现。 映射到不同进程的虚拟空间时,不同进程可以直接使用,不需要像消息队列那样进行复制,所以共享内存效率很高。 共享内存(mmap ) )可以通过映射常规文件机制实现,也可以通过系统v共享内存机制实现,通过映射特殊文件系统shm中的文件实现进程之间的共享内存通信。 这意味着每个共享内存区域对应于特殊文件系统shm中的一个文件。
二.共享内存原理
System V共享内存将所有共享数据放在共享内存区域。 访问此数据的进程必须在此进程的地址区域中添加内存空间,以映射存储共享数据的物理内存页。 System V共享内存使用shmget函数获取或创建IPC共享内存区域,并返回相应的标识符。 内核确保shmget获取或创建共享内存区域,并初始化共享内存区域的相应shmid_kernel结构。 它还会在特殊文件系统shm中创建并打开一个同名的文件,并在内存中为该文件创建相应的dentry和innel结构
三. sysctl.conf配置文件
以上两个说明部分是从互联网上找到的理解的内容。 作为Linux系统维护人员,您可以访问的与共享内存相关的设置主要是/etc/sysctl.conf中的一些配置。 具体情况如下。
kernel.shmmax=4398046511104
kernel.shmall=1073741824
kernel.shmmni=4096
以下是redhat6官方提供的有关安装了oracle的文档的共享内存的部分说明。
完整版的redhat官方文档请看这里。
需要注意的是,虽然free -m命令的输出中也包含shared,但当您查看多个主机时,这都是0,free命令共享内存是废弃的,以后再找资料以确保没有任何作用。 因此,在本项目中无法确认共享内存的显示。
四. ipcs和ipcrm
ipcs
ipcs是在Linux上显示进程间通信设备状态的工具。 可以显示消息队列、共享内存和信号量的信息。 对程序员非常有用,一般的系统管理员不能使用这个命令。
$ipcs -m显示系统使用的IPC共享内存资源
显示$ipcs -q系统使用的IPC队列资源
$ipcs -s显示系统使用的IPC信号量资源
查看$ipcs -l系统参数配置
缺省情况下,如果不指定参数,则使用的参数为-a(all,显示全部)
输出示例如下。
# ipcs
-----消息队列----- -消息队列
keymsqidownerpermsused-bytes消息
------sharedmemorysegments------ sharedmemorysegments
keyshmidownerpermsbytesnattchstatus
0x6c 04 c 831294912 zabbix 600219056
0x0112be9b458753路由60010007
0x 0112 be9d 491522 root 60012007127
------semaphore arrays------ semaphore arrays
key semid owner perms nsems
0x7a04c831 1245184 zabbix 600 13
0x00000000 1802241 apache 600 1
0x00000000 1835010 apache 600 1
ipcrm
使用ipcrm命令清除IPC资源。 此命令还会删除与IPC对象相关联的数据。 当然,只有root用户或ipc对象的创建者具有此权利;
ipcrm -M shmkey删除使用shmkey创建的共享内存段
ipcrm -m shmid删除由shmid标识的共享内存段
ipcrm -Q msgkey删除用msqkey创建的消息队列
删除由ipcrm-qmsqidmsqid标识的消息队列
ipcrm -S semkey删除用semkey创建的信号
ipcrm -s semid删除由semid识别的信号
以下是ipcs与ipcrm配合使用的资源示例。
IPCS-q|awk ' { print ' ipcrm-q ' $2} '|sh/dev/null 21;
IPCS-m|awk ' { print ' ipcrm-m ' $2} '|sh/dev/null 21;
IPCS-s|awk ' { print ' ipcrm-s ' $2} '|sh/dev/null 21;
ipcs的其他应用
您还可以使用ipcs检查用户是否有消息队列堆栈。
1、查询消息队列$ipcs -q
-----消息队列----- -消息队列
keymsqidownerpermsused-bytes消息
0x49060005 58261504 user1 660 0 0
0x4f060005 58294273 user1 660 0 0
2、找到消息大于0的队列
$IPCs-q|grepuser1|awk'{if($50 ) print $0}
0x 000000001071579324 user 164419545304826
0x 000000001071644862 user 164419618204844
0x 000000001071677631 user 164419448104802
0x 000000001071710400 user 164419618204844
五.为什么需要手动释放共享内存
在Linux上使用API函数shmget创建的共享内存通常由程序使用shmctl释放,但开发人员可能会通过Ctrl C等发送中断信号来终止程序以调试程序。 在这种情况下,如果程序没有更改,再次运行程序时将使用上次申请的共享内存,但如果修改了程序,由于共享内存大小不一致等原因,我们总是希望在每次退出时释放申请的共享内存
有两种方法可以释放共享内存。
第一,如果总是以Crtl C结束,则可以制作信号处理器在接收到这个信号时释放共享内存,然后结束程序。
第二,如果无论如何退出程序都不会释放共享内存,则可以使用linux命令ipcrm shm shmid将其释放。 使用此命令之前,可以使用ipcs -m命令显示共享内存。