有兩種方法創(chuàng)建共享內(nèi)存,第一種用shmop提供的函數(shù),第二種通過(guò)mmap(2)函數(shù)
man shmop 查看共享內(nèi)存操作函數(shù)
shmget( )
獲得一個(gè)共享存儲(chǔ)標(biāo)識(shí)符
函數(shù)聲明
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
參數(shù)含義
第一個(gè)參數(shù)為ftok(3)函數(shù)返回值,如果 key值為 IPC_PRIVATE 則只能用于有親緣關(guān)系
第二個(gè)參數(shù)為共享內(nèi)存空間的大小
第三個(gè)參數(shù)可選(多選用或運(yùn)算)
IPC_CREAT 創(chuàng)建,需要或上文件權(quán)限
IPC_EXCL 與IPC_CREAT一起使用,確保如果消息隊(duì)列已經(jīng)創(chuàng)建,則返回失敗
返回值
成功返回 共享內(nèi)存示例
失敗返回 -1 并且設(shè)置errno 如果標(biāo)識(shí)符使用了IPC_CREAT 和 IPC_EXCL 并且errno的值為EEXIST,代表消息隊(duì)列已經(jīng)存在
shmat()
掛載共享內(nèi)存,將共享內(nèi)存連接到進(jìn)程的可用地址上
函數(shù)聲明
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
參數(shù)含義
第一個(gè)參數(shù)為共享內(nèi)存示例
第二個(gè)參數(shù)如果是NULL,則內(nèi)核自動(dòng)分配到進(jìn)程所在的第一個(gè)可用地址上,不傳NULL,則分配地址由用戶指定;
返回值
成功返回共享內(nèi)存地址,失敗返回-1,設(shè)置errno值
shmdt()
卸載共享內(nèi)存,將共享內(nèi)存從進(jìn)程的可用地址上刪除
函數(shù)聲明
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);
參數(shù)含義
shmaddr為shmdt函數(shù)的返回值
shmctl()
移除共享內(nèi)存
函數(shù)聲明
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
共享內(nèi)存示例1
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
int main(void)
{
pid_t pid;
int shmid;
int flag = 1;
shmid = shmget(IPC_PRIVATE, 1024, IPC_CREAT | IPC_EXCL | 0600);
if (shmid < 0) {
if (errno == EEXIST) {
shmid = shmget(IPC_PRIVATE, 1024, 0);
flag = 0;
} else {
perror("shmid()");
exit(1);
}
}
pid = fork();
if (pid < 0) {
perror("fork()");
goto FORK_ERROR;
}
if (pid == 0) {
void *p = shmat(shmid, NULL, 0);
memcpy(p, "hello world", 11);
shmdt(p);
exit(1);
}
wait(NULL);
void *ptr = shmat(shmid, NULL, 0);
puts((char *)ptr);
shmdt(ptr);
if (flag)
shmctl(shmid, IPC_RMID, NULL);
exit(0);
FORK_ERROR:
if (flag)
shmctl(shmid, IPC_RMID, NULL);
exit(1);
}