当前位置: 首页 > news >正文

nginx http模块

1.模块依赖

2. 模块的初始化

2.1 location的定义

location的定义包含以下几种

location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }

=:表示精确匹配,只有请求的url路径与后面的字符串完全相等时,才会命中,不支持location嵌套

~:表示使用正则定义的,区分大小写

~*:表示是使用正则定义的,不区分大小写

^~:表示该符号后面的字符是最佳匹配,采用该规则,不再进行后续的查找

@name:用于定义一个内部 Location 块,该块不能被外部 Client 所访问,只能被 NGINX 内部配置指令所访问,比如 try_files 或者error_page。其修饰的location不能嵌套到其它location,也不能再嵌套其它location,即只能是server这一层的

2.2 分配ngx_http_conf_ctx_t

2.2.1 ngx_http_block

其是在解析配置文件中的http分配

ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
ctx->main_conf = ngx_pcalloc(cf->pool,sizeof(void *) * ngx_http_max_module);
ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);

2.2.2 ngx_http_core_location

其是在解析配置文件中的http块内location时分配

其中main_conf,srv_conf是延用上一层级的,loc_conf会再一次分配内存

ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
pctx = cf->ctx;
ctx->main_conf = pctx->main_conf;
ctx->srv_conf = pctx->srv_conf;
ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);

同时也会遍历模块调用create_loc_conf创建location的配置

for (i = 0; cf->cycle->modules[i]; i++) {if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) {continue;}module = cf->cycle->modules[i]->ctx;if (module->create_loc_conf) {ctx->loc_conf[cf->cycle->modules[i]->ctx_index] =module->create_loc_conf(cf);if (ctx->loc_conf[cf->cycle->modules[i]->ctx_index] == NULL) {return NGX_CONF_ERROR;}}}

设置http_core_module配置的loc_conf来源

clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
clcf->loc_conf = ctx->loc_conf;

2.3 ngx_http_add_location

构造ngx_http_location_queue_t,将当前ngx_http_core_loc_conf_t添加到上一层级ngx_http_core_loc_conf_t中的location队列中。如果是精确匹配,正则,有名或者是无名,构造的ngx_http_location_queue_t的exact来存放ngx_http_core_loc_conf_t配置,否则使用ngx_http_location_queue_t的inclusive来存放ngx_http_core_loc_conf_t配置

if (clcf->exact_match
#if (NGX_PCRE)|| clcf->regex
#endif|| clcf->named || clcf->noname){lq->exact = clcf;lq->inclusive = NULL;} else {lq->exact = NULL;lq->inclusive = clcf;}

将构造的队列添加到上一层级的队列中

ngx_queue_insert_tail(*locations, &lq->queue);

2.4 主配置中的server

在ngx_http_block中会分配main_conf

ctx->main_conf = ngx_pcalloc(cf->pool,sizeof(void *) * ngx_http_max_module);

在处理server时(ngx_http_core_server),当前层的ctx中的main_conf会延用上一层的main_conf

http_ctx = cf->ctx;
ctx->main_conf = http_ctx->main_conf;

将server放入cmcf->server中

cscf = ctx->srv_conf[ngx_http_core_module.ctx_index];
cscf->ctx = ctx;cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];cscfp = ngx_array_push(&cmcf->servers);
if (cscfp == NULL) {return NGX_CONF_ERROR;
}*cscfp = cscf;

2.5 初始化location(ngx_http_init_locations)

处理ngx_http_core_srv_conf_t中的有名location(named_locations)以及ngx_http_core_loc_conf_t中的正则location(regex_locations),在作割裂之前,会先对ngx_http_core_loc_conf_t中的locations排序,使用的排序规则为ngx_http_cmp_locations,即按照exact(sorted) -> inclusive(sorted) -> regex -> named -> noname的原则进行排序,经过处理后,原先的location队列就只剩下经过排序后的exact以及inclusive类型的location了。这两类location对应配置文件中的定义,就是不含修饰符的location,带有=和^~前缀的location。

2.6 将queue转为list(ngx_http_create_locations_list)

将locations queue变成locations list

2.7 创建location的二叉查找树(ngx_http_create_locations_tree)

创建精确匹配location的二叉查找树,使用ngx_queue_middle(其时间度为O(n))得到location_list中的中间位置,如果location_list的元素个数为奇数,则是中间的一个,否则是后半部分的第一个。

ngx_queue_t *
ngx_queue_middle(ngx_queue_t *queue)
{ngx_queue_t  *middle, *next;middle = ngx_queue_head(queue);if (middle == ngx_queue_last(queue)) {return middle;}next = ngx_queue_head(queue);for ( ;; ) {middle = ngx_queue_next(middle);next = ngx_queue_next(next);if (next == ngx_queue_last(queue)) {return middle;}next = ngx_queue_next(next);if (next == ngx_queue_last(queue)) {return middle;}}
}

使用递归来构建二叉查找树

/** to keep cache locality for left leaf nodes, allocate nodes in following* order: node, left subtree, right subtree, inclusive subtree*/static ngx_http_location_tree_node_t *
ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,size_t prefix)
{size_t                          len;ngx_queue_t                    *q, tail;ngx_http_location_queue_t      *lq;ngx_http_location_tree_node_t  *node;q = ngx_queue_middle(locations);lq = (ngx_http_location_queue_t *) q;len = lq->name->len - prefix;node = ngx_palloc(cf->pool,offsetof(ngx_http_location_tree_node_t, name) + len);if (node == NULL) {return NULL;}node->left = NULL;node->right = NULL;node->tree = NULL;node->exact = lq->exact;node->inclusive = lq->inclusive;node->auto_redirect = (u_char) ((lq->exact && lq->exact->auto_redirect)|| (lq->inclusive && lq->inclusive->auto_redirect));node->len = (u_short) len;ngx_memcpy(node->name, &lq->name->data[prefix], len);ngx_queue_split(locations, q, &tail);if (ngx_queue_empty(locations)) {/** ngx_queue_split() insures that if left part is empty,* then right one is empty too*/goto inclusive;}node->left = ngx_http_create_locations_tree(cf, locations, prefix);if (node->left == NULL) {return NULL;}ngx_queue_remove(q);if (ngx_queue_empty(&tail)) {goto inclusive;}node->right = ngx_http_create_locations_tree(cf, &tail, prefix);if (node->right == NULL) {return NULL;}inclusive:if (ngx_queue_empty(&lq->list)) {return node;}node->tree = ngx_http_create_locations_tree(cf, &lq->list, prefix + len);if (node->tree == NULL) {return NULL;}return node;
}

2.8 http的处理阶段

包含11个阶段

枚举

名称

NGX_HTTP_POST_READ_PHASE

在接收到完整的HTTP头部后处理的HTTP阶段

NGX_HTTP_SERVER_REWRITE_PHASE

在将请求的URI与location表达式匹配前, 修改请求的URI(所谓的重定向) 是一个独立的HTTP阶段

NGX_HTTP_FIND_CONFIG_PHASE

根据请求的URI寻找匹配的location表达式, 这个阶段只能由ngx_http_core_module模块实现, 不建议其他HTTP模块重新定义这一阶段的行为

NGX_HTTP_REWRITE_PHASE

在NGX_HTTP_FIND_CONFIG_PHASE阶段寻找到匹配的location之后再修改请求的URI

NGX_HTTP_POST_REWRITE_PHASE

这一阶段是用于在rewrite重写URL后, 防止错误的

nginx.conf配置导致死循环(递归地修改URI) , 因此, 这一阶段仅由ngx_http_core_module模块处理。 目前, 控制死循环的方式很简单, 首先检查

rewrite的次数, 如果一个请求超过10次重定向

,就认为进入了rewrite死循环, 这时在

NGX_HTTP_POST_REWRITE_PHASE阶段就会向用户返回500, 表示服务器内部错误

NGX_HTTP_PREACCESS_PHASE

表示在处理NGX_HTTP_ACCESS_PHASE阶段决定请求的访问权限前HTTP模块可以介入的处理阶段

NGX_HTTP_ACCESS_PHASE

这个阶段用于让HTTP模块判断是否允许这个请求访问

Nginx服务器

NGX_HTTP_POST_ACCESS_PHASE

在NGX_HTTP_ACCESS_PHASE阶段中, 当

HTTP模块的handler处理函数返回不允许访问的错误码时(实际就是NGX_HTTP_FORBIDDEN或者

NGX_HTTP_UNAUTHORIZED) , 这里将负责向用户发送拒绝服务的错误响应。 因此, 这个阶段实际上用于给NGX_HTTP_ACCESS_PHASE阶段收尾

NGX_HTTP_PRECONTENT_PHASE

http请求内容前置处理

NGX_HTTP_CONTENT_PHASE

用于处理HTTP请求内容的阶段, 这是大部分

HTTP模块最愿意介入的阶段

NGX_HTTP_LOG_PHASE

处理完请求后记录日志的阶段

2.9 阶段处理器的初始化

ngx_http_init_phases初始化以下阶段的handlers

  • NGX_HTTP_POST_READ_PHASE

  • NGX_HTTP_SERVER_REWRITE_PHASE

  • NGX_HTTP_REWRITE_PHASE

  • NGX_HTTP_PREACCESS_PHASE

  • NGX_HTTP_ACCESS_PHASE

  • NGX_HTTP_PRECONTENT_PHASE

  • NGX_HTTP_CONTENT_PHASE

  • NGX_HTTP_LOG_PHASE

static ngx_int_t
ngx_http_init_phases(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
{if (ngx_array_init(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers,cf->pool, 1, sizeof(ngx_http_handler_pt))!= NGX_OK){return NGX_ERROR;}if (ngx_array_init(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers,cf->pool, 1, sizeof(ngx_http_handler_pt))!= NGX_OK){return NGX_ERROR;}if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers,cf->pool, 1, sizeof(ngx_http_handler_pt))!= NGX_OK){return NGX_ERROR;}if (ngx_array_init(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers,cf->pool, 1, sizeof(ngx_http_handler_pt))!= NGX_OK){return NGX_ERROR;}if (ngx_array_init(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers,cf->pool, 2, sizeof(ngx_http_handler_pt))!= NGX_OK){return NGX_ERROR;}if (ngx_array_init(&cmcf->phases[NGX_HTTP_PRECONTENT_PHASE].handlers,cf->pool, 2, sizeof(ngx_http_handler_pt))!= NGX_OK){return NGX_ERROR;}if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers,cf->pool, 4, sizeof(ngx_http_handler_pt))!= NGX_OK){return NGX_ERROR;}if (ngx_array_init(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers,cf->pool, 1, sizeof(ngx_http_handler_pt))!= NGX_OK){return NGX_ERROR;}return NGX_OK;
}

2.10 配置后置处理(postconfiguration)

遍历调用http模块的postconfiguration,用来注册阶段的handler

for (m = 0; cf->cycle->modules[m]; m++) {if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {continue;}module = cf->cycle->modules[m]->ctx;if (module->postconfiguration) {if (module->postconfiguration(cf) != NGX_OK) {return NGX_CONF_ERROR;}}}

2.11 阶段引擎handler的初始化

将各个不同阶段的handler汇聚成一个处理链表

static ngx_int_t
ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
{ngx_int_t                   j;ngx_uint_t                  i, n;ngx_uint_t                  find_config_index, use_rewrite, use_access;ngx_http_handler_pt        *h;ngx_http_phase_handler_t   *ph;ngx_http_phase_handler_pt   checker;cmcf->phase_engine.server_rewrite_index = (ngx_uint_t) -1;cmcf->phase_engine.location_rewrite_index = (ngx_uint_t) -1;find_config_index = 0;use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0;use_access = cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.nelts ? 1 : 0;n = 1                  /* find config phase */+ use_rewrite      /* post rewrite phase */+ use_access;      /* post access phase */for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {n += cmcf->phases[i].handlers.nelts;}ph = ngx_pcalloc(cf->pool,n * sizeof(ngx_http_phase_handler_t) + sizeof(void *));if (ph == NULL) {return NGX_ERROR;}cmcf->phase_engine.handlers = ph;n = 0;for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {h = cmcf->phases[i].handlers.elts;switch (i) {case NGX_HTTP_SERVER_REWRITE_PHASE:if (cmcf->phase_engine.server_rewrite_index == (ngx_uint_t) -1) {cmcf->phase_engine.server_rewrite_index = n;}checker = ngx_http_core_rewrite_phase;break;case NGX_HTTP_FIND_CONFIG_PHASE:find_config_index = n;ph->checker = ngx_http_core_find_config_phase;n++;ph++;continue;case NGX_HTTP_REWRITE_PHASE:if (cmcf->phase_engine.location_rewrite_index == (ngx_uint_t) -1) {cmcf->phase_engine.location_rewrite_index = n;}checker = ngx_http_core_rewrite_phase;break;case NGX_HTTP_POST_REWRITE_PHASE:if (use_rewrite) {ph->checker = ngx_http_core_post_rewrite_phase;ph->next = find_config_index;n++;ph++;}continue;case NGX_HTTP_ACCESS_PHASE:checker = ngx_http_core_access_phase;n++;break;case NGX_HTTP_POST_ACCESS_PHASE:if (use_access) {ph->checker = ngx_http_core_post_access_phase;ph->next = n;ph++;}continue;case NGX_HTTP_CONTENT_PHASE:checker = ngx_http_core_content_phase;break;default:checker = ngx_http_core_generic_phase;}n += cmcf->phases[i].handlers.nelts;for (j = cmcf->phases[i].handlers.nelts - 1; j >= 0; j--) {ph->checker = checker;ph->handler = h[j];ph->next = n;ph++;}}return NGX_OK;
}

2.12 初始监听端口, 服务以及监听回调

ngx_http_optimize_servers中的ngx_http_add_listening会设置端口的回调

ls->handler = ngx_http_init_connection;

3. 运行时的处理

3.1 accept事件处理

在处理accept连接事件时,会调用ngx_listening_t的回调handler函数ngx_http_init_connection

对于新分配的连接,如果读事件的ready为1,即iocp或者延时的accept事件,在有使用accept锁情况 下,将事件放入posted_events队列中,否则直接调用事件的回调handler

if (rev->ready) {/* the deferred accept(), iocp */if (ngx_use_accept_mutex) {ngx_post_event(rev, &ngx_posted_events);return;}rev->handler(rev);return;
}

如果读事件的ready不为1,则将事件加入定时器的红黑树中。定时器超时后,就会调用它的 handler ngx_http_wait_request_handler 函数。

ngx_add_timer(rev, cscf->client_header_timeout);

将连接设置为可重用,因为该连接上还没有请求到来,所以当连接池中的连接不够用时,就可以重用这个连接。将当前connection添加可重用的连接队列中,同时可重用连接数加1

ngx_reusable_connection(c, 1);void
ngx_reusable_connection(ngx_connection_t *c, ngx_uint_t reusable)
{ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,"reusable connection: %ui", reusable);if (c->reusable) {ngx_queue_remove(&c->queue);ngx_cycle->reusable_connections_n--;#if (NGX_STAT_STUB)(void) ngx_atomic_fetch_add(ngx_stat_waiting, -1);
#endif}c->reusable = reusable;if (reusable) {/* need cast as ngx_cycle is volatile */ngx_queue_insert_head((ngx_queue_t *) &ngx_cycle->reusable_connections_queue, &c->queue);ngx_cycle->reusable_connections_n++;#if (NGX_STAT_STUB)(void) ngx_atomic_fetch_add(ngx_stat_waiting, 1);
#endif}
}

ngx_handle_read_event将分配连接的事件添加到事件驱动模块中

ngx_int_t
ngx_handle_read_event(ngx_event_t *rev, ngx_uint_t flags)
{if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {/* kqueue, epoll */if (!rev->active && !rev->ready) {if (ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT)== NGX_ERROR){return NGX_ERROR;}}return NGX_OK;} else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {/* select, poll, /dev/poll */if (!rev->active && !rev->ready) {if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT)== NGX_ERROR){return NGX_ERROR;}return NGX_OK;}if (rev->active && (rev->ready || (flags & NGX_CLOSE_EVENT))) {if (ngx_del_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT | flags)== NGX_ERROR){return NGX_ERROR;}return NGX_OK;}} else if (ngx_event_flags & NGX_USE_EVENTPORT_EVENT) {/* event ports */if (!rev->active && !rev->ready) {if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {return NGX_ERROR;}return NGX_OK;}if (rev->oneshot && rev->ready) {if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {return NGX_ERROR;}return NGX_OK;}}/* iocp */return NGX_OK;
}

3.2 首次可读事件处理

是通过ngx_http_wait_request_handler来处理

首先从网络上读取数据到连接中的buffer

ngx_connection_t          *c;
ngx_buf_t                 *b;
c = rev->data;
b = c->buffer;
if (b == NULL) {b = ngx_create_temp_buf(c->pool, size);if (b == NULL) {ngx_http_close_connection(c);return;}c->buffer = b;} else if (b->start == NULL) {b->start = ngx_palloc(c->pool, size);if (b->start == NULL) {ngx_http_close_connection(c);return;}b->pos = b->start;b->last = b->start;b->end = b->last + size;
}
n = c->recv(c, b->last, size);
b->last += n;

在可重用连接中删除当前连接

ngx_reusable_connection(c, 0);

创建http_request,在创建请求中,会将上面读取的缓冲区放在ngx_http_request_t中的header_in用于处理请求头

c->data = ngx_http_create_request(c);

处理请求头,同时将当前连接读事件的回调函数设置为ngx_http_process_request_line,用于处理单次接收的数据不完整

rev->handler = ngx_http_process_request_line;
ngx_http_process_request_line(rev);

3.3 请求行的处理

是通过ngx_http_process_request_line来处理的

先解析请求行

rc = ngx_http_parse_request_line(r, r->header_in);

相关文章:

nginx http模块

1.模块依赖2. 模块的初始化2.1 location的定义location的定义包含以下几种location [ | ~ | ~* | ^~ ] uri { ... } location name { ... }:表示精确匹配&#xff0c;只有请求的url路径与后面的字符串完全相等时&#xff0c;才会命中&#xff0c;不支持location嵌套~&#xff…...

守护进程 || 精灵进程

目录 守护进程&#xff08;deamon&#xff09; || 精灵进程 特点 什么是前台进程组 把自己写的服务器deamon deamon代码 守护进程&#xff08;deamon&#xff09; || 精灵进程 特点 01. 他的PPID是1&#xff08;附件特征&#xff09;02. COMMAND --- 称为进程启动的命令03…...

Zookeeper3.5.7版本——客户端命令行操作(znode 节点数据信息)

目录一、命令行语法二、znode 节点数据信息2.1、查看当前znode中所包含的内容2.2、查看当前节点详细数据2.3、节点详细数据解释一、命令行语法 命令行语法列表 命令基本语法功能描述help显示所有操作命令ls path使用 ls 命令来查看当前 znode 的子节点 [可监听]-w 监听子节点变…...

如何写好单测

1、为什么要写单测&#xff1f; 单测即单元测试&#xff08;Unit Test&#xff09;&#xff0c;是对软件的基本组成单元进行的测试&#xff0c;比如函数、过程或者类的方法。其意义是&#xff1a; 功能自测&#xff0c;发现功能缺陷自我Code Review测试驱动开发促进代码重构并…...

CDH-6.3.2内置spark-2.4.0的BUG

1. 背景 公司最近在新建集群&#xff0c;全部采用开源的大数据框架&#xff0c;并且将之前使用的阿里云的所有服务进行下线&#xff0c;其中就涉及到了旧任务的迁移。 2. 任务 2.1. 简述 我接手到一个之前的 spark 任务&#xff0c;是读取阿里 LogStore 数据&#xff0c;然…...

SpringCloud之ElasticSearch笔记

ElasticSearch 初识ElasticSearch ElasticSearch是什么 ElasticSearch一个基于Lucene的底层的开源的分布式搜索引擎&#xff0c;可用来实现搜索&#xff0c;日志统计&#xff0c;分析&#xff0c;系统监控 正向索引和倒排索引 正向索引&#xff1a;逐条扫描&#xff08;my…...

数字图像学笔记 —— 17. 图像退化与复原(自适应滤波之「最小二乘方滤波」)

文章目录维纳滤波的缺点约束最小二乘方滤波给一个实际例子吧维纳滤波的缺点 维纳滤波&#xff08;Wiener Filter&#xff09;&#xff0c;虽然是一种非常强大的退化图像还原算法&#xff0c;但是从实验过程我们也发现它存在着致命的缺陷&#xff0c;那就是要求输入退化系统的 …...

2023-03-05:ffmpeg推送本地视频至lal流媒体服务器(以RTMP为例),请用go语言编写。

2023-03-05&#xff1a;ffmpeg推送本地视频至lal流媒体服务器&#xff08;以RTMP为例&#xff09;&#xff0c;请用go语言编写。 答案2023-03-05&#xff1a; 使用 github.com/moonfdd/ffmpeg-go 库。 先启动lal流媒体服务器软件&#xff0c;然后再执行命令&#xff1a; go…...

MathType7最新版免费数学公式编辑器

话说我也算是 MathType准资深(DB)用户了,当然自从感觉用DB不好之后,我基本上已经抛弃它了,只是前不久因为个别原因又捡起来用了用,30天试用期间又比较深入的折腾了下,也算是变成半个MathType砖家,coco玛奇朵简单介绍一下这款软件:在很可能看到这儿的你还没有出生的某个年月&…...

一文带你入门angular(中)

一、angular中的dom操作原生和ViewChild两种方式以及css3动画 1.原生操作 import { Component } from angular/core;Component({selector: app-footer,templateUrl: ./footer.component.html,styleUrls: [./footer.component.scss] }) export class FooterComponent {flag: b…...

单例设计模式共享数据问题分析、解决(c++11)设计多线程。

系列文章目录 单例设计模式共享数据问题分析、解决; 文章目录系列文章目录前言一、单例模式1.1 基本概念1.2 单例设计模式共享数据问题分析、解决1.3 std::call_once()介绍二、代码案例1.代码示例总结前言 关键内容&#xff1a;c11、多线程、共享数据、单例类 本章内容参考git…...

Embedding-based Retrieval in Facebook Search

facebook的社交网络检索与传统的搜索检索的差异是&#xff0c;除了考虑文本&#xff0c;还要考虑搜索者的背景。通用搜索主要考虑的是文本匹配&#xff0c;并没有涉及到个性化。像淘宝&#xff0c;youtube这些其实都是涉及到了用户自身行为的&#xff0c;除了搜索还有推荐&…...

xmu 离散数学 卢杨班作业详解【8-12章】

文章目录第八章 树23456810第九章46811第十章24567第十一章14571116第十二章131317第八章 树 2 (2) 设有k片树叶 2∗m2∗43∗3k2*m2*43*3k2∗m2∗43∗3k n23kn23kn23k mn−1mn-1mn−1 联立解得k9 T中有9片树叶 3 有三颗非同构的生成树 4 (1) c --abc e–abed f–dgf…...

Linux入门篇-权限管理

简介 用户管理也是和权限相关的知识点。权限的作用 权限对于普通文件和目录文件作用是不一样的 。[kioskfoundation0 ~]$ ls -l total 264 -rw-rw-r--. 2 kiosk kiosk 31943 May 29 2019 ClassPrep.txt -rw-rw-r--. 2 kiosk kiosk 7605 Jun 14 2019 ClassRHAPrep.txt -rw-rw-r…...

Linux(基于 Centos7) 常用操作

1.Linux 简介Linux 是一种 免费使用、自由传播的类 Unix 操作系统Linux操作系统内核&#xff0c;由林纳斯托瓦兹在1991年10月5日首次发布...Linux 是一套开源操作系统&#xff0c;它有稳定、消耗资源小、安全性高等特点大多数人都是直接使用 Linux 发行版&#xff08;就是将 Li…...

Math类详解与Random类、三种随机数生成方式(java)

文章目录&#x1f4d6;前言&#xff1a;&#x1f380;认识Random类&#x1f380;三种随机数生成方式&#x1f380;Math类的用途&#x1f380;Math类的方法&#x1f4d6;前言&#xff1a; 本篇博客主要以介绍Math类的常用方法及认识Random类&#xff0c;及三种随机数生成方式 …...

Mac编译QT程序出现Undefined symbols for architecture x86_64

在Mac编写日志服务类, Logging_d.h内容如下 #pragma once #include <QLoggingCategory> Q_DECLARE_LOGGING_CATEGORY(hovering) Q_DECLARE_LOGGING_CATEGORY(creation) Q_DECLARE_LOGGING_CATEGORY(mouseevents) Q_DECLARE_LOGGING_CATEGORY(state) Q_DECLARE_LOGGING_C…...

蓝桥杯-李白打酒加强版

蓝桥杯-李白打酒加强版1、问题描述2、解题思路3、代码实现1、问题描述 话说大诗人李白, 一生好饮。幸好他从不开车。 一天, 他提着酒显, 从家里出来, 酒显中有酒 2 斗。他边走边唱: 无事街上走&#xff0c;提显去打酒。 逢店加一倍, 遇花喝一斗。 这一路上, 他一共遇到店 N 次…...

AtCoder Beginner Contest 292 (A - E) 记录第一场ABC

AtCoder Beginner Contest 292 A - E前言Q1 A - CAPS LOCKQ2 Yellow and Red CardQ3 Four VariablesQ4 D - Unicyclic ComponentsQ5 E - Transitivity前言 本来晚上在打Acwing周赛&#xff0c;最后一题Trie想不出来咋写&#xff0c;看群里有人说ABC要开始了&#xff0c;想着没…...

ubuntu安装使用putty

一、安装 安装虚拟机串口 sudo apt-get install putty sudo apt install -y setserial 二、使用 虚拟机连接串口 sudo setserial -g /dev/ttyS* 查看硬件对应串口 找到不是unknown的串口 sudo putty...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

安卓基础(aar)

重新设置java21的环境&#xff0c;临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的&#xff1a; MyApp/ ├── app/ …...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...