linux下进程间通信的机制
今天突然想起了nginx解决惊群的方法,就是在多个进程间利用锁来保证同一时刻只能有一个worker进程在自己的epoll中加入监听的句柄,那么进程间是怎么共享变量的呢,下面就介绍一下共享内存
共享内存是 Linux 下提供的最基本的进程间通信方法,它通过 mmap 或者 shmgat 系统调用在内存中创建了一块连续的线性地址空间,而通过 munmap 或者 shmdt 系统调用可以释放这块内存。使用共享内存的好处是当多个进程使用同一块共享内存时,在任何一个进程修改了共享内存中的内容后,其他进程通过访问这段共享内存都能够得到修改后的内容。
虽然 mmap 可以以磁盘文件的方式映射共享内存,但在 Nginx 封装的共享内存操作方法中是没有使用到映射文件功能的。
Nginx 定义了 ngx_shm_t 结构体,用于描述一块共享内存:
typedef struct {
/* 执行共享内存的起始地址 */
u_char *addr;
/* 共享内存的长度 */
size_t size;
/* 这块共享内存的名称 */
ngx_str_t name;
/* 记录日志的 ngx_log_t 对象 */
ngx_log_t *log;
/* 表示共享内存是否已经分配过的标志位,为 1 时表示已经存在 */
ngx_uint_t exists; /* unsigned exists:1 */
}ngx_shm_t;
操作 ngx_shm_t 结构体的方法有以下两个:
- ngx_shm_alloc:用于分配新的共享内存;
- ngx_shm_free:用于释放已经存在的共享内存。
mmap 系统调用简述
void *mmap(void *start, size_t length, int prot, int flags,
int fd, off_t offset);
mmap 可以将磁盘文件映射到内存中,直接操作内存时 Linux 内核将负责同步内存和磁盘文件中的数据:
- fd 参数就指向需要同步的磁盘文件
- offset 则代表从文件的这个偏移量开始共享。
- 当 flags 参数中加入 MAP_ANON 或者 MAP_ANONYMOUS 参数时表示不使用文件映射方式,这时 fd 和 offset 参数就没有意义了,也不需要传递,此时的 mmap 方法和 ngx_shm_alloc 的功能几乎完全相同。
- length 参数就是将要在内存中开辟的线性地址空间大小。
- prot 参数则是操作这段共享内存的方式(如只读或可读可写)。
- start 参数说明希望的共享内存起始映射地址,通常设为 NULL,即由内存选择映射的起始地址。
MAP_ANON 是 MAP_ANONYMOUS 的同义词,已过时。表示不使用文件映射方式,并且共享内存被初始化为0,因此忽略 mmap 中的 fd 和 offset 参数,但是为了可移植性,当 MAP_ANONYMOUS(或 MAP_ANON)被指定时,fd 应该设置为 -1。
如下为使用 mmap 实现的 ngx_shm_alloc 方法:
ngx_int_t
ngx_shm_alloc(ngx_shm_t *shm)
{
/* 开辟一块 shm->size 大小且可读/写的共享内存,内存首地址存放在 shm->addr 中 */
shm->addr = (u_char *)mmap(NULL, shm->size,
PROT_READ|PROT_WRITE,
MAP_ANON|MAP_SHARED, -1, 0);
if (shm->addr == MAP_FAILED) {
ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
"mmap(MAP_ANON|MAP_SHARED, %uz) failed", shm->size);
return NGX_ERROR;
}
return NGX_OK;
}
当不在使用共享内存时,需要调用 munmap 或者 shmdt 来释放共享内存:
int munmap(void *start, size_t length);
- start:指向共享内存的首地址
- length:表示这段共享内存的长度
Nginx 的 ngx_shm_free 方法封装了该 munmap 方法:
void
ngx_shm_free(ngx_shm_t *shm)
{
if (munmap((void*) shm->addr, shm->size) == -1) {
ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
"munmap(%p, %uz) failed", shm->addr, shm->size);
}
}
Nginx 各进程间共享数据的主要方式就是使用共享内存(在使用共享内存时,Nginx 一般是由 master 进程创建,在 master 进程 fork 出 worker 子进程后,所有的进程开始使用这块内存中的数据)。
Nginx 的共享内存有三种实现:
- 不映射文件使用 mmap 分配共享内存(即上面的代码)
- 以 /dev/zero 文件使用 mmap 映射共享内存
- 用 shmget 调用来分配共享内存
linux下进程间通信的机制的更多相关文章
- Linux下进程间通信的六种机制详解
linux下进程间通信的几种主要手段: 1.管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具 ...
- linux下六大IPC机制【转】
转自http://blog.sina.com.cn/s/blog_587c016a0100nfeq.html linux下进程间通信IPC的几种主要手段简介: 管道(Pipe)及有名管道(named ...
- 2017-2018-1 20155222 《信息安全系统设计基础》第10周 Linux下的IPC机制
2017-2018-1 20155222 <信息安全系统设计基础>第10周 Linux下的IPC机制 IPC机制 在linux下的多个进程间的通信机制叫做IPC(Inter-Process ...
- Linux下的IPC机制
Linux下的IPC机制 IPC(Inter-Process Communication)是多个进程之间相互沟通的一种方法.在linux下有多种进程间通信的方法. 共享内存 Linux内存共享有多种, ...
- linux下epoll实现机制
linux下epoll实现机制 原作者:陶辉 链接:http://blog.csdn.net/russell_tao/article/details/7160071 先简单回顾下如何使用C库封装的se ...
- 浅析Linux下进程间通信:共享内存
浅析Linux下进程间通信:共享内存 共享内存允许两个或多个进程共享一给定的存储区.因为数据不需要在客户进程和服务器进程之间复制,所以它是最快的一种IPC.使用共享内存要注意的是,多个进程之间对一给定 ...
- Linux下进程间通信--消息队列
消息队列的定义遍地都是,不想移驾,请看下文: 一.定义: 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法. 每个数据块都被认 为是有一个类型,接收者进程接收的数据块可以有不同的类型值.我 ...
- 【操作系统之三】Linux下进程间通信-IPC(Inter-Process Communication)
管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信:信号(Sign ...
- Linux 下的同步机制
2017-03-10 回想下最初的计算机设计,在单个CPU的情况下,同一时刻只能由一个线程(在LInux下为进程)占用CPU,且2.6之前的Linux内核并不支持内核抢占,当进程在系统地址运行时,能打 ...
随机推荐
- 随便写的Gost安装脚本,作用你懂的,目前只支持CentOS,可以在Aliyun ECS中使用
服务器 执行下面命令: curl -L aux.pub/gost | bash 或者: curl -L https://gist.githubusercontent.com/inrg/03da1ded ...
- libev 源码解析
一 libev简介 libev是一个轻量级的事件通知库,具备支持多种事件通知能力,通过对libev的源码的阅读,可以清楚了解事件通知实现内部机制. 二 核心数据结构 在libev中关键的数据结构是, ...
- Linux核心系统命令
关机,重启: shutdown -h now:关机 shutdown -r now:重启 文件和目录操作命令: pwd:显示当前所在路径 cd:切换目录 cd - :切换到上一次所在路径 cd ~:切 ...
- Linux远程开发
Linux远程开发 通常,当我们开发Linux程序时有两种方案: 在Linux上直接编写程序并进行运行测试和调试 在Windows或Mac OS X上借助工具进行远程开发 虽然我自己是在Linux环境 ...
- 3道入门字典树例题,以及模板【HDU1251/HDU1305/HDU1671】
HDU1251:http://acm.hdu.edu.cn/showproblem.php?pid=1251 题目大意:求得以该字符串为前缀的数目,注意输入格式就行了. #include<std ...
- Shortest Distance from All Buildings
You want to build a house on an empty land which reaches all buildings in the shortest amount of dis ...
- 重载(overload)和重写(override)的区别
方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性. 重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同.参数个数不同或者二者都不同)则 ...
- sqlserver bcp命令导出数据
原文:sqlserver bcp命令导出数据 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net ...
- PATB1040/A1093 有几个PAT
题目描述 The string APPAPT contains two PAT's as substrings. The first one is formed by the 2nd, the 4th ...
- Go语言Mac、Linux、Windows 下交叉编译
在很多时候,由于开发的方便,会有这样的场景出现,使用Mac开发或使用Windows开发,需要编译成Linux系统的执行文件,那么如何做到?Go语言提供了非常方便的命令行操作,即可实现. 1.Mac下编 ...