an_introduction_to_gcc.md
Convention
compilation: 从源代码到机器码的所有过程的总称
include path: 头文件搜索路径
liarary search path(或者link path): 库文件搜索路径
Compiling a C program警告相关
-Wall: 开启所有常用的编译警告, __推荐任何情况下都加上该option__。当有警告信息输出时,信息的格式为file:row-number:column-number:message
Compiling files independently
In general, linking is faster than compilation—in a large project with many source files, recompiling only those that have been modified can make a significant saving. The process of recompiling only the modified files in a project can be au ...
muduo源码深入剖析
base
Atomic通过GCC内置的原子操作函数进行实现
关于旋转数组的最值寻找问题
寻找旋转数组中的极小值 - leetcode
此类问题,不管是求最大值还是最小值,都是二分问题中的经典问题。对于这类问题晚上也都有很多经典的解析,但大多数都忽略了一个最重要的问题:到底是选取nums[0]还是nums.back()作为参考点,以及为什么?
我翻阅了一些解析,就拿上面所列出的这道题,很多答案直接就说:拿nums.back()做参考点,只要nums[mid]>nums.back(),那么最小值就肯定在nums[mid]的右边(开区间);反之,只要nums[mid]<nums.back(),那么最小值肯定在nums[mid]的左边(闭区间);
那么问题来了,我拿nums[0]做参考点不是照样满足条件吗?然后用nums[0]去做题,ok,马上就错了,举个case:[2,0,2,2,2,2,2],最后就得不到正确答案;
原因出在哪里?其实不难想,就是当nums数组本身就没有旋转的时候,此时nums[left]就已经是最小值了,但是由于先前是拿nums[left]做参考点,所以反而会跳过这个最小值;
拿nums.back()做参考点就一定不会出现这个问题吗?其实不然,只 ...
redisServer
命令执行过程在服务端,跟服务器连接的所有客户端都对应一个redisClient结构体;当服务器接收到某个客户端发来的命令请求时,先将字符串存到对应的redisClient结构体的缓冲区中,然后调用分析器进行分析,提取出对于的argv和argc;然后根据argv[0]到命令表中查找对应的执行函数,进行执行(命令表是一个字典,key就是命令名,比如SET,value就是对应的redisCommand结构体,保存了函数指针,所需参数个数,等信息),当然,执行之前还需要进行检查,比如权限是否匹配,输入参数是否有效等等。
执行完毕后,将执行结果保存在redisClient的缓冲区中,随后向客户端所关联的socket发送信息即可。
serverCron函数cron是时辰的意思,意味着这个函数需要定期执行,它的目的是管理服务器的资源,保证其良好运行。资源管理会涉及到很多方面的细节:
服务器状态的时间缓存会得到更新,这是一个不太精确的时刻;
服务器的LRU时钟unsigned lruclock会得到更新,该变量用于计算服务器中各个redis对象的空转时间(因为每个redis对象拥有一个变量,用于存储 ...
cmake - local variable 以及cache variable
关于local variable通过set命令设置需要的local variable;通过list命令可以对list变量执行多种形式的操作;通过${MY_VARIABLE}来使用对应的变量;注意,如果MY_VARIABLE包含空格,那么必须加上双引号"${MY_VARIABLE}";
list变量在cmake中就是通过;分隔的字符串,比如set(MY_VARIABLE "a" "b" "c"),那么MY_VARIABLE的值就是"a;b;c"
关于cache variable所谓的cache variable,其实就是可以在命令行中进行设置的变量,比如CMAKE_BUILD_TYPE;通过set(MY_CACHE_VARIABLE "VALUE" CACHE STRING "Description")来声明并设置所需的cache variable;
注意,cache variable存在的本意是为了使开 ...
nginx - variable
WHY Nginx Variable其实完全可以把Nginx configuration file视为一种微型的编程语言,其语言风格深受shell和perl的影响。而编程语言的核心之一就是变量。
Nginx的变量类型只能是string(除开一些扩展module)。变量在nginx.conf中的声明和定义很简单:set $my_variable "value"(当然,一些其他命令也能声明定义变量),之后通过$符号转义使用即可。
module:Nginx的世界其实就是由module组成,所有的命令都来自于不同的module(包括上面的set,其来自于标准modulengx_rewrite)。module可以分为标准模块和第三方模块;
那么如何打印$符号呢?很遗憾,在nginx中,没有直接可用于转义$符号的方法。比较折中的方法是使用geo命令将一个变量的值设置为$,随后再对其进行引用(因为geo不支持转义),如下:
123geo $dollar { default "$";}
Variable Declaration另外 ...
nginx - 指令执行顺序
WHY the Directive Execution Order在Nginx的世界里,程序的执行是分为多个阶段(phase)的,不同phase的先后顺序是完全固定的。举个例子,假设两个命令分属于不同的phase,则无论这两条指令在conf file中谁在前面谁在后面,都不影响最终的结果,因为它们的执行顺序是根据phase确定的。
最常见、最common的3类phase是:rewrite, access, content;rewrite最早执行,content最晚执行。
如何确定某条指令属于哪个phase:查文档!!!
某些指令不属于任何phase:它们仅仅是一个声明式的指令,常见的有geo和map
对于属于同一个module内的指令,其执行顺序就和conf file中对应的顺序一致,这没什么疑问。但如果是属于不同module的指令,而这些module又属于同一个phase的话,则这些指令的执行顺序就变的不可预料了。所以,大部分时候,此类情况的配置是相当危险的,应该禁止。
当然,一些第三方模块本身是支持和一些内置模块进行混合调用且顺序是一致的,比如ngx_lua和ngx_rewri ...
redis sentinel
初始
作用可以监视主服务器、从服务器等多种服务器,甚至还可以监视其他的sentinel服务器;
sentinel服务器和普通服务器的区别sentinel服务器不使用数据库,因此初始化的时候不需要RDB或者AOF文件;另外,包括一些操作键值对的命令(SET等),发布订阅,脚本,事务等功能,sentinel服务器均不使用;sentinel服务器的命令表中也并没有存储这些命令;客户端可以对sentinel服务器使用的命令仅包括:PING, SENTINEL, INFO, SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE;(新版本中可能会有增加)
命令连接和订阅连接sentinel服务器需要和每一个由它监视的主(从)服务器创建2个连接,分别是命令连接和订阅连接。命令连接的作用是向主(从)服务器发送命令以及接收相应的回复;订阅连接的作用是订阅主(从)服务器的sentinel:hello频道,避免频道发送的信息丢失;
监视网络
dict *masters和dict *slaves字典dict *masters就是sentinel服务器所监视的 ...
redis cluster
初始
作用集群是redis提供的一种分布式数据库方案,可以提供数据共享、复制、故障转移的功能。通过CLUSTER MEET <IP> <PORT>完成集群中各个节点间的连接;通过cluster-enable配置选项来配置某个redis服务器是否转为集群模式;
槽槽(slot)就是分片的单位,所谓分片,就是将所有的数据进行切分,不同的节点负责不同的数据。集群将整个数据库的所有数据划分为16384个槽,每个槽由某一个节点来处理,而各个节点负责多个槽。当所有的槽都有对应的节点来处理时,该集群才是上线状态。
底层数据结构
struct clusterNode用来保存节点的各个基本信息,包括:创建时间、节点名、角色(主节点还是从节点)、状态(在线还是下线)、IP及端口、和该节点相连接的其他节点的信息(clusterLink *);
struct clusterLink保存着连接节点的信息,包括:连接的创建时间、套接字、输入缓冲区、输出缓冲区、和该节点相连接的其他节点的信息(clusterNode *)(即节点在某个时刻正在相互通信的另一个节点的信息)
struc ...