共享内存
注意:没有血缘关系的进程之间是可以通过文件进行通信的
只是文件描述符不一样,但是内核帮我们开辟的缓冲区是一个
复习
1、管道 环形队列 半双工 血缘关系进程间通信
2、FIFO 无血缘关系进程间通信 伪文件
管道的特点 数据读取之后 缓冲区就不再保留数据了
3、信号 异步通信机制
4、共享内存 效率最高
数据可反复读取
共享内存
可将磁盘上的东西映射到内存,那么就有地址了,好处就是可以使用指针操作了 。
缺点:容易发生进程的互斥,需要同步。
优点:通信效率高
共享内存使用步骤
1、创建共享内存 shmget()
2、将共享内存映射到自己的进程空间 shmat()
3、对共享内存进行读写
4、解除共享内存映射(shmdt())
5、删除共享内存(shmctl())
shmget()
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, int size, int shmflg);
//通过同一个key可以得到同一块共享内存的ID
key的生成方式有三种
1、不同的进程约定好的一个值;
非0值表示,创建一个指定ID的共享内存
多个进程可以通过key值访问同一共享内存
2、通过相同的路径名和项目ID,调用ftok()函数,生成一个键;
key_t ftok(const char *pathname, int proj_id);
创建IPC通讯时所必需的ID值。
pathname:指定已经存在的文件名,一般是当前目录
proj_id:子序列号,大小为1-255。
返回值:ID值,大小是文件的索引节点号前加上子序列号,例如:pathname索引节点号为0x101010,proj_id为0x32,则ID为0x32101010。
3、还可以设置为IPC_PRIVATE(0),表示此共享内存是私有的,
只能在父子进程之间使用
IPC_CREAT
成功,创建新对象
成功,引用已存在对象
IPC_CREAT|IPC_EXCL
成功,创建新对象
出错,errno=EEXIST
共享内存练习题
#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);//删除共享内存
}
}
注意: shmctl(shmid,IPC_RMID, NULL);//删除共享内存
千万别放在子进程中,否则直接就删除了。