在使用共享內存的程序異常退出時,由於沒有釋放掉共享內存,在調試時會出現錯誤。您可以使用shell命令來查看與釋放已經分配的共享內存,下面將詳細說明如何進行查看和釋放分配的共享內存的方法。
預備知識
Linux中通過API函數shmget創建的共享內存一般都是在程序中使用shmctl來釋放的,但是有時爲了調試程序,開發人員可能通過Ctrl + C等方式發送中斷信號來結束程序,此時程序申請的共享內存就不能得到釋放,當然如果程序沒有改動的話,重新運行程序時仍然會使用上次申請的共享內存,但是如果我們修改了程序,由於共享內存的大小不一致等原因會導致程序申請共享內存錯誤。因此,我們總是希望每次結束時就能釋放掉申請的共享內存。
有兩種方法可以用來釋放共享內存:
第一種:如果總是通過Crtl+C來結束的話,可以做一個信號處理器,當接收到這個信號的時候,先釋放共享內存,然後退出程序。
第二種:不管你以什麼方式結束程序,如果共享內存還是得不到釋放,那麼可以通過linux命令ipcrm shm shmid來釋放,在使用該命令之前可以通過ipcs -m命令來查看共享內存。
共享內存查看
使用ipcs命令,不加如何參數時,會把共享內存、信號量、消息隊列的信息都打印出來,如果只想顯示共享內存信息,使用如下命令:
[root@localhost ~]# ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 1867776 root 600 393216 2 dest
0x00000000 1900545 root 600 393216 2 dest
0x00030021 1703938 zc 666 131104 1
0x0003802e 1736707 zc 666 131104 1
0x00030004 1769476 zc 666 131104 1
0x00038002 1802245 zc 666 131104 1
0x00000000 1933318 root 600 393216 2 dest
0x00000000 1966087 root 600 393216 2 dest
0x00000000 1998856 root 600 393216 2 dest
0x00000000 2031625 root 600 393216 2 dest
0x00000000 2064394 root 600 393216 2 dest
0x0014350c 2261003 cs 666 33554432 2
0x00000000 2129932 root 600 393216 2 dest
0x00000000 2162701 root 600 393216 2 dest
0x00143511 395837454 root 666 1048576 1
其中:
第一列就是共享內存的key;
第二列是共享內存的編號shmid;
第三列就是創建的用戶owner;
第四列就是權限perms;
第五列爲創建的大小bytes;
第六列爲連接到共享內存的進程數nattach;
第七列是共享內存的狀態status。其中顯示“dest”表示共享內存段已經被刪除,但是還有用戶在使用它,當該段內存的mode字段設置爲SHM_DEST時就會顯示“dest”。當用戶調用shmctl的IPC_RMID時,內存先查看多少個進程與這個內存關聯着,如果關聯數爲0,就會銷燬這段共享內存,否者設置這段內存的mod的mode位爲SHM_DEST,如果所有進程都不用則刪除這段共享內存。
共享內存釋放
要釋放共享內存,需要使用ipcrm命令,使用shmid作爲參數,shmid在ipcs命令中會有輸出,下面的命令可以釋放所有已經分片的共享內存:
# ipcrm <shmid>
# ipcs -m | awk ‘$2 ~/[0-9]+/ {print $2}’ | while read s; do sudo ipcrm –m $s; done
注:Linux中vi使用Ctrl+s來鎖定,需要使用Ctrl+q來解除鎖定。
使用Python編寫的rmsharemem.py腳本如下:
# -*- coding: utf-8 -*-
# Remove the share memory
import os
import sys
import getopt
def usage():
print "usage: python rmsharemem.py -h -o <owner> -s size <shmid list>"
print " -h show help information"
print " -o <owner> the owner create share memory need to delete"
print " -s <size> the share memory size"
print " <shmid list> the shmid list need to delete"
def getsharemem():
sharemap = {}
fp = os.popen('ipcs -m')
lines = fp.readlines()
for l in lines:
if not l.startswith('0x'):
continue
s = l.split()
if sharemap.has_key(s[2]):
sharemap[s[2]].append(s)
else:
sharemap[s[2]] = [s]
#print 'Share memory map:\n', sharemap
return sharemap
if __name__ == "__main__":
opts, args = getopt.getopt(sys.argv[1:], "o:hs:")
# opts is the parameter with options
# args is the parameter no ptions
owner = None
size = 0
for o, p in opts:
if o == '-h':
usage()
sys.exit(0)
elif o == '-o':
owner = p
elif o == '-s':
size = p
if not owner:
val = raw_input("Are you sure to remove all share memory?(yes/no)");
if (val <> "yes"):
usage()
sys.exit(0)
count = 0
total = 0
if len(args) > 0:
for shmid in args:
cmd = 'ipcrm -m %s' % shmid
print 'execute command: %s' % cmd
ret = os.system(cmd)
total += 1
if ret == 0:
count += 1
print 'remove %s shared memory success' % shmid
else:
print 'remove %s shared memory failed' % shmid
else:
shmmap = getsharemem()
for o, l in shmmap.items():
if owner and o <> owner:
continue
for p in l:
total += 1
if size and size <> p[4]:
continue
cmd = 'ipcrm -m %s' % p[1]
print 'execute command: %s' % cmd
ret = os.system(cmd)
if ret == 0:
count += 1
print 'remove %s shared memory success' % p[1]
else:
print 'remove %s shared memory failed' % p[1]
print 'total share memory number = %s' % total
print 'remove success number = %s' % count
sys.exit(0)
共享內存大小修改
使用下面的命令查看共享內存的大小:
# cat /proc/sys/kernel/shmmax
修改共享內存大小:
臨時修改:在root用戶下執行# echo 268435456 > /proc/sys/kernel/shmmax把共享內存大小設置爲256MB;
永久修改:在root用戶下修改/etc/rc.d/rc.local文件,加入下面一行:
echo 268435456 > /proc/sys/kernel/shmmax
即可每次啓動時把共享內存修改爲256MB。