Linux IPC实践(9) --System V共享内存
共享內(nèi)存API
#include <sys/ipc.h> #include <sys/shm.h>int shmget(key_t key, size_t size, int shmflg); void *shmat(int shmid, const void *shmaddr, int shmflg); int shmdt(const void *shmaddr); int shmctl(int shmid, int cmd, struct shmid_ds *buf); //System V 共享內(nèi)存基本數(shù)據(jù)結(jié)構(gòu) struct shmid_ds {struct ipc_perm shm_perm; /* Ownership and permissions: System V IPC所共有的數(shù)據(jù)結(jié)構(gòu) */size_t shm_segsz; /* Size of segment (bytes): 共享內(nèi)存段的大小 */time_t shm_atime; /* Last attach time */time_t shm_dtime; /* Last detach time */time_t shm_ctime; /* Last change time */pid_t shm_cpid; /* PID of creator */pid_t shm_lpid; /* PID of last shmat(2)/shmdt(2) */shmatt_t shm_nattch; /* No. of current attaches */... };shmget
int shmget(key_t key, size_t size, int shmflg);? ?創(chuàng)建共享內(nèi)存,并將該內(nèi)存的內(nèi)容初始化為0;?
? ?打開一個已經(jīng)存在共享內(nèi)存,?如果打開時不知道共享內(nèi)存的大小,?可以將size指定為0,?shmflg可以指定為0(按照默認的權(quán)限打開);? ??
參數(shù):
? ?key:這個共享內(nèi)存段名字;
? ?size:共享內(nèi)存大小(bytes);
? ?shmflg:用法類似msgget中的msgflg參數(shù);
返回值:
? ?成功返回一個非負整數(shù),即該共享內(nèi)存段的標識碼;失敗返回-1
/**示例: 創(chuàng)建并打開一個共享內(nèi)存 **/ int main(int argc,char **argv) {const int SHM_SIZE = 1024;int shmid = shmget(0x1234, SHM_SIZE, 0666|IPC_CREAT);if (shmid == -1)err_exit("shmget error");cout << "share memory get success" << endl; }shmat
void *shmat(int shmid, const void *shmaddr, int shmflg);? ?連接到本進程地址空間,?成功連接之后,?對該內(nèi)存的操作就與malloc來的一塊內(nèi)存非常類似了,?而且如果這塊內(nèi)存中有數(shù)據(jù),?則就可以直接將其中的數(shù)據(jù)取出來!!
參數(shù):
? ?shmaddr:指定連接的地址(推薦使用NULL)
? ?shmflg:一般指定為0,?表示可讀,可寫;?而它的另外兩個可能取值是SHM_RND和SHM_RDONLY(見下)
返回值:
? ?成功返回一個指針,指向共享內(nèi)存起始地址;失敗返回(void?*)?-1
shmaddr與shmflg組合說明 | |
shmaddr為NULL | Linux內(nèi)核自動為進程連接到進程的內(nèi)存(推薦使用) |
shmaddr不為NULL且shmflg無SHM_RND標記 | 以shmaddr為連接地址 |
shmaddr不為NULL且shmflg設(shè)置了SHM_RND標記 | 連接的地址會自動向下調(diào)整為SHMLBA的整數(shù)倍; 公式:shmaddr?-?(shmaddr?%?SHMLBA) SHMLBA為內(nèi)存頁面的大小(4K) |
shmflg=SHM_RDONLY | 只讀共享內(nèi)存,?不然的話就是可讀,可寫的,?注意:?此處沒有可讀,可寫這個概念 |
?
shmdt
int shmdt(const void *shmaddr);參數(shù):
? ?shmaddr:?由shmat所返回的指針
注意:將共享內(nèi)存段與當前進程脫離不等于刪除共享內(nèi)存段
/** 示例: 將數(shù)據(jù)寫入/讀出共享內(nèi)存 程序write: 將數(shù)據(jù)寫入共享內(nèi)存 程序read: 將數(shù)據(jù)讀出共享內(nèi)存(當然, 可以讀取N多次) **/ //write程序 struct Student {char name[26];int age; }; int main(int argc,char **argv) {int shmid = shmget(0x1234, sizeof(Student), 0666|IPC_CREAT);if (shmid == -1)err_exit("shmget error");// 以可讀, 可寫的方式連接該共享內(nèi)存Student *p = (Student *)shmat(shmid, NULL, 0);if (p == (void *)-1)err_exit("shmat error");strcpy(p->name, "xiaofang");p->age = 22;shmdt(p); } //read程序 int main(int argc,char **argv) {int shmid = shmget(0x1234, 0, 0);if (shmid == -1)err_exit("shmget error");// 以只讀方式連接該共享內(nèi)存Student *p = (Student *)shmat(shmid, NULL, 0);if (p == (void *)-1)err_exit("shmat error");// 直接將其中的內(nèi)容打印輸出cout << "name: " << p->name << ", age: " << p->age << endl;shmdt(p); }shmctl
int shmctl(int shmid, int cmd, struct shmid_ds *buf);設(shè)置/獲取共享內(nèi)存屬性
參數(shù):
? ?cmd:將要采取的動作(三個取值見下)
? ?buf:指向一個保存著共享內(nèi)存的模式狀態(tài)和訪問權(quán)限的數(shù)據(jù)結(jié)構(gòu)
System?V共享內(nèi)存小結(jié):
? ?1.共享內(nèi)存被別的程序占用,則刪除該共享內(nèi)存時,不會馬上刪除(引用計數(shù)計數(shù));
? ?2.此時會出現(xiàn)一個現(xiàn)象:該共享內(nèi)存的key變?yōu)?x00000000,變?yōu)樗接?
? ?3.此時還可以讀,但必須還有辦法獲取該共享內(nèi)存的ID(shmid),因為此時試圖通過該共享內(nèi)存的key獲取該共享內(nèi)存,是白費的!
/** 示例: 刪除共享內(nèi)存 **/ int main(int argc,char *argv[]) {int shmid = shmget(0x1234, 0, 0);if (shmid == -1)err_exit("shmget error");if (shmctl(shmid, IPC_RMID, NULL) == -1)err_exit("shmctl IPC_RMID error");cout << "share memory remove success" << endl; }總結(jié)
以上是生活随笔為你收集整理的Linux IPC实践(9) --System V共享内存的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VS2010数据库项目不能正常工作解决方
- 下一篇: 内存泄漏检测工具(转载)