Linux共享記憶體的核心實現
1 功能
System V共享記憶體作為多程式間通訊的最高效手段,是因為:
1、 其將實體記憶體直接對映為虛擬地址,通過虛擬地址即可直接訪問資料,避免了rd/wr等系統呼叫的開銷
2、 其避免了msg及socket通訊方式的資料拷貝過程
基本原理介紹可參考“Linux環境程式間通訊(五): 共享記憶體(下)”
2 示例程式碼
/**********************************************************
*實驗要求: 建立兩個程式,通過共享記憶體進行通訊。
*功能描述: 本程式申請了上一段程式相同的共享記憶體塊,然後迴圈向共享中
* 寫資料,直至寫入“end”。
*日 期: 2010-9-17
*作 者: 國嵌
**********************************************************/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "shm_com.h"
/*
* 程式入口
**/
int main(void)
{
int running=1;
void *shared_memory=(void *)0;
struct shared_use_st *shared_stuff;
char buffer[BUFSIZ];
int shmid;
/*建立共享記憶體*/
shmid=shmget((key_t)1234,sizeof(structshared_use_st),0666|IPC_CREAT);
if(shmid==-1)
{
fprintf(stderr,"shmget failed\n");
exit(EXIT_FAILURE);
}
/*對映共享記憶體*/
shared_memory=shmat(shmid,(void *)0,0);
if(shared_memory==(void *)-1)
{
fprintf(stderr,"shmat failed\n");
exit(EXIT_FAILURE);
}
printf("Memory attached at %X\n",(int)shared_memory);
/*讓結構體指標指向這塊共享記憶體*/
shared_stuff=(struct shared_use_st *)shared_memory;
/*迴圈的向共享記憶體中寫資料,直到寫入的為“end”為止*/
while(running)
{
while(shared_stuff->written_by_you==1)
{
sleep(1);//等到讀程式讀完之後再寫
printf("waiting for client...\n");
}
printf("Ener some text:");
fgets(buffer,BUFSIZ,stdin);
strncpy(shared_stuff->some_text,buffer,TEXT_SZ);
shared_stuff->written_by_you=1;
if(strncmp(buffer,"end",3)==0)
{
running=0; //結束迴圈
}
}
/*detach共享記憶體*/
if(shmdt(shared_memory)==-1)
{
fprintf(stderr,"shmdt failed\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
/**********************************************************
*實驗要求: 建立兩個程式,通過共享記憶體進行通訊。
*功能描述: 本程式申請和分配共享記憶體,然後輪訓並讀取共享中的資料,直至
* 讀到“end”。
*日 期: 2010-9-17
*作 者: 國嵌
**********************************************************/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "shm_com.h"
/*
* 程式入口
**/
int main(void)
{
int running=1;
void *shared_memory=(void *)0;
struct shared_use_st *shared_stuff;
int shmid;
/*建立共享記憶體*/
shmid=shmget((key_t)1234,sizeof(structshared_use_st),0666|IPC_CREAT);
if(shmid==-1)
{
fprintf(stderr,"shmget failed\n");
exit(EXIT_FAILURE);
}
/*對映共享記憶體*/
shared_memory=shmat(shmid,(void *)0,0);
if(shared_memory==(void *)-1)
{
fprintf(stderr,"shmat failed\n");
exit(EXIT_FAILURE);
}
printf("Memory attached at %X\n",(int)shared_memory);
/*讓結構體指標指向這塊共享記憶體*/
shared_stuff=(struct shared_use_st *)shared_memory;
/*控制讀寫順序*/
shared_stuff->written_by_you=0;
/*迴圈的從共享記憶體中讀資料,直到讀到“end”為止*/
while(running)
{
if(shared_stuff->written_by_you)
{
printf("You wrote:%s",shared_stuff->some_text);
sleep(1); //讀程式睡一秒,同時會導致寫程式睡一秒,這樣做到讀了之後再寫
shared_stuff->written_by_you=0;
if(strncmp(shared_stuff->some_text,"end",3)==0)
{
running=0; //結束迴圈
}
}
}
/*刪除共享記憶體*/
if(shmdt(shared_memory)==-1)
{
fprintf(stderr,"shmdt failed\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
3 主要資料結構及其關係
通過上面的示例程式碼我們大概瞭解了共享記憶體的使用者API,但其是如何實現的呢,讓我們來一探究竟。首先介紹相關的主要資料結構。
3.1 ipc_params
該資料結構為使用者空間和核心空間通訊的API,key、flg、size為建立共享記憶體的必備引數
/*
*Structure that holds the parameters needed by the ipc operations
*(see after)
*/
struct ipc_params {
key_t key;
intflg;
union{
size_t size; /* for shared memories */
intnsems; /* for semaphores */
}u; /* holds thegetnew() specific param */
};
3.2 shmid_kernel
shmid_kernel一個共享記憶體區在核心態的ipc標識
8 struct shmid_kernel /* private to thekernel */
9 {
10 struct kern_ipc_perm shm_perm;
11 struct file *shm_file; /* 定位共享記憶體在ramfs中的inode */
12 unsigned long shm_nattch; /* 被對映的次數,為0時才能刪除此共享記憶體區*/
13 unsigned long shm_segsz; /* 為使用者態傳遞下來的共享記憶體區size*/
14 time_t shm_atim;
15 time_t shm_dtim;
16 time_t shm_ctim;
17 pid_t shm_cprid;
18 pid_t shm_lprid;
19 struct user_struct *mlock_user;
20
21 /* The task created the shmobject. NULL if the task is dead. */
22 struct task_struct *shm_creator;
23 };
3.3 kern_ipc_perm
kern_ipc_perm儲存使用者態shm key值和核心態的shmid及其他許可權資訊
10 /* used by in-kernel data structures*/
11 struct kern_ipc_perm
12 {
13 spinlock_t lock;
14 bool deleted;
15 int id; /* shm的核心標識,同一個key多次對映的shmid可能不一樣*/
16 key_t key; /* 使用者空間用於識別shm的key標識,該key標識可以靜態約定或者根據某個值唯一標識,避免衝突*/
17 kuid_t uid;
18 kgid_t gid;
19 kuid_t cuid;
20 kgid_t cgid;
21 umode_t mode;
22 unsigned long seq;
23 void *security;
24 };
3.4 shm_file_data
當程式attach到某個共享記憶體區時,即建立該資料結構,後續所有操作都通過該資料結構訪問到其他所有資訊。
struct shm_file_data {
intid;
structipc_namespace *ns;
structfile *file;
conststruct vm_operations_struct *vm_ops;
};
3.5 shm_file_operations
static const struct file_operationsshm_file_operations = {
.mmap = shm_mmap,
.fsync = shm_fsync,
.release = shm_release,
};
3.6 shm_vm_ops
static const struct vm_operations_structshm_vm_ops = {
.open = shm_open, /* callback for a new vm-area open */
.close = shm_close, /* callback for when the vm-area is released */
.fault = shm_fault,
};
3.7 ipc_ops
/*
*Structure that holds some ipc operations. This structure is used to unify
*the calls to sys_msgget(), sys_semget(), sys_shmget()
* .routine to call to create a new ipc object. Can be one of newque,
* newary, newseg
* .routine to call to check permissions for a new ipc object.
* Can be one of security_msg_associate, security_sem_associate,
* security_shm_associate
* .routine to call for an extra check if needed
*/
struct ipc_ops {
int(*getnew) (struct ipc_namespace *, struct ipc_params *);
int(*associate) (struct kern_ipc_perm *, int);
int(*more_checks) (struct kern_ipc_perm *, struct ipc_params *);
};
shm_ops.getnew = newseg;
shm_ops.associate = shm_security;
shm_ops.more_checks = shm_more_checks;
3.8 資料結構之間的關係
隨著共享記憶體的建立、對映、訪問等過程,最終會在建立如下的資料資訊關聯表,通過此表即可完全搞懂共享記憶體的內部原理。
4 建立or開啟share memory
4.1 主流程
以key為關鍵字獲取shm資訊。若在ipc中未建立,則在shm檔案系統(tempfs)裡分配一個inode,其對應檔案為/SYSV-shmid(使用者態不可見),並分配一個file檔案描述符指向此inode的dentry,並儲存在ipc shm資料結構shmid_kernel裡,並返回shmid。若已經建立,則獲取shmid即可。
共享記憶體的實體地址儲存在inode的struct address_space*i_mapping域的structradix_tree_root page_tree; /* radix treeof all pages */成員中。共享記憶體也使用了page cache的框架來管理物理頁,但並不是通過read/write等系統呼叫方式來訪問共享記憶體“檔案”。
在核心態建立的相關資料關聯資訊如下:
黃色是使用者態的引數輸入,藍色部分是shmget過程中動態建立的資訊,其中shmid為最終返回值。
用systemtap(可參考文章)監測到的函式呼叫棧資訊如下:
-------------------------------------
shmem_alloc_inode(sb=0xf5c3ac00)
0xc1153110 : shmem_alloc_inode+0x0/0x30[kernel]
0xc11a5a50 : alloc_inode+0x20/0x80 [kernel]
0xc11a7ba6 : new_inode_pseudo+0x16/0x60[kernel]
0xc11a7c07 : new_inode+0x17/0x30 [kernel]
0xc115409b : shmem_get_inode+0x2b/0x170[kernel]
0xc11545c4 : shmem_file_setup+0xb4/0x1b0[kernel]
0xc12915b9 : newseg+0x239/0x2a0 [kernel]
0xc128dc51 : ipcget+0x111/0x1d0 [kernel]
0xc1291cf2 : sys_shmget+0x52/0x60 [kernel]
0xc1292b39 : sys_ipc+0x249/0x280 [kernel]
0xc161abb4 : syscall_call+0x7/0xb [kernel]
-------------------------------------
4.2 Shmget
使用者空間以key為關鍵字來區分不同的share memory
SYSCALL_DEFINE3(shmget, key_t, key, size_t,size, int, shmflg)
{
structipc_namespace *ns;
structipc_ops shm_ops;
structipc_params shm_params;
ns= current->nsproxy->ipc_ns;
shm_ops.getnew = newseg;
shm_params.key = key;
shm_params.flg = shmflg;
shm_params.u.size = size;
returnipcget(ns, &shm_ids(ns), &shm_ops, &shm_params);
}
4.3 ipcget_public
/**
* ipcget_public - get an ipc object or create anew one
* @ns: namespace
* @ids: IPC identifer set
* @ops: the actual creation routine to call
* @params: its parameters
*
* This routine is called by sys_msgget,sys_semget() and sys_shmget()
* when the key is not IPC_PRIVATE.
* It adds a new entry if the key is not found and does somepermission
* /security checkings if the key is found.
*
* On success, the ipc id is returned.
*/
static int ipcget_public(structipc_namespace *ns, struct ipc_ids *ids,
structipc_ops *ops, struct ipc_params *params)
{
ipcp = ipc_findkey(ids,params->key);
if(ipcp == NULL) {
/*key not used */
if(!(flg & IPC_CREAT))
err= -ENOENT;
else
err = ops->getnew(ns,params);
}else {
if(ops->more_checks)
err= ops->more_checks(ipcp, params);
}
}
以key為關鍵字在現有的share memory例項中查詢,查詢失敗,則ops->getnew(ns,params)建立一個新的shm例項;查詢成功,做一些必要的安全性檢查即可。
4.4 newseg
/**
*newseg - Create a new shared memory segment
* @params: ptr to the structure thatcontains key, size and shmflg
*/
static int newseg(struct ipc_namespace *ns,struct ipc_params *params)
{
key_tkey = params->key;
intshmflg = params->flg;
size_tsize = params->u.size;
structshmid_kernel *shp;
int numpages = (size + PAGE_SIZE-1) >> PAGE_SHIFT; /* 計算shm檔案大小*/
structfile * file;
shp= ipc_rcu_alloc(sizeof(*shp));
shp->shm_perm.key= key;
shp->shm_perm.mode= (shmflg & S_IRWXUGO);
sprintf(name, "SYSV%08x", key); /* shm檔名稱,包含keyid */
file= shmem_file_setup(name, size, acctflag); /* 在shm的tempfs中建立一個檔案inode節點,並返回一個檔案描述符,檔案存在哪個路徑了呢??是個隱藏檔案,使用者空間看不到!!*/
id= ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni);
shp->shm_segsz= size;
shp->shm_nattch= 0;
shp->shm_file = file; /* 將file指標儲存在ipc shmid_kernel中shp->shm_file 中以備後用 */
/*
* shmid gets reported as "inode#" in /proc/pid/maps.
* proc-ps tools use this. Changing this willbreak them.
*/
file->f_dentry->d_inode->i_ino= shp->shm_perm.id; /* shm ID作為inodenumber */
error= shp->shm_perm.id;
returnerror;
}
4.5 shmem_file_setup
/**
*shmem_file_setup - get anunlinked file living in tmpfs
*@name: name for dentry (to be seen in /proc/<pid>/maps
*@size: size to be set for the file
*/
struct file *shmem_file_setup(const char*name, loff_t size, unsigned long flags)
{
interror;
structfile *file;
structinode *inode;
structpath path;
structdentry *root;
error= -ENOMEM;
this.name= name;
this.len= strlen(name);
root= shm_mnt->mnt_root;
path.dentry= d_alloc(root, &this); /*在shm所mount檔案系統根目錄下建立dentry節點 */
path.mnt= mntget(shm_mnt);
inode= shmem_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0, flags); /* 建立inode節點 */
d_instantiate(path.dentry,inode); /* 將dentry和inode節點關聯起來 */
inode->i_size= size;
file= alloc_file(&path, FMODE_WRITE | FMODE_READ,
&shmem_file_operations); /*分配一個file檔案描述符指向該inode節點,並指定該檔案操作指標為shmem_file_operations */
returnfile;
}
EXPORT_SYMBOL_GPL(shmem_file_setup);
4.6 alloc_file
分配一個file描述符,並指向引數中的dentry和inode,並初始化file operations指標
http://lxr.free-electrons.com/source/fs/file_table.c#L166
/**
*alloc_file - allocate and initialize a 'struct file'
* @mnt: the vfsmount on whichthe file will reside
*@dentry: the dentry representing the new file
*@mode: the mode with which the new file will be opened
* @fop: the 'structfile_operations' for the new file
*/
struct file *alloc_file(struct path *path,fmode_t mode,
conststruct file_operations *fop)
{
structfile *file;
file= get_empty_filp();
file->f_path= *path;
file->f_mapping =path->dentry->d_inode->i_mapping;
file->f_mode= mode;
file->f_op = fop;
}
EXPORT_SYMBOL(alloc_file);
4.7 使用者態資訊
drq@ubuntu:/mnt/hgfs/systemtap$ ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x000004d2 32768 drq 666 2052 0
drq@ubuntu:/mnt/hgfs/systemtap/share-m$ cat/proc/sysvipc/shm
key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime rss swap
1234 65536 666 2052 6924 6924 1 1000 1000 1000 1000 1411221835 0 1411221835 4096 0
drq@ubuntu:/mnt/hgfs/systemtap/share-m$
drq@ubuntu:/mnt/hgfs/systemtap/share-m$ cat/proc/meminfo | grep Shmem
Shmem: 144 kB
drq@ubuntu:/mnt/hgfs/systemtap/share-m$mount
/dev/sda1 on / type ext4(rw,errors=remount-ro)
tmpfs on /run type tmpfs(rw,noexec,nosuid,size=10%,mode=0755)
none on /run/shm type tmpfs (rw,nosuid,nodev)
drq@ubuntu:/mnt/hgfs/systemtap/share-m$ df-h
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 39G 17G 20G 47% /
udev 494M 4.0K 494M 1% /dev
tmpfs 201M 812K 200M 1% /run
none 5.0M 0 5.0M 0% /run/lock
none 501M 152K 501M 1% /run/shm
5 attach到share memory
5.1 主流程
以shmid attach到shm上,最終在程式空間分配一塊記憶體區域vm_area_struct指向shm檔案的物理頁,加入程式的記憶體描述符current->mm,此vm_area_struct可通過cat /proc/$pid/maps檢視。
在核心態建立的資料關聯資訊如下:
紅色部分為shmat期間在核心新建立的資料資訊,並最終返回vm_start即使用者可直接訪問的使用者態地址。
用systemtap監測到的函式呼叫棧資訊如下:
-------------------------------------
shmem_mmap(file=0xc4b42e40 vma=0xddacb000)
0xc11544e0 : shmem_mmap+0x0/0x30 [kernel]
0xc12918d2 : shm_mmap+0x22/0x60 [kernel]
0xc1169380 : mmap_region+0x3d0/0x590 [kernel]
0xc1169726 : do_mmap_pgoff+0x1e6/0x2d0[kernel]
0xc12925af : do_shmat+0x30f/0x3c0 [kernel]
0xc1292af2 : sys_ipc+0x202/0x280 [kernel]
0xc161abb4 : syscall_call+0x7/0xb [kernel]
-------------------------------------
-------------------------------------
shm_open(vma=0xddacb000)
0xc1291850 : shm_open+0x0/0x60 [kernel]
0xc12918f3 : shm_mmap+0x43/0x60 [kernel]
0xc1169380 : mmap_region+0x3d0/0x590 [kernel]
0xc1169726 : do_mmap_pgoff+0x1e6/0x2d0[kernel]
0xc12925af : do_shmat+0x30f/0x3c0 [kernel]
0xc1292af2 : sys_ipc+0x202/0x280 [kernel]
0xc161abb4 : syscall_call+0x7/0xb [kernel]
-------------------------------------
5.2 do_shmat
建立share memory後,以shmid進行後續訪問操作
SYSCALL_DEFINE3(shmat, int, shmid, char__user *, shmaddr, int, shmflg)
{
err= do_shmat(shmid, shmaddr, shmflg, &ret);
return(long)ret;
}
/*
*Fix shmaddr, allocate descriptor, map shm, add attach descriptor to lists.
*/
long do_shmat(int shmid, char __user*shmaddr, int shmflg, ulong *raddr)
{
struct shmid_kernel *shp;
unsignedlong addr;
unsignedlong size;
structfile * file;
structpath path;
ns= current->nsproxy->ipc_ns;
shp = shm_lock_check(ns, shmid); /*通過shmid找到ipc資料結構shmid_kernel */
path= shp->shm_file->f_path; /* 獲得共享檔案的路徑 */
path_get(&path);
shp->shm_nattch++;
size =i_size_read(path.dentry->d_inode); /*根據dentry找到inode,獲取檔案大小 */
sfd= kzalloc(sizeof(*sfd), GFP_KERNEL); /*每個程式自身維護的資訊*/
file = alloc_file(&path,f_mode,
is_file_hugepages(shp->shm_file) ?
&shm_file_operations_huge:
&shm_file_operations); /* 分配一個新檔案描述符指向共享檔案,檔案訪問指標為shm_file_operations)*/
file->private_data= sfd;
file->f_mapping= shp->shm_file->f_mapping; /*指向共享檔案的address_space */
sfd->id= shp->shm_perm.id; /* 儲存shmid*/
sfd->ns= get_ipc_ns(ns);
sfd->file = shp->shm_file;/*指向共享檔案的file描述符 */
sfd->vm_ops = NULL;
user_addr = do_mmap (file, addr,size, prot, flags, 0);
*raddr = user_addr; /* 返回在程式空間分配的虛擬地址空間指標*/
}
5.3 shm_mmap
do_mmap最終呼叫shm_file_operations的shm_mmap
static int shm_mmap(struct file * file,struct vm_area_struct * vma)
{
structshm_file_data *sfd = shm_file_data(file);
intret;
ret =sfd->file->f_op->mmap(sfd->file, vma); /*最終呼叫shmem_file_setup階段建立的shm裡的file檔案的f_op指標shmem_file_operations中的mmap實現shmem_mmap*/
sfd->vm_ops= vma->vm_ops; /* shmem_vm_ops */
vma->vm_ops =&shm_vm_ops; /* 將shmem_vm_ops替換為shm_vm_ops,以便vm_ops的其他地方可以進行額外封裝處理如shm_open */
shm_open(vma);
returnret;
}
5.4 shmem_mmap
static int shmem_mmap(struct file *file,struct vm_area_struct *vma)
{
file_accessed(file);
vma->vm_ops= &shmem_vm_ops;
vma->vm_flags|= VM_CAN_NONLINEAR;
return0;
}
5.5 shm_open
程式attache到shm後,更新相關訪問資訊如時間,attach的個數
/* This is called by fork, once for everyshm attach. */
static void shm_open(struct vm_area_struct*vma)
{
structfile *file = vma->vm_file;
structshm_file_data *sfd = shm_file_data(file);
structshmid_kernel *shp;
shp= shm_lock(sfd->ns, sfd->id);
BUG_ON(IS_ERR(shp));
shp->shm_atim= get_seconds();
shp->shm_lprid= task_tgid_vnr(current);
shp->shm_nattch++;
shm_unlock(shp);
}
5.6 使用者態資訊
程式attach到shm後,其nattch會增加
drq@ubuntu:/mnt/hgfs/systemtap$ ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x000004d2 262144 drq 666 2052 1
可以從程式mm中看到對映的虛擬地址空間
drq@ubuntu:/mnt/hgfs/systemtap/share-m$ ps-ef | grep sh-read
drq 11803 5829 99 02:00 pts/7 00:00:17 ./sh-read
b76f0000-b76f1000為shm對映後的虛擬地址空間,/SYSV000004d2為shm的虛擬檔案
drq@ubuntu:/mnt/hgfs/systemtap/share-m$ cat/proc/11803/maps | grep SYS
b76f0000-b76f1000 rw-s 00000000 00:04262144 /SYSV000004d2 (deleted)
6 資料訪問
使用者空間經過shmat後,得到用於訪問共享記憶體的虛擬地址,即可以通過該地址直接訪問共享的實體記憶體。但因為頁表尚未建立起來,因此觸發page fault,然後建立頁表。
-------------------------------------
shmem_fault(vma=0xddacb000 vmf=0xc25cbe7c)
0xc1155eb0 : shmem_fault+0x0/0x90 [kernel]
0xc12911a4 : shm_fault+0x14/0x20 [kernel]
0xc11606ce : __do_fault+0x6e/0x550 [kernel]
0xc11631cf : handle_pte_fault+0x8f/0xaf0[kernel]
0xc1164d4d : handle_mm_fault+0x1dd/0x280[kernel]
0xc161ddea : do_page_fault+0x15a/0x4b0[kernel]
0xc161b2a3 : error_code+0x67/0x6c [kernel]
-------------------------------------
6.1 shm_fault
在shm_mmap的最後將vm_operations的操作指標更新為了shm_vm_ops,其page fault處理函式為shm_fault。其最終仍然呼叫的是shmem_vm_ops的shmem_fault
static int shm_fault(struct vm_area_struct*vma, struct vm_fault *vmf)
{
structfile *file = vma->vm_file;
structshm_file_data *sfd = shm_file_data(file);
returnsfd->vm_ops->fault(vma,vmf);
}
6.2 shmem_fault
shmem_fault根據產生缺頁異常的線性地址找到對應的物理頁(vma->vm_file->f_path.dentry->d_inode),並將這個物理頁加入頁表,之後使用者就可以像訪問本地資料一樣直接訪問共享記憶體
static int shmem_fault(structvm_area_struct *vma, struct vm_fault *vmf)
{
struct inode *inode =vma->vm_file->f_path.dentry->d_inode;
interror;
intret;
if(((loff_t)vmf->pgoff << PAGE_CACHE_SHIFT) >= i_size_read(inode))
returnVM_FAULT_SIGBUS;
error= shmem_getpage(inode, vmf->pgoff,&vmf->page, SGP_CACHE, &ret);
if(error)
return((error == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS);
returnret | VM_FAULT_LOCKED;
}
7 Detach shm
Detach shm時只會將進城對應的mm_struct資訊release,但不會刪除shm自身。其中shm_nattch--。
-------------------------------------
shm_close(vma=0xddadf8f0)
0xc1291910 : shm_close+0x0/0xb0 [kernel]
0xc1167086 : remove_vma+0x26/0x60 [kernel]
0xc1168a5c : do_munmap+0x21c/0x2e0 [kernel]
0xc129272b : sys_shmdt+0x9b/0x140 [kernel]
0xc1292b1b : sys_ipc+0x22b/0x280 [kernel]
0xc161abb4 : syscall_call+0x7/0xb [kernel]
-------------------------------------
-------------------------------------
shm_release(ino=0xf69f9e50 file=0xddbdb540)
0xc1291330 : shm_release+0x0/0x40 [kernel]
0xc1190ab6 : fput+0xe6/0x210 [kernel]
0xc1167092 : remove_vma+0x32/0x60 [kernel]
0xc1168a5c : do_munmap+0x21c/0x2e0 [kernel]
0xc129272b : sys_shmdt+0x9b/0x140 [kernel]
0xc1292b1b : sys_ipc+0x22b/0x280 [kernel]
0xc161abb4 : syscall_call+0x7/0xb [kernel]
-------------------------------------
8 刪除share memory
相關命令如下:
drq@ubuntu:/mnt/hgfs/systemtap$ ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 262144 drq 666 2052 1 dest
drq@ubuntu:/mnt/hgfs/systemtap$ ipcrm -m262144
drq@ubuntu:/mnt/hgfs/systemtap$ ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
程式可以通過shmctl IO呼叫刪除shm。
轉自 http://blog.csdn.net/sailor_8318/article/details/39484747
相關文章
- linux共享記憶體Linux記憶體
- Linux共享記憶體的管理Linux記憶體
- Linux共享記憶體(二)Linux記憶體
- linux共享記憶體段研究Linux記憶體
- 有管理共享記憶體設計方法的具體實現記憶體
- 資料庫實現原理#6(共享記憶體)資料庫記憶體
- linux下的記憶體共享引數Linux記憶體
- 共享記憶體記憶體
- live555實現共享記憶體視訊直播記憶體
- OpenResty 和 Nginx 的共享記憶體區是如何消耗實體記憶體的RESTNginx記憶體
- Linux:深入淺出 Linux 共享記憶體Linux記憶體
- 實現共享記憶體的又一方法 (轉)記憶體
- Golang 共享記憶體Golang記憶體
- POSIX共享記憶體記憶體
- oracle 共享記憶體Oracle記憶體
- POSIX 共享記憶體記憶體
- linux程式間的通訊(C): 共享記憶體Linux記憶體
- linux記憶體管理(一)實體記憶體的組織和記憶體分配Linux記憶體
- php實現共享記憶體程式通訊函式之_shmPHP記憶體函式
- Linux釋放記憶體及手動釋放Oracle共享記憶體段Linux記憶體Oracle
- Linux程式間通訊之共享記憶體Linux記憶體
- Linux程式間通訊——使用共享記憶體Linux記憶體
- nginx共享記憶體分析Nginx記憶體
- QT之共享記憶體QT記憶體
- 共享記憶體函式記憶體函式
- shmget() -- 建立共享記憶體記憶體
- SGA與共享記憶體記憶體
- Linux核心記憶體管子系統分析Linux記憶體
- nginx中共享記憶體的使用Nginx記憶體
- UNIX共享記憶體的程式(轉)記憶體
- Linux核心筆記004 - 從記憶體管理開始,認識Linux核心Linux筆記記憶體
- 給PHP開啟shmop擴充套件實現共享記憶體PHP套件記憶體
- java記憶體模型的實現Java記憶體模型
- 程式間通訊——基於共享記憶體和訊號量實現共享佇列記憶體佇列
- 自動共享記憶體管理 自動記憶體管理 手工記憶體管理記憶體
- linux mmap應用與驅動共享記憶體Linux記憶體
- C++記憶體管理:簡易記憶體池的實現C++記憶體
- 求助:關於linux下共享記憶體的問題(轉)Linux記憶體