shmdt() 与 shmctl() 的区别

http://blog.sina.com.cn/s/blog_818dc7aa0100v3n3.html

操作共享内存,我们用到了下面的函数
==============================================
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int shmid = shmget( key_t shmkey , int shmsize , int flag );
(void *)shmaddr = shmat( int shmid , char *shmaddr , int shmflag );
int shmdt( char *shmaddr );

【shmget】—— 是用来开辟/指向一块共享内存的函数
 参数:
     shmkey    是这块共享内存的标识符,如果是IPC_PRIVATE,则表示使用系统分配的键值创建;
     shmsize   申请内存大小
     flag      标志、权限;
               当只有IPC_CREAT选项打开时,不管是否已存在该块共享内存,则都返回该共享内存的ID,若不存在则创建共享内存;
               当只有IPC_EXCL选项打开时,不管有没有该块共享内存,shmget()都返回-1;(即:单独使用该标志无意义)
               当IPC_CREAT | IPC_EXCL时, 如果没有该块共享内存,则创建,并返回共享内存ID,若已有该块共享内存,则返回-1;
 返回值:
        shmid  内存标识的ID
       
【shmat】—— 链接上指定ID标识的共享内存
 参数:
     shmid     内存标识ID,由shmget()函数返回;
     shmaddr   (输出参数)共享内存的首地址,同该函数返回值一致;
     shmflag   SHM_RDONLY 只读, 0 可读写;(SHM_COPY\SHM_MAP\SHM_RND不在此说明)
 
【shmdt】—— 断开链接的共享内存指针
 参数:
     shmaddr    调用函数shmat()链接上共享内存的指针;

 

当一个进程不再需要共享内存段时,它将调用shmdt()系统调用取消这个段,但是,这并不是从内核真正地删除这个段,而是把相关shmid_ds结构的 shm_nattch域的值减1,当这个值为0时,内核才从物理上删除这个共享段
========================================================


用来控制共享内存的shmctl()函数如下:
=========================================================
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int shmctl( int shmid , int cmd , struct shmid_ds *buf );

【shmctl】—— 控制共享内存
 参数:
     shmid   共享内存标识ID;
     cmd     IPC_STAT 得到共享内存的状态
             IPC_SET 改变共享内存的状态
             IPC_RMID 删除共享内存
     buf     是一个结构体指针。IPC_STAT的时候,取得的状态放在这个结构体中。如果要改变共享内存的状态,用这个结构体指定;
struct shmid_ds结构体

   struct shmid_ds {

       struct ipc_perm shm_perm;       

       int     shm_segsz;              

       time_t  shm_atime;              

       time_t  shm_dtime;              

       time_t  shm_ctime;              

       unsigned short  shm_cpid;       

       unsigned short  shm_lpid;       

       short   shm_nattch;             

       unsigned short   shm_npages;    

      unsigned long   *shm_pages;     

                struct vm_area_struct *attaches;

   };

 

IPC_RMID 命令实际上不从内核删除一个段,而是仅仅把这个段标记为删除,实际的删除发生在最后一个进程离开这个共享段时。
==========================================================


总结:
shmdt(addr)使进程中的shmaddr指针无效化,不可以使用,但是保留空间。
shmctl(shmid,IPC_RMID,0) 删除共享内存,彻底不可用,释放空间。

posted @ 2012-04-05 21:16  java简单例子  阅读(311)  评论(0编辑  收藏  举报