用於Linux進程通信共享記憶體。共享記憶體函式由shmget、shmat、shmdt、shmctl四個函式組成。
基本介紹
- 外文名:shmat
- 用於:用於Linux進程通信共享記憶體。
- 共享記憶體:共享記憶體函式由shmget、shmat
- 共享函式:shmat函式原型
共享函式
shmat(把共享記憶體區對象映射到調用進程的地址空間) | ||
所需頭檔案 | #include <sys/types.h> #include <sys/shm.h> | |
函式說明 | 連線共享記憶體標識符為shmid的共享記憶體,連線成功後把共享記憶體區對象映射到調用進程的地址空間,隨後可像本地空間一樣訪問 | |
函式原型 | void *shmat(int shmid, const void *shmaddr, int shmflg) | |
函式傳入值 | shmid | 共享記憶體標識符 |
shmaddr | 指定共享記憶體出現在進程記憶體地址的什麼位置,直接指定為NULL讓核心自己決定一個合適的地址位置 | |
shmflg | SHM_RDONLY:為唯讀模式,其他為讀寫模式 | |
函式返回值 | 成功:附加好的共享記憶體地址 | |
出錯:-1,錯誤原因存於errno中 | ||
附加說明 | fork後子進程繼承已連線的共享記憶體地址。exec後該子進程與已連線的共享記憶體地址自動脫離(detach)。進程結束後,已連線的共享記憶體地址會自動脫離(detach) | |
錯誤代碼 | EACCES:無許可權以指定方式連線共享記憶體 EINVAL:無效的參數shmid或shmaddr ENOMEM:核心記憶體不足 |
shmget(得到一個共享記憶體標識符或創建一個共享記憶體對象) | ||
所需頭檔案 | #include <sys/ipc.h> #include <sys/shm.h> | |
函式說明 | 得到一個共享記憶體標識符或創建一個共享記憶體對象並返回共享記憶體標識符 | |
函式原型 | int shmget(key_t key, size_t size, int shmflg) | |
函式傳入值 | key | 0(IPC_PRIVATE):會建立新共享記憶體對象 |
大於0的32位整數:視參數shmflg來確定操作。通常要求此值來源於ftok返回的IPC鍵值 | ||
size | 大於0的整數:新建的共享記憶體大小,以位元組為單位 | |
0:只獲取共享記憶體時指定為0 | ||
shmflg | 0:取共享記憶體標識符,若不存在則函式會報錯 | |
IPC_CREAT:當shmflg&IPC_CREAT為真時,如果核心中不存在鍵值與key相等的共享記憶體,則新建一個共享記憶體;如果存在這樣的共享記憶體,返回此共享記憶體的標識符 | ||
IPC_CREAT|IPC_EXCL:如果核心中不存在鍵值與key相等的共享記憶體,則新建一個訊息佇列;如果存在這樣的共享記憶體則報錯 | ||
函式返回值 | 成功:返回共享記憶體的標識符 | |
出錯:-1,錯誤原因存於errno中 | ||
附加說明 | 上述shmflg參數為模式標誌參數,使用時需要與IPC對象存取許可權(如0600)進行|運算來確定信號量集的存取許可權 | |
錯誤代碼 | EINVAL:參數size小於SHMMIN或大於SHMMAX EEXIST:預建立key所指的共享記憶體,但已經存在 EIDRM:參數key所指的共享記憶體已經刪除 ENOSPC:超過了系統允許建立的共享記憶體的最大值(SHMALL) ENOENT:參數key所指的共享記憶體不存在,而參數shmflg未設IPC_CREAT位 EACCES:沒有許可權 ENOMEM:核心記憶體不足 |
shmdt(斷開共享記憶體連線) | |
所需頭檔案 | #include <sys/types.h> #include <sys/shm.h> |
函式說明 | 與shmat函式相反,是用來斷開與共享記憶體附加點的地址,禁止本進程訪問此片共享記憶體 |
函式原型 | int shmdt(const void *shmaddr) |
函式傳入值 | shmaddr:連線的共享記憶體的起始地址 |
函式返回值 | 成功:0 |
出錯:-1,錯誤原因存於error中 | |
附加說明 | 本函式調用並不刪除所指定的共享記憶體區,而只是將先前用shmat函式連線(attach)好的共享記憶體脫離(detach)目前的進程 |
錯誤代碼 | EINVAL:無效的參數shmaddr |
shmctl(共享記憶體管理) | ||
所需頭檔案 | #include <sys/types.h> #include <sys/shm.h> | |
函式說明 | 完成對共享記憶體的控制 | |
函式原型 | int shmctl(int shmid, int cmd, struct shmid_ds *buf) | |
函式傳入值 | shmid | 共享記憶體標識符 |
cmd | IPC_STAT:得到共享記憶體的狀態,把共享記憶體的shmid_ds結構複製到buf中 | |
IPC_SET:改變共享記憶體的狀態,把buf所指的shmid_ds結構中的uid、gid、mode複製到共享記憶體的shmid_ds結構內 | ||
IPC_RMID:刪除這片共享記憶體 | ||
buf | 共享記憶體管理結構體。具體說明參見共享記憶體核心結構定義部分 | |
函式返回值 | 成功:0 | |
出錯:-1,錯誤原因存於errno中 | ||
錯誤代碼 | EACCESS:參數cmd為IPC_STAT,確無許可權讀取該共享記憶體 EFAULT:參數buf指向無效的記憶體地址 EIDRM:標識符為shmid的共享記憶體已被刪除 EINVAL:無效的參數cmd或shmid EPERM:參數cmd為IPC_SET或IPC_RMID,卻無足夠的許可權執行 |
套用範例
#include <stdio.h>#include <unistd.h>#include <string.h>#include <sys/ipc.h>#include <sys/shm.h>#include <error.h>#define SIZE 1023int main(){int shmid ;char *shmaddr ;struct shmid_ds buf ;int flag = 0 ;int pid ;shmid = shmget(IPC_PRIVATE, SIZE, IPC_CREAT|0600 ) ;if ( shmid < 0 ){perror("get shm ipc_id error") ;return -1 ;}pid = fork() ;if ( pid == 0 ){shmaddr = (char *)shmat( shmid, NULL, 0 ) ;if ( (int)shmaddr == -1 ){perror("shmat addr error") ;return -1 ;}strcpy( shmaddr, "Hi, I am child process!\n") ;shmdt( shmaddr ) ;return 0;} else if ( pid > 0) {sleep(3 ) ;flag = shmctl( shmid, IPC_STAT, &buf) ;if ( flag == -1 ){perror("shmctl shm error") ;return -1 ;}printf("shm_segsz =%d bytes\n", buf.shm_segsz ) ;printf("parent pid=%d, shm_cpid = %d \n", getpid(), buf.shm_cpid ) ;printf("chlid pid=%d, shm_lpid = %d \n",pid , buf.shm_lpid ) ;shmaddr = (char *) shmat(shmid, NULL, 0 ) ;if ( (int)shmaddr == -1 ){perror("shmat addr error") ;return -1 ;}printf("%s", shmaddr) ;shmdt( shmaddr ) ;shmctl(shmid, IPC_RMID, NULL) ;}else{perror("fork error") ;shmctl(shmid, IPC_RMID, NULL) ;}return 0 ;}
#include <stdio.h>#include <sys/ipc.h>#include <sys/shm.h>#include <sys/types.h>#include <unistd.h>#include <string.h>typedef struct{char name[8];int age;} people;int main(int argc, char** argv){int shm_id,i;key_t key;char temp[8];people *p_map;char pathname[30] ;strcpy(pathname,"/tmp") ;key = ftok(pathname,0x03);if(key==-1){perror("ftok error");return -1;}printf("key=%d\n",key) ;shm_id=shmget(key,4096,IPC_CREAT|IPC_EXCL|0600);if(shm_id==-1){perror("shmget error");return -1;}printf("shm_id=%d\n", shm_id) ;p_map=(people*)shmat(shm_id,NULL,0);memset(temp, 0x00, sizeof(temp)) ;strcpy(temp,"test") ;temp[4]='0';for(i = 0;i<3;i++){temp[4]+=1;strncpy((p_map+i)->name,temp,5);(p_map+i)->age=0+i;}shmdt(p_map) ;return 0 ;}
#include <stdio.h>#include <string.h>#include <sys/ipc.h>#include <sys/shm.h>#include <sys/types.h>#include <unistd.h>typedef struct{char name[8];int age;} people;int main(int argc, char** argv){int shm_id,i;key_t key;people *p_map;char pathname[30] ;strcpy(pathname,"/tmp") ;key = ftok(pathname,0x03);if(key == -1){perror("ftok error");return -1;}printf("key=%d\n", key) ;shm_id = shmget(key,0, 0);if(shm_id == -1){perror("shmget error");return -1;}printf("shm_id=%d\n", shm_id) ;p_map = (people*)shmat(shm_id,NULL,0);for(i = 0;i<3;i++){printf( "name:%s\n",(*(p_map+i)).name );printf( "age %d\n",(*(p_map+i)).age );}if(shmdt(p_map) == -1){perror("detach error");return -1;}return 0 ;}