进程间的通信(三)

看了看之后的内容,信号量和共享内存。这两个都不太熟,算不上再次。

相对共享内存熟悉一点,从它开始吧。


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内存共享区

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
    ...
};







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章