2019年12月

相关资料

https://en.wikipedia.org/wiki/Normalization_(statistics)
https://en.wikipedia.org/wiki/Standard_score
https://en.wikipedia.org/wiki/Feature_scaling
https://en.wikipedia.org/wiki/Coefficient_of_variation

https://www.cnblogs.com/feiyumo/p/9866818.html
https://blog.csdn.net/binlin199012/article/details/84638649
归一化:normalization
Z分数:Z-score
特征缩放:Feature scaling
变异系数:Coefficient of variation
In statistics and applications of statistics, normalization can have a range of meanings.
In the simplest cases, normalization of ratings means adjusting values measured on different scales to a notionally common scale, often prior to averaging.
In more complicated cases, normalization may refer to more sophisticated adjustments where the intention is to bring the entire probability distributions of adjusted values into alignment.

归一化是一种简化计算的方式,即将有量纲的表达式,经过变换,化为无量纲的表达式,成为标量。

Z分数

意义:一个给定的值距离平均数多少个标准差?

20191227112606.png

特征缩放

意义:将不同特征的值量化到同一区间。

20191227115303.png

变异系数

意义:离散程度的归一化,用于比较两组数据离散程度的大小。

20191227120048.png

相关资料

https://en.wikipedia.org/wiki/Position-independent_code
https://www.cnblogs.com/Xiao_bird/archive/2010/03/01/1675821.html
https://www.jianshu.com/p/2e12c6180d13

《深入理解计算机系统》链接
静态库解决了许多关于如何让大量相关函数对应用程序可用的问题。然而,静态库仍然有一些明显的缺点。
静态库和所有的软件一样,需要定期维护和更新。如果应用程序员想要使用一个库的最新版本,他们必须以某种方式了解到该库的更新情况,然后显式地将他们的程序与更新了的库重新链接。
另一个问题是几乎每个 C 程序都使用标准 I/O 函数,比如 printf 和 scanf。在运行时,这些函数的代码会被复制到每个运行进程的文本段。在一个运行上百个进程的典型系统上,这将是对稀缺的内存系统资源的极大浪费。(内存的一个有趣属性就是不论系统的内存有多大,它总是一种稀缺资源。)
共享库(shared library)是致力于解决静态库缺陷的一个现代创新产物。共享库是一个目标模块,在运行或加载时,可以加载到任意的内存地址,并和一个在内存中的程序链接起来。
在 Linux 系统中通常用 .so 后缀来表示。

位置无关代码

共享库的一个主要目的就是允许多个正在运行的进程共享内存中相同的库代码,因而节约宝贵的内存资源。那么,多个进程是如何共享程序的一个副本的呢?
可以加载而无需重定位的代码称为位置无关代码(Position-Independent Code, PIC)。用户对 GCC 使用 -fpic 选项指示 GNU 编译系统生成 PIC 代码。共享库的编译必须总是使用该选项。

ldd

ldd prints the shared libraries required by each program.
# ldd nginx
显示 nginx 依赖的共享库。

ldconfig

# -p
Print the lists of directories and candidate libraries stored in the current cache.
显示当前缓存文件所保存的共享库列表。
# /etc/ld.so.cache
File containing an ordered list of libraries found in the directories specified in /etc/ld.so.conf, as well as those found in /lib and /usr/lib.

hello.h

#ifndef HELLO_H
#define HELLO_H

void hello(const char *name);

#endif

hello.c

#include <stdio.h>
void hello(const char *name)
{
    printf("hello,%s!\n",name);
}

main.c

#include "hello.h"
int main()
{
    hello("world");
    return 0;
}

编译运行

# gcc hello.c -fPIC -shared -o libhello.so
# gcc main.c libhello.so -o hello
# mv libhello.so /usr/lib(64)
# ./hello

显式调用

#include <dlfcn.h>

void *dlopen(const char *filename, int flag);
void *dlsym(void *handle, const char *symbol);
int dlclose(void *handle);

相关资料

https://en.wikipedia.org/wiki/Static_library

《深入理解计算机系统》链接

# man ar
# man ranlib
In computer science, a static library or statically-linked library is a set of routines, external functions and variables which are resolved in a caller at compile-time and copied into a target application by a compiler, linker, or binder, producing an object file and a stand-alone executable.

静态库、静态链接库
将所有相关的目标模块打包成为一个单独的文件,称为静态库,它可以用做链接器的输入。
当链接器构造一个可输出的可执行文件时,它只复制静态库里被应用程序引用的目标模块。
在 Linux 系统中,静态库以一种称为存档(archive)的特殊文件格式存放在磁盘中。存档文件是一组连接起来的可重定位目标文件的集合,有一个头部用来描述每个成员目标文件的大小和位置。
存档文件名由后缀 .a 标识。

ar

The GNU ar program creates, modifies, and extracts from archives.

An archive is a single file holding a collection of other files in a structure that makes it possible to retrieve the original individual files.

The original files' contents, mode (permissions), timestamp, owner, and group are preserved in the archive, and can be restored on extraction.
r : Insert the files member... into archive (with replacement).
c : Create the archive.
s : Add an index to the archive, or update it if it already exists.
t : Display a table listing the contents of archive, or those of the files listed in member... that are present in the archive.
v : This modifier requests the verbose version of an operation.
# ar rcs libxxx.a xxx1.o xxx2.o
创建静态库。

# ar t libxxx.a
显示文件列表。

# ar tv libxxx.a
显示文件列表详细信息。

ranlib

ranlib generates an index to the contents of an archive and stores it in the archive.
The index lists each symbol defined by a member of an archive that is a relocatable object file.

You may use nm -s to list this index.
# ranlib libxxx.a
添加索引。

nm

GNU nm lists the symbols from object files objfile....

显示符号表。
# -s
When listing symbols from archive members, include the index: a mapping of which modules contain definitions for which names.
# nm libxxx.a
显示符号表。

# nm -s libxxx.a
显示带索引的符号表。

hello.h

#ifndef HELLO_H
#define HELLO_H

void hello(const char *name);

#endif

hello.c

#include <stdio.h>
void hello(const char *name)
{
    printf("hello,%s!\n",name);
}

main.c

#include "hello.h"
int main()
{
    hello("world");
    return 0;
}

编译运行

# gcc -c hello.c
# ar rcs libhello.a hello.o
# gcc main.c libhello.a -o hello
# ./hello

说明

静态库是由.o文件创建的。因此必须将源程序先编译成.o文件。
静态库文件名的命名规范是:以lib为前缀,紧接着是静态库名,扩展名为.a。

相关资料

https://www.cnblogs.com/zhenyuyaodidiao/p/9288430.html

https://openresty.org/download/agentzh-nginx-tutorials-zhcn.html
https://www.cnblogs.com/jackey2015/p/10375549.html
Nginx 处理请求的过程一共划分为 11 个阶段,按照执行顺序依次是 post-read、server-rewrite、find-config、rewrite、post-rewrite、preaccess、access、post-access、try-files、content 以及 log.

857040-20190417175641694-1612377057.png

内部跳转

所谓“内部跳转”,就是在处理请求的过程中,于服务器内部,从一个 location 跳转到另一个 location 的过程。
既然是内部跳转,当前正在处理的请求就还是原来那个,只是当前的 location 发生了变化,所以还是原来的那一套 Nginx 变量的容器副本。
echo_exec 指令和 rewrite 指令可以发起“内部跳转”。这种跳转会自动修改当前请求的 URI,并且重新匹配与之对应的 location 配置块,再重新执行 rewrite、access、content 等处理阶段。因为是“内部跳转”,所以有别于 HTTP 协议中定义的基于 302 和 301 响应的“外部跳转”,最终用户的浏览器的地址栏也不会发生变化,依然是原来的 URI 位置。
而 ngx_index 模块一旦找到了 index 指令中列举的文件之后,就会发起这样的“内部跳转”,仿佛用户是直接请求的这个文件所对应的 URI 一样。

post-read

最先执行的 post-read 阶段在 Nginx 读取并解析完请求头(request headers)之后就立即开始运行。
支持 Nginx 模块注册处理程序。比如标准模块 ngx_realip 就在 post-read 阶段注册了处理程序。

server-rewrite

post-read 阶段之后便是 server-rewrite 阶段。
当 ngx_rewrite 模块的配置指令直接书写在 server 配置块中时,基本上都是运行在 server-rewrite 阶段。

find-config

紧接在 server-rewrite 阶段后边的是 find-config 阶段。
这个阶段并不支持 Nginx 模块注册处理程序,而是由 Nginx 核心来完成当前请求与 location 配置块之间的配对工作。
换句话说,在此阶段之前,请求并没有与任何 location 配置块相关联。因此,对于运行在 find-config 阶段之前的 post-read 和 server-rewrite 阶段来说,只有 server 配置块以及更外层作用域中的配置指令才会起作用。

rewrite

运行在 find-config 阶段之后的便是我们的老朋友 rewrite 阶段。

post-rewrite

rewrite 阶段再往后便是所谓的 post-rewrite 阶段。
这个阶段也像 find-config 阶段那样不接受 Nginx 模块注册处理程序,而是由 Nginx 核心完成 rewrite 阶段所要求的“内部跳转”操作(如果 rewrite 阶段有此要求的话)。

preaccess

运行在 post-rewrite 阶段之后的是所谓的 preaccess 阶段。
标准模块 ngx_limit_req 和 ngx_limit_zone 就运行在此阶段,前者可以控制请求的访问频度,而后者可以限制访问的并发度。

access

运行在 preaccess 阶段之后的则是我们的另一个老朋友,access 阶段。
标准模块 ngx_access、第三方模块 ngx_auth_request 以及第三方模块 ngx_lua 的 access_by_lua 指令就运行在这个阶段。

post-access

access 阶段之后便是 post-access 阶段。

try-files

紧跟在 post-access 阶段之后的是 try-files 阶段。
这个阶段专门用于实现标准配置指令 try_files 的功能,并不支持 Nginx 模块注册处理程序。

content

Nginx 的 content 阶段是所有请求处理阶段中最为重要的一个,因为运行在这个阶段的配置指令一般都肩负着生成“内容”(content)并输出 HTTP 响应的使命。

log