linux shmget shmctl
shmget
int shmget(key_t key, size_t size, int flag);
key: 標(biāo)識符的規(guī)則
size:共享存儲段的字節(jié)數(shù)
flag:讀寫的權(quán)限
返回值:成功返回共享存儲的id,失敗返回-1
key_t key
-----------------------------------------------
??? key標(biāo)識共享內(nèi)存的鍵值: 0/IPC_PRIVATE。?當(dāng)key的取值為IPC_PRIVATE,則函數(shù)shmget()將創(chuàng)建一塊新的共享內(nèi)存;如果key的取值為0,而參數(shù)shmflg中設(shè)置了IPC_PRIVATE這個標(biāo)志,則同樣將創(chuàng)建一塊新的共享內(nèi)存。
??? 在IPC(InterProcess Communication)的通信模式下,不管是使用消息隊列還是共享內(nèi)存,甚至是信號量,每個IPC的對象(object)都有唯一的名字,稱為“鍵”(key)。通過“鍵”,進(jìn)程能夠識別所用的對象。“鍵”與IPC對象的關(guān)系就如同文件名稱之于文件,通過文件名,進(jìn)程能夠讀寫文件內(nèi)的數(shù)據(jù),甚至多個進(jìn)程能夠共用一個文件。而在IPC的通訊模式下,通過“鍵”的使用也使得一個IPC對象能為多個進(jìn)程所共用。
??? Linux系統(tǒng)中的所有表示System V中IPC對象的數(shù)據(jù)結(jié)構(gòu)都包括一個ipc_perm結(jié)構(gòu),其中包含有IPC對象的鍵值,該鍵用于查找System V中IPC對象的引用標(biāo)識符。如果不使用“鍵”,進(jìn)程將無法存取IPC對象,因為IPC對象并不存在于進(jìn)程本身使用的內(nèi)存中。
??? 通常,都希望自己的程序能和其他的程序預(yù)先約定一個唯一的鍵值,但實際上并不是總可能的成行的,因為自己的程序無法為一塊共享內(nèi)存選擇一個鍵值。因此,在此把key設(shè)為IPC_PRIVATE,這樣,操作系統(tǒng)將忽略鍵,建立一個新的共享內(nèi)存,指定一個鍵值,然后返回這塊共享內(nèi)存IPC標(biāo)識符ID。而將這個新的共享內(nèi)存的標(biāo)識符ID告訴其他進(jìn)程可以在建立共享內(nèi)存后通過派生子進(jìn)程,或?qū)懭胛募蚬艿纴韺崿F(xiàn)。
int size(單位字節(jié)Byte)
-----------------------------------------------
??? size是要建立共享內(nèi)存的長度。所有的內(nèi)存分配操作都是以頁為單位的。所以如果一段進(jìn)程只申請一塊只有一個字節(jié)的內(nèi)存,內(nèi)存也會分配整整一頁(在i386機(jī)器中一頁的缺省大小PACE_SIZE=4096字節(jié))這樣,新創(chuàng)建的共享內(nèi)存的大小實際上是從size這個參數(shù)調(diào)整而來的頁面大小。即如果size為1至4096,則實際申請到的共享內(nèi)存大小為4K(一頁);4097到8192,則實際申請到的共享內(nèi)存大小為8K(兩頁),依此類推。
int shmflg
-----------------------------------------------
??? shmflg主要和一些標(biāo)志有關(guān)。其中有效的包括IPC_CREAT和IPC_EXCL,它們的功能與open()的O_CREAT和O_EXCL相當(dāng)。
????IPC_CREAT?? 如果共享內(nèi)存不存在,則創(chuàng)建一個共享內(nèi)存,否則打開操作。
????IPC_EXCL??? 只有在共享內(nèi)存不存在的時候,新的共享內(nèi)存才建立,否則就產(chǎn)生錯誤。
??? 如果單獨使用IPC_CREAT,shmget()函數(shù)要么返回一個已經(jīng)存在的共享內(nèi)存的操作符,要么返回一個新建的共享內(nèi)存的標(biāo)識符。如果將IPC_CREAT和IPC_EXCL標(biāo)志一起使用,shmget()將返回一個新建的共享內(nèi)存的標(biāo)識符;如果該共享內(nèi)存已存在,或者返回-1。IPC_EXEL標(biāo)志本身并沒有太大的意義,但是和IPC_CREAT標(biāo)志一起使用可以用來保證所得的對象是新建的,而不是打開已有的對象。對于用戶的讀取和寫入許可指定SHM_R和SHM_W,(SHM_R>3)和(SHM_W>3)是一組讀取和寫入許可,而(SHM_R>6)和(SHM_W>6)是全局讀取和寫入許可。
需要注意的是,使用參數(shù)要加上 | 0666 作為校驗,在有些Linux系統(tǒng)中,如果不加此校驗,則不能順利獲取共享空間的值(如Ubuntu)。此外,有兩個常用參數(shù),一般要同時出現(xiàn),他們是:S_IRUSH | S_IWUSR 。由于這兩個參數(shù)非常常用,程序員一般做這樣的操作
#define PERM S_IRUSR | S_IWUSR | IPC_CREAT
這樣一來,第三個參數(shù)就可以直接用PERM來表示了!
返回值
-----------------------------------------------
成功返回共享內(nèi)存的標(biāo)識符;不成功返回-1,errno儲存錯誤原因。
??? EINVAL??????? 參數(shù)size小于SHMMIN或大于SHMMAX。
??? EEXIST??????? 預(yù)建立key所致的共享內(nèi)存,但已經(jīng)存在。
??? EIDRM???????? 參數(shù)key所致的共享內(nèi)存已經(jīng)刪除。
??? ENOSPC??????? 超過了系統(tǒng)允許建立的共享內(nèi)存的最大值(SHMALL )。
??? ENOENT??????? 參數(shù)key所指的共享內(nèi)存不存在,參數(shù)shmflg也未設(shè)IPC_CREAT位。
??? EACCES??????? 沒有權(quán)限。
??? ENOMEM??????? 核心內(nèi)存不足。
struct shmid_ds
-----------------------------------------------
??? shmid_ds數(shù)據(jù)結(jié)構(gòu)表示每個新建的共享內(nèi)存。當(dāng)shmget()創(chuàng)建了一塊新的共享內(nèi)存后,返回一個可以用于引用該共享內(nèi)存的shmid_ds數(shù)據(jù)結(jié)構(gòu)的標(biāo)識符。
include/linux/shm.h
??? struct shmid_ds {?
??????? struct ipc_perm??? shm_perm;????? /* operation perms */?
??????? int??????????????? shm_segsz;???? /* size of segment (bytes) */?
??????? __kernel_time_t??? shm_atime;???? /* last attach time */?
??????? __kernel_time_t??? shm_dtime;???? /* last detach time */?
??????? __kernel_time_t??? shm_ctime;???? /* last change time */?
??????? __kernel_ipc_pid_t shm_cpid;????? /* pid of creator */?
??????? __kernel_ipc_pid_t shm_lpid;????? /* pid of last operator */?
??????? unsigned short???? shm_nattch;??? /* no. of current attaches */?
??????? unsigned short???? shm_unused;??? /* compatibility */?
??????? void?????????????? *shm_unused2; /* ditto - used by DIPC */?
??????? void?????????????? *shm_unused3; /* unused */?
??? };
struct ipc_perm
-----------------------------------------------
??? 對于每個IPC對象,系統(tǒng)共用一個struct ipc_perm的數(shù)據(jù)結(jié)構(gòu)來存放權(quán)限信息,以確定一個ipc操作是否可以訪問該IPC對象。
??? struct ipc_perm {?
??????? __kernel_key_t?? key;?
??????? __kernel_uid_t?? uid;?
??????? __kernel_gid_t?? gid;?
??????? __kernel_uid_t?? cuid;?
??????? __kernel_gid_t?? cgid;?
??????? __kernel_mode_t mode;?
??????? unsigned short?? seq;?
};
//----------------------------------------
shmat
void *shmat(int shmid, const void *addr, int flag);
shmid:共享存儲的id
addr:一般為0,表示連接到由內(nèi)核選擇的第一個可用地址上,否則,如果flag沒有指定SHM_RND,則連接到addr所指定的地址上,如果flag為SHM_RND,則地址取整
flag:如前所述,一般為0
返回值:如果成功,返回共享存儲段地址,出錯返回-1
共享存儲器的執(zhí)行方式是將一個儲存器區(qū)段標(biāo)記為共用,這時各進(jìn)程可以把這個區(qū)段映射到該進(jìn)程本身的虛擬地址里。建立共享存儲器可通過shmget系統(tǒng)調(diào)用,shmget執(zhí)行后,核心程序就保留一塊指定大小的空間,同時關(guān)于此共享存儲器的一切數(shù)據(jù),如區(qū)段的長度,區(qū)段的存取權(quán),區(qū)段建立者的進(jìn)程識別碼等存入一個叫shmid_ds的結(jié)構(gòu)。現(xiàn)在共享存儲器雖然已經(jīng)建立了,可是仍無法連上它,這時就須通過shmat系統(tǒng)調(diào)用得到一個指向共享存儲器基址的指針,通過此指針,就可以如同于操作一般存儲器似的取用共享存儲器。shmdt進(jìn)行相反的工作,用來脫離已連上的共享存儲器。
shmdt
int shmdt(void *addr);
addr:共享存儲段的地址,以前調(diào)用shmat時的返回值
shmdt將使相關(guān)shmid_ds結(jié)構(gòu)中的shm_nattch計數(shù)器值減1
當(dāng)一個進(jìn)程不再需要共享內(nèi)存段時,它將調(diào)用shmdt()系統(tǒng)調(diào)用取消這個段,但是,這并不是從內(nèi)核真正地刪除這個段,而是把相關(guān)shmid_ds結(jié)構(gòu)的?shm_nattch域的值減1,當(dāng)這個值為0時,內(nèi)核才從物理上刪除這個共享段
shmctl
int shmctl(int shmid,int cmd,struct shmid_ds *buf)
shmid:共享存儲段的id
cmd:一些命令
IPC_STAT 得到共享內(nèi)存的狀態(tài)
????????IPC_SET 改變共享內(nèi)存的狀態(tài)
????????IPC_RMID 刪除共享內(nèi)存?
IPC_RMID?命令實際上不從內(nèi)核刪除一個段,而是僅僅把這個段標(biāo)記為刪除,實際的刪除發(fā)生在最后一個進(jìn)程離開這個共享段時。?
請注意,共享內(nèi)存不會隨著程序結(jié)束而自動消除,要么調(diào)用shmctl刪除,要么自己用手敲命令去刪除,否則永遠(yuǎn)留在系統(tǒng)中。
?
實例:
?
C代碼???這個程序是父進(jìn)程將參數(shù)寫入到共享內(nèi)存,然后子進(jìn)程把內(nèi)容讀出來.最后我們要使用ip
crm 釋放資源的.先用ipcs 找出ID 然后用ipcrm shm ID 刪除.
轉(zhuǎn)載于:https://www.cnblogs.com/jkred369/p/6733141.html
總結(jié)
以上是生活随笔為你收集整理的linux shmget shmctl的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 自己动手,制作.net35离线安装包
- 下一篇: 阿里云OSS linux使用备忘录