XSI 共享内存
传统的 XSI(X/Open System Interfaces) shmem 也被成为 System V shmem。开辟的共享内存生命周期为 内核生命周期 ,因此需要手动删除。
XSI shmem 依赖于以下几个 系统调用 :
shmat
shmctl
shmdt
shmget
XSI 共享内存不支持写时复制和部分共享,但它支持匿名共享内存。
写端如下:
extern "C" {
#include <string.h>
#include <sys/shm.h>
}
int main(int argc, char* argv[]) {
key_t key = ftok("/dev/shm/test_shmem", 0);
int shmid = shmget(key, 1 * 1024 * 1024, IPC_CREAT | 0755);
char* addr = (char*)shmat(shmid, nullptr, 0);
memset(addr, 0x1f, 1 * 1024 * 1024);
shmdt(addr);
return 0;
}
读端如下:
extern "C" {
#include <stdio.h>
#include <string.h>
#include <sys/shm.h>
}
int main(int argc, char* argv[]) {
key_t key = ftok("/dev/shm/test_shmem", 0);
int shmid = shmget(key, 1 * 1024 * 1024, IPC_CREAT | 0755);
char* addr = (char*)shmat(shmid, nullptr, 0);
// memset(addr, 0x1f, 1 * 1024 * 1024);
printf("0x%xd, 0x%xd, 0x%xd\n", addr[0], addr[1], addr[2]);
shmdt(addr);
return 0;
}
由于共享内存和进程的生命周期不绑定,因此先运行写端,然后再运行读端也是可行的。
要删除 shmem,需要运行:
shmctl(shmid, IPC_RMID, nullptr);
使用 ipcs 可以查看当前系统中用于进程通信的资源。 |
POSIX 共享内存
和 XSI 共享内存一样,POSIX 共享内存提供的内存也是内核生命周期,但是 POSIX 共享内存无法使用 ipcs 。POSIX 共享内存在 Linux 下位于 /dev/shmem
路径下,在 MacOS 上则以匿名的形式存放在内核中,无法查看。
写端如下:
extern "C" {
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
}
int main(int argc, char* argv[]) {
int fd = shm_open("test_shmem", O_CREAT | O_RDWR, 0755);
ftruncate(fd, 1 * 1024 * 1024);
char* addr = (char*)mmap(nullptr, 1 * 1024 * 1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
memset(addr, 0x1f, 1 * 1024 * 1024);
munmap(addr, 1 * 1024 * 1024);
return 0;
}
读端如下:
extern "C" {
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
}
int main(int argc, char* argv[]) {
int fd = shm_open("test_shmem", O_CREAT | O_RDWR, 0755);
ftruncate(fd, 1 * 1024 * 1024);
char* addr = (char*)mmap(nullptr, 1 * 1024 * 1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
printf("0x%xd, 0x%xd, 0x%xd, 0x%xd", addr[0], addr[1], addr[2], addr[3]);
munmap(addr, 1 * 1024 * 1024);
return 0;
}
如果需要删除 POSIX shmem,需要调用 shmem_unlink
:
shm_unlink("test_shmem");
memfd
memfd 创建一个文件并返回其 fd。和普通文件一样也能被修改、截断、内存映射,但是是位于内存中的。一旦所有指向它的引用被删除,则此文件自动删除。由于 Unix domain 允许在进程间传递 fd,因此能被用于共享内存。
memfd 目前只存在于 Linux/FreeBSD 中。 |