看了看之后的内容,信号量和共享内存。这两个都不太熟,算不上再次。
相对共享内存熟悉一点,从它开始吧。
void *mmap(void *addr, size_t len, int prot, int flag, int fd, off_t offset);
mmap函数将一个文件或者一个Posix共享内存区对象映射到调用进程的地址空间addr指定被映射到的进程空间的起始地址(非强制状态下由内核指定,这个值只是“建议”)。该函数返回地址通常为映射到的内存区的起始地址
len是映射长度,offset为距离文件开头的偏移
prot参数:
PROT_READ 数据可读
PROT_WRITE 可写
PROT_EXEC 可执行
PROT_NONE 不可访问
flag参数:
MAP_SHARED 进程对被映射数据所作的修改对于共享该对象的所有进程可见
MAP_PRIVATE 进程对被映射数据所作的修改只对该进程可见
MAP_FIXED 强制采用addr参数的地址
MAP_ANON 匿名映射
MAP_SHARED和MAP_PRIVATE必须指定一个
父子进程之间共享内存的方法之一是在调用fork之前指定MAP_SHARED调用mmap,Posix.1保证父进程内存映射保存到子进程。
int munmap(void *addr, size_t len);
解除映射,再次访问将导致一个错误信号。如果被映射区使用的是MAP_PRIVATE,则解除映射后进程对它所作的变动都会被丢弃
int msync(void *addr, size_t len, int flag);
内核的虚拟内存算法保持内存映射文件(一般在硬盘上)与内存映射区同步,前提是一个MAP_SHARED映射区。
msync函数可以用来确保同步
flag参数:
MS_ASYNC 执行异步写
MS_SYNC 执行同步写
MS_INVALIDATE 使高速缓存数据失效
MS_ASYNC和MS_SYNC二选一。当写操作已由内核排入队列,MS_ASYNC返回,MS_SYNC要等到写操作完成后才返回。
MS_INVALIDATE 使所有与最终副本不一致的文件数据的所有内存中的副本失效。
BSD提供匿名映射避免文件的创建和打开。将flag设为MAP_SHARED | MAP_ANON,将fd设为-1,offset为0
如下
mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
Posix.1提供了两种在无亲缘关系的进程间共享内存区的方法
内存映射文件:由open函数打开,进行映射
共享内存区对象:有shm_open打开一个Posix.1 IPC名字,返回的描述符进行映射
这两种合称为内存区对象
int shm_open(const char *name, int oflag, mode_t mode);
int shm_unlink(const char *name);
oflag必须包含O_RDONLY(只读)或者O_RDWR(读写)标志,还可以指定如下标志O_CREAT、O_EXCL或O_TRUNC
O_CREAT和O_EXCL与消息队列当中相同,O_TRUNC如果随O_RDWR指定则若对象已存在,那么长度将被截短成0
mode参数指定权限位,内容与Posix消息队列一致,必须指定,如果没有指定O_CREAT可以指定为0。
shm_unlink函数删除一个对象的名字。
int ftruncate(int fd, off_t length);
ftruncate函数可以修改普通文件或共享内存区对象的大小
当打开一个已存在的共享内存区对象,可以调用fstat来获取有关该对象的信息
int fstat(int fd, struct stat *buf);
stat结构有12个或以上成员,然而当fd指代一个共享内存对象时,只有四个成员含有信息
struct stat{
...
mode_t st_mode;//mode: S_I{RW}{USR, GRP, OTH}
uid_t st_uid; //user ID
gid_t st_gid; //group ID
off_t st_size; //size in byte
...
};