nginx 的进程建通信机制-共享内存/channel/信号

2023-11-05

nginx是跨平台的库,但以下分享均为基于linux的

nginx 进程间通信的方法:

1、共享内存

linux 提供了进程间通信的的共享内存的方式,通过mmap和shmget来获取一块连续的内存,然后通过munmapheshmdt来释放这块内存,多个进程均可访问这块共享内存

nginx定义的结构体


typedef struct {
    u_char      *addr;
    size_t       size;
    ngx_str_t    name;
    ngx_log_t   *log;
    ngx_uint_t   exists;   /* unsigned  exists:1;  */
} ngx_shm_t;

// 用于分配内存
ngx_int_t ngx_shm_alloc(ngx_shm_t *shm);
// 用于释放内存
void ngx_shm_free(ngx_shm_t *shm);

nginx 共享内存接口

没有使用linux可以直接映射到文件的方式,所以mmap的最后两个参数没有送。

ngx_int_t ngx_shm_alloc(ngx_shm_t *shm)
{
    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;
}

nginx 释放共享内存

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

使用方式:

master进程创建,fork子进程来使用。

2、nginx channel频道

学习过go语言的应该知道,协程间通讯使用channel,而nginx封装了一个进程间通讯的机制,ngx_channel_t,来实现父子进程间的通讯。

nginx channel的数据结构

typedef struct {
    // 传递的TCP消息中的命令
    ngx_uint_t  command;
    // 进程ID
    ngx_pid_t   pid;
    // 表示发送命令方在ngx_processes进程数组间的序号
    ngx_int_t   slot;
    // 通讯的套接字
    ngx_fd_t    fd;
} ngx_channel_t;
// 实现channel的读,写,添加,关闭。
ngx_int_t ngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
    ngx_log_t *log);
ngx_int_t ngx_read_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
    ngx_log_t *log);
ngx_int_t ngx_add_channel_event(ngx_cycle_t *cycle, ngx_fd_t fd,
    ngx_int_t event, ngx_event_handler_pt handler);
void ngx_close_channel(ngx_fd_t *fd, ngx_log_t *log);

另外,需要涉及到的另一个接口

typedef struct {
    .....
    ngx_socket_t        channel[2];
    ngx_spawn_proc_pt   proc;
    .....
} ngx_process_t;

nginx channel 实现方法

nginx就是通过channel来监控管理worker的子进程,每次创建子进程时,就通过socketpair创建了套接字对,并存储到channel的数组中。

ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data,
    char *name, ngx_int_t respawn)
{
    ...
        if (socketpair(AF_UNIX, SOCK_STREAM, 0, ngx_processes[s].channel) == -1)
        {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "socketpair() failed while spawning \"%s\"", name);
            return NGX_INVALID_PID;
        }
    ...
}

其中 ngx_processes时所有的进程的数组,包括master进程。

其中master进程使用channel[0],子进程使用channel[1],channel分别对应socketpair的两个套接字。

nginx进程间时如果调度来进行ngx_read_channel的呢?

就是通过nginx 添加事件函数ngx_add_channel_event,然后epoll发现有事件时,实现ngx_channel_handler回调并读取。从而实现进程间通信。

3、信号 

信号的数据结构 ngx_signal_t

typedef struct{

    //需要处理的信号
    int signo;
    //信号对应的字符串名称
    char*signame;
    //这个信号对应着的Nginx命令
    char*name;
    //收到signo信号后就会回调handler方法
    void(*handler) (int signo) ;
}ngx_signal_t;

需要处理的信号定义在signals中

ngx_signal_t  signals[] = {
    { ngx_signal_value(NGX_RECONFIGURE_SIGNAL),
      "SIG" ngx_value(NGX_RECONFIGURE_SIGNAL),
      "reload",
      ngx_signal_handler },
    ......
}

信号的初始化:

其实现以下已经注释

// 初始化所有信号
ngx_int_t ngx_init_signals(ngx_log_t *log)
{
    ngx_signal_t      *sig;
    struct sigaction   sa;
    // 遍历所有信号数组
    for (sig = signals; sig->signo != 0; sig++) {
        ngx_memzero(&sa, sizeof(struct sigaction));
        // 添加回调函数
        if (sig->handler) {
            sa.sa_sigaction = sig->handler;
            sa.sa_flags = SA_SIGINFO;

        } else {
            sa.sa_handler = SIG_IGN;
        }
        // 清空信号标志位
        sigemptyset(&sa.sa_mask);
        // 向系统注册信号的回调。
        if (sigaction(sig->signo, &sa, NULL) == -1) {
            return NGX_ERROR;
        }
    }

    return NGX_OK;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

nginx 的进程建通信机制-共享内存/channel/信号 的相关文章

随机推荐

  • 【信号与系统】系统线性时不变、因果稳定性的判定

    1 线性 线性包含均匀性和叠加性 其中均匀性是指输入乘以一个常数 输出也乘一个相同的常数 叠加性是指两个输入信号相加 其对应的输出也是相加关系 判定 假设系统输入E1对应输出R1 输入E2对应输出R2 若信号C1E1 C2E2输入系统后得到
  • Kmeans聚类

    一 特征预处理 1 处理缺失 异常值 缺失值直接补0 异常值可以设置一个阈值 比喻小于数据的1分位数 或者大于95分位数 就把数据进行四舍五入 用相应的分位数赋值 这样可以减少异常值对于聚类的影响 因为聚类一般计算的是距离 有异常值影响会比
  • 谷歌瓦片的网址

    有时我们需要离线谷歌地图 最简单的办法是通过网页获取 网上有很多方法 这里介绍一种非常简单实用的 闲话少叙 先上一个网址 http mt0 google cn vt lyrs s x 0 y 0 z 0 打开后在浏览器中可以看到如下图 这张
  • [第二章 web进阶]文件上传]

    先看一下题目源码
  • dataframe先分组运算再合并输出

    dataframe先分组运算再合并输出 主要用到分组函数groupby和合并函数append concat 具体代码 比如先分组 对每组数据进行删除异常值处理 MAD 然后将处理后的数据合并成一个dataframe输出 import os
  • ArcGIS Maps SDK for Unity 0.3旋转

    ArcGIS Maps SDK for Unity1 0版本已出 基础参考 API https developers arcgis com unity sdk 基础 https cloud tencent com developer new
  • Maple学习(一)Maple的安装

    老板找了高尔夫球的代码 想让我运行得出结果 老板做企业管理的 在代码上比我不着急 又是发Maple教程 又是发文档的 看来我的好日子结束了 Maple系统内置高级技术解决建模和仿真中的数学问题 包括世界上最强大的符号计算 无限精度数值计算
  • vhdx中的win10进行大版本系统升级

    文章目录 前言 普通的win10大版本iso升级方式 vhdx中的win10大版本升级方式 难点分析 无法在虚拟驱动器上安装windows 解决方案 HyperV升级vhdx win10 过程效果图 hyperV虚机创建mbr引导启动项 h
  • Java中如何通过键盘输入一个字符串(数组等相关操作)

    如何在自己的程序中进行键盘输入与输出 废话不多说 直接上代码 第一种 1不限制输入数组的长度 import java util Scanner public class InputArrayNoLimitLength public stat
  • 【编程笔试】美团2021校招笔试-通用编程题第3场(附思路及C++代码)

    导览 练习地址 小美的仓库整理 小美的跑腿代购 小美的用户名 小美的区域会议 总结 练习地址 点此前往练习 小美的仓库整理 小美是美团仓库的管理员 她会根据单据的要求按顺序取出仓库中的货物 每取出一件货物后会把剩余货物重新堆放 使得自己方便
  • Jenkins pipeline中获取执行用户的账号和邮件地址

    有时候在pipeline中需要获取执行build 的用户信息 如用户名 用于自动给用户授权另外一个工具 用户邮箱 用于自动给用户发邮件 这时可以使用插件 Buid User Var 具体pipeline 写法如下 pipeline agen
  • ListView刷新的实现(加上自己的分析)

    本文转载地址为http blog csdn net guolin blog article details 9255575 这里我们将采取的方案是使用组合View的方式 先自定义一个布局继承自LinearLayout 然后在这个布局中加入下
  • 有哪些道理是你毕业多年后才明白的?

    12 1更新 1 感情的中不存在离开谁 ta就活不下去的说法 被甩了不要一直沉溺于悲痛中 伤身 你最初喜欢一个人开始可能因为他的颜值 身高等外在条件 后面被他的才华等等所吸引 最后被他的一些品质 诸如诚实 友善等等品质所折服 如果某一天 他
  • maximum call stack size exceeded ajax,javascript - AJAX Maximum call stack size exceeded - Stack Ove...

    I have a javascript function that reads an xml From that function it calls a second function to prompt the user to updat
  • python连接hiveserver2_hiveserver2 python client

    一个hiveserver2 python客户端的例子 大部分代码来自于hue 忽略了一些必要的判断 只是做一个简单的例子 需要安装thrift以及把hive 0 10 0 cdh4 3 0 src service src gen thrif
  • python中通过super()调用父类构造方法

    可能是java写多了 当我准备通过super self xxx 这样调用父类的构造方法时候 一直报错 上网查资料 发现python的super 的机制和java还是有很大区别的 首先看一下super 函数的定义 super type obj
  • 对“端到端”原则的理解

    对 端到端 原则的理解 前些天读了两篇论文 一篇是J H Saltzer D P Read和D D Clark在80年代初发表的 The End TO End Arguments in System Design 另一篇是David D C
  • java为什么有些异常throw出去需要在函数头用throws声明,一些就不用。

    https www cnblogs com paul011 p 7850552 html
  • python可以嵌在vba中吗_在python-cod中嵌入VB宏

    要使用WinI的新模块32COM 我在网上找到了以下生成excel的代码 import win32com client as win32 class generate excel def excel self excel win32 gen
  • nginx 的进程建通信机制-共享内存/channel/信号

    nginx是跨平台的库 但以下分享均为基于linux的 nginx 进程间通信的方法 1 共享内存 linux 提供了进程间通信的的共享内存的方式 通过mmap和shmget来获取一块连续的内存 然后通过munmapheshmdt来释放这块