共享內存
共享內存概念
所謂共享內存,就是多個進程間共同地使用同一段物理內存空間,它是通過將同一段物理內存映射到不同進程的虛擬空間來實現的。由於映射到不同進程的虛擬空間中,不同進程可以直接使用,不需要像消息隊列那樣進行復制,所以共享內存的效率很高。共享內存可以通過mmap()映射普通文件機制來實現,也可以System V共享內存機制來實現,System V是通過映射特殊文件系統shm中的文件實現進程間的共享內存通信,也就是說每個共享內存區域對應特殊文件系統shm中的一個文件。
共享內存原理
System V共享內存把所有共享數據放在共享內存區,任何想要訪問該數據的進程都必須在本進程的地址空間新增一塊內存區域,用來映射存放共享數據的物理內存頁面。 System V共享內存通過shmget函數獲得或創建一個IPC共享內存區域,並返回相應的標識符,內核在保證shmget獲得或創建一個共享內存區,初始化該共享 內存區相應的shmid_kernel結構,同時還將在特殊文件系統shm中創建並打開一個同名文件,並在內存中建立起該文件的相應的dentry及 inode結構,新打開的文件不屬於任何一個進程,所有這一切都是系統調用shmget函數完成的。
共享內存相關配置說明
Linux運維人員涉及的共享內存相關配置主要是/etc/sysctl.conf
kernel.shmmax = 4398046511104 # 配置了最大的內存segment的大小 kernel.shmall = 1073741824 # 全部允許使用的共享內存大小 kernel.shmmni = 4096 # 整個系統的內存segment的總個數
ipcs與ipcrm
ipcs
ipcs是Linux下顯示進程間通信設施狀態的工具。可以顯示消息隊列、共享內存和信號量的信息。對於程序員非常有用,普通的系統管理員一般用不到此指令。
[root@saltstack ~]# ipcs -h ipcs provides information on ipc facilities for which you have read access. Resource Specification: -m : shared_mem # 查看系統使用的IPC共享內存資源 -q : messages # 查看系統使用的IPC隊列資源 -s : semaphores # 查看系統使用的IPC信號量資源 -a : all (default) # 默認顯示所有 Output Format: -t : time -p : pid -c : creator -l : limits -u : summary -i id [-s -q -m] : details on resource identified by id usage : ipcs -asmq -tclup ipcs [-s -m -q] -i id ipcs -h for help.
[root@saltstack ~]# ipcs ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status ------ Semaphore Arrays -------- key semid owner perms nsems 0x00000000 0 root 600 1 0x00000000 32769 root 600 1 ------ Message Queues -------- key msqid owner perms used-bytes messages
ipcrm
使用ipcrm 命令來清除IPC資源:這個命令同時會將與ipc對象相關聯的數據也一起移除。當然,只有root用戶,或者ipc對象的創建者才有這項權利;
[root@saltstack ~]# ipcrm usage: ipcrm [ [-q msqid] [-m shmid] [-s semid] [-Q msgkey] [-M shmkey] [-S semkey] ... ] -M:移除用shmkey創建的共享內存段 -m:移除用shmid標識的共享內存段 -Q:移除用msqkey創建的消息隊列 -q:移除用msqid標識的消息隊列 -S:移除用semkey創建的信號 -s:移除用semid標識的信號
ipcs與ipcrm配合清理使用的資源案例:
ipcs -q | awk '{ print "ipcrm -q "$2}' | sh > /dev/null 2>&1; ipcs -m | awk '{ print "ipcrm -m "$2}' | sh > /dev/null 2>&1; ipcs -s | awk '{ print "ipcrm -s "$2}' | sh > /dev/null 2>&1;
ipcs的其他應用
使用ipcs還可以用以確認某個用戶是否存在消息隊列的堆積 1、查詢消息隊列 $ipcs -q ------ Message Queues -------- key msqid owner perms used-bytes messages 0x49060005 58261504 user1 660 0 0 0x4f060005 58294273 user1 660 0 0 2、找出messages大於0的隊列 $ ipcs -q |grep user1 |awk '{if($5>0) print $0}' 0x00000000 1071579324 user1 644 1954530 4826 0x00000000 1071644862 user1 644 1961820 4844 0x00000000 1071677631 user1 644 1944810 4802 0x00000000 1071710400 user1 644 1961820 4844
為什么需要手動釋放共享內存?
Linux中通過API函數shmget創建的共享內存一般都是在程序中使用shmctl來釋放的,但是有時為了調試程序,開發人員可能通過Ctrl + C等方式發送中斷信號來結束程序,此時程序申請的共享內存就不能得到釋放,當然如果程序沒有改動的話,重新運行程序時仍然會使用上次申請的共享內存,但是如果我們修改了程序,由於共享內存的大小不一致等原因會導致程序申請共享內存錯誤。因此,我們總是希望每次結束時就能釋放掉申請的共享內存。
有兩種方法可以用來釋放共享內存:
第一種:如果總是通過Crtl+C來結束的話,可以做一個信號處理器,當接收到這個信號的時候,先釋放共享內存,然后退出程序。
第二種:不管你以什么方式結束程序,如果共享內存還是得不到釋放,那么可以通過linux命令ipcrm shm shmid來釋放,在使用該命令之前可以通過ipcs -m命令來查看共享內存。
