系列文章:
Linux IPC進程間通信(一):管道
Linux IPC進程間通信(二):共享內存
Linux IPC進程間通信(三):信號量
Linux IPC進程間通信(四):消息隊列
共享內存
key_t ftok(const char* filename, int proj_id)
通過已經存在的文件(filename) 與 proj_id(通常大於0) 創建出一個key值,用於進行共享內存的生成。
int shmget(key_t key, size_t size, int shmflag)
key代表着與共享內存相關的一個關鍵字,如果該關鍵字已經存在,那麼直接打開該共享內存,反之創建共享內存(一般使用 IPC_PRIVATE 用於創建新的共享內存)
size代表共享內存的大小
shmflag表示權限(一般爲0600), 如果時要進行創建的話則是 IPC_CREAT, 也可以加上 IPC_EXCL , 代表必須創建新的共享內存,已有則返回-1
成功返回shmid(共享內存段的id),失敗返回-1
void* shmat(int shmid, char* shmaddr, int shmflag)
操作類似mmap內存映射。
shmid代表已經存在的共享內存id
shmaddr代表是否需要自定義共享內存映射到特定位置(一般爲NULL,讓系統來選擇)
shmflag代表位標識(通常爲0)
成功返回共享內存段的首地址,失敗返回(void*)-1
int shmctl(int shmid, int cmd, shmid_ds* buf)
一般用來刪除共享內存段
shmid 代表共享內存段號
cmd 代表執行命令(一般爲 IPC_RMID)
buf 結構體的信息(一般爲NULL)
如果想要使用結構體的信息,也可以在cmd命令中輸入 IPC_STAT 來獲取結構體的信息,或是 IPC_SET 來設置結構體信息以改變共享內存
int test0()
{
int ret;
key_t key = ftok("file", 1);
ERROR_CHECK(key, -1, "ftok")
int shmid = shmget(key, 1024, 0600 | IPC_CREAT);
ERROR_CHECK(shmid, -1, "shmget");
char *buf = (char *)shmat(shmid, NULL, 0);
ERROR_CHECK(buf, (char *)-1, "shmat");
strcpy(buf, "hello");
cout << "shared memory:" << buf << endl;
struct shmid_ds shminfo;
ret = shmctl(shmid, IPC_STAT, &shminfo);
ERROR_CHECK(ret, -1 , "IPC_STAT");
cout << shminfo.shm_perm.cgid << endl;
shminfo.shm_perm.cgid = 666;
shmctl(shmid, IPC_SET, &shminfo);
cout << shminfo.shm_perm.cgid << endl;
ret = shmctl(shmid, IPC_RMID, NULL);
ERROR_CHECK(ret, -1, "shmctl");
return 0;
}
另外,我們通常會使用 ipcs
命令來查看共享內存的使用:
案例一:親屬進程間通信
父進程寫入Hello, 子進程讀
int test1()
{
int shmid = shmget(IPC_PRIVATE, 1024, 0600);
ERROR_CHECK(shmid, -1, "shmget");
char* buf = (char*)shmat(shmid, NULL, 0);
ERROR_CHECK(buf, (char*)-1, "shmat");
if (fork() > 0)
{
strncpy(buf, "hello", 5);
wait(NULL);
int ret = shmctl(shmid, IPC_RMID, NULL);
ERROR_CHECK(ret, -1, "shmctl");
exit(0);
}
else
{
sleep(1);//等待父進程寫完再讀
cout << "reading from shared memory:" << buf << endl;
exit(0);
}
return 0;
}
輸出:
案例二:非親屬進程通信
寫端 寫入HelloWorld , 讀端進行讀取
reader.cpp
:
int main()
{
key_t key = ftok("file", 1);
ERROR_CHECK(key, -1, "ftok");
int shmid = shmget(key, 1024, 0600 | IPC_CREAT);
ERROR_CHECK(shmid, -1, "shmget");
char* buf = (char*)shmat(shmid, NULL, 0);
ERROR_CHECK(buf, (char*)-1, "shmat");
strncpy(buf, "Hello", 5);
return 0;
}
writer.cpp
:
int main()
{
key_t key = ftok("file", 1);
ERROR_CHECK(key, -1, "ftok");
int shmid = shmget(key, 1024, 0600);
ERROR_CHECK(shmid, -1, "shmget");
char* buf = (char*)shmat(shmid, NULL, 0);
ERROR_CHECK(buf, (char*)-1, "shmat");
cout << "reading from shared memory:" << buf << endl;
int ret = shmctl(shmid, IPC_RMID, NULL);
ERROR_CHECK(ret, -1, "shmctl");
return 0;
}
輸出: