共享內(nèi)存
注意:沒有血緣關(guān)系的進程之間是可以通過文件進行通信的
只是文件描述符不一樣禽翼,但是內(nèi)核幫我們開辟的緩沖區(qū)是一個
復習
1简卧、管道 環(huán)形隊列 半雙工 血緣關(guān)系進程間通信
2兔魂、FIFO 無血緣關(guān)系進程間通信 偽文件
管道的特點 數(shù)據(jù)讀取之后 緩沖區(qū)就不再保留數(shù)據(jù)了
3、信號 異步通信機制
4举娩、共享內(nèi)存 效率最高
數(shù)據(jù)可反復讀取
共享內(nèi)存
可將磁盤上的東西映射到內(nèi)存析校,那么就有地址了,好處就是可以使用指針操作了 铜涉。
缺點:容易發(fā)生進程的互斥智玻,需要同步。
優(yōu)點:通信效率高
共享內(nèi)存使用步驟
1芙代、創(chuàng)建共享內(nèi)存 shmget()
2吊奢、將共享內(nèi)存映射到自己的進程空間 shmat()
3、對共享內(nèi)存進行讀寫
4纹烹、解除共享內(nèi)存映射(shmdt())
5页滚、刪除共享內(nèi)存(shmctl())
shmget()
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, int size, int shmflg);
//通過同一個key可以得到同一塊共享內(nèi)存的ID
key的生成方式有三種
1召边、不同的進程約定好的一個值;
非0值表示裹驰,創(chuàng)建一個指定ID的共享內(nèi)存
多個進程可以通過key值訪問同一共享內(nèi)存
2隧熙、通過相同的路徑名和項目ID,調(diào)用ftok()函數(shù)邦马,生成一個鍵贱鼻;
key_t ftok(const char *pathname, int proj_id);
創(chuàng)建IPC通訊時所必需的ID值。
pathname:指定已經(jīng)存在的文件名滋将,一般是當前目錄
proj_id:子序列號邻悬,大小為1-255。
返回值:ID值随闽,大小是文件的索引節(jié)點號前加上子序列號父丰,例如:pathname索引節(jié)點號為0x101010,proj_id為0x32掘宪,則ID為0x32101010蛾扇。
3、還可以設置為IPC_PRIVATE(0)魏滚,表示此共享內(nèi)存是私有的镀首,
只能在父子進程之間使用
IPC_CREAT
成功,創(chuàng)建新對象
成功鼠次,引用已存在對象
IPC_CREAT|IPC_EXCL
成功更哄,創(chuàng)建新對象
出錯,errno=EEXIST
共享內(nèi)存練習題
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc,char *argv[]){
key_t key = ftok("./", 0x70);
int shmid = shmget(key,10*sizeof(int),IPC_CREAT|0666);//IPC_PRIVATE
printf("shmid = %x\n",shmid);
if(-1 == shmid){
perror("shmget error!");
exit(1);
}
pid_t pid = fork();
if(-1 == pid){
perror("fork error!");
exit(1);
}else if(0 == pid){
int *p = shmat(shmid, NULL,0);
int i = 0;
for(;i<10;i++){
p[i]=i+1;
}
shmdt(p);
//子進程
}else{
//父進程
wait(NULL);
int *p = shmat(shmid, NULL,0);
int i = 0;
for(;i<10;i++){
//write(STDOUT_FILENO,p,sizeof(int)*10);
printf("%3d",p[i]);
}
shmdt(p);
shmctl(shmid,IPC_RMID, NULL);//刪除共享內(nèi)存
}
}
注意: shmctl(shmid,IPC_RMID, NULL);//刪除共享內(nèi)存
千萬別放在子進程中腥寇,否則直接就刪除了成翩。