进程通信之共享内存
1. 共享内存共有两种方式:
a) 内存映射 : 用于具有亲缘关系的进程中。
b) 共享内存机制: 不局限于父子进程,与消息队列。内核维护一段内存。用于共享内存。
2.采用共享内存有什么好处?
a) 共享内存进行通信效率高。因为进程可以直接读写内存,而不需要任何数据的拷贝。且共享内存只需要拷贝两次,一次从输入文件到共享区,另一次从共享内存到文件。而像消息队列这种方式,则需要四次才能完成。写操作,先在用户空间bu中,然后再拷贝到内核buf中,读也是一样的,所以完成一次消息的共享,需要四次数据拷贝。
3. 内存映射
a) 可以通过映射一个普通文件,而后可以像访问普通内存一样对文件进行访问,不必再调用read/write等这些文件操作函数。
b) 而内存映射这种属于匿名映射,跟匿名管道一样。限于亲缘关系进程。
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <stdlib.h>
int main()
{
pid_t pid;
char *p_map = NULL;
char *p_m = NULL;
p_m = (char *)malloc(100);
strcpy(p_m, "this is parent process");
p_map = (char *)mmap(NULL, sizeof(char)*100, PROT_READ| PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
pid = fork();
if(pid == 0)
{
strcpy(p_map, "hello world");
strcpy(p_m, "this is child process\n");
munmap(p_map, sizeof(char)*100);
free(p_m);
return 0;
}else{
"mmap.c" 38L, 725C 17,36-43 顶端
>>> 为什么父进程malloc的空间,在子进程中也malloc了一份,因这是子进程完成复制了父进程的资源。
>>>为什么mmap的空间,在子进程中还是跟父进程用的同一份,因为mmap的空间不属于进程所有,而是内核所属,进程只是建立一个内存段的结构体来管理这段内存,进程只有读写的权限,却不能删除。所以子进程从父进程继承的只是一张表,而不是映射内存本身。
4. 共享内存
a) 共享内存与内存映射道理是一样的。只不过共享内存用的一个KEY,来让其他进程可以访问这段内存。
代码就不举例了:
int shmget(key_t key, size_t size, int shmflg);
创建共享内存
Key: 这个key, 就是为了让其他进程可以链接到同一内存。
Size: 共享内存的容量。
Shmflg: 共享内存权限。它的作用与open函数的mode参数一样,如果要想在key标识的共享内存不存在时,创建它的话,可以与IPC_CREAT做或操作。共享内存的权限标志与文件的读写权限一样,举例来说,0644,它表示允许一个进程创建的共享内存被内存创建者所拥有的进程向共享内存读取和写入数据,同时其他用户创建的进程只能读取共享内存。
void *shmat(int shm_id, const void *shm_addr, int shmflg);
连接内存
Shm_id: 由shmget函数返回的共享内存标识。
Shm_addr: 指定连接到当前进程的地址。通常为NULL
Shmflg: 权限
int shmdt(const void *shmaddr);
解连接
参数shmaddr是shmat()函数返回的地址指针,调用成功时返回0,失败时返回-1.
int shmctl(int shm_id, int command, struct shmid_ds *buf);
删除共享内存。