Nginx学习(10)—— event模块、core模块、变量

Nginx源码剖析--event类型模块 目录目录 前言 核心模块 几种event模块 ngx_event_core_module epoll和kqueue等功能性的event模块 嵌入到Nginx框架中 总结前言前面梗概介绍了Nginx模块配置的信息。简单地说,nginx的灵活性主要归功于他的高度模块化和可配置性。其中可配置性依赖于配置文件。在nginx中,模块就是一个struct类型的全局变量。Nginx通过为每个模块维护一个配置结构体 阅读详情

Nginx的模块种类有很多,除了HTTP模块,还有一些核心模块和mail系列模块。核心模块主要是做一些基础功能,
比如Nginx的启动初始化,event处理机制,错误日志的初始化,ssl的初始化,正则处理初始化。
mail模块可以对imap,pop3,smtp等协议进行反向代理,这些模块本身不对邮件内容进行处理。

core模块

Nginx启动模块

  • 启动模块从启动Nginx进程开始,做了一系列的初始化工作,源代码位于src/core/nginx.c,从main函数开始:
    1. 时间、正则、错误日志、ssl等初始化。
    2. 读入命令行参数。
    3. OS相关初始化。
    4. 读入并解析配置。
    5. 核心模块初始化。
    6. 创建各种暂时文件和目录。
    7. 创建共享内存。
    8. 打开listen的端口。
    9. 所有模块初始化。
    10. 启动worker进程。

event模块

event的类型和功能

Nginx是以event(事件)处理模型为基础的。它为了支持跨平台,抽象出了event模块。

  • 它支持的event处理类型有:
    1. AIO(异步IO)
    2. /dev/poll(Solaris 和Unix特有)
    3. epoll(Linux特有)
    4. eventport(Solaris 10特有)
    5. kqueue(BSD特有)
    6. poll,rtsig(实时信号),select等。

event模块的主要功能就是,对accept后建立的连接进行监听,对读写事件进行添加删除。事件处理模型和Nginx的非阻塞IO模型结合在一起使用。
当IO可读可写的时候,相应的读写事件就会被唤醒,此时就会去处理事件的回调函数。

特别对于Linux,Nginx大部分event采用epoll EPOLLET(边沿触发)的方法来触发事件,只有listen端口的读事件是EPOLLLT(水平触发)。
对于边沿触发,如果出现了可读事件,必须及时处理,否则可能会出现读事件不再触发,连接饿死的情况。

event处理抽象出来的关键结构体 ngx_event_actions_t 如下:

typedef struct {
	// 添加删除事件
    ngx_int_t  (*add)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags);
    ngx_int_t  (*del)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags);

    ngx_int_t  (*enable)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags);
    ngx_int_t  (*disable)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags);

	// 添加删除连接,同时会监听读写事件
    ngx_int_t  (*add_conn)(ngx_connection_t *c);
    ngx_int_t  (*del_conn)(ngx_connection_t *c, ngx_uint_t flags);

    ngx_int_t  (*notify)(ngx_event_handler_pt handler);

	// 处理事件函数
    ngx_int_t  (*process_events)(ngx_cycle_t *cycle, ngx_msec_t timer,
                                 ngx_uint_t flags);

    ngx_int_t  (*init)(ngx_cycle_t *cycle, ngx_msec_t timer);
    void       (*done)(ngx_cycle_t *cycle);
} ngx_event_actions_t;

可以看到,每个event处理模型,都需要实现部分功能。最关键的是add和del功能,就是最基本的添加和删除事件的函数。

accept锁

Nginx是多进程程序,80端口是各进程所共享的,多进程同时listen 80端口,势必会产生竞争,也产生了所谓的“惊群”效应。
所以Nginx采用了自有的一套accept加锁机制,避免多个进程同时调用accept。Nginx多进程的锁在底层默认是通过CPU自旋锁来实现。如果操作系统不支持自旋锁,就采用文件锁。

什么是惊群效应:
当内核accept一个连接时,会唤醒所有等待中的进程,但实际上只有一个进程能获取连接,其他的进程都是被无效唤醒的。
因为它惊动了所有进程,但是除了那一个可以accept的进程外都是被无效唤醒的,所以叫“惊群”。

Nginx事件处理的入口函数是ngx_process_events_and_timers()
可以看到ngx_process_events_and_timers函数中加锁的过程代码如下:

if (ngx_use_accept_mutex) {
    if (ngx_accept_disabled > 0) {
        ngx_accept_disabled--;

    } else {
        if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
            return;
        }

        if (ngx_accept_mutex_held) {
            flags |= NGX_POST_EVENTS;

        } else {
            if (timer == NGX_TIMER_INFINITE
                || timer > ngx_accept_mutex_delay)
            {
                timer = ngx_accept_mutex_delay;
            }
        }
    }
}

在ngx_trylock_accept_mutex()函数里面,如果拿到了锁,Nginx会把listen的端口读事件加入event处理,该进程在有新连接进来时就可以进行accept了。

ngx_process_events_and_timers函数中:

(void) ngx_process_events(cycle, timer, flags);

ngx_event_process_posted(cycle, &ngx_posted_accept_events);

if (ngx_accept_mutex_held) {
    ngx_shmtx_unlock(&ngx_accept_mutex);
}

ngx_process_events()函数是所有事件处理的入口,它会遍历所有的事件。抢到了accept锁的进程跟一般进程稍微不同的是,它被加上了NGX_POST_EVENTS标志,
也就是说在ngx_process_events() 函数里面只接受而不处理事件,并加入post_events的队列里面。
直到ngx_accept_mutex锁释放以后才去处理具体的事件。
为什么这样?
因为ngx_accept_mutex是全局锁,这样做可以尽量减少该进程抢到锁以后,从accept开始到结束的时间,以便其他进程继续接收新的连接,提高吞吐量。

ngx_posted_accept_events和ngx_posted_events就分别是accept延迟事件队列和普通延迟事件队列。
可以看到ngx_posted_accept_events还是放到ngx_accept_mutex锁里面处理的。
该队列里面处理的都是accept事件,它会一口气把内核backlog里等待的连接都accept进来,注册到读写事件里。

而ngx_posted_events是普通的延迟事件队列。
一般情况下,什么样的事件会放到这个普通延迟队列里面呢?
那些CPU耗时比较多的都可以放进去。因为Nginx事件处理都是根据触发顺序在一个大循环里依次处理的,因为Nginx一个进程同时只能处理一个事件,所以有些耗时多的事件会把后面所有事件的处理都耽搁了。

除了加锁,Nginx也对各进程的请求处理的均衡性作了优化,也就是说,如果在负载高的时候,进程抢到的锁过多,会导致这个进程被禁止接受请求一段时间。

在ngx_event_accept函数中,有如下代码:

ngx_accept_disabled = ngx_cycle->connection_n / 8 - ngx_cycle->free_connection_n;

ngx_cycle->connection_n是进程可以分配的连接总数,ngx_cycle->free_connection_n是空闲的进程数。上述等式说明了,当前进程的空闲进程数小于1/8的话,就会被禁止accept一段时间。

定时器

Nginx在需要用到超时的时候,都会用到定时器机制。

比如,建立连接以后的那些读写超时。Nginx使用红黑树来构造定期器。
红黑树是一种有序的二叉平衡树,其查找插入和删除的复杂度都为O(logn),所以是一种比较理想的二叉树。

定时器的机制就是,二叉树的值是其超时时间,每次查找二叉树的最小值,如果最小值已经过期,就删除该节点,然后继续查找,直到所有超时节点都被删除。

变量

Nginx中的变量指的是什么

在Nginx中同一个请求需要在模块之间传递数据或者说在配置文件里面使用模块动态的数据一般来说都是使用变量。

比如在HTTP模块中导出了host/remote_addr等变量,这样我们就可以在配置文件中以及在其他的模块使用这个变量。

在Nginx中,有两种定义变量的方式,一种是在配置文件中,使用set指令,一种就是在模块中定义变量,然后导出。

在Nginx中所有的变量都是与HTTP相关的 (也就是说赋值都是在请求阶段) ,并且基本上都是同时保存在两个数据结构中,一个就是hash表(可选),另一个是数组。

比如一些特殊的变量,比如arg_xxx/cookie_xxx等,这些变量的名字是不确定的 (因此不能内置),而且他们还是只读的 (不能交由用户修改),如果每个都要放到hash表中的话 (不知道用户会取多少个),会很占空间。因此这些变量就没有hash,只有索引。
注意,用户不能定义这样的变量,这样的变量只存在于Nginx内部。

Nginx中存放变量的结构体ngx_http_variable_s如下:

typedef struct ngx_http_variable_s  ngx_http_variable_t;
struct ngx_http_variable_s {
    ngx_str_t                     name;   /* must be first to build the hash */
    ngx_http_set_variable_pt      set_handler;
    ngx_http_get_variable_pt      get_handler;
    uintptr_t                     data;
    ngx_uint_t                    flags;
    ngx_uint_t                    index;
};

// name: 表示变量的名称。
// set_handler: 设置变量的回调函数。
// get_handler: 获取变量的回调函数。
/* data: 传递给回调的第三个参数,
		set和get回调函数都有三个参数(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) */
/* flags: 表示变量的属性。
	flag属性是由下列属性组合而成:
		1. #define NGX_HTTP_VAR_CHANGEABLE    1	 表示这个变量是可变的
				Nginx有很多内置变量是不可变的,比如arg_xxx这变量,如果你使用set指令来修改,那么Nginx就会报错
		2. #define NGX_HTTP_VAR_NOCACHEABLE   2  表示这个变量每次都要去取值,而不是直接返回上次cache的值(配合对应的接口)
		3. #define NGX_HTTP_VAR_INDEXED 	  4  表示这个变量是用索引读取的
		4. #define NGX_HTTP_VAR_NOHASH 		  8  表示这个变量不需要被hash.
		5. #define NGX_HTTP_VAR_WEAK         16	 表示这个变量是易变的
		6. #define NGX_HTTP_VAR_PREFIX       32	 表示前缀变量 */
	
// index: 提供了一个索引(数组的脚标),从而可以迅速定位到对应的变量。

get/set回调函数的原型:

typedef void (*ngx_http_set_variable_pt) (ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data);
typedef ngx_int_t (*ngx_http_get_variable_pt) (ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data);

// r: 当前请求。
// v: 需要设置或者获取的变量值。
// data: 初始化时的回调指针。
  • ngx_http_variable_value_t结构体:
    typedef ngx_variable_value_t  ngx_http_variable_value_t;
    typedef struct {
        unsigned    len:28;
    
        unsigned    valid:1;
        unsigned    no_cacheable:1;
        unsigned    not_found:1;
        unsigned    escape:1;
    
        u_char     *data;	// 当我们在get_handle中设置变量值的时候,只需要将对应的值放入到data中就可以了。
        					// 这里data需要在get_handle中分配内存。
    } ngx_variable_value_t;
    
  • 以一个get_handle的回调函数ngx_http_fastcgi_script_name_variable函数的部分代码举例,data需要在其中分配内存:
    v->len = f->script_name.len + flcf->index.len;
    
    v->data = ngx_pnalloc(r->pool, v->len);
    if (v->data == NULL) {
        return NGX_ERROR;
    }
    
    p = ngx_copy(v->data, f->script_name.data, f->script_name.len);
    ngx_memcpy(p, flcf->index.data, flcf->index.len);
    

变量在Nginx中的初始化流程如下:

  1. 首先当解析HTTP之前会调用ngx_http_variables_add_core_vars(pre_config)来将HTTP core模块导出的变量(http_host/remote_addr…)添加进全局的hash key链中。
  2. 解析完HTTP模块之后,会调用ngx_http_variables_init_vars来初始化所有的变量(不仅包括HTTP core模块的变量,也包括其他的HTTP模块导出的变量,以及配置文件中使用set命令设置的变量),这里的初始化包括初始化hash表,以及初始化数组索引。
  3. 当每次请求到来时会给每个请求创建一个变量数组 (数组的个数是第二步保存的变量的个数)。然后只有取变量值的时候,才会将变量保存在数组对应的位置。

Nginx中如何创建变量

  • 在Nginx中,创建变量有两种方式:
    1. 在配置文件中使用set指令。
    2. 在模块中调用对应的接口。

在配置文件中创建变量比较简单,因此我们主要来看如何在模块中创建自己的变量。

  • Nginx提供了接口,可以供模块调用来创建变量:
    ngx_http_variable_t *ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags);
    
    这个函数所做的工作就是将变量 “name”添加进全局的hash key表中,然后初始化一些域。对应变量的get/set回调,需要当这个函数返回之后,显式的设置。
    比如src/http/modules/ngx_http_split_clients_module.c中:
    var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
    if (var == NULL) {
       return NGX_CONF_ERROR;
    }
    // 设置回调函数
    var->get_handler = ngx_http_split_clients_variable;
    var->data = (uintptr_t) ctx;
    

Nginx中如何使用变量

Nginx的内部变量指的就是Nginx的官方模块中所导出的变量,在Nginx中,大部分常用的变量都是CORE和HTTP模块导出的。

而在Nginx中,不仅可以在模块代码中使用变量,而且还可以在配置文件中使用。

假设我们需要在配置文件中使用http模块的host变量,那么只需要这样在变量名前加一个$符号就可以了($host)

而如果需要在模块中使用host变量,那么就比较麻烦。
Nginx提供了下面几个接口来取得变量:(在src/http/ngx_http_variables.h文件中有声明)

// 用来取得有索引的变量
ngx_http_variable_value_t *ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index);

/* 用来取得有索引的变量,但是该函数会处理 NGX_HTTP_VAR_NOCACHEABLE这个标记。
 也就是说如果你想要cache你的变量值,那么你的变量属性就不能设置NGX_HTTP_VAR_NOCACHEABLE,
 并且通过ngx_http_get_flushed_variable来获取变量值*/
ngx_http_variable_value_t *ngx_http_get_flushed_variable(ngx_http_request_t *r, ngx_uint_t index);

// 它能够得到没有索引的变量值
ngx_http_variable_value_t *ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key);

通过上面我们知道可以通过索引来得到变量值,可是这个索引该如何取得呢,Nginx也提供了对应的接口:

// 通过这个接口,就可以取得对应变量名的索引值
ngx_int_t ngx_http_get_variable_index(ngx_conf_t *cf, ngx_str_t *name);

举个例子

在http_log模块中,如果在log_format中配置了对应的变量,那么它会调用ngx_http_get_variable_index来保存索引:
(代码位置:src/http/modules/ngx_http_log_module.c)

static ngx_int_t
ngx_http_log_variable_compile(ngx_conf_t *cf, ngx_http_log_op_t *op,
    ngx_str_t *value, ngx_uint_t escape)
{
    ngx_int_t  index;

    index = ngx_http_get_variable_index(cf, value);
    if (index == NGX_ERROR) {
        return NGX_ERROR;
    }

    op->len = 0;

    switch (escape) {
    case NGX_HTTP_LOG_ESCAPE_JSON:
        op->getlen = ngx_http_log_json_variable_getlen;
        op->run = ngx_http_log_json_variable;
        break;

    case NGX_HTTP_LOG_ESCAPE_NONE:
        op->getlen = ngx_http_log_unescaped_variable_getlen;
        op->run = ngx_http_log_unescaped_variable;
        break;

    default: /* NGX_HTTP_LOG_ESCAPE_DEFAULT */
        op->getlen = ngx_http_log_variable_getlen;
        op->run = ngx_http_log_variable;
    }

    op->data = index;

    return NGX_OK;
}

然后http_log模块会使用ngx_http_get_indexed_variable来得到对应的变量值,这里要注意,就是使用这个接口的时候,判断返回值,不仅要判断是否为空,也需要判断value->not_found,这是因为只有第一次调用才会返回空,后续返回就不是空,因此需要判断value->not_found:

static u_char *
ngx_http_log_variable(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
{
    ngx_http_variable_value_t  *value;

    value = ngx_http_get_indexed_variable(r, op->data);		// 获取变量值

    if (value == NULL || value->not_found) {
        *buf = '-';
        return buf + 1;
    }

    if (value->escape == 0) {
        return ngx_cpymem(buf, value->data, value->len);

    } else {
        return (u_char *) ngx_http_log_escape(buf, value->data, value->len);
    }
}

结束!

Nginx http_core模块 配置文件解析 Nginx 的配置文件解析很麻烦,数据结构交织在一起,特别恶心,经过几天的分析,得到了一幅大概的关系图,自以为是正确的。 cycle = ngx_init_cycle(&init_cycle):        1、在内存池中分配一个ngx_cycle_t变量,并初始化它的各个成员。        2、调用core类型的create_conf,实际只有一个ngx_cor 阅读详情

相关推荐

nginx各个模块的监听怎么建立

概括 文章描述的前提是开启了SO_REUSEPORT特性 在init_cycle会调用modlue的解析配置,各个moudle会在NGX_CORE_MODULE配置中将自己要监听的端口放入cycle->listening的数组中。 master会在解析完配置后初始化各个module,按照需要启动worker的个数复制相同个数ngx_listening_t,给每个ngx_listening_t记录上对应的编号。对所有的ngx_listening_t开启监听。 master调用fork()创建相对应个数

lqq_419的博客 450

nginx events 模块配置

这里写目录标题1.简介2.主要指令2.1 accept_mutex2.2 multi_accept2.3 worker_connections2.4 use3. nginx event模块的基本配置 1.简介 nginx events 模块主要是nginx 和用户交互网络连接优化的配置内容 2.主要指令 nginx events模块主要包含了accept_mutex, multi_accept,worker_connections 和 use这几个指令 2.1 accept_mutex 这个配置主要可以用

qq_21134059的博客 3186

Python爬虫实战:巧用HEAD请求和Cookie令牌绕过沃尔玛反爬(附完整代码)

本文详细介绍了如何利用Python爬虫技术,通过HEAD请求和Cookie令牌绕过沃尔玛的反爬机制。文章深入解析了人机验证系统的运作原理,并提供了完整的工程化实现代码,包括令牌池设计、高并发架构和异常处理策略,帮助开发者高效采集电商数据。

weixin_29046035的博客 1007

【Nginx03】Nginx学习:事件模块Event

Nginx学习:事件模块Event基础的核心模块中,事件模块是非常重要的一个部分,但是,它的配置项其实并不多,常见的或者说需要我们去配置的更少。不过本着基础学习和了解的态度,咱们还是要一个个的学习一下。首先来看一下什么是事件模块。在 Nginx 中,模块相关的配置都是在一对大花括号中的,比如 http{} 、server{} 这些,事件模块也是类似的。events{……………………}事件模块主要...

硬核项目经理 1150

使用 Unity Sentis 和 Compute Shader,det_10g.onnx 进行高效人脸五官定位

在计算机视觉领域,人脸五官定位是一个重要的任务。本文将介绍如何使用 Unity Sentis 和 Compute Shader,结合模型,实现高效的人脸五官定位。我们将详细讲解每一步骤,并提供完整的代码示例。

m0_55632444的博客 2393

PPPoe的抓包分析(详细)

PPPoe的报文结构 可以看出PPPoe的报文结构其实很简单,只不过是将PPPoe的报文塞到以太网的载荷中,而且它的头部字段也十分的简单,TLV就不说了,code字段表示了PPPoe不同的报文类型,比较常见的就是上面的五个报文了,PPPoe的报文类型其实还蛮多的。session ID主要的作用就是标识一段会话,因为使用PPPoe的最主要作用就是使得多台设备可以借助以太网多点接入多点访问的特点去和一台设备做上网认证请求,这样运营商一台认证设备就可以满足多个用户的认证请求,这和PPP相比起来好的不止一点。

qq_47529104的博客 7868

Nginx源码分析 - Event事件篇 - Event模块和配置的初始化(16)

目录 一、Event模块的数据结构 1. event事件模块的配置 2. ngx_events_module 事件模块 3. ngx_event_core_module 事件核心模块 4. ngx_event_conf_t 事件conf结构 二、Event模块结构图 三、Event模块的初始化 1. ngx_event_module_init 模块初始化函数 四、Event模块配置的初始化 1. ngx_events_module 模块配置初始化 2. ngx_conf_parse 解

alpha_love的博客 650

MIKE21桥墩模拟实战:抠网格与构筑物法对比与选型指南

本文详细对比了MIKE21软件中抠网格法与构筑物法在桥墩模拟中的应用,包括操作步骤、适用场景及优缺点分析。通过实际案例数据展示两种方法的精度与效率差异,并提供选型决策树和常见问题解决方案,帮助工程师根据项目需求选择最优模拟方法。

weixin_42656416的博客 322

Nginx event 模块

在Nginx的设计中,event模块抽象了操作系统提供的不同类型的事件通知机制(如epoll、kqueue、select等),使得Nginx能够根据运行平台自动选择最优的事件模型进行高效地监听和处理多个客户端连接的读写事件。总之,Nginx event模块是构建高性能Web服务器不可或缺的基础组件,它为Nginx提供了高效处理并发连接的能力,确保了在高负载情况下也能保持较低的延迟和较高的吞吐量。:维护一个连接池,对每个连接都注册相应的读写事件,当某个连接上有事件发生时,会立即调度执行关联的处理程序。

qq_33240556的博客 530

别再为数码管引脚发愁了!用STM32的普通IO口驱动TM1650数码管模块(附完整模拟I2C代码)

本文详细介绍了如何利用STM32的普通IO口通过模拟I2C协议驱动TM1650数码管模块,提供了完整的硬件连接方案和软件实现代码。通过模拟I2C技术,开发者可以灵活使用任意GPIO引脚控制多位数码管显示,解决了传统驱动方式占用大量IO资源的问题。文章包含TM1650寄存器解析、亮度控制等实用功能实现,并分享了常见问题排查与性能优化技巧。

weixin_30764771的博客 657

LVGL在单色屏上运行

本文主要讲述LVGL在单色屏应用中的实现思路,并已验证通过。网上关于lvgl移植的文章有很多了,本文不加以赘述。

weixin_43278295的博客 4462

Nginx源码分析 - Event事件篇 - Nginx的Event事件模块概览(17)

目录 一、event模块的概览 二、重要数据结构 1. ngx_listening_s 侦听结构 2. ngx_connection_s socket连接对象结构 3. ngx_event_s 事件数据结构 前一章,我们讲解了《Nginx源码分析 - 主流程篇 - 多进程的惊群和进程负载均衡处理 》中实际上已经涉及到了一部分事件模块的概念。细心的可以发现,Nginx的事件都是由nginx_event.c文件中的ngx_process_events_and_timers进程事件分发器这个函数开..

alpha_love的博客 864

TC3XX - MCAL知识点(三):MCU EB-tresos配置说明及代码浅析

AURIX 2G Tc3xx的配置相较AURIX 1G Tc2xx来讲简化了许多,但是依赖于数据手册的理解来讲整个MCU功能做了较大增强,此处先简单的介绍一下,本文前期先补充介绍一下英飞凌手册的阅读规则,因为后面的文章会基于此文的一些缩写进行截图寄存器之类的。MCU在AUTOSAR架构里面的图示如下MCU驱动程序负责配置SCU、GTM、CCU6、GPT12和STM外设。驱动程序提供由AUTOSAR指定的运行时服务。

梦想技术家 2872

nginx源码阅读(十).ngx_event_core_module模块

前言 所有模块的通用接口ngx_module_t 感兴趣的配置项ngx_event_core_commands 存储配置项的结构体ngx_event_conf_t 事件模块的通用性接口ngx_event_module_t 小结前言本小节将进入到ngx_event_core_module模块,它是所有事件模块中排第一位的模块,因为要负责创建连接池,还要选择I/O多路复用机制等工作。接下来我们就来看看它

Move_now的博客 1365

【unity游戏开发入门到精通——通用篇】Post Processing 后处理插件Post-process Volume 和 Volume最全基础使用说明

之前我已经实现了不少后处理功能,本文其实就是将他们归类整理,以便更好的查找和理解。在Unity中,后处理(Post-Processing)是在相机所捕捉的图像上应用一些特殊效果的过程,后处理会让图像视觉效果更好(前提是做的好)。这些效果的范围有非常细微的颜色调整,也包括整体的美术风格的大修,可以让场景看起来更加真实或风格化,或者只是变得更好看。就像我们都会用手机拍照,但很多时候我们拍的原始的相片都打不到我们想要的效果。比如照片可能亮度不够,颜色不饱和或者对比度不好等。

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 7895

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

ngx_event_core_module

在。

weixin_41812346的博客 765

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

nginx源码阅读 ---- Event模块和配置的初始化

1.配置文件 event事件模块,配置分为两层:ngx_events_module 事件模块 和 ngx_event_core_module 事件核心模块。 ngx_events_module:模块类型NGX_CORE_MODULE,所以此模块在最外层核心模块解析“events”命令的时候会回调ngx_events_block函数。 ngx_event_core_module:模块类型NGX_EVENT_MODULE,所以此模块在ngx_events_block函数被回调后,才能解析配置信息 最外

alpha_love的博客 381

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

nginx模块化结构分析

nginx模块化设计 模块化设计是nginx的架构基础。在nginx中,除了少量核心代码,其他一切皆为模块。 nginx定义模块的方式很简单,例如: ngx_module_t ngx_http_test_module; 其中,ngx_module_t是nginx模块的数据结构,由于本文主要介绍nginx的模块化设计结构,所有只介绍两个成员: typedef struct ngx_module_s...

dev_essay 717

nginx ngx_core_module(main event)

例子 user www www; worker_processes 2; error_log /var/log/nginx-error.log info; events { use kqueue; worker_connections 2048; } main 语法 默认 描述 daemon on | off; on daemon debug_points...

Claroja 178

Nginx编译配置脚本篇(3)- 源码相关变量脚本auto/sources

Nginx编译配置脚本篇(3)- 源码相关变量脚本auto/sources1、相关文章2、前言3、auto/sources文件内容详解3.1、核心模块3.1.1、核心模块名称(CORE_MODULES)3.1.2、核心模块头文件所在目录(CORE_INCS)3.1.3、核心模块头文件(CORE_DEPS)3.1.4、核心模块源文件(CORE_SRCS)3.2、事件模块3.2.1、事件模块名称(EVENT_MODULES)3.2.2、事件模块头文件所在目录(EVENT_INCS)3.2.3、事件模块头文件(E

游戏行业资深搬砖人员 6160

【Linux网络编程】Nginx -- 事件模块(二)

【Linux网络编程】Nginx -- 事件模块(二) 【1】ngx_events_module 核心模块 【1.1】ngx_events_module 核心模块 -- 相关接口定义 ngx_events_module 模块是事件的核心模块,该模块的功能是定义新的事件类型,并为每个事件模块定义通用接口 ngx_event_module_t 结构体,管理事件模块生成的配置项结构体,并解析事件类配置项; ngx_events_module 的定义 // src\event\ngx_event.c //

CopperSun 技术博客 620

22.Nginx模块

看Nginx代码时, src目录下的结构为core、event、http和os,可见Nginx的代码层次十分清晰;同样,我们在代码中也经常看到ngx_modules这个全局变量,可见在Nginx中是有模块概念的,事实上Nginx的设计就是高度模块化的,这一节我们学习下Nginx的模块结构体和ngx_modules数组。 /* core/ngx_core.h */ typedef str

疯哥哥带你飞 5872

Nginx模块详解

title: Nginx模块详解 date: 2019-06-05 20:58:43 tags: Nginx categories: Nginx toc: true 1. Nginx模块综述 nginx的模块非常之多,可以认为所有代码都是以模块的形式组织,这包括核心模块和功能模块,针对不同的应用场合,并非所有的功能模块都要被用到,附录A给出的是默认configure(即简单的http服务器应用)下被连接的模块,这里虽说是模块连接,但nginx不会像apache或lighttpd那样在编译时生成so动态库.

倦还的博客 1753

Nginx模块初识

Nginx模块需要提前编译进Nginx的二进制文件中 了解模块配置项 模块何时被使用 提供哪些变量 nginx模块官方文档

error311的博客 370

nginx 源码学习笔记(三)——nginx精粹-模块

下面开始真正"nginx之旅",屏住呼吸吧! 首先找好入手点,对于nginx的入手点就是ngx_module_t结构,他的声明在src/core/ngx_conf_file.h中(我的版本nginx-1.0.13) #define NGX_MODULE_V1 0, 0, 0, 0, 0, 0, 1 #define NGX_MODULE_V1_PADDING 0, 0, 0, 0, 0, 0, 0, 0 struct ngx_module_s { ngx_uint_t

qq_23350817的博客 283
上一篇: Nginx学习(9)—— 负载均衡模块
下一篇: C语言中命令行工具 (getopt和getopt_long)
丶星下灯
博客等级 码龄6年 125粉丝 77原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值