From ef45c011d32061955d2423d0a5f720354dcbf1eb Mon Sep 17 00:00:00 2001 From: coderall Date: Tue, 17 Mar 2020 14:17:53 +0800 Subject: [PATCH 01/78] add jbod device & du/df tool related --- file_system.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/file_system.txt b/file_system.txt index d29c93e..9567116 100644 --- a/file_system.txt +++ b/file_system.txt @@ -539,3 +539,12 @@ lower layer的文件会被隐藏。 它的实现是在内核中加入了重定向功能,即对overlayfs目录下文件的操作在内核中会重定向到实际的文件。 这样系统的page-cache 也只需要保留一份。 + +177、JBOD一种为各个磁盘单独控制,且结合RAID技术;另一种则是简单的将多个磁盘抽象为一个大空间, + iops等和一个磁盘相同,且操作系统或文件系统的元数据在第一个盘上, + 如果第一个盘损坏,则整个数据将不可读。 + +178、du 和 df 展示的结果不同,数据对不上,这是因为du基于stat系统调用,看到的是一个文件的数据; + df 使用的是 statvfs 系统调用,是展示整个系统或分区的角度来获取数据;du可能还要考虑follow + symlink或 hard link的重复计算,而 df 可能还需要考虑系统预留空间,inode的inline data, + journal 的预留空间等 From faebf7c47c35701e437821d2dffa3fcd3d7e93ed Mon Sep 17 00:00:00 2001 From: coderall Date: Tue, 24 Mar 2020 16:39:45 +0800 Subject: [PATCH 02/78] add some ext4 questions --- file_system.txt | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/file_system.txt b/file_system.txt index 9567116..0ca7f13 100644 --- a/file_system.txt +++ b/file_system.txt @@ -449,7 +449,15 @@ 155、iostat 命令中 avgrq-sz 和 avgqu-sz表示什么意思? (tips:avgrq-sz 表示平均 request大小,单位为 sector - avgqu-sz表示发送给设备的requests队列长度) + avgqu-sz表示发送给设备的requests队列长度, + 这里有个问题就是iostat的输出和dd或fio工具命令行中的bs大小不一致, + 从上面的描述中可以看到,avgrq-sz表示的是 request 结构所表示的io请求大小, + 所以在用户层面的写入后,(1)在 writeback page_cache时; + (2)在block层的 plug机制 (3)io 调度器的merge机制 会尝试合并请求, + 所以会看到avgrq-sz比较大; + avgrq-sz的最大值为 /sys/block/sdx/queue/max_sectors_kb ,单位为kb, + 如果取值 256,则avgrq-sz的最大值为 512, + 且需要注意,这里统计的是读请求和写请求的和) 156、EAGAIN 和 EWOULDBLOCK 两个错误码有什么区别? (tips:在Linux上,这两个错误码的定义数值是相同的, @@ -548,3 +556,31 @@ df 使用的是 statvfs 系统调用,是展示整个系统或分区的角度来获取数据;du可能还要考虑follow symlink或 hard link的重复计算,而 df 可能还需要考虑系统预留空间,inode的inline data, journal 的预留空间等 + +179、ext系文件系统为什么要有块组的概念? + (tips:如果没有块组,那么所有的磁盘数据块只存在于一个大的块组中, + 对应的,block bitmap也比较大,查询空闲数据块的耗时将增加,解决这个问题的办法就是把磁盘空间 + 再划分为对应的块组,拿到inode number或者block number,只需要进行一个除法运算就可以快速确认 + 属于哪个块组) + +180、每一个块组中inode bitmap占一个block,一个block按 4096 bytes计算,则,一个块组中可以包括 + 4096*8 = 32768 个 inode。 + 但是用 mke2fs等工具格式化磁盘时,整个分区的indoe数量 按照 每 16KB 一个indoe的方式来计算,目的是为了 + 节省空间,因为一个inode需要占用 256 bytes空间(super block中存储了一个块组中有几个inode)。 + 使用 mke2fs -N 可以扩大inode数量,但是仍然没有突破 inode bitmap占一个block,只不过inode table数量变大。 + +181、ext4文件系统中,如果当前的Journal模式为JOURNAL_DATA_MODE,即数据也要写入Journal, + 那么不支持DirectIO;如果当前文件有inline data,那么也会切回buffer IO模式。 + +182、在进行DirectIO写入后,需要invalid对应的page cache中的page,这样才能保证在下次buffer I/O操作中 + 拿到最新的数据 + +183、iostat的数据源来自于/proc/diskstats文件,里面记录了raw data,iostat读取这些数据, + 然后展示出来。 + (avgrq-sz是用 读写成功的 bytes/读写请求次数,前者和一个request相关,后者则和这个request里面的bio + 数量一一对应,虽然在scheduler层会对bio进行merge(merge时需要位置严格相邻),将bio链接 + 到request的bio_tail链表中,整体上bio num不变。 + 在使用 dd if of bs=4K count=1000 oflag=direct 进行测试时,发现 avgrq-sz 为8,刚好为4K, + 实现为 direct 绕开了 page cache,就不会在生成bio之前对 请求进行merge,所以提交到 request 链表中的 + 都是 4K 的bio,这样在 plug 或 io scheduler merge之后,bio数量没变,所以用 total_bytes/bio_num = 8*512 + 即8个 sector) From 8e4f8cd4e93b6ed554c4ad21c91d6c59eb83edd5 Mon Sep 17 00:00:00 2001 From: coderall Date: Tue, 24 Mar 2020 16:40:03 +0800 Subject: [PATCH 03/78] add new cmd_line file --- cmd_line.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 cmd_line.txt diff --git a/cmd_line.txt b/cmd_line.txt new file mode 100644 index 0000000..9ac03c0 --- /dev/null +++ b/cmd_line.txt @@ -0,0 +1,10 @@ +// common cmd questions + +1、ls -l 显示的total表示很么意思? + (tips:表示当前目录下文件占用的底层磁盘block数量, + -l 显示的第二列表示当前文件的hard link数量) + +2、stat 命令显示的Blocks表示什么? + (tips:表示占用的底层磁盘的block数量,即使创建一个很小的文件, + block数量也为8,是因为文件系统层面和底层磁盘使用的单位不一样, + 文件系统层是 page,也就是4096,所以即使文件很小,也会分配8个block来存储) From 8344b5558dcada601b657567b3d2afa9e5ebe478 Mon Sep 17 00:00:00 2001 From: coderall Date: Tue, 24 Mar 2020 16:40:47 +0800 Subject: [PATCH 04/78] add malloc implementation details & swap related questions --- kernel.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/kernel.txt b/kernel.txt index 1bac6e9..592a10f 100644 --- a/kernel.txt +++ b/kernel.txt @@ -277,8 +277,13 @@ // 内存管理 mm 1、malloc的实现 + (tips:malloc申请空间时,直觉上进程不会触发sleep逻辑,因为申请的是虚拟内存, + 但是需要注意,内核有可能申请vma_area结构,在申请时用的GFP_KERNEL标志, + 这有可能sleep,所以整体上 malloc 有可能sleep;C++的 new 因为是在malloc之后在对应内存写入数据, + 触发缺页中断,这就有可能导致当前进程sleep,甚至OOM) 2、简单介绍下 tcmalloc 或 jemalloc 或 ptmalloc + (tips:tcmalloc在申请内存失败时,直接abort了当前进程) 3、简单介绍下 buddy system @@ -332,6 +337,11 @@ 23、Linux的页表访问分为几个层级?具体实现方式? 24、什么是swap,有什么作用? + (tips:将内存物理页面写回backup storage,减轻内存压力,写回时, + 需要修改页表内容,通过PTE表项可以拿到对应虚拟地址对应的在swap中的 + 物理页面内容。 + 2.6 内核针对多个连续页面内容新增了 extent 属性,可以向文件系统那样 + 操作多个连续物理页面) 25、什么是内存overcommit? (tips:操作系统向外提供的内存总量比 RAM+Swap 多,这里有一个假设就是, From 5647cb26378fd85354940fb11c2b58a4b2236571 Mon Sep 17 00:00:00 2001 From: coderall Date: Tue, 24 Mar 2020 16:41:51 +0800 Subject: [PATCH 05/78] add slow speed attck questions --- network.txt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/network.txt b/network.txt index f46e2f4..1296e28 100644 --- a/network.txt +++ b/network.txt @@ -338,8 +338,10 @@ 108、ss 命令看到 处于 listen 状态的 socket 的 Recv-Q 和 Send-Q表示什么意思? (tips:listen状态的Recv-Q表示当前accept队列中等待accept的连接数量, 最大数量受 题目106中所述变量控制,Send-Q表示当前socket的accept backlog取值, - 为 max(listen_backlog, /proc/net/core/somaxconn), - 当命令输出中这两个参数相等时,表示当前accept队列满,考虑调大somaxconn数值) + 为 min(listen_backlog, /proc/sys/net/core/somaxconn), + 当命令输出中这两个参数相等时,表示当前accept队列满,考虑调大somaxconn数值; + 如果是已经建立好的链接,Recv-Q表示内核已经收到但是应用还没有读取的数据量, + Send-Q表示还在SendBuf中,没有ack的数据量) 109、当半连接队列满时,新来的连接的处理方式为? (tips:丢弃新来的连接请求,客户端的connect会超时) @@ -429,6 +431,13 @@ 内网环境带宽高,时延低,建议继续使用CUBIC 外网访问可以继续使用BBR +127、当客户端和服务端开启keep-alive特性,且客户端向服务端回复了zero-window, + 那么,带来的效果就是在 服务端一个链接会长时间的存在 + 可以认为这是慢速攻击的一种 + +128、当client回复给server zero window后,server会用 persistence timer来向client发送 + 特殊的keep-alive报文,以确保及时知道client可以正常接收数据 + // http 1、什么是CNAME? From a69c18a5f0443d57f2094b1d8370c11f317e8963 Mon Sep 17 00:00:00 2001 From: coderall Date: Mon, 13 Apr 2020 14:21:48 +0800 Subject: [PATCH 06/78] add bio usage description --- file_system.txt | 19 +++++++++++++++++++ gcc_gdb.txt | 9 +++++++++ nginx.txt | 7 +++++++ 3 files changed, 35 insertions(+) create mode 100644 gcc_gdb.txt create mode 100644 nginx.txt diff --git a/file_system.txt b/file_system.txt index 0ca7f13..52f9867 100644 --- a/file_system.txt +++ b/file_system.txt @@ -43,6 +43,8 @@ 21、DIRECT I/O 和 SYNC I/O 的区别是什么? 22、free 命令的显示中 buffer 和 cache 分别代表什么? + (tips:现在buffer 和 cache统一都由page cache实现,只不过buffer是比较特殊的直接操作设备文件产生的空间占用, + 例如,直接读取 /dev/ 设备) 23、文件的覆盖写和追加写有什么区别? @@ -584,3 +586,20 @@ 实现为 direct 绕开了 page cache,就不会在生成bio之前对 请求进行merge,所以提交到 request 链表中的 都是 4K 的bio,这样在 plug 或 io scheduler merge之后,bio数量没变,所以用 total_bytes/bio_num = 8*512 即8个 sector) + +184、free命令会显示cache/buffer,其实现在的buffer也是通过page cache实现的,而buffer在内核中的表示是 + buffer_head 结构,这个struct之前用来表示block_device中的block在内存中的数据,也是老的系统中文件系统 + 访问底层的结构,不过现在被bio结构取代,但是在 直接 mmap /dev/下的设备时,仍然有使用,这也就对应了 + 有的文章说 现在的buffer只是对应了裸设备的数据映射。 + 同样的,之前也有文章说 直接 mmap /dev/ 然后再通过其他普通文件系统 read 同一份数据,page cache中有两份 + 这是因为 两者使用了不同的文件系统,对应了不同的inode,也就对应了不同的address_space,这样数据就有了两份, + 如果修改其中一份数据,另一份不会直接同步。 + +185、BIO结构完成了从page cache内存地址到dev中sector地址的转换,每一个bio中代表一段连续的地址空间, + 里面有可能包括多个bio_vec,一个bio_vec表示一个file system block。 + 以16KB连续数据为例,需要一个bio结构,里面包括了4个bio_vec;如果数据不连续,则需要多个bio结构 + +186、使用 echo '' > file 这一步,其实是在open中传入了O_TRUNC标志,进而在打开文件时完成文件长度修改。 + +187、在 /etc/mke2fs.conf 文件中有创建文件系统时的默认配置,通过这些配置可以熟悉了解文件系统都实现了哪些功能, + 有哪些常用feature diff --git a/gcc_gdb.txt b/gcc_gdb.txt new file mode 100644 index 0000000..9804aea --- /dev/null +++ b/gcc_gdb.txt @@ -0,0 +1,9 @@ +// gcc & gdb related + +1、在查看coredump文件时,如果遇到调用栈栈顶附近的函数为 ??,则可能是 + 栈被破坏了,调查的一个方向是 f 0 ,p $rsp 查看第一层函数栈顶指针, + 再 f $top , p $rsp 查看调用栈栈顶的栈指针,两者相减,看是否是调用栈 + 过深导致。 + +2、上述过程中,不能使用rbp寄存器,因为使用 -fomit-frame-pointer 选项编译时, + 会去掉rbp寄存器的使用 diff --git a/nginx.txt b/nginx.txt new file mode 100644 index 0000000..d97f791 --- /dev/null +++ b/nginx.txt @@ -0,0 +1,7 @@ +// question collection about awesome nginx + +1、keepalive_timeout + (tips:keepalive连接的超时时间,超过这个时间而没有请求过来,连接会断掉) + +2、keepalive_requests + (tips:一个连接可以发送的请求数量,超过这个数量后,会断开连接) From 37c95312c6f50ce04e32d9ba88800cdd046f9160 Mon Sep 17 00:00:00 2001 From: coderall Date: Mon, 13 Apr 2020 14:22:31 +0800 Subject: [PATCH 07/78] add prctl questions --- kernel.txt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/kernel.txt b/kernel.txt index 592a10f..24d94d1 100644 --- a/kernel.txt +++ b/kernel.txt @@ -666,6 +666,13 @@ 114、实现atomic指令时的lock前缀,提供了一种保证,后续对相关的数据访问独占进行, 如果之前的指令有修改这个数据,那么在lock指令执行前也会执行写回 +115、prctl可以设置运行进程的名,其实现细节应该是设置task_struct里面的cmd等结构 + +116、free命令显示的 -/+ buffer/cache +表示系统还有多少可用,-表示系统当前已用的, + 通过向 /proc/sys/vm/drop_cache 写入不同的数值,可以强制刷回cache,但是需要注意, + 当前的 共享内存和mmap shared page,都是基于tmpfs实现,且 tmpfs不可以刷回,所以, + 不是所有cache都可以回收。 + // 其他 @@ -723,6 +730,3 @@ (tips:/proc/sys/kernel/core_pattern) 7、Ubuntu系统不再使用/var/log/messages来记录系统事件,现在使用/var/log/syslog来替代 - -test -test2 From 8463f25e30e3e907a50120b641bc266516574543 Mon Sep 17 00:00:00 2001 From: coderall Date: Mon, 13 Apr 2020 14:22:59 +0800 Subject: [PATCH 08/78] add ifconfig note --- network.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/network.txt b/network.txt index 1296e28..f73daa6 100644 --- a/network.txt +++ b/network.txt @@ -603,3 +603,8 @@ 这了强调 非阻塞 是因为,如果采用阻塞 system call,则整个server都会block, 无法执行其他逻辑,效率较低,还涉及睡眠唤醒等逻辑, 常见的Nginx Redis Node都采用的 Reactor,分发器则为系统提供的 epoll 等) + +38、ifconfig命令的显示中,frame栏表示未对齐的frame长度(默认按8对齐),而被网卡丢弃; + errors表示CRC校验错误,太短,或者太长的frame; + overruns表示超过网卡处理速度而被丢弃,通常在网络繁忙时出现; + droped则表示访问了未配置的功能,例如,在没有配置ipv6的情况下,收到ipv6报文 From cace29812d3b705679d834b754467797b94d1563 Mon Sep 17 00:00:00 2001 From: coderall Date: Mon, 8 Jun 2020 11:51:37 +0800 Subject: [PATCH 09/78] add netstat&wathc command --- cmd_line.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd_line.txt b/cmd_line.txt index 9ac03c0..9344eb3 100644 --- a/cmd_line.txt +++ b/cmd_line.txt @@ -8,3 +8,7 @@ (tips:表示占用的底层磁盘的block数量,即使创建一个很小的文件, block数量也为8,是因为文件系统层面和底层磁盘使用的单位不一样, 文件系统层是 page,也就是4096,所以即使文件很小,也会分配8个block来存储) + +3、netstat -s 命令的输出有很多网络详细信息 + +4、watch -d -n1 'command'是个很有用的命令,可以动态演示一些命令的输出变化,例如丢包数量等。 From 59d0c1336673a0a234773d80a5d85727d434027d Mon Sep 17 00:00:00 2001 From: coderall Date: Mon, 8 Jun 2020 11:52:16 +0800 Subject: [PATCH 10/78] add debugfs&direct io related questions --- file_system.txt | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/file_system.txt b/file_system.txt index 52f9867..56a4a65 100644 --- a/file_system.txt +++ b/file_system.txt @@ -603,3 +603,35 @@ 187、在 /etc/mke2fs.conf 文件中有创建文件系统时的默认配置,通过这些配置可以熟悉了解文件系统都实现了哪些功能, 有哪些常用feature + +188、debugfs 命令还有个交互模式,里面有一些很有用的命令,可以用于查看磁盘上的数据 + +189、网友测试中遇到了一个场景,用 dd if=/dev/zero oflag=direct 写入nvme SSD,速度比默认使用buffer快很多, + 自己找了测试环境验证了下,确实是这样。 + 使用 direct 写入sata HDD,速度和使用 sync 模式差不多,但是nvme快很多。 + 看了对应的代码有如下可能原因: + (1)direct IO 直接使用了 用户态buffer 对应的 page,没有数据的拷贝,这在写入场景下同样适用 + (2)direct IO 直接将request提交到了对应device的 request queue,HDD通常是单队列, + 但是,nvme SSD队列数可以非常多,处理的速度也比较快 + (3)nvme SSD 和 HDD设备侧使用的调度算法不同,nvme由于处理速度快,更多的使用noop, + HDD常使用CFQ + +190、direct I/O 有什么好处? + direct I/O 有如下几个好处: + (1) 减少CPU利用率,因为如果使用buffered I/O,那么需要将用户空间的数据拷贝到page cache中, + 相当于执行memcpy + (2) 使用buffered I/O 会增加系统内存压力,有可能导致其他cache 命中率较高的文件提前刷回, + 在下次访问时,又需要读回,即减少page cache整体的抖动。很多数据库产品都是在用户态实现文件的内容缓存, + 写入数据时采用direct。 + 但是,在采用direct时,需要注意,read/write调用的执行时间可能会增加,这是由direct的执行特点决定的, + 具体需要考虑direct是将请求一直要发送到通用块层才返回的。而buffered I/O只需要到page cache层就结束了。 + +191、如果文件之前已经通过buffered I/O访问过,那么direct I/O 的写请求会同步更新page cache。 + +192、怎么增加磁盘的队列深度? + (tips: + 1、使用异步IO + 2、多线程并发提交IO任务 + 3、每次写入大块数据,块层会自动按照内核的配置将一个任务切分为多个子任务 + + 在压测磁盘时,需要增大磁盘的队列深度,也就是说有积压的任务在等待处理,从而提交dist util) From a8f416fc35094256aeb65650fd52fff0a07b8563 Mon Sep 17 00:00:00 2001 From: coderall Date: Mon, 8 Jun 2020 11:52:39 +0800 Subject: [PATCH 11/78] gcc related --- gcc_gdb.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/gcc_gdb.txt b/gcc_gdb.txt index 9804aea..93f5921 100644 --- a/gcc_gdb.txt +++ b/gcc_gdb.txt @@ -7,3 +7,22 @@ 2、上述过程中,不能使用rbp寄存器,因为使用 -fomit-frame-pointer 选项编译时, 会去掉rbp寄存器的使用 + +3、gcc 4.x及以下的版本的 string实现是基于引用计数和 COW,gcc 5.x 替换了另一种短字符优化sso的方案, + 其实现就是string分配16字节的预留空间,和allocated_capacity保存在一个union中。 + +4、gcc的-l选项只在编译时起作用,如果是静态库,那么因为已经打包进入binary,运行时无需特殊指定库路径, + 如果是动态库,那么gcc会在默认路径下找库,和编译时库路径无关。 + LD_LIBRARY_PATH环境变量就是指定运行时库路径的。 + 编译时可以通过 -W,--rpath 来指定运行时的动态库路径 + +5、gcc在使用静态库时,不会把整个库都打包进去,而是会分析调用链,按需加载使用,减小binary大小 + +6、想查看gcc默认的搜索头文件路径,可以在编译时加上 --verbose选项 + +7、/lib64/ld-linux-x86-64.so.2 这个文件是linux默认的 dynamic-linker,在命令行执行 chmod 等程序时, + 系统其实执行的是 /lib64/ld-linux-x86-64.so.2 chmod,它的作用是完成动态库的加载,然后执行ELF程序 + 所以可以测试一个binary 没有 可执行权限,然后由 /lib64/ld-linux-x86-64.so.2 binary 也是可以启动的 + +8、为什么编译时不需要显示的指定 glibc的库 + glibc库的路径已经固化到gcc中了,不用再显示指定,除非要用自己的glibc库 From f1cfaed6049c1351c8212d8a3593601223a0a450 Mon Sep 17 00:00:00 2001 From: coderall Date: Mon, 8 Jun 2020 11:53:19 +0800 Subject: [PATCH 12/78] add multi-thread virtual mem high questions --- kernel.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel.txt b/kernel.txt index 24d94d1..55ee6a4 100644 --- a/kernel.txt +++ b/kernel.txt @@ -673,6 +673,12 @@ 当前的 共享内存和mmap shared page,都是基于tmpfs实现,且 tmpfs不可以刷回,所以, 不是所有cache都可以回收。 +117、使用多线程程序观察到虚拟内存很高,为什么? + (tips: glibc从2.10版本开始引入了一个MALLOC_ARENA_MAX参数来申请thread_local的arena空间, + arena的数量在64位系统下默认为2*cpu cores,对应的内存空间大小为 2*cpu cores * arena size, + arena size为 64M; + 可以通过设置MALLOC_ARENA_MAX环境变量或者通过mallopt函数来控制这一行为) + // 其他 From a836f793186f6da38cd5fa0b566b0e9d7a80953a Mon Sep 17 00:00:00 2001 From: coderall Date: Mon, 8 Jun 2020 11:54:46 +0800 Subject: [PATCH 13/78] add some new network related questions --- network.txt | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/network.txt b/network.txt index f73daa6..fb01e75 100644 --- a/network.txt +++ b/network.txt @@ -113,7 +113,11 @@ (tips:RPS表示Recieve Packet Steering, RFS 表示 Recieve Flow Steering, RPS依据hash计算数据包软中断处理CPU, RFS在RPS基础上,根据流表来选择用户态收包的CPU - 两个策略都尝试最大化的利用Cache,减少因为上下文切换带来的Cache命中率的下降) + 两个策略都尝试最大化的利用Cache,减少因为上下文切换带来的Cache命中率的下降, + 注意,RPS的实现中需要注意,开启后,并不会减少原来CPU的软中断数量, + 它的工作原理是通过IPI来告诉其他CPU进行软中断处理来收包,对应的CPU的 %soft 会增加, + 留给应用层的CPU时间减少 + RSS 表示 Receive Side Steering 即常说的 网卡多队列,可以通过查看 /proc/interrupts 来确认对应网卡是否有开启) 28、accept 调用返回时,三次握手是否结束? @@ -438,6 +442,20 @@ 128、当client回复给server zero window后,server会用 persistence timer来向client发送 特殊的keep-alive报文,以确保及时知道client可以正常接收数据 +129、tcp_max_tw_buckets 这个参数的意思是规定了系统中time_wait状态的socket的数量上限,如果 + 超过这个限制,则time_wait状态的socket会立即关闭,不再等待2MSL。 + +130、TCP关闭连接时使用四次握手,什么时候会变成三次握手呢? + (tips:被动关闭方启用了延时ack机制,收到主动方的 FIN时,没有立即回复ack, + 但应用层同时也没有数据要发送,所以ack 和 fin 一起发送,四次握手变成三次) + +131、epoll触发EPOLLIN 或 EPOLLOUT事件有什么条件吗? + (tips: EPOLLIN事件需要满足sk队列中的 rcv_next - copied_seq >= target,即tcp队列收到的数据量, + 减去已经拷贝到用户态的数据量,大于SO_RECVLOWAT值,这个值默认为1,所以说EPOLLIN事件基本每次都会触发; + 但是上面也只是考虑了tcp sock,还有EPOLL自己的逻辑需要考虑; + EPOLLOUT事件,即socket可写需要满足wmem 空间大于 总量的1/3,这通常用来计算客户端的最小接收速度, + 因为通常情况下,服务端会设置send timeout) + // http 1、什么是CNAME? @@ -608,3 +626,5 @@ errors表示CRC校验错误,太短,或者太长的frame; overruns表示超过网卡处理速度而被丢弃,通常在网络繁忙时出现; droped则表示访问了未配置的功能,例如,在没有配置ipv6的情况下,收到ipv6报文 + +39、在配置了bond0的机器上用tcpdump 抓包时,不能使用 -i any ,而要指定bond的网卡 From 458bac8d24eb4c6f97871cbecee37c25bd683168 Mon Sep 17 00:00:00 2001 From: coderall Date: Tue, 14 Jul 2020 09:51:31 +0800 Subject: [PATCH 14/78] add thread safe API --- C and C++.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/C and C++.txt b/C and C++.txt index 7598f4d..c502a44 100644 --- a/C and C++.txt +++ b/C and C++.txt @@ -152,6 +152,9 @@ (tips:是的,这里联想Unix环境高级编程中的示例,先fork, 然后子进程exec,主进程wait) +42、在使用localtime, inet_ntoa 等等函数需要小心,建议使用对应的多线程版本 + 例如:localtime_r, inet_ntop 等 + @@ -225,6 +228,9 @@ (tips:一种简单的实现是 在类中定义private 拷贝构造函数,但是这种方式不够清晰 更好的做法是 定义个 模板类,定义 pravate的拷贝构造函数,然后 子类 private 继承 Uncopyable 类) + +27、C++里面的匿名namespace中的成员,相当于添加了static属性,因为编译器实际上会为每一个匿名的namespace + 生成一个名称,且添加using声明,但是这个名称在其他模块是不可见的,这也就添加了internal属性。 // debug From 484faba7592ba7c780546357d24cb50eb9744acd Mon Sep 17 00:00:00 2001 From: coderall Date: Tue, 14 Jul 2020 09:51:57 +0800 Subject: [PATCH 15/78] add extern c declaration --- gcc_gdb.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gcc_gdb.txt b/gcc_gdb.txt index 93f5921..a619026 100644 --- a/gcc_gdb.txt +++ b/gcc_gdb.txt @@ -26,3 +26,6 @@ 8、为什么编译时不需要显示的指定 glibc的库 glibc库的路径已经固化到gcc中了,不用再显示指定,除非要用自己的glibc库 + +9、gcc编译出来的C库,不能直接在g++编译的C++程序中使用,如果使用,需要在对应的header文件中添加 extern "C" 标识, + 但是C中没有extern "C" 的写法,所以,需要在程序中使用预编译宏来判断,例如 #ifdef __cplusplus From 0b7b8b1ac85dd6143b1424f32eedb6df7cfe2f89 Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 5 Aug 2020 09:47:13 +0800 Subject: [PATCH 16/78] add byte order & smart ptr related questions --- C and C++.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/C and C++.txt b/C and C++.txt index c502a44..20ba8cc 100644 --- a/C and C++.txt +++ b/C and C++.txt @@ -155,6 +155,9 @@ 42、在使用localtime, inet_ntoa 等等函数需要小心,建议使用对应的多线程版本 例如:localtime_r, inet_ntop 等 +43、字节序通常在单字节的数据上不用关心,但是在struct使用位域,则引入了位序, + 在不同硬件平台下,需要关注字节内部的字段定义。 + 具体可参考内核中 tcphdr 和 iphdr 的定义。 @@ -231,6 +234,8 @@ 27、C++里面的匿名namespace中的成员,相当于添加了static属性,因为编译器实际上会为每一个匿名的namespace 生成一个名称,且添加using声明,但是这个名称在其他模块是不可见的,这也就添加了internal属性。 + +28、unique_ptr不能进行拷贝操作,也就是不能直接进行传参和从函数中返回,取而代之的是调用move函数 // debug From 4c6d13a6fb486353f53cbb57f762b10963ad7400 Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 5 Aug 2020 09:47:29 +0800 Subject: [PATCH 17/78] add top usage --- cmd_line.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd_line.txt b/cmd_line.txt index 9344eb3..6941d6a 100644 --- a/cmd_line.txt +++ b/cmd_line.txt @@ -12,3 +12,5 @@ 3、netstat -s 命令的输出有很多网络详细信息 4、watch -d -n1 'command'是个很有用的命令,可以动态演示一些命令的输出变化,例如丢包数量等。 + +5、top命令显示中,按 F,然后空格选中P,那么可以展示对应进程运行在哪个CPU上 From a4eba8f981bced5ed2064bdd2e7b330db7f90e06 Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 5 Aug 2020 09:49:08 +0800 Subject: [PATCH 18/78] add failure processing questions --- distributed system.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/distributed system.txt b/distributed system.txt index df17344..782923e 100644 --- a/distributed system.txt +++ b/distributed system.txt @@ -33,3 +33,8 @@ 2、空间利用率低,和 cuckoo filter相比 3、不支持反响删除操作,基本用于只读场景下 4、不支持计数操作) + +14、分布式系统中一个需要解决的问题是将 partial-failure 转换为 fail-stop failure, + 因为在常见的心跳设计有时只考虑链接的稳定性和进程的存在性,而忽视了进程真正的服务能力, + 当遇到partial failure时,因为无法通过心跳检测到异常,所以整个服务处于亚健康状态。 + 这种情况下,直接让异常进程退出,通过其他机制(如,一致性协议)来恢复服务可能更好 From b310f3c19228d97de938495e6e8cf00e9cd30024 Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 5 Aug 2020 09:49:42 +0800 Subject: [PATCH 19/78] add SSD related questions --- file_system.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/file_system.txt b/file_system.txt index 56a4a65..cfc0f38 100644 --- a/file_system.txt +++ b/file_system.txt @@ -139,6 +139,7 @@ 63、SSD的预留空间对于文件系统可见吗? (tips:不可见,不同厂家的预留空间占总存储比例不同) + 预留空间被称为OP(Over-Provision),是为了应对写放大问题,如果OP空间大,那么适合于写密集型应用 64、机械硬盘和SSD的Cache采用的是? (tips:SRAM) @@ -540,6 +541,7 @@ TBW(Total Bytes Writen) TBW = Total Capacity * 擦写次数/写放大率 + 关于TBW,网上还有另一种单位,TeraBytes Written,与之对应的还有 PBW,即SSD可以写入的总PB数据量 175、查看磁盘空间时,需要明确文件系统有预留空间,inode table 也会占用空间 需要使用 tune2fs -l /dev/sda 查看下 super block的信息,确认空间占用 @@ -635,3 +637,14 @@ 3、每次写入大块数据,块层会自动按照内核的配置将一个任务切分为多个子任务 在压测磁盘时,需要增大磁盘的队列深度,也就是说有积压的任务在等待处理,从而提交dist util) + +193、对于SSD设备,因为可以并行处理IO请求,所以iostat的工具输出中 util% 和 svctm% 不能表达出真实的情况 + 这一点与磁盘设备不同。 + +194、rename这个函数,新的文件路径和旧的文件路径必须位于同一文件系统下,否则会报错。 + 从其实现上讲,rename其实就是修改inode指向,同时inode里包含了文件操作相关的operation指针, + 文件系统不同,这些函数实现不同,所以不能直接修改。 + +195、现在的磁盘都采用的ZBR(Zoned Bit Recording),将磁盘划分为zone,zone内部扇区数量相同,zone间, + 扇区数可以不一样。这样,当磁盘转速一定,那么外圈的磁头单位时间的线速度将更高,能读取的扇区数更大。 + 以前的磁盘,内圈和外圈的扇区数一样,这样磁盘的空间小,利用率不高。 From 1d93ada42dbb18d7f2ae0f4e2ddba626e1f4cee9 Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 5 Aug 2020 09:50:22 +0800 Subject: [PATCH 20/78] add spin_lock & manpage related questions --- gcc_gdb.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/gcc_gdb.txt b/gcc_gdb.txt index a619026..2b013ca 100644 --- a/gcc_gdb.txt +++ b/gcc_gdb.txt @@ -29,3 +29,13 @@ 9、gcc编译出来的C库,不能直接在g++编译的C++程序中使用,如果使用,需要在对应的header文件中添加 extern "C" 标识, 但是C中没有extern "C" 的写法,所以,需要在程序中使用预编译宏来判断,例如 #ifdef __cplusplus + +10、在实现用户态的spin_lock时,建议使用CPU的 pause 指令,这可以提高在 spin wait场景下的性能 + 具体可以参考网上文章的说明和Nginx的spin lock实现 + +11、在使用glibc等库中的函数时,如果不确定,一定要先man一下,看看应该引用哪些头文件, + 如果没用正确的引用头文件,会引入奇怪的问题,例如调用 strerror core, + lseek 函数偏移量异常等。 + strerror core的原因是,编译器将函数返回值转为int,而64位环境下指针为8bytes,int为4bytes,访存异常。 + lseek这个是因为,如果第二个参数显示的写为字面值,编译器传参为 int,但是函数中用的是 8bytes的数据, + 会引入一些非预期数据,导致seek结果非预期。 From 736abc53a2ab0123e2a781a2a9ef6e714d01b1c0 Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 5 Aug 2020 09:50:45 +0800 Subject: [PATCH 21/78] add hugepage related --- kernel.txt | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/kernel.txt b/kernel.txt index 55ee6a4..bcc6c1a 100644 --- a/kernel.txt +++ b/kernel.txt @@ -679,6 +679,28 @@ arena size为 64M; 可以通过设置MALLOC_ARENA_MAX环境变量或者通过mallopt函数来控制这一行为) +118、在/proc/$PID/task目录下可以看到当前进程下各个线程的详细信息 + +119、SIGSEGV信号如果是由进程自己触发,则信号信息中的pid为0 + +120、NUMA与SMP相比,个人认为最大的区别在于拓扑结构上的差异,这些差异带来了 + 跨node内存访问延迟(QPI访问),cache一致性等等的问题,其他一些问题上面也有讨论。 + +121、vfork新建进程时,不拷贝父进程的页表,所以创建进程的速度比较快,且父进程阻塞,直到 + 子进程调用了execve或者 _exit(),注意在vfork创建的子进程退出时,不能使用exit,而要 + 使用_exit(),之所以只能使用_exit,是因为glibc库在调用exit时,会进行一些清理工作, + 会访问到父进程的内存空间,而vfork创建的进程,不能直接访问父进程的数据。 + +122、hugepage的使用有两种方式,一种是使用系统预留的hugepage,数量由 + /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages 文件内容控制, + 使用前需要在上述文件中写入期望系统预留的hugepage数量,然后在mmap等调用中显示的传入MAP_HUGETLB参数。 + 这种预留的内存空间常驻内存不会被swap,常用于和设备的DMA操作,公司里面实现的用户态文件系统和NVMe设备交互时也有采用。 + +123、内核会针对每一个page统计MCE(Machine Check Exception),如果超过阈值,那么会进行 + soft_offline_page,即将出错的页面内容拷贝到其他物理页面,然后将出错的页面下线, + 这一操作对应用透明。 + MCE的相关配置文件位于 /etc/mcelog.conf + // 其他 From 0a464f1022fe91749aef4eeb7b1da66a2ae62bcb Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 5 Aug 2020 09:51:08 +0800 Subject: [PATCH 22/78] add sharding & partition --- mysql.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mysql.txt b/mysql.txt index 29be194..15a061d 100644 --- a/mysql.txt +++ b/mysql.txt @@ -223,3 +223,6 @@ (tips:依赖于libaio,但不是所有的IO操作都依靠异步,一般只用于read-ahead和write data file pages场景) 100、MySQL show profile, show profile cpu for query 1 查看具体SQL性能数据 + +101、sharding 和 partition的区别,sharding是为了解决单机存储空间不够而对数据进行物理划分, + 而partition是一种逻辑划分,partition中可以有sharding,sharding中也可以有partition From c0b22ac4515d74617b37051c951df6fec32df647 Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 5 Aug 2020 09:51:27 +0800 Subject: [PATCH 23/78] add tcp wmen related --- network.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/network.txt b/network.txt index fb01e75..6ca5072 100644 --- a/network.txt +++ b/network.txt @@ -456,6 +456,9 @@ EPOLLOUT事件,即socket可写需要满足wmem 空间大于 总量的1/3,这通常用来计算客户端的最小接收速度, 因为通常情况下,服务端会设置send timeout) +132、TCP的wmem,不是说一发送数据,就有空间释放出来,因为TCP是可靠协议,需要ack来确保对端收到, + 所以,wmem的释放需要对方ack了数据后才释放。 + // http 1、什么是CNAME? From 1a3311c1280af55fb3aedf79181ebb1acb0ee123 Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 5 Aug 2020 09:51:58 +0800 Subject: [PATCH 24/78] add nginx reload questions --- nginx.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nginx.txt b/nginx.txt index d97f791..782cd91 100644 --- a/nginx.txt +++ b/nginx.txt @@ -5,3 +5,8 @@ 2、keepalive_requests (tips:一个连接可以发送的请求数量,超过这个数量后,会断开连接) + +3、Nginx的平滑升级通过 execve 实现,过程中不改变进程的open file table, + old master将listen fd写入环境变量,new master进程启动后会尝试读取listen fd, + 然后加入自己的epoll list中,中间还有其他一些信号操作。 + 整体上,平滑升级的关键是listen fd的迁移,其他通信用的fd则采用lazy模式,等待通信完成自然关闭 From 1f69fa203ed6ea57abd694814cfb7f745b39ea12 Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 5 Aug 2020 09:52:27 +0800 Subject: [PATCH 25/78] add redis redlock related questions --- nosql.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/nosql.txt b/nosql.txt index 9d110af..e827841 100644 --- a/nosql.txt +++ b/nosql.txt @@ -7,6 +7,15 @@ (tips:避免了集中式rehash导致系统繁忙,将整个rehash过程均摊到每一次的GET PUT 操作中,一步步完成) +2、Redis实现分布式lock的问题在于,如果某个持有锁的client因为GC或者IO操作suspend, + 在恢复后,没办法确认当前的锁状态,当然,在恢复执行后可以再次执行加锁操作,以 + 确认是否持有锁,但是这没有完全避免GC和sleep的可能,还是会有可能持有一个过期的 + 锁,然后写入非预期的数据。 + 一种解决方案就是锁中带有一个单调递增的token,server只允许比当前记录的token大的client的 + 写操作,之前因为sleep而过期的锁会被拒绝写入数据。 + 当前redlock算法依赖于集群中的大多数返回加锁成功,但是当出现网络分区等异常场景时, + 算法没法保证加锁的正确性。 + // Memcached From 3636eed69da7457929e27a349d9741df2fb7db08 Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 5 Aug 2020 09:53:19 +0800 Subject: [PATCH 26/78] add bfs file --- bfs.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 bfs.txt diff --git a/bfs.txt b/bfs.txt new file mode 100644 index 0000000..dbb7adb --- /dev/null +++ b/bfs.txt @@ -0,0 +1,17 @@ +// bfs related + +1、bfs SDK的接口整体上继承了Posix风格,理解起来比较容易。 + +2、bfs SDK中写入逻辑是先写到本地缓存中,大小为 256KB,满了后,后台异步的刷新到chunkserver中, + 所以当SDK接口返回时,数据并一定写入chunkserver,且chunkserver在open本地文件时, + 没有使用O_SYNC标志。 + +3、现在看,bfs没有将文件切分为 chunk,本地上传一个大文件,对应的chunkserver也有一个同样大小的文件 + (注:这个理解可能随着后面代码阅读的深入改变) + +4、bfs SDK写入支持链式写和星型写,但是没有相关的慢盘规避策略。 + +5、chunkserver中有统计load,数据源来自于pending状态的buffer数量。 + +6、CreateFile逻辑中,先Create成功,然后同步日志,如果在Create完成, + 但是在同步Log前,程序异常退出,是否会造成某些数据不一致。 From 13bda2005801baf73e5a0d0691b2ac12e0d62d76 Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 5 Aug 2020 09:54:02 +0800 Subject: [PATCH 27/78] add fastdfs related questions --- fastdfs.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 fastdfs.txt diff --git a/fastdfs.txt b/fastdfs.txt new file mode 100644 index 0000000..3d39b07 --- /dev/null +++ b/fastdfs.txt @@ -0,0 +1 @@ +# fastdfs related questions From 774fed934dc1eb51470a4ef3cd3538aa13a95c10 Mon Sep 17 00:00:00 2001 From: coderall Date: Thu, 13 Aug 2020 15:40:58 +0800 Subject: [PATCH 28/78] add fast retransmit & fast recovery related --- network.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/network.txt b/network.txt index 6ca5072..07696c5 100644 --- a/network.txt +++ b/network.txt @@ -148,8 +148,12 @@ 40、什么是慢启动? 41、什么是快重传? + (tips:发送端手动按连续三个重复的ack时,认为有数据丢失,立即重传丢失的数据包, + 而不等待RTO,同时,慢启动门限取值为 1/2 的 cwnd,cwnd取值为 慢启动门限+3*数据包大小) 42、什么是快恢复? + (tips:快恢复在上面快重传中其实已经描述了,就是ssthresh取值为 1/2 的cwnd, + 但是,如果遇到RTO,那么cwnd取值为1,sstresh 为 1/2 的遇到RTO时的cwnd) 43、Tahoe 和 Reno 算法中,判断出现丢包的依据是什么? (tips:三次重复的ack) @@ -459,6 +463,18 @@ 132、TCP的wmem,不是说一发送数据,就有空间释放出来,因为TCP是可靠协议,需要ack来确保对端收到, 所以,wmem的释放需要对方ack了数据后才释放。 +133、socket在多进程分发有两种实现方式 + (1)父进程创建socket,然后fork,子进程拷贝父进程的打开文件表,此时 + socket 结构只有一个,多个进程共享这个socket。这里就存在之前的惊群问题, + 即数据来了后,同时唤醒了多个进程 + (2)通过SOCK_REUSEPORT标志,多个socket可以监听同一个port,这时listen的fd只需要处理 + 新建连接请求,而数据请求由五元组来分发。 + +134、netstat -s 的输出中关于重传的有如下几个重要指标 + segments retransmitted 这个计数统计了所有的重传事件,包括RTO,包括快速重传等等 + 在TcpExt 部分,有一个TCPLostRestransmit 这个表示丢失的重传包数量,这个更能表示网络质量 + 还有一个 fast retransmit,具体可以参考快重传的解释 + // http 1、什么是CNAME? From cbf2157acf13a2ff78af03394439bbeb667c60f1 Mon Sep 17 00:00:00 2001 From: coderall Date: Thu, 13 Aug 2020 15:41:34 +0800 Subject: [PATCH 29/78] add CAP & id generator related --- distributed system.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/distributed system.txt b/distributed system.txt index 782923e..eac6b04 100644 --- a/distributed system.txt +++ b/distributed system.txt @@ -6,6 +6,10 @@ 2、分布式系统需要面对的问题有哪些? 3、简单描述下CAP理论?举例说明CA对应什么系统,CP对应什么系统,AP对应什么系统? + CA不保证分区容忍性,对应的是本地数据库系统,本地文件系统等。但是C和A本身是 + 对立的两个概念,本地数据库已经不是分布式系统了。 + CP不保证可用性,常见的如分布式数据库,大多数的分布式一致性协议等 + AP则不保证数据的一致性,常见的如NoSQL数据库,DNS系统等 4、什么是2PC? @@ -38,3 +42,12 @@ 因为在常见的心跳设计有时只考虑链接的稳定性和进程的存在性,而忽视了进程真正的服务能力, 当遇到partial failure时,因为无法通过心跳检测到异常,所以整个服务处于亚健康状态。 这种情况下,直接让异常进程退出,通过其他机制(如,一致性协议)来恢复服务可能更好 + +15、分布式系统中可以使用mlock算法来保证请求的QoS + +16、分布式唯一ID生成算法,常用的有facebook开源的雪花算法,还有国内开源的mist薄雾算法。 + 雪花算法中使用了时间戳,在遇到时间回退时,有可能会产生相同ID,且整个ID的区间比较小, + 时间戳也只能保证使用70年。 + 薄雾算法没有使用时间戳,没有时间回退的问题。但是当程序重启后,再次运行,其基准计数有可能 + 相同,导致有可能ID重复。薄雾算法产生的ID空间更大,每天使用10亿,能使用300年。 + so,算法各有优劣,需要权衡使用。 From d505e0d2a23ba22eee9e54e635ab4e83ac3802f5 Mon Sep 17 00:00:00 2001 From: coderall Date: Tue, 1 Sep 2020 16:53:52 +0800 Subject: [PATCH 30/78] core file related --- cmd_line.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd_line.txt b/cmd_line.txt index 6941d6a..23fbd02 100644 --- a/cmd_line.txt +++ b/cmd_line.txt @@ -14,3 +14,5 @@ 4、watch -d -n1 'command'是个很有用的命令,可以动态演示一些命令的输出变化,例如丢包数量等。 5、top命令显示中,按 F,然后空格选中P,那么可以展示对应进程运行在哪个CPU上 + +6、file core_file 可以查看core文件是哪个binary产生的 From f69f1bd5ecd50049167d32cb3bb959e71cb28f71 Mon Sep 17 00:00:00 2001 From: coderall Date: Tue, 1 Sep 2020 16:54:23 +0800 Subject: [PATCH 31/78] add raft&paxos related questions --- distributed system.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/distributed system.txt b/distributed system.txt index eac6b04..a64aedf 100644 --- a/distributed system.txt +++ b/distributed system.txt @@ -51,3 +51,12 @@ 薄雾算法没有使用时间戳,没有时间回退的问题。但是当程序重启后,再次运行,其基准计数有可能 相同,导致有可能ID重复。薄雾算法产生的ID空间更大,每天使用10亿,能使用300年。 so,算法各有优劣,需要权衡使用。 + +17、raft 和 multi-paxos算法的区别 + (1)raft算法要求,所有请求都是串行的发送给leader节点,而multi-paxos则可以并发的发送到多个节点 + (2)raft的选主算法中,只有拥有最全的日志节点才能当选 + +18、简单的master-slave模型,在master故障后,slave提升为master有两个问题,一是异步同步算法下,有可能有数据还没同步完成, + 二是,新的master带来的单点问题;如果使用强同步模型,那么性能会降低;如果一个master对应多个slave,那么在master掉线后, + 又有多个slave的选举问题。 + raft等算法都是基于 Replicated State Machine 模型,在各个节点间同步log From 1a97a4985d31b8aae7ce2c5976eae984902ae2c1 Mon Sep 17 00:00:00 2001 From: coderall Date: Tue, 1 Sep 2020 16:55:06 +0800 Subject: [PATCH 32/78] add df usage & DAX related questions --- file_system.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/file_system.txt b/file_system.txt index cfc0f38..e088450 100644 --- a/file_system.txt +++ b/file_system.txt @@ -648,3 +648,22 @@ 195、现在的磁盘都采用的ZBR(Zoned Bit Recording),将磁盘划分为zone,zone内部扇区数量相同,zone间, 扇区数可以不一样。这样,当磁盘转速一定,那么外圈的磁头单位时间的线速度将更高,能读取的扇区数更大。 以前的磁盘,内圈和外圈的扇区数一样,这样磁盘的空间小,利用率不高。 + +196、在使用df看磁盘的使用率时,会遇到磁盘空间满,但是du 得到的占用和df结果不匹配的情况。 + 这种情况下,可以使用lsof | grep deleted,看下是否存在文件被删除,但是进程仍然持有 + file handle的情况,这时删除文件的空间还没有被操作系统回收,所以df显示磁盘满。 + +197、DAX(direct access)访问文件时,绕过了page cache,直接访问硬件上的数据,在NVMDIMM等设备上使用较多。 + 与O_DIRECT的软件实现不同,DAX是一种硬件特性,且内部实现了一整套的访问(内核代码中的各种operation实现), + 包括page fault的处理,硬件驱动的支持等。其本身实现的基础就是高端存储硬件提供直接的访问支持。 + 现在支持DAX的文件系统有XFS和EXT4 + +198、NVMDIMM是一种结合了DRAM和FLASH的硬件,它本身提供了电容,保证了掉电时DRAM中的数据可以写回FLASH, + 电力恢复后,再将FLASH中的数据加载到系统内存中。 + +199、AEP(Apache Pass)是intel Optane产品的代称,是一种以3D XPoint介质为基础实现的非易失性存储介质, + 它提供的数据访问带宽比内存低,但是比FLASH高,同时具有持久化功能,可以用来实现更快速的缓存系统 + +// block layer +1、io_submit调用理论上是非阻塞的,但是如果执行sync写入,或者有meta data I/O,或者,设备中能提供的 + request数量有限,如果超过这个限制,也只能阻塞进入等待。 From 43576aab821b3e685d9a6e6b65f5d008afb59159 Mon Sep 17 00:00:00 2001 From: coderall Date: Tue, 1 Sep 2020 16:57:08 +0800 Subject: [PATCH 33/78] add gcc usage --- gcc_gdb.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gcc_gdb.txt b/gcc_gdb.txt index 2b013ca..ff247a2 100644 --- a/gcc_gdb.txt +++ b/gcc_gdb.txt @@ -39,3 +39,9 @@ strerror core的原因是,编译器将函数返回值转为int,而64位环境下指针为8bytes,int为4bytes,访存异常。 lseek这个是因为,如果第二个参数显示的写为字面值,编译器传参为 int,但是函数中用的是 8bytes的数据, 会引入一些非预期数据,导致seek结果非预期。 + +12、高版本中的gdb可以直接查看vector中的数据,在较低版本中,需要 *(vector.M_impl.M_start)@vector.size() + 这种方法来看 vector 全部内容 + +13、gcc -M test.c 选项可以看到编译时所有include的头文件 + gcc -MM选项是过滤了系统头文件之后的输出 From ad5d2defad56a0aa894b4eb000ee95536b629cf1 Mon Sep 17 00:00:00 2001 From: coderall Date: Tue, 1 Sep 2020 16:58:39 +0800 Subject: [PATCH 34/78] add mem min_free_kbytes related questions --- kernel.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/kernel.txt b/kernel.txt index bcc6c1a..eb79fdb 100644 --- a/kernel.txt +++ b/kernel.txt @@ -701,6 +701,20 @@ 这一操作对应用透明。 MCE的相关配置文件位于 /etc/mcelog.conf +124、x64程序中,cpu的fs寄存器用于存储stack canary + +125、内核回收内存空间时,可能会导致sys cpu利用率升高,对应的解决办法是查看 /proc/buddyinfo 确认是 + 哪一阶的内存比较紧张。然后可以通过调低vm.min_free_kbytes系统参数来以更高的频率主动触发内核的回收行为。 + 内核管理内存是划分Zone的,具体信息保存在 /proc/zoneinfo 。每一个Zone中都有 high,low,min三个watermark, + 当某个zone中的内存水位低于low时,kswapd会被唤醒,当水位低于min时,大块的内存申请可能会触发direct reclaim或者 + OOM。 + vm.min_free_kbytes 调整的过低,那么系统回收内存的速度将会非常慢,在运行的过程中,当需要回收内存时,可能会导致死锁。 + vm.min_free_kbytes 调整的过高,那么会导致OOM过于频繁,应用会异常退出。 + 当我们设置了 vm.min_free_kbytes后,内核会根据各个Zone的大小分别计算出min数值。 + 在使用free命令时,我们看到的可用内存空间不一定就可以用来申请,因为min以下的空间是保留给内核使用的, + 应用可用内存需要减去这个数值。所以在malloc或者mmap失败时,可以查看这个参数,确认下是否配置正确。 + 在线上系统中,可以适当的调整这个数值来适当的增加内核主动回收频率,减少direct reclaim + // 其他 From f8d7bba97259a5527ece15b15f78b046c836b583 Mon Sep 17 00:00:00 2001 From: coderall Date: Tue, 1 Sep 2020 16:59:28 +0800 Subject: [PATCH 35/78] add tcp related questions --- network.txt | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/network.txt b/network.txt index 07696c5..ee9e855 100644 --- a/network.txt +++ b/network.txt @@ -76,6 +76,8 @@ 但像下面nginx的说明一样,在高并发环境下,惊群并不显著) 11、time_wait 状态作用是什么? + (tips: 1、避免老的链接上的数据再次发给新建立的连接,导致数据一致性问题 + 2、如果回复对端FIN的Ack丢失,可以进行重传) 12、怎样避免出现 time_wait @@ -475,6 +477,36 @@ 在TcpExt 部分,有一个TCPLostRestransmit 这个表示丢失的重传包数量,这个更能表示网络质量 还有一个 fast retransmit,具体可以参考快重传的解释 +135、在建立连接时,SYN包中的Sequence Number就是Initial Sequence Number, + 这个数字在两端可以不一样 + 这个数字在每次建立连接时,都不一样,这样可以避免前后两次建立连接带来的混淆 + +136、Path MTU怎么确定? + (tips:发送一个大的ip数据包,然后添加IP_DONTFRAG标志,如果超时没有收到ack,那么减少包的大小 + 直到收到ack + 这个和traceroute的原理很像) + +137、TCP允许同时打开一个socket,那允许同时关闭吗?状态流转是怎样的? + (tips: 允许同时关闭,两边的socket都会完整的经历 ESTAB->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT 状态流转) + +138、TCP的接收端怎么确认包丢失? + (tips: 如果收到的包的Sequence Number出现跳变或缺失,则可以判断有数据包丢失) + +139、ssthresh 取值为 INFINITE,在后面的传输过程中,依靠拥塞控制算法,ssthresh会逐渐的靠近准确值 + +140、tcp慢启动过程中的cwnd怎么取值呢,首先尝试从路由信息中获取cwnd,如果没有,那么取系统定义的 + TCP_INIT_CWND,同时还要参考接收方的接收窗口。 + 对于发送小数据量来说,如果链路RTT比较高,那么传输时间所占比例较小,大部分时间花费在了数据 + 传输路径上,这时一个调优选项就是调高 TCP_INIT_CWND值。 + 同时,建议关闭 tcp_slow_start_after_idle。 + 但是关闭这个flag后,有一个问题,就是会带来burst流量,例如,链接空闲一段时间后,突然要 + 发送数据,复用了之前的窗口值,这时数据包在中间路由器被drop的可能性增加(因为比较大)。 + +141、tcp incast是指多对一的数据流向拓扑,即多个源向一个目的写入数据,会导致目的端交换机buffer满, + 出现丢包,反馈到源端就是出现数据重传。 + 解决方案一般是升级到更高buffer容量的交换机,另一方面尝试源和目的就近部署, + 减少网络跳数 + // http 1、什么是CNAME? @@ -513,6 +545,9 @@ 但是,多个HTTP请求必须串行发送,即一个request等待对应response返回后才能继续发送下一个请求, 在HTTP2.0中引入了 Multiplexing机制,这样多个request可以并行发送) +15、标准http header中的字段都是大小写不敏感的,浏览器已经对这个进行了处理, + 在做服务端开发,或者客户端解析时需要注意 + // 其他相关 1、iptables实现原理,使用了哪些算法? @@ -544,6 +579,11 @@ 11、tcpdump工作原理? 12、什么是bonding技术?常用的工作模式有哪些? + (bond0 的配置选项可以参考 /etc/sysconfig/network-script/ifcfg-bond0 文件, + 参数中 mode=4 表示采用 802.3ad标准来组成聚合链路来发送和接收数据包,这个需要 + 上游交换机支持;miimon 参数表示 mii 监控的时间间隔,用来监听底层硬件是否正常; + xmit_hash_policy表示采用的hash规则,常用的有 layer3+4 表示利用ip层的源&目的地址和 + TCP层的源&目的端口) 13、网络设备中 什么叫 “MAN Core”? From f9ae744065e69e945537cb15dc54c5084037b313 Mon Sep 17 00:00:00 2001 From: coderall Date: Tue, 1 Sep 2020 17:00:20 +0800 Subject: [PATCH 36/78] add nginx log rotate tools cronolog description --- nginx.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nginx.txt b/nginx.txt index 782cd91..1ee679e 100644 --- a/nginx.txt +++ b/nginx.txt @@ -10,3 +10,7 @@ old master将listen fd写入环境变量,new master进程启动后会尝试读取listen fd, 然后加入自己的epoll list中,中间还有其他一些信号操作。 整体上,平滑升级的关键是listen fd的迁移,其他通信用的fd则采用lazy模式,等待通信完成自然关闭 + +4、Nginx自身没有带日志切分功能,但是可以通过管道的方式将日志输出到cronolog中,日志文件定义中有 + 格式化的字符串,cronolog自动切换文件进行写入,也就完成了日志切割。 + From 3452f9630c0c805ee43ce56607e48c0603a44196 Mon Sep 17 00:00:00 2001 From: coderall Date: Tue, 1 Sep 2020 17:01:29 +0800 Subject: [PATCH 37/78] add DB index & redis hot key scenes --- nosql.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/nosql.txt b/nosql.txt index e827841..6e7c24f 100644 --- a/nosql.txt +++ b/nosql.txt @@ -1,6 +1,15 @@ // NoSql 1、NoSQL 可以水平扩展的原因有? (tips:NoSQL数据模型简单,没有事务支持,没有Join操作) + +2、数据库的索引数据结构在选型时,面临三方面的问题,即RUM(Read Optimization / Update Optimization / Memory space), + 这三个方面分别对应着不同的索引算法实现。 + (1)读优化的数据结构有,hash,trie等 + (2)写优化的数据结构有,lsm,partitioned-B-Tree等 + (3)空间优化的数据结构有,bloom filter等 + 不同的应用应该根据自己的特点进行选择 + 上述细节可以参考RUM的论文 + // Redis 1、Redis中渐进式rehash实现? @@ -16,6 +25,11 @@ 当前redlock算法依赖于集群中的大多数返回加锁成功,但是当出现网络分区等异常场景时, 算法没法保证加锁的正确性。 +3、redis中如果某个key出现热点,怎么解决呢?思路可能有如下几点 + (1)QoS限流,当前也是这么做的 + (2)本地缓存,减少访问redis量 + (3)热点key添加其他信息,如timestamp,这样人为区分开访问节点 + // Memcached From a704232f18508289b6cc88314ae18d44d0e49768 Mon Sep 17 00:00:00 2001 From: coderall Date: Mon, 28 Sep 2020 20:08:20 +0800 Subject: [PATCH 38/78] add ss command to show listen port --- cmd_line.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd_line.txt b/cmd_line.txt index 23fbd02..ea27cb3 100644 --- a/cmd_line.txt +++ b/cmd_line.txt @@ -16,3 +16,6 @@ 5、top命令显示中,按 F,然后空格选中P,那么可以展示对应进程运行在哪个CPU上 6、file core_file 可以查看core文件是哪个binary产生的 + +7、ss -at '( sport = :80 or dport = :80 )' 可以通过端口来过滤链接, + 也就可以快速的确认是否有服务在监听某个端口 From 60340a4998ff42d0df3ae83252037bf89272fe1a Mon Sep 17 00:00:00 2001 From: coderall Date: Mon, 28 Sep 2020 20:08:53 +0800 Subject: [PATCH 39/78] add some iostat & ext4 related questions --- file_system.txt | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/file_system.txt b/file_system.txt index e088450..87c2994 100644 --- a/file_system.txt +++ b/file_system.txt @@ -482,6 +482,8 @@ 160、iostat 命令中的 rKB/s 或 wKB/s表示? (tips:表示每秒 读取 或 写入的数据量) + r/s 和 w/s 分别表示什么 + (tips:表示完成merge后的读写请求request数量,对应内核中的request,注意,是merge后的) 161、产品宣传时提到 IOPS 的数据时,也要同样考虑 IO 的 latency 数据, 这两个同步提高了,才能说明从硬件到软件都有优化 @@ -664,6 +666,47 @@ 199、AEP(Apache Pass)是intel Optane产品的代称,是一种以3D XPoint介质为基础实现的非易失性存储介质, 它提供的数据访问带宽比内存低,但是比FLASH高,同时具有持久化功能,可以用来实现更快速的缓存系统 +200、lsof的输出中,FD列中的显示中,mem表示mmap的文件,mmap表示内存映射的设备,txt表示二进制可执行文件, + 数字后面跟 r w u,其中,数字表示进程中fd number,r w u分别表示读 写 混合读写 + +201、在调查磁盘读写高时,除了考虑常用的 read/write 调用,其他还有 mmap 需要考虑, + 还有一个就是libaio的使用,这在需要trace系统调用的场景下尤其需要注意 + (tips:libaio并没有增加新的读写接口,数据还是要通过file_operation中的接口来完成读取, + 所以在某些 trace 工具中,通过hook generic_read/generate_write来统计除mmap以外的读写 + 是可行的) + +202、binary的text section加载进内存后,page属性会被标记为 executable,且禁止写入,那么在内存紧张时, + 这部分内存会被回收,带来的问题就是可以看到进程在不停的读磁盘文件,其实是加载binary的文件内容到 + 内存中,这个现象和swap有点像,但还不一样,因为clean page是可以直接被回收的,没开启swap时, + 也不同执行swap out + +203、ext3/ext4 文件系统在文件删除后,会清除inode中的size 和 block pointer字段。如果需要恢复被删除的文件, + 则需要读取文件系统 journal 中记录的日志来undo对应的操作。 + 文件系统的journal并不是一个普通的文件,对用户不可见,但是文件系统可以对它进行读写。debugfs 工具的logdump + 可以看到文件内容。 + 网上说 ext2 在文件被删除后只是将inode标记为 deleted,没有清楚对应的block pointer等字段,但是在1.12的代码中 + 看到是会清楚 block pointer,所以这里待进一步确定! + +204、内部ext4 挂载时都用了 nodelalloc选项来关闭delay alloc。delay alloc的作用是在buffer I/O中,数据写入 + page cache时不立即进行磁盘快的分配,而是等到上层调用fsync或定时写回时才分配。 + 但是在文件写入时(不管是写入page cache,还是写入磁盘),要持有一把锁,一般情况下,写入很快完成;但是 + delay alloc 因为将块的分配推后,等到真正需要分配时,需要的块有可能很多,导致延迟增加,进一步影响 + 应用的响应。 + delay alloc的优点有减少分配块次数,单次的写入延迟降低;且批量分配能将文件内容尽可能存放在连续的磁盘块上, + 有利于后续的I/O; + 缺点就是:有可能某一次的写入延迟增加,且存在page cache内容准备刷回磁盘发现磁盘没有空间这种情况。 + // block layer 1、io_submit调用理论上是非阻塞的,但是如果执行sync写入,或者有meta data I/O,或者,设备中能提供的 request数量有限,如果超过这个限制,也只能阻塞进入等待。 + +// trace +1、通过iostat看到某个磁盘util高,怎么确认是哪个进程在进行I/O? + (tips:首先通过df查看磁盘挂载在哪个目录,然后通过lsof输出对应目录下所有打开的文件,参考文件打开模式, + 然后过滤进程,利用 pidstat -d -p $PID,查看具体某个进程的IO量,同时,也可以通过strace查看read和mmap + 系统调用的使用情况,进一步确定是在读写哪个文件) + +2、怎么确认某块硬盘状态是正常的? + (tips:现在的硬盘,包括SSD都支持SMART特性,所以可以使用smartctl --all 或 smartctl -H dev 命令来查看对应盘的信息 + 如果确认磁盘发生了错误,可以使用badblocks命令来扫盘,以确认具体哪个block损坏; + 执行检查时,可能需要辅助使用 fdisk -l 或 dumpe2fs -h dev 命令来确认一些硬件或文件系统元数据) From 8a26cded1c40625b108fcfc2df99266d620bbc12 Mon Sep 17 00:00:00 2001 From: coderall Date: Mon, 28 Sep 2020 20:09:30 +0800 Subject: [PATCH 40/78] add uptime & free command explanation --- kernel.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/kernel.txt b/kernel.txt index eb79fdb..467c5e0 100644 --- a/kernel.txt +++ b/kernel.txt @@ -272,7 +272,9 @@ 92、系统级的load数据从哪里来? (tips:uptime等工具可以查看当前系统的load,这个数值正比于 active process 和 处于 uninterruptable状态的进程, - load = old * e + (1-e)*processes,即也会参考前一次的load数据) + load = old * e + (1-e)*processes,即也会参考前一次的load数据 + 所以说,如果通过命令看到系统负载高,不一定是CPU繁忙,也有可能是 + 系统I/O繁忙,更多的进程在等待着从磁盘等设备读取数据) // 内存管理 mm @@ -715,6 +717,12 @@ 应用可用内存需要减去这个数值。所以在malloc或者mmap失败时,可以查看这个参数,确认下是否配置正确。 在线上系统中,可以适当的调整这个数值来适当的增加内核主动回收频率,减少direct reclaim +126、free命令的各项数据来自于/proc/meminfo这个文件,而这个文件的内容又是来自于procfs, + 其中buffer来自于sysinfo中的bufferram字段,这个字段又是来自于nr_blockdev_pages,即 + 统计devfs中inode结构中i_mapping字段映射的页面数量,一般直接读取设备时,会分配这一数据, + 这也就和之前看的buffer表示块设备文件数据占用内存的说法一致。 + 这部分内存和普通内存的用法一样,如果写入数据,也需要刷回磁盘,如果只读,那么对应内存会被回收(干净页) + // 其他 From d0e4a4089fe77b2f968cda87cb282ee8eb2048e9 Mon Sep 17 00:00:00 2001 From: coderall Date: Mon, 28 Sep 2020 20:10:05 +0800 Subject: [PATCH 41/78] add some socket related questions --- network.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/network.txt b/network.txt index ee9e855..8ed13f6 100644 --- a/network.txt +++ b/network.txt @@ -507,6 +507,15 @@ 解决方案一般是升级到更高buffer容量的交换机,另一方面尝试源和目的就近部署, 减少网络跳数 +142、socket的REUSEPORT属性在服务端构造了一个多队列多服务模型,与之对应的是早期的fork版本构建了一个 + 单队列多服务模型。 + 单队列模型如果服务阻塞,那么前提是所有服务端都阻塞;多队列如果服务阻塞,那么有可能只是一个服务阻塞, + 所以多队列模型的平均访问延迟分布的更广,有可能个别客户端的延迟非常高。 + (from dog250) + +143、网络模块中的连接表是全局的,在recv中,计算四元组hash,然后在连接表中找到sock, + 完成后续的通信过程 + // http 1、什么是CNAME? @@ -687,3 +696,13 @@ droped则表示访问了未配置的功能,例如,在没有配置ipv6的情况下,收到ipv6报文 39、在配置了bond0的机器上用tcpdump 抓包时,不能使用 -i any ,而要指定bond的网卡 + +40、一个进程在运行时,可以确定的知道使用了哪些socket,但是反过来,知道socket却无法明确的得到对应的进程, + 因为socket有可能被多个进程使用。 + 这两者是通过进程的打开文件表关联起来的。 + netstat 命令是通过列举 /proc/net/tcp中的inode,然后和 /proc/$task/fd 下面列举的 socket inode进行比对, + 如果相等,则判断对应进程打开了某一个socket。 + /proc/$task/fd/ 下面的link文件格式有时是 socket:$number 或 pipe:$number,这个数字表示对应socket或pipe的inode number + 即,上面和进程关联时使用 + ss 命令同样可以查看网络socket的信息,但是ss使用的是 netlink,一种更适合于传输大量数据的内核-用户态通信方式, + 但是这两个命令都会 lock sock list From 569c15d4d37acfe88d0556c6a72109bc82f7a87a Mon Sep 17 00:00:00 2001 From: coderall Date: Mon, 28 Sep 2020 20:10:37 +0800 Subject: [PATCH 42/78] add some awesome project name or url --- awesome_project.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 awesome_project.txt diff --git a/awesome_project.txt b/awesome_project.txt new file mode 100644 index 0000000..398ff65 --- /dev/null +++ b/awesome_project.txt @@ -0,0 +1,2 @@ +1、ext3grep + url: https://code.google.com/archive/p/ext3grep/source/default/source From 62997971f3962e7d4e111ec9e8eff0325e5d53f8 Mon Sep 17 00:00:00 2001 From: coderall Date: Fri, 23 Oct 2020 16:48:47 +0800 Subject: [PATCH 43/78] add lsof & procfs & disk write cache related --- file_system.txt | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/file_system.txt b/file_system.txt index 87c2994..462de65 100644 --- a/file_system.txt +++ b/file_system.txt @@ -696,6 +696,25 @@ 有利于后续的I/O; 缺点就是:有可能某一次的写入延迟增加,且存在page cache内容准备刷回磁盘发现磁盘没有空间这种情况。 +205、lsof的输出 或者 ls -l /proc/$PID/fd/ 结果中有 anon_inode,这是内核中的anon_inodefs伪文件系统下面的 + inode,一般多用于eventfd,signalfd,timerfd等,这类文件描述符并没有真正对应inode,但是为了保持语义一致, + 内核会为对应的fd分配inode。 + /proc/$PID/fd/ 输出格式一般为 type:[inode number],如果type为socket,那么通过inode number可以在 + /proc/net/ 目录下的 tcp/udp/unix 等文件中找到详细信息 + +206、当磁盘开启了write cache时,数据写入磁盘上的DRAM后,立即向上层返回成功,保证了顺序写和随机写性能, + 但是存在数据掉电丢失的问题。如果关闭write cache,那么可以保证数据安全。 + 现在有PWC技术,可以保证在掉电时,仍然能写入少量数据(M级别) + 使用 hdparm -W /dev/sda 命令可以查看磁盘的write cache是否打开 + +207、/proc/$PID/io 文件里面的rchar表示read或pread系统调用中传入的参数之和,对应的wchar表示write或pwrite + 传入的参数之和;read_bytes 表示真正从后端设备读取的数据量,统计发生在submit_io这一层,write_bytes则 + 表示page-cache写回后端设备的数据量 + iotop命令中,total 列统计的就是各个process的rchar和wchar + 而actual 列统计的则是/proc/vmstat中的pgpgin 和 pgpgout,单位为KB + 对于读操作,pgpgin 和 read_bytes 保持同步更新,但是写操作在submit_bio层更新pgpgout,在__set_page_dirty调用 + 中更新write_bytes + // block layer 1、io_submit调用理论上是非阻塞的,但是如果执行sync写入,或者有meta data I/O,或者,设备中能提供的 request数量有限,如果超过这个限制,也只能阻塞进入等待。 @@ -704,7 +723,9 @@ 1、通过iostat看到某个磁盘util高,怎么确认是哪个进程在进行I/O? (tips:首先通过df查看磁盘挂载在哪个目录,然后通过lsof输出对应目录下所有打开的文件,参考文件打开模式, 然后过滤进程,利用 pidstat -d -p $PID,查看具体某个进程的IO量,同时,也可以通过strace查看read和mmap - 系统调用的使用情况,进一步确定是在读写哪个文件) + 系统调用的使用情况,进一步确定是在读写哪个文件,有时存在一种情况,使用iostat或iotop可以看到读写流量, + 但是trace并没有发现有read/write,那么有一种情况就是进程在频繁的调用fsync,需要使用其他工具来trace sync + 类的调用) 2、怎么确认某块硬盘状态是正常的? (tips:现在的硬盘,包括SSD都支持SMART特性,所以可以使用smartctl --all 或 smartctl -H dev 命令来查看对应盘的信息 From d475bb87366c9697ba974c884f73a9dc19bbb143 Mon Sep 17 00:00:00 2001 From: coderall Date: Fri, 23 Oct 2020 16:49:33 +0800 Subject: [PATCH 44/78] add /proc/meminfo related --- kernel.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel.txt b/kernel.txt index 467c5e0..0534b3c 100644 --- a/kernel.txt +++ b/kernel.txt @@ -717,8 +717,8 @@ 应用可用内存需要减去这个数值。所以在malloc或者mmap失败时,可以查看这个参数,确认下是否配置正确。 在线上系统中,可以适当的调整这个数值来适当的增加内核主动回收频率,减少direct reclaim -126、free命令的各项数据来自于/proc/meminfo这个文件,而这个文件的内容又是来自于procfs, - 其中buffer来自于sysinfo中的bufferram字段,这个字段又是来自于nr_blockdev_pages,即 +126、free命令的各项数据来自于/proc/meminfo这个文件(代码在fs/proc/meminfo.c),而这个文件的内容又是来自于procfs, + 其中buffer来自于sysinfo中的bufferram字段(代码在mm/page_alloc.c),这个字段又是来自于nr_blockdev_pages,即 统计devfs中inode结构中i_mapping字段映射的页面数量,一般直接读取设备时,会分配这一数据, 这也就和之前看的buffer表示块设备文件数据占用内存的说法一致。 这部分内存和普通内存的用法一样,如果写入数据,也需要刷回磁盘,如果只读,那么对应内存会被回收(干净页) From a5861ae725e61d7d14deee71fa1754c3dfc36774 Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 18 Nov 2020 14:21:10 +0800 Subject: [PATCH 45/78] add disk related questions --- C and C++.txt | 2 ++ file_system.txt | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/C and C++.txt b/C and C++.txt index 20ba8cc..b03ed68 100644 --- a/C and C++.txt +++ b/C and C++.txt @@ -236,6 +236,8 @@ 生成一个名称,且添加using声明,但是这个名称在其他模块是不可见的,这也就添加了internal属性。 28、unique_ptr不能进行拷贝操作,也就是不能直接进行传参和从函数中返回,取而代之的是调用move函数 + +29、shared_ptr的引用计数更新是线程安全的,但是指针的更新不是,需要注意 // debug diff --git a/file_system.txt b/file_system.txt index 462de65..0a25dd4 100644 --- a/file_system.txt +++ b/file_system.txt @@ -476,6 +476,8 @@ 158、Ext4 默认开启barrier特性,且 Journal中有校验 checksum,如果乱序写入,且transaction中断, 那么后续的校验将不通过,本次操作会abort;在高端存储磁盘有 battery-backend时,可以考虑关闭 barrier以提高性能 + (barrier之前是通过drain request_queue 然后再发送一个flush请求实现的,这样虽然可以达到预期效果, + 但是会影响性能) 159、fsync 函数返回EIO错误时,如果直接进行重试,fsync会 clear之前有出错标志的page, 这会潜在的导致数据丢失,Pg数据库目前的做法是fsync返回EIO时,直接panic @@ -604,6 +606,11 @@ 以16KB连续数据为例,需要一个bio结构,里面包括了4个bio_vec;如果数据不连续,则需要多个bio结构 186、使用 echo '' > file 这一步,其实是在open中传入了O_TRUNC标志,进而在打开文件时完成文件长度修改。 + (tips:O_TRUNC的实现中,首先对inode->i_mutex加锁,然后修改inode->i_size,再invalid page cache, + 这时有一个特殊的点,就是如果这个page mmap到用户态,则需要修改页表,用户的下次访问需要走page fault的流程, + 重新读取文件内容 + 这次还验证了一个场景,一个进程读文件,另一个后台进程覆盖文件内容,那么第一个线程会读取到新内容, + 所以说,文件系统并没有保证一致性) 187、在 /etc/mke2fs.conf 文件中有创建文件系统时的默认配置,通过这些配置可以熟悉了解文件系统都实现了哪些功能, 有哪些常用feature @@ -715,6 +722,10 @@ 对于读操作,pgpgin 和 read_bytes 保持同步更新,但是写操作在submit_bio层更新pgpgout,在__set_page_dirty调用 中更新write_bytes +208、磁盘控制器频繁的下发SMART指令,也会对性能产生影响,一般都是分钟级的采样。 + 这也就带来一个问题,上层怎么快速的发现磁盘的问题,这就要用一些写入测试来辅助, + 例如现在在用的 write_test 方法等 + // block layer 1、io_submit调用理论上是非阻塞的,但是如果执行sync写入,或者有meta data I/O,或者,设备中能提供的 request数量有限,如果超过这个限制,也只能阻塞进入等待。 From 6e70c44a4e9b98f3743ebd7a7e75a5dcffea4b41 Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 18 Nov 2020 14:22:59 +0800 Subject: [PATCH 46/78] add mem related questions --- kernel.txt | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/kernel.txt b/kernel.txt index 0534b3c..28171a5 100644 --- a/kernel.txt +++ b/kernel.txt @@ -276,6 +276,9 @@ 所以说,如果通过命令看到系统负载高,不一定是CPU繁忙,也有可能是 系统I/O繁忙,更多的进程在等待着从磁盘等设备读取数据) +93、操作系统中并没有为cgroup添加专用的system call,而是通过 cgroup fs来完成 + 进程的资源隔离操作 + // 内存管理 mm 1、malloc的实现 @@ -708,12 +711,14 @@ 125、内核回收内存空间时,可能会导致sys cpu利用率升高,对应的解决办法是查看 /proc/buddyinfo 确认是 哪一阶的内存比较紧张。然后可以通过调低vm.min_free_kbytes系统参数来以更高的频率主动触发内核的回收行为。 内核管理内存是划分Zone的,具体信息保存在 /proc/zoneinfo 。每一个Zone中都有 high,low,min三个watermark, - 当某个zone中的内存水位低于low时,kswapd会被唤醒,当水位低于min时,大块的内存申请可能会触发direct reclaim或者 - OOM。 + 当某个zone中的内存水位低于low时,kswapd会被唤醒,直到水位回到high以上, + 当水位低于min时,大块的内存申请可能会触发direct reclaim或者OOM。 vm.min_free_kbytes 调整的过低,那么系统回收内存的速度将会非常慢,在运行的过程中,当需要回收内存时,可能会导致死锁。 vm.min_free_kbytes 调整的过高,那么会导致OOM过于频繁,应用会异常退出。 当我们设置了 vm.min_free_kbytes后,内核会根据各个Zone的大小分别计算出min数值。 - 在使用free命令时,我们看到的可用内存空间不一定就可以用来申请,因为min以下的空间是保留给内核使用的, + 在使用free命令时,我们看到的可用内存空间不一定就可以用来申请,/proc/sys/vm/lowmem_reserve_ratio这个文件 + 里面定义了各个zone中保留的页面比例,当高端内存向低端内存申请内存时,需要判断 free_pages 和 min + reserved_page + 的大小关系,如果小于,那么申请失败(参考mm/page_alloc.c __zone_watermark_ok函数) 应用可用内存需要减去这个数值。所以在malloc或者mmap失败时,可以查看这个参数,确认下是否配置正确。 在线上系统中,可以适当的调整这个数值来适当的增加内核主动回收频率,减少direct reclaim @@ -723,6 +728,9 @@ 这也就和之前看的buffer表示块设备文件数据占用内存的说法一致。 这部分内存和普通内存的用法一样,如果写入数据,也需要刷回磁盘,如果只读,那么对应内存会被回收(干净页) +127、/var/log/messages 这个文件记录了系统中很多信息,包括系统启动,关闭,OOM,shell的操作日志等。 + Ubuntu等发行版使用的是 /var/log/syslog 来记录这些信息 + // 其他 From 2f2141df5aab857c2727b1b2dcd66cb789fc07d9 Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 18 Nov 2020 14:24:01 +0800 Subject: [PATCH 47/78] add network related questions --- network.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/network.txt b/network.txt index 8ed13f6..3846184 100644 --- a/network.txt +++ b/network.txt @@ -642,9 +642,9 @@ (tips:上文中提到的TSO只是针对 TCP协议的优化,而GSO这是针对所有上层协议做的一种优化) 31、网络收敛比的概念? - (tips:有两方面的理解,首先是交换机不支持线速转发, - 例如,12个网口,每个口输入1Gbps,但是出口只有8gbps,这时网络收敛比为 3:2。 - 还有一种来自于架构层面,核心交换机万兆,后接12个千兆,则网络收敛比为 10:12,即 1:1.2) + (tips: 硬件方面,交换机不支持线速转发, + 架构层面,核心交换机万兆,后接12个千兆,则网络收敛比为 10:12,其实就是北向和南向能提供的带宽比值, + 理想情况下收敛比应该是1:1,但是这样会增加网络硬件的成本投入) 32、网络数据发送前的操作都有哪些? (tips:1、首先根据ip 和 路由表决定数据从哪个网卡发出 From 863e00cdc3a12f8ca76da2caf884ff696f48d6ef Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 18 Nov 2020 14:30:52 +0800 Subject: [PATCH 48/78] add 'last' command --- cmd_line.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd_line.txt b/cmd_line.txt index ea27cb3..71bcd8c 100644 --- a/cmd_line.txt +++ b/cmd_line.txt @@ -19,3 +19,7 @@ 7、ss -at '( sport = :80 or dport = :80 )' 可以通过端口来过滤链接, 也就可以快速的确认是否有服务在监听某个端口 + +8、last reboot可以查看机器的重启信息 + (tips:last命令读取的/var/log/wtmp文件,可以查看对应用户的登录信息,例如: + last -n 10 user_name) From e45537f82fb9f3406e111cb629ade7e374fbc408 Mon Sep 17 00:00:00 2001 From: coderall Date: Thu, 19 Nov 2020 14:41:17 +0800 Subject: [PATCH 49/78] add C++ performance book --- books.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/books.txt b/books.txt index d1f6e7e..a14bf55 100644 --- a/books.txt +++ b/books.txt @@ -8,4 +8,6 @@ 4、《The Garbage Collection Handbook》 Author Richard Jones -5、《Virtual Machines》 Author James E. Smith \ No newline at end of file +5、《Virtual Machines》 Author James E. Smith + +6、《Technical Report on C++ Performance》 From a9b35ac414798a1e9b7b0b0fb9127e4ae2d0a52f Mon Sep 17 00:00:00 2001 From: coderall Date: Tue, 24 Nov 2020 16:26:31 +0800 Subject: [PATCH 50/78] add mm overcommit & segment fault related questions --- kernel.txt | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/kernel.txt b/kernel.txt index 28171a5..1642120 100644 --- a/kernel.txt +++ b/kernel.txt @@ -354,7 +354,10 @@ 还是要申请物理内存,并且要考虑OOM机制的影响) 26、系统可配置的处理overcommit策略都有哪些? - (tips:vm.overcommit_memory和vm.overcommit_ratio proc变量的取值) + (tips:vm.overcommit_memory和vm.overcommit_ratio proc变量的取值 + 具体修改的是/proc/sys/vm/overcommit 和 /proc/sys/vm/overcommit_ration 这两个文件中的内容 + 其中overcommit=0,mmap传入MAP_NORESERVE则不进行参数检查;如果为1,表示允许overcommit; + 如果为2,可以使用的最大虚存为Swap+RAM*overcommit_ration/100,且不允许超过这个限制) 27、怎样判断进程有overcommit行为? @@ -731,6 +734,16 @@ 127、/var/log/messages 这个文件记录了系统中很多信息,包括系统启动,关闭,OOM,shell的操作日志等。 Ubuntu等发行版使用的是 /var/log/syslog 来记录这些信息 +128、dmesg 或者上面 /var/log/messages有记录进程发生segment fault时的信息,常见的是 segfault at xxx ip xxx sp xxx error xxx + 其中 ip 指向的是当前正在执行的指令,加上 at 后面的偏移量可以得到调用栈中的的caller(栈地址是从大到小,栈顶的地址小) + error 是一个位图,记录具体的错误信息 + page fault error code bits: + * + * bit 0 == 0: no page found 1: protection fault + * bit 1 == 0: read access 1: write access + * bit 2 == 0: kernel-mode access 1: user-mode access + * bit 3 == 1: use of reserved bit detected + * bit 4 == 1: fault was an instruction fetch // 其他 From 89c7ee6c028b898627bd7f72058d946f2bcf6675 Mon Sep 17 00:00:00 2001 From: coderall Date: Tue, 24 Nov 2020 16:26:55 +0800 Subject: [PATCH 51/78] add new storage related file --- storage.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 storage.txt diff --git a/storage.txt b/storage.txt new file mode 100644 index 0000000..838004a --- /dev/null +++ b/storage.txt @@ -0,0 +1,10 @@ +# 存储硬件 or 存储产品相关 +# storage hardware or production related + +1 NoF(NVMe over Fabrics)的实现中和本地NVMe访问有哪些区别 + (tips: 从如下几点来分析 + (1) 设备的识别,本地盘通过总线系统和完成,而NoF则需要NVMe Qualified Name即NQN来识别 + (2) 设备的发现,本地盘通过总线通知,而NoF需要一种协议模式来发现和连接,有点像TCP + (3) 存储命令的排队模型,本地盘直接使用基于内存的Queue,但是NoF则需要一个Message-based的排队系统 + (4) 数据传输方面,本地盘直接使用PCIe协议中的Physical Region Page,而NoF需要Scatter-Gather List的支持) + From add87a65e0ff54911a0a4db0a4e3286524bf851e Mon Sep 17 00:00:00 2001 From: coderall Date: Thu, 10 Dec 2020 17:05:21 +0800 Subject: [PATCH 52/78] add SIGSEGV related --- kernel.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel.txt b/kernel.txt index 1642120..e4f8630 100644 --- a/kernel.txt +++ b/kernel.txt @@ -346,7 +346,9 @@ 需要修改页表内容,通过PTE表项可以拿到对应虚拟地址对应的在swap中的 物理页面内容。 2.6 内核针对多个连续页面内容新增了 extent 属性,可以向文件系统那样 - 操作多个连续物理页面) + 操作多个连续物理页面 + 线上有可能不开swap,因为swap会带来额外的磁盘IO,会引起应用进程延迟增加, + 同时,swap的读回又会带来随机IO) 25、什么是内存overcommit? (tips:操作系统向外提供的内存总量比 RAM+Swap 多,这里有一个假设就是, @@ -735,7 +737,8 @@ Ubuntu等发行版使用的是 /var/log/syslog 来记录这些信息 128、dmesg 或者上面 /var/log/messages有记录进程发生segment fault时的信息,常见的是 segfault at xxx ip xxx sp xxx error xxx - 其中 ip 指向的是当前正在执行的指令,加上 at 后面的偏移量可以得到调用栈中的的caller(栈地址是从大到小,栈顶的地址小) + 其中 ip 指向的是当前正在执行的指令,加上 at 后面的偏移量可以得到调用栈中的的caller(栈地址是从大到小,栈顶的地址小),这里记录的 + 地址都可以使用addr2line工具得到对应的代码行信息 error 是一个位图,记录具体的错误信息 page fault error code bits: * From 81872a0ac106b39fc5a0e5a1ec8f6cd68b48e0ed Mon Sep 17 00:00:00 2001 From: coderall Date: Thu, 10 Dec 2020 17:05:49 +0800 Subject: [PATCH 53/78] add tcp status related --- network.txt | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/network.txt b/network.txt index 3846184..1b935b0 100644 --- a/network.txt +++ b/network.txt @@ -351,7 +351,7 @@ 为 min(listen_backlog, /proc/sys/net/core/somaxconn), 当命令输出中这两个参数相等时,表示当前accept队列满,考虑调大somaxconn数值; 如果是已经建立好的链接,Recv-Q表示内核已经收到但是应用还没有读取的数据量, - Send-Q表示还在SendBuf中,没有ack的数据量) + Send-Q表示还在SendBuf中,没有ack的数据量,单位是字节) 109、当半连接队列满时,新来的连接的处理方式为? (tips:丢弃新来的连接请求,客户端的connect会超时) @@ -516,6 +516,35 @@ 143、网络模块中的连接表是全局的,在recv中,计算四元组hash,然后在连接表中找到sock, 完成后续的通信过程 +144、tcp用到的mem参数有如下几个: + ( + net.core.rmem_default 所有socket的读取buffer默认值 + net.core.rmem_max 所有socket的读取buffer最大值,可以由setsockopt SO_RECVBUF 修改,单位字节 + net.core.wmem_default 所有socket的发送buffer默认值 + net.core.wmem_max 所有socket的发送buffer最大值,可以由setsockopt SO_SNDBUF 修改,单位字节 + net.ipv4.tcp_mem tcp socket 能用到的mem量,分 min pressure max,以page为单位 + net.ipv4.tcp_rmem 单tcp socket 能用到的接收buffer量,分 min pressure max,调用setsockopt修改rmem后,内核的自适应调节功能关闭 + net.ipv4.tcp_wmem 单tcp socket 能用到的发送buffer量,分 min pressure max,调用setsockopt修改wmem后,内核的自适应调节功能关闭 + ) + +145、tcp各个状态简述 + ( + FIN_WAIT_1,主动调用close的一方在发送了FIN包之后的状态,当收到对方的ack后,状态流转到FIN_WAIT_2;如果没有收到ack,那么重新发送FIN包 + FIN_WAIT_2,处于FIN_WAIT_1状态的socket收到FIN的ack后,状态转为FIN_WAI_2,socket在这个状态的超时时间为tcp_fin_timeout,如果系统中有较多的 + 此状态的socket,那么表示对端可能异常,没有正确的调用close + time_wait,主动关闭的一方在收到对方发送的FIN后,回复ACK,状态转为time_wait,在2 msl 时间后,socket 关闭 + close_wait,被动关闭的一方收到对端的FIN包后,状态转为close_wait,注意,这个状态没有超时时间,需要后端配合来释放socket链接 + last_ack,被动关闭的一方发送FIN后,状态转为last_ack,如果没有收到对方的ack,需要重传,如果收到ack,那么socket状态为closed + ) + +146、什么是orphan sockets + (tips:orphan socket可以理解为没有和fd关联的socket,对应TCP中socket的状态为 FIN_WAIT_1,LAST_ACK,TCP_CLOSING, + 其中TCP_CLOSING用于表示同时关闭的场景,即在FIN_WAIT_1状态下同时受到FIN包 + CLOSE_WAIT 不计入 orphan socket + TIME_WAIT 不计入 orphan socket + FIN_WAIT_2 根据 fin_timeout 不同时长,有可能计入 + 如果系统上orphan socket 过多,那么需要统计处于哪个状态的socket较多,再结合[145]来分析) + // http 1、什么是CNAME? @@ -557,6 +586,12 @@ 15、标准http header中的字段都是大小写不敏感的,浏览器已经对这个进行了处理, 在做服务端开发,或者客户端解析时需要注意 +16、http协议中的Connection header定义了当前Trans完成后,服务端怎么处理当前这个连接。 + 默认为 close,即常见的短链接 + 如果为 Keep-Alive,那么链接将会维持 + http Header中同样有Keep-Alive字段,可以定义timeout 和 max 字段来控制当前链接的超时时间 + 和发送的request数量 + // 其他相关 1、iptables实现原理,使用了哪些算法? From 1264242bfd7fbf77cd558df58d29ce0021a3741a Mon Sep 17 00:00:00 2001 From: coderall Date: Thu, 10 Dec 2020 17:06:38 +0800 Subject: [PATCH 54/78] add sata & sas --- storage.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/storage.txt b/storage.txt index 838004a..51df98a 100644 --- a/storage.txt +++ b/storage.txt @@ -1,10 +1,12 @@ # 存储硬件 or 存储产品相关 # storage hardware or production related -1 NoF(NVMe over Fabrics)的实现中和本地NVMe访问有哪些区别 +1、 NoF(NVMe over Fabrics)的实现中和本地NVMe访问有哪些区别 (tips: 从如下几点来分析 (1) 设备的识别,本地盘通过总线系统和完成,而NoF则需要NVMe Qualified Name即NQN来识别 (2) 设备的发现,本地盘通过总线通知,而NoF需要一种协议模式来发现和连接,有点像TCP (3) 存储命令的排队模型,本地盘直接使用基于内存的Queue,但是NoF则需要一个Message-based的排队系统 (4) 数据传输方面,本地盘直接使用PCIe协议中的Physical Region Page,而NoF需要Scatter-Gather List的支持) +2、SATA3.0 的最大传输速度为6G,但是SAS3.0支持12G,如果直接在SAS口上链接SATA盘,会有带宽浪费的问题 + 所以在SCSI协议层支持多路复用,最大化带宽利用 From 6dc26ea4c48903f408d12db31077f2adb4b3af53 Mon Sep 17 00:00:00 2001 From: coderall Date: Sat, 13 Feb 2021 18:29:41 +0800 Subject: [PATCH 55/78] add mem & vdso related questions --- kernel.txt | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/kernel.txt b/kernel.txt index e4f8630..0661672 100644 --- a/kernel.txt +++ b/kernel.txt @@ -15,6 +15,7 @@ 6、pthread_mutex 默认情况下 对同一个锁 重复加锁两次 会有什么效果,为什么? 7、pthread_mutex 怎么实现? 使用了哪个系统调用? + (tips:futex) 8、可以在线程中调用fork吗?为什么? @@ -70,6 +71,10 @@    tips:PTRACE_TRACEME & SIGTRAP handler & /proc/self/status 30、简单解释下 vsyscall & vdso ? + (tips:vsyscall是为了解决常用的time,gettimeofday等函数频繁调用时上下文切换过多的问题, + 它提供了一种映射机制,将内核中的时间数据映射到用户态中。 + vdso则更进一步,将这种映射封装为动态链接库,可以利用ADSR机制来对数据进行保护, + 在/proc/$pid/smap中,可以通过dd来将vdso导出得到一个elf格式的库文件) 31、/proc/kcore文件有什么用? @@ -274,11 +279,18 @@ active process 和 处于 uninterruptable状态的进程, load = old * e + (1-e)*processes,即也会参考前一次的load数据 所以说,如果通过命令看到系统负载高,不一定是CPU繁忙,也有可能是 - 系统I/O繁忙,更多的进程在等待着从磁盘等设备读取数据) + 系统I/O繁忙,更多的进程在等待着从磁盘等设备读取数据, + 系统的负载有两种,一种是CPU,一种是IO,uninterruptable状态的进程就是反馈系统 + 的IO情况) 93、操作系统中并没有为cgroup添加专用的system call,而是通过 cgroup fs来完成 进程的资源隔离操作 +94、内核会为每个cpu启动一个优先级很高的实时内核线程watchdog/x,尝试每5s调度一次,更新时间戳, + 如果对应线程长时间没有被调度执行,则打印soft lockup告警 + +95、同样内核会为每个CPU启动一个高精度的timer来检测中断的执行是否被长时间阻塞,这个timer默认每4s触发一次来更新时间戳 + // 内存管理 mm 1、malloc的实现 @@ -748,6 +760,20 @@ * bit 3 == 1: use of reserved bit detected * bit 4 == 1: fault was an instruction fetch +129、通常在不可睡眠,或不可调度的上下文中使用GFP_ATOMIC标志调用kmalloc申请内存 + 如果当前zone的内存水位低于min,那么GFP_ATOMIC可以使用到 min/4的量。对应的,如果使用GFP_KERNEL标志, + 则可能会触发direct reclaim + PF_MEMALLOC则是kswapd在回收内存空间时申请空间,所以带这个标志的内存申请必须得到满足 + 可以使用对应的预留空间。 + +130、某个问题中,程序在异常时有一段退出逻辑,但是刚好磁盘hang,导致对应代码段没有load上来 + 程序没有按照预定的逻辑退出,出现问题。 + 这个问题有如下几个启示 + (1)怎么确认代码里面的某个函数,或某几个函数在磁盘文件的哪个block + (2)内核从磁盘读取文件异常时,通常会打印带sector的日志,那么怎么和第一点的信息对应上来, + 即通过sector找到对应block,在匹配到操作的文件 + (3)怎么解决代码段不能load的问题(可以通过mlock来避免对应页面被换出) + // 其他 1、内核和用户空间通信都有哪些方法? From 3846ffb240ed074ce743b147c5f55db079ee8a14 Mon Sep 17 00:00:00 2001 From: coderall Date: Sat, 13 Feb 2021 18:30:11 +0800 Subject: [PATCH 56/78] add tcp related questions --- network.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/network.txt b/network.txt index 1b935b0..0f6d761 100644 --- a/network.txt +++ b/network.txt @@ -545,6 +545,9 @@ FIN_WAIT_2 根据 fin_timeout 不同时长,有可能计入 如果系统上orphan socket 过多,那么需要统计处于哪个状态的socket较多,再结合[145]来分析) +147、TCP的SYN报文可以携带数据吗? + (tips:虽然在发送SYN阶段,双方的序列号还没有协商好,但是实现中可以携带数据) + // http 1、什么是CNAME? From 70be49f0fe1fe0ec524c463c08a84a7d3e8a08d7 Mon Sep 17 00:00:00 2001 From: coderall Date: Sat, 13 Feb 2021 18:31:36 +0800 Subject: [PATCH 57/78] add disk related questions --- file_system.txt | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/file_system.txt b/file_system.txt index 0a25dd4..3165994 100644 --- a/file_system.txt +++ b/file_system.txt @@ -44,7 +44,8 @@ 22、free 命令的显示中 buffer 和 cache 分别代表什么? (tips:现在buffer 和 cache统一都由page cache实现,只不过buffer是比较特殊的直接操作设备文件产生的空间占用, - 例如,直接读取 /dev/ 设备) + 例如,直接读取 /dev/ 设备 + cache 包括了page cache 和 slab中的可回收部分,其中cache的计算中已经减去了buffer 和 swap用到的page) 23、文件的覆盖写和追加写有什么区别? @@ -409,7 +410,9 @@ 再写入,这一步也会有开销,已3+1 模式为例,会有4倍的数据流量) 147、EC编码和RAID技术的比较? - (tips:RAID技术不适用于大容量存储中,RAID5 5个9 RAID6 8个9的数据安全性) + (tips:RAID技术不适用于大容量存储中,RAID5 5个9 RAID6 8个9的数据安全性 + RAID5 采用 n+1 的编码模式,即允许坏一块盘,且校验码打散在各个盘上 + RAID6 采用 n+2 的编码模式,允许坏两块盘,校验码打散在各个盘上) 148、磁盘静默错误怎么解决? (tips:使用 DIX/DIF在每一个扇区后追加校验字段来解决, @@ -726,6 +729,21 @@ 这也就带来一个问题,上层怎么快速的发现磁盘的问题,这就要用一些写入测试来辅助, 例如现在在用的 write_test 方法等 +209、磁盘的低级格式化主要是将盘片划分出磁道,柱面,扇区,且通常由磁盘厂商完成。 + 磁盘的高级格式化主要是文件系统相关的元数据的从新划分,例如,重新初始化空闲块位图, + inode位图等。 + (tips:磁盘寻址使用CHS地址,即C 柱面,Head 磁头,S 扇区 + CHS寻址方式受限于地址存储位长,当前的大容量磁盘采用LBA方式寻址, + CHS只留给磁盘驱动来处理) + +210、磁盘读写操作的最小单位是扇区,写入时如果不按照扇区大小(512字节)对齐,那么下次的写入只能 + 另外找空闲扇区来写。 + 普通的read/write是buffer写的,数据先写入page cache,由于内存的随机读写特性,数据可以以任意单位写入,随后由 + 内核线程写回磁盘。 + 另外,由于direct模式的写入对buffer地址,file offset,写入大小都要求以512对齐,所以,就避免了扇区浪费。 + (之前还想着写个程序,每次以direct模式追加写入1字节,这样就可以快速的占满磁盘,但是有了上述的限制, + 就没法实现了) + // block layer 1、io_submit调用理论上是非阻塞的,但是如果执行sync写入,或者有meta data I/O,或者,设备中能提供的 request数量有限,如果超过这个限制,也只能阻塞进入等待。 From 2fec2ed4df3b2b7c623948b0c7d632a98ad7726a Mon Sep 17 00:00:00 2001 From: coderall Date: Thu, 25 Feb 2021 18:57:57 +0800 Subject: [PATCH 58/78] add redis vm implementation related --- nosql.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/nosql.txt b/nosql.txt index 6e7c24f..83aaccf 100644 --- a/nosql.txt +++ b/nosql.txt @@ -30,6 +30,17 @@ (2)本地缓存,减少访问redis量 (3)热点key添加其他信息,如timestamp,这样人为区分开访问节点 +4、Redis基于LRU实现了一套VM管理机制,原因有如下几个点 + (tips: + 1、Redis管理的数据结构比较复杂,不适合直接用操作系统的page管理 + 2、操作系统的page是4KB大小固定的,但是像Redis中的list结构,有可能包含了很多的node, + 需要由Redis自己来将整个结构进行写回 + 3、Redis如果依赖操作系统的page,由于本身实现是单线程的,前一个请求访问到了在磁盘中的key, + 那么会阻塞后续的所有client访问 + 为了绕过page cache,很多数据库的实现都是自己管理VM,自己实现flush,然后以 O_DIRECT 的模式 + 将数据写回,避免数据的二次拷贝 + ) + // Memcached From d99f2046c985e8d84d3520bdf252a4e08970d76f Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 3 Mar 2021 22:25:18 +0800 Subject: [PATCH 59/78] add bloom filter related questions --- nosql.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/nosql.txt b/nosql.txt index 83aaccf..23bd1f4 100644 --- a/nosql.txt +++ b/nosql.txt @@ -41,6 +41,12 @@ 将数据写回,避免数据的二次拷贝 ) +// LevelDB +1、BloomFilter有什么缺点? + (tips: + 1、如果判断一个key不在,那就真的不在,但是如果判断在,那有可能不在 + 2、BloomFilter结构不支持delete操作,不过这个在LevelDB中还好,因为levelDB在SSTable中 + 使用BloomFilter,且SSTable结构是不变的,避开了这一问题,有其他结构提出了改进的操作) // Memcached From abf7237923c22e843cd5a6024e25121c57f8d34c Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 3 Mar 2021 22:26:20 +0800 Subject: [PATCH 60/78] add REQ_FLUSH and data safety related questions --- file_system.txt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/file_system.txt b/file_system.txt index 3165994..77ad4f5 100644 --- a/file_system.txt +++ b/file_system.txt @@ -217,7 +217,9 @@ 87、Ext4 extents的作用是? (tips:将同一文件的数据临近存放,减少之前间接块索引导致的多次读取元数据, - 同时增加预读效果,加快truncate操作) + 同时增加预读效果,加快truncate操作 + 单个extent最多包括32768个block,即128M的空间,如果当前文件系统开启了extent属性, + 那么在写入时就会按照extent的规则来写,同时 ioctl也支持从块指针的方式转为extent) 88、Ext4 multiblock allocation概念? (tips:之前的ext文件系统分配文件block时是一次分配一个block,性能较低) @@ -329,6 +331,7 @@ 而不是磁盘上,这样解决了Ext2上的预分配导致的Crash恢复时数据的不一致问题 124、Ext4 Extent 树高最高为 5 + (tips:实际上不大于2) 125、fsync在保证当前文件本身的数据落盘的同时,对于包含这个文件的文件夹的更新则没有保证 @@ -748,6 +751,15 @@ 1、io_submit调用理论上是非阻塞的,但是如果执行sync写入,或者有meta data I/O,或者,设备中能提供的 request数量有限,如果超过这个限制,也只能阻塞进入等待。 +2、怎么确保文件系统下发的写入操作返回时,数据真正落盘呢? + (tips:使用SCSI中的FUA命令,可以将磁盘的缓存模式调整为write through,这样当磁盘驱动器向操作系统返回写入成功信号时, + 数据就真正落盘了) + +3、Linux系统中,文件系统下发的bio可以带 REQ_PREFLUSH 和 REQ_FUA两个flag,前者保证在处理bio之前将磁盘cache写回, + 后者的作用如2所述。block layer不用关注这两个flag的底层实现逻辑,磁盘驱动需要实现这两个功能, + 如果磁盘没有non-volatile buffer,REQ_PREFLUSH不作任何操作。 + 如果物理磁盘不支持FUA,那么可以将FUA操作模拟为一个写入+FLUSH + // trace 1、通过iostat看到某个磁盘util高,怎么确认是哪个进程在进行I/O? (tips:首先通过df查看磁盘挂载在哪个目录,然后通过lsof输出对应目录下所有打开的文件,参考文件打开模式, From 4bdb1102e2ff892311beaa2d313f430e5495df85 Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 3 Mar 2021 22:26:55 +0800 Subject: [PATCH 61/78] add NUMA related questions --- kernel.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/kernel.txt b/kernel.txt index 0661672..97a2a12 100644 --- a/kernel.txt +++ b/kernel.txt @@ -706,7 +706,14 @@ 119、SIGSEGV信号如果是由进程自己触发,则信号信息中的pid为0 120、NUMA与SMP相比,个人认为最大的区别在于拓扑结构上的差异,这些差异带来了 - 跨node内存访问延迟(QPI访问),cache一致性等等的问题,其他一些问题上面也有讨论。 + 跨node内存访问延迟(QPI访问),cache一致性等等的问题。 + (tips:从UMA到NUMA,有三个问题需要解决 + 1、内存的非一致性访问组织 + 2、CPU点对点互连(在SMP架构下,CPU之前不需要互连,大家访问的是公共的内存池,现在 + 有的架构CPU内部各个core以 full mesh结构互连,以避免数据访问时的多跳问题) + 3、可扩展的cache一致性协议,NUMA架构下,每个socket下CPU内部的core + 都有自己独有的L3级cache,L3级cache也是oncore的) + 121、vfork新建进程时,不拷贝父进程的页表,所以创建进程的速度比较快,且父进程阻塞,直到 子进程调用了execve或者 _exit(),注意在vfork创建的子进程退出时,不能使用exit,而要 From 444a8a49f332502ef13896c0ad510ae218d61520 Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 3 Mar 2021 22:27:39 +0800 Subject: [PATCH 62/78] add 499 explanation --- nginx.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nginx.txt b/nginx.txt index 1ee679e..44e24da 100644 --- a/nginx.txt +++ b/nginx.txt @@ -14,3 +14,5 @@ 4、Nginx自身没有带日志切分功能,但是可以通过管道的方式将日志输出到cronolog中,日志文件定义中有 格式化的字符串,cronolog自动切换文件进行写入,也就完成了日志切割。 +5、nginx自己定义了一个http 499的错误码,表示在服务端处理超时,未及时返回http resp的情况下, + 客户端主动断开了链接。http标准中并没有定义这个http status From a40b89b0660a83a1f40292cfc47467301b5b4bda Mon Sep 17 00:00:00 2001 From: coderall Date: Sat, 7 Aug 2021 11:30:45 +0800 Subject: [PATCH 63/78] add numa related --- kernel.txt | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/kernel.txt b/kernel.txt index 97a2a12..080acc2 100644 --- a/kernel.txt +++ b/kernel.txt @@ -327,7 +327,8 @@ 位置靠后的CPU访存延迟增高) 13、使用哪个命令来查看NUMA信息? - (tips:numactl命令) + (tips:numactl命令 + numactl --hardware or numactl --show) 14、/proc/interrupts 文件内容解释? @@ -665,7 +666,10 @@ (tips:因为如果应用没有针对NUMA进行优化,那么有可能父进程在Node0运行, 启动时预分配了运行时需要的的总内存,如果后续spawn的子进程迁移到Node1,这时, 访问原来的内存就需要经过QPI总线,走point-to-point link,导致数据访问延时增加, - QPI总线的数据传输速度低于CPU访问内存的) + QPI总线的数据传输速度低于CPU访问内存的 + 所以在使用NUMA时,对进程绑核是必须操作,减少跨node访存;当某一个numa node内存紧张时 + 早期的实现会回收本node的page cache,造成上层应用延迟升高;当时2014年之后的内核代码已经修复 + 了这个问题,修改为尝试申请其他node的内存) 111、OOM计算的是物理内存的使用,malloc返回非NULL,只是表示分配了虚拟内存, 后续访问时,有可能触发缺页中断,进而引发OOM,一个可取的方法就是malloc之后, @@ -781,6 +785,12 @@ 即通过sector找到对应block,在匹配到操作的文件 (3)怎么解决代码段不能load的问题(可以通过mlock来避免对应页面被换出) +131 NUMA中node是一种物理划分,表示哪些CPU core是一组,可以用numactl --hardware 看到对应的local内存的大小 + 而CPU Sockets表示的是插槽的数量,所以,CPU Sockets和NUMA node数量没有关系,两者可能相等,也可能不相等 + +132 sched_setaffinity在设置时, dest_cpu = cpumask_first_and(cpu_active_mask, new_mask),并尝试将对应的 + thread迁移到目标cpu的runqueue中. + // 其他 1、内核和用户空间通信都有哪些方法? From 1e09e14db51ba8bb018dc116222ad16a20c93fe1 Mon Sep 17 00:00:00 2001 From: coderall Date: Sat, 7 Aug 2021 11:32:08 +0800 Subject: [PATCH 64/78] add SO_REUSEADDR & SO_REUSEPORT related and other tcp questions --- network.txt | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/network.txt b/network.txt index 0f6d761..dbdf93e 100644 --- a/network.txt +++ b/network.txt @@ -137,8 +137,17 @@ (tips:TCP_NODELAY用来关闭nagle算法) 35、SO_REUSEADDR 标志有什么作用? + (tips:作用有如下几个 + 1、默认情况下,如果有两个socket,socketA=ipA:portA,socketB=ipB:portB, + 只要ipA 和 ipB不冲突,就可以bind成功, + 如果有一个socket绑定了 0.0.0.0:21,如果不打开SO_REUSEADDR,那么其他socket + 就不能再bind 192.168.0.1:21,同样绑定其他端口也不行,因为地址冲突了。 + 总结而言就是 SO_REUSEADDR可以让0.0.0.0地址和其他地址共同使用) + 2、还有一点就是当socket处于 TIME_WAIT状态时,如果不指定SO_REUSEADDR,那么 + 后续如果有socket想绑定相同的addr:port,就会失败,这里不考虑SO_REUSEPORT) 36、SO_REUSEPORT 标志有什么作用? + (tips:SO_REUSEPORT则条件更为宽松,ip+port都相等也可以,由内核来分配对应的链接sock) 37、SO_REUSEADDR 和 SO_REUSEPORT有什么区别?使用中分别要注意什么? @@ -270,7 +279,8 @@ 89、TCP_DEFER_ACCEPT 标志有什么作用? (tips:设置了这个option的listen socket 只有在连接上真正收到了数据时,listener才会被唤醒, - 这样会减少listener的wake up次数,提高效率) + 这样会减少listener的wake up次数,提高效率 + 客户端socket同样可以设置这个标志,这样会减少一次客户端向服务器发送的ack) 90、sysctl -a | grep "tcp" | grep "re" 中各种重试次数与时间的设置都有哪些作用? @@ -372,8 +382,10 @@ 服务端发送SYN包,服务端回复ACK里面带有seq数据,这样就可以拿到正确的seqid,然后手动构造RST包给服务端) 113、TCP头中的PSH 标志什么意思? - (tips:当接收端收到带有PSH标志的包时,不会继续等待数据,而是直接唤醒上层的socket接收数据, - 所以,PSH一般用在 发送端 已经发送完数据,在最后一个包上带上PSH标志 + (tips: + 接收端收到带有PSH标志的包时,不会继续等待数据,而是直接唤醒上层的socket接收数据 + 发送端看到有PSH标志的包时,不会继续等待后续数据,而是立即将对应数据包发送出去, + PSH一般用在 发送端 已经发送完数据,在最后一个包上带上PSH标志 应用层无法控制TCP头中的PSH) 114、TCP头中的URG 标志什么意思? From 67df94e807d9ed4b746c4f285e72e73a698f6b28 Mon Sep 17 00:00:00 2001 From: coderall Date: Sat, 7 Aug 2021 11:32:35 +0800 Subject: [PATCH 65/78] add MAID related --- storage.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/storage.txt b/storage.txt index 51df98a..a703483 100644 --- a/storage.txt +++ b/storage.txt @@ -10,3 +10,6 @@ 2、SATA3.0 的最大传输速度为6G,但是SAS3.0支持12G,如果直接在SAS口上链接SATA盘,会有带宽浪费的问题 所以在SCSI协议层支持多路复用,最大化带宽利用 + +3、当前的深度归档实现的思想在20年前就有了,即MAID(Massive Arrays of idle disk),实现的难点在于 + 调度 From e3709d34ec54d74d3b0a42807c9e2f4284036775 Mon Sep 17 00:00:00 2001 From: coderall Date: Sat, 7 Aug 2021 11:33:05 +0800 Subject: [PATCH 66/78] add openssl & rpm related tools --- tools.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools.txt b/tools.txt index 97ff2c4..a18aea9 100644 --- a/tools.txt +++ b/tools.txt @@ -8,3 +8,13 @@ this doc record some useful tools to trace problem or optimize performance #No.3 bloom filter caculator 网上有计算 bloom filter 占用空间的公式 + +#No.4 OpenSSL 开源tls库 +检查证书中的域名: +openssl x509 -in certificate.crt -text -noout + +生成自签名证书: +openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout privateKey.key -out certificate.crt + +#No.5 rpm 解包 +rpm2cpio ./xxx.x86_64.rpm | cpio -idmv From 26349c23aea7712b2daff91407af6b54df28bb01 Mon Sep 17 00:00:00 2001 From: coderall Date: Mon, 11 Oct 2021 16:23:54 +0800 Subject: [PATCH 67/78] add gcc related questions --- gcc_gdb.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/gcc_gdb.txt b/gcc_gdb.txt index ff247a2..c7d358a 100644 --- a/gcc_gdb.txt +++ b/gcc_gdb.txt @@ -45,3 +45,16 @@ 13、gcc -M test.c 选项可以看到编译时所有include的头文件 gcc -MM选项是过滤了系统头文件之后的输出 + +14、在用GDB跟踪某些binary时,step比较慢,可以在GDB的命令行中 set env LD_BIND_NOW=true来解决 + +15、在用GDB attach 进程时,可以使用 info sharedlibrary 命令来查看当前加载动态链接库的情况, + 同时也可以使用sharedlibrary 命令来手动加载某些库 + +16、GDB调试C++程序时,如果定位到this指针的位置,那么可以使用 x /10a 命令来查看虚表的内容 + 方便定位问题 + +17、gcc可以编译.cpp文件,但是会遇到 undefined reference 的报错,这是因为没有链接C++的 + stdc++ 库,只要在编译cpp文件时,加上 -lstdc++ 选项,则编译可以正常进行。 + 同时,编译分为如下几步 + cc1 / cc1plus (编译) --> as (汇编) --> collect2 () --> ld (链接) From fefa10026d287f10eb207238240f18eb629633c3 Mon Sep 17 00:00:00 2001 From: coderall Date: Mon, 11 Oct 2021 16:26:12 +0800 Subject: [PATCH 68/78] add c & cplusplus FAQ --- C and C++.txt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/C and C++.txt b/C and C++.txt index b03ed68..6510f1c 100644 --- a/C and C++.txt +++ b/C and C++.txt @@ -237,7 +237,16 @@ 28、unique_ptr不能进行拷贝操作,也就是不能直接进行传参和从函数中返回,取而代之的是调用move函数 -29、shared_ptr的引用计数更新是线程安全的,但是指针的更新不是,需要注意 +29、shared_ptr的引用计数更新是线程安全的,但是指针的更新不是,需要注意,对于*直接使用指针的形式 + 也不是线程安全的。 + +30、delete NULL是安全的,delete的实现中直接调用了 free(p),而析构函数的调用是编译器插入的; + 如果delete void*,编译器会给出warning;各个malloc的实现中,free(NULL) 都是直接返回,没有啥直接效果。 + +31、虚函数为啥不能inline? + 其实,如果是由object来调用虚函数,那么函数可以inline; + 但是如果通过指针或者引用来访问,那么就走运行时多态特性了,即拿到类对象指针,访问虚函数表, + 解引用对应function pointer,整个过程中必须有call指令调用 // debug From 4a5b10043c8116762c1003f1980d383daea625b2 Mon Sep 17 00:00:00 2001 From: coderall Date: Mon, 11 Oct 2021 16:26:57 +0800 Subject: [PATCH 69/78] add nuwa & mmap questions --- kernel.txt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/kernel.txt b/kernel.txt index 080acc2..6a448c4 100644 --- a/kernel.txt +++ b/kernel.txt @@ -785,12 +785,17 @@ 即通过sector找到对应block,在匹配到操作的文件 (3)怎么解决代码段不能load的问题(可以通过mlock来避免对应页面被换出) -131 NUMA中node是一种物理划分,表示哪些CPU core是一组,可以用numactl --hardware 看到对应的local内存的大小 +131、NUMA中node是一种物理划分,表示哪些CPU core是一组,可以用numactl --hardware 看到对应的local内存的大小 而CPU Sockets表示的是插槽的数量,所以,CPU Sockets和NUMA node数量没有关系,两者可能相等,也可能不相等 -132 sched_setaffinity在设置时, dest_cpu = cpumask_first_and(cpu_active_mask, new_mask),并尝试将对应的 +132、sched_setaffinity在设置时, dest_cpu = cpumask_first_and(cpu_active_mask, new_mask),并尝试将对应的 thread迁移到目标cpu的runqueue中. +132、在使用mmap加载磁盘文件时,如果出现越界访问(例如:超过文件长度的访问),或者访问时,其他程序对文件内容 + 进行了截断,那么会报SIGBUS的错误。 + 同时,如果对READ_ONLY的区域,进行写入,则会产生SIGSEGV错误;这与常见的段错误不同;应用层程序尝试写 + 内核区域的内存时,也会产生SIGSEGV + // 其他 1、内核和用户空间通信都有哪些方法? From ced7a679cd425b0ac1290b2ab7f0733581b40a02 Mon Sep 17 00:00:00 2001 From: coderall Date: Mon, 11 Oct 2021 16:27:24 +0800 Subject: [PATCH 70/78] add tcpdump related questions --- network.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/network.txt b/network.txt index dbdf93e..7b309c3 100644 --- a/network.txt +++ b/network.txt @@ -636,6 +636,7 @@ 10、netfilter都有哪些hook点? 11、tcpdump工作原理? + (tips:调用socket(AF_PACKET, SOCK_RAW, ETH_P_ALL) 创建一个RAW Socket来接收所有的包) 12、什么是bonding技术?常用的工作模式有哪些? (bond0 的配置选项可以参考 /etc/sysconfig/network-script/ifcfg-bond0 文件, From 825271c0e16f42d54806607e18401d4b042e8a88 Mon Sep 17 00:00:00 2001 From: coderall Date: Tue, 26 Oct 2021 14:57:19 +0800 Subject: [PATCH 71/78] add kill -0 --- kernel.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel.txt b/kernel.txt index 6a448c4..1dfee4d 100644 --- a/kernel.txt +++ b/kernel.txt @@ -291,6 +291,9 @@ 95、同样内核会为每个CPU启动一个高精度的timer来检测中断的执行是否被长时间阻塞,这个timer默认每4s触发一次来更新时间戳 +96、kill -0 $pid 可以用来检测给定的进程是否存在(不发送任何实际的signal),对于一些有pid文件的服务来讲, + 可以通过判断 kill -0 `cat /var/xxx.pid` 命令的返回值来确认对应的进程是否存在 + // 内存管理 mm 1、malloc的实现 From 51503ca4ecc39bbb8ab134f08a8226bf488d3e84 Mon Sep 17 00:00:00 2001 From: coderall Date: Tue, 8 Feb 2022 19:57:28 +0800 Subject: [PATCH 72/78] add daily questions --- cmd_line.txt | 8 ++++++++ distributed system.txt | 12 ++++++++++++ file_system.txt | 13 +++++++++++++ gcc_gdb.txt | 9 +++++++++ kernel.txt | 6 ++++++ network.txt | 21 +++++++++++++++++++-- storage.txt | 31 +++++++++++++++++++++++++++++++ 7 files changed, 98 insertions(+), 2 deletions(-) diff --git a/cmd_line.txt b/cmd_line.txt index 71bcd8c..187c6f8 100644 --- a/cmd_line.txt +++ b/cmd_line.txt @@ -23,3 +23,11 @@ 8、last reboot可以查看机器的重启信息 (tips:last命令读取的/var/log/wtmp文件,可以查看对应用户的登录信息,例如: last -n 10 user_name) + +9、groups命令可以查看当前登录的用户对应的用户组 + +10、python -m py_compile your_python_script.py可以完成python脚本的语法检测 + +11、命令前加 \ 可以跳过alias,运行original command + +12、pkill -9 -P 1,pkill -P参数可以根据父进程id来向目标进程发信号 diff --git a/distributed system.txt b/distributed system.txt index a64aedf..c53b039 100644 --- a/distributed system.txt +++ b/distributed system.txt @@ -12,8 +12,16 @@ AP则不保证数据的一致性,常见的如NoSQL数据库,DNS系统等 4、什么是2PC? + (tips:协调者发送canCommit,当执行者回复ack后,事务提交; + 问题在于,当第一步执行者回复ack后,执行者会blocking等待,如果这时协调者crash, + 那么整个系统将不可用) 5、什么是3PC? + (tips:3PC为了解决2PC的blocking问题,引入pre-commit阶段 + 1、在participant转为pre-commit状态前,coordinator crash,那么事务可以安全的abort + 2、在partitipant转为pre-commit状态后,coordinator crash,那么新的coordinator启动后, + 通过询问其他participant的状态,如果全部为pre-commit,那么事务可以安全提交;如果状态 + 不一致,那么需要abort transaction) 6、什么是leader 选举? @@ -60,3 +68,7 @@ 二是,新的master带来的单点问题;如果使用强同步模型,那么性能会降低;如果一个master对应多个slave,那么在master掉线后, 又有多个slave的选举问题。 raft等算法都是基于 Replicated State Machine 模型,在各个节点间同步log + +19、什么是脑裂? + (tips:即因为网络等其他原因,导致集群或者某个服务出现两个primary对外提供服务, + 常用的paxos等算法中,会通过选举+版本控制的方法来避免这一情况出现) diff --git a/file_system.txt b/file_system.txt index 77ad4f5..4566dbc 100644 --- a/file_system.txt +++ b/file_system.txt @@ -747,6 +747,19 @@ (之前还想着写个程序,每次以direct模式追加写入1字节,这样就可以快速的占满磁盘,但是有了上述的限制, 就没法实现了) +211、/etc/fstab 文件中记录了在机器启动时需要挂载的磁盘信息; + /etc/mtab 文件中记录了当前机器上已经挂载的磁盘信息 + +212、遇到 Disk quota exceed 报错时,先 df -hi 查看对应磁盘的inode使用情况; + 如果没有超;那么查看/etc/mtab文件查看对应挂载点的挂载属性中是否有 usrquota/grpquota, + 如果有,那么可以使用 edquota -u $USER 或 edquota -u $GROUP 来查看当前为用户/组设置的quota + 设置quota可以使用 setquota 命令。 + edquota命令查看不到社会的quota时,可以使用 repquota -g or repquota -u mount_point来确认 + 对应目录是否有设置quota + +213、getfattr -d -m '-' /some/file 命令可以获取文件的所有扩展属性,EXT系列文件支持这一属性。 + 大小限制可以 man 5 attr 查看 + // block layer 1、io_submit调用理论上是非阻塞的,但是如果执行sync写入,或者有meta data I/O,或者,设备中能提供的 request数量有限,如果超过这个限制,也只能阻塞进入等待。 diff --git a/gcc_gdb.txt b/gcc_gdb.txt index c7d358a..dfbc0d0 100644 --- a/gcc_gdb.txt +++ b/gcc_gdb.txt @@ -58,3 +58,12 @@ stdc++ 库,只要在编译cpp文件时,加上 -lstdc++ 选项,则编译可以正常进行。 同时,编译分为如下几步 cc1 / cc1plus (编译) --> as (汇编) --> collect2 () --> ld (链接) + +18、gcc工具编译链接时(具体是ld工具)查找符号的顺序是从左到右,且.a 或 .o 文件只会被处理一次; + 所以被依赖的库需要放在右边,而项目.o文件需要放在靠左边的位置; + 或者同一库文件,多写几次 -l; + 动态链接库就没有这个问题 + +19、使用 LD_DEBUG 环境变量可以查看可执行文件的链接库/符号查找细节。常用命令如下: + LD_DEBUG=symbols,files $COMMAND + LD_DEBUG环境变量本身支持的取值可以通过 LD_DEBUG=help cat 查看。 diff --git a/kernel.txt b/kernel.txt index 1dfee4d..6e590b4 100644 --- a/kernel.txt +++ b/kernel.txt @@ -294,6 +294,12 @@ 96、kill -0 $pid 可以用来检测给定的进程是否存在(不发送任何实际的signal),对于一些有pid文件的服务来讲, 可以通过判断 kill -0 `cat /var/xxx.pid` 命令的返回值来确认对应的进程是否存在 +97、lazy FPU context switch + (tips:Intel CPU 支持lazy FPU context switch的特性,在没有使用FPU的进程进行切换时, + 不用保存涉及浮点数运算的寄存器 + 当进程确实用到了浮点数运算时,会触发一个异常,然后下一次的context switch会保存浮点数寄存器 + 不过这个功能好像有安全风险) + // 内存管理 mm 1、malloc的实现 diff --git a/network.txt b/network.txt index 7b309c3..79f48c4 100644 --- a/network.txt +++ b/network.txt @@ -1,6 +1,20 @@ --- some popular network interview questions,mostly about TCP/IP --- --- TCP/IP 常见网络面试 笔试题 --- +// MAC +1、MAC 层的frame format中有一个CRC32字段,网卡会对源、目的地址、length和DATA计算CRC + 但是,IP/TCP/UDP header中的CRC只计算header本身的数据 + +2、netstat -s 的输出中有 InCsumErrors,这个计数来自于两个文件 /proc/net/netstat /proc/net/snmp, + 内核代码中对于 InCsumErrors 有 ip,tcp,udp的统计 + "InCsumErrors", IPSTATS_MIB_CSUMERRORS + "InCsumErrors", TCP_MIB_CSUMERRORS + "InCsumErrors", UDP_MIB_CSUMERRORS + +3、链路层的crc error可以cat /sys/class/net/eth0/statistics/rx_crc_errors 拿到 + 数据来自于 struct rtnl_link_stats64 + 日常可以使用 ip -s -s link show dev eth0 命令来快速查看 + // IP 1、路由器可以隔离广播域吗? 交换机可以隔离广播域吗? @@ -8,7 +22,7 @@ 2、什么是VLAN? (tips:虚拟局域网) - + 3、什么是VxLAN? (tips:扩展版的VLAN,具体作用后面再补充) @@ -517,7 +531,7 @@ 141、tcp incast是指多对一的数据流向拓扑,即多个源向一个目的写入数据,会导致目的端交换机buffer满, 出现丢包,反馈到源端就是出现数据重传。 解决方案一般是升级到更高buffer容量的交换机,另一方面尝试源和目的就近部署, - 减少网络跳数 + 减少网络跳数,还需要考虑数据打散 142、socket的REUSEPORT属性在服务端构造了一个多队列多服务模型,与之对应的是早期的fork版本构建了一个 单队列多服务模型。 @@ -607,6 +621,9 @@ http Header中同样有Keep-Alive字段,可以定义timeout 和 max 字段来控制当前链接的超时时间 和发送的request数量 +17、系统本地默认没有DNS cache缓存,即每次使用域名进行访问时,都要进行域名解析;但是libcurl库的 + 实现中有DNS cache,每个handler中默认保存60s + // 其他相关 1、iptables实现原理,使用了哪些算法? diff --git a/storage.txt b/storage.txt index a703483..8eacef1 100644 --- a/storage.txt +++ b/storage.txt @@ -13,3 +13,34 @@ 3、当前的深度归档实现的思想在20年前就有了,即MAID(Massive Arrays of idle disk),实现的难点在于 调度 + +4、怎么应对磁盘盘符漂移 + (tips:使用e2label程序为某个盘写入label,然后在挂载时,按照label挂载;如果要 + 自动挂载,则将这些信息写入/etc/fstab文件中; + 另,同样可以使用by UUID的方式来) + +5、ext2 ext3 ext4的super block中有字段 s_volume_name 用来保存设置的label,最长16个字节 + +6、当前的FaultTolerant部署模式为啥不采用Active-Active的模式? + +7、SSD的Read Disturb问题 + (tips:SSD由于其自身电器属性,在读取一个paeg时,会影响其他page上的数据,有可能造成bit 翻转等错误 + 解决方法是从硬件层面引入类似RAID方法来在错误出现时纠错 + 另一方变是引入统计信息,统计某一个page或者block的读次数,到达上限后,进行回收) + +8、https://ma.ttias.be/change-reserved-blocks-ext3-ext4-filesystem-linux 根据这里的描述,对于 + 当前越来越大的磁盘来讲,5%的预留空间太大了,可以考虑调小 + 可以继续看下动态调整的影响面 + +9、机械硬盘的磁头旋转角速度固定,单位时间内,可以读取的外道长度较长,读取速度更快; + 早期生产商将外道的磁密度降低来平衡这种差异。 + 但是上述做法的一个缺陷是浪费了磁盘track空间(外圈的sector数量和内圈保持一致)。 + ZBR(Zone Bit Recording)将单位角度内,具有相同数量sector的track组成一个zone,这样外圈的磁密度和内圈保持一致, + 这样做的效果就是数据存储在外圈访问速度高。 + +10、磁盘中可能有多个碟片,但是有一个碟片的一个面是不能保存数据的,生产商用这一面来存储一些硬件信息。 + 例如有两个碟片的磁盘,那么可以用作数据存储只有三个面。 + +11、从2010年起,IDEMA组织完成了 Advanced Format标准的制定,磁盘的physical sector size值扩大到4096 bytes,即4K + 用 hdparm -I /dev/sda 也能查看这一信息 + 使用了上述标准的磁盘,数据读写的最小单位为4K,即小于4K的,写入时,需要考虑Read-Modify-Write带来的放大 From 1bd1f4863611d33001c0ce22cd3fb553cf6fa5bf Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 29 Jun 2022 10:30:31 +0800 Subject: [PATCH 73/78] add tcp related --- network.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/network.txt b/network.txt index 79f48c4..9d8854b 100644 --- a/network.txt +++ b/network.txt @@ -574,6 +574,16 @@ 147、TCP的SYN报文可以携带数据吗? (tips:虽然在发送SYN阶段,双方的序列号还没有协商好,但是实现中可以携带数据) +148、TCP是全双工通信的吗? + (tips:虽然各种文档中都说TCP是全双工的,但是实现上,有如下几点限制了TCP的全双工通信 + 1、接收ACK以及触发后续的数据发送的处理逻辑跑在同一个CPU上 + 2、接收数据以及触发后续的ACK发送的逻辑跑在同一个CPU上 + 3、socket的读写都需要lock) + +149、TCP协议本身的实现就有队头拥塞问题,也可以认为TCP无法提供柔性的降级有损服务 + 而如果想让TCP实现"不可靠传输",则需要在协议层进行修改,但需要考虑整个链路中间节点 + 兼容性情况 + // http 1、什么是CNAME? From 38cd0a970f610ee39e04815e48f094df1b68fba8 Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 29 Jun 2022 10:30:51 +0800 Subject: [PATCH 74/78] add some low-level storage related --- storage.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/storage.txt b/storage.txt index 8eacef1..945ff82 100644 --- a/storage.txt +++ b/storage.txt @@ -44,3 +44,21 @@ 11、从2010年起,IDEMA组织完成了 Advanced Format标准的制定,磁盘的physical sector size值扩大到4096 bytes,即4K 用 hdparm -I /dev/sda 也能查看这一信息 使用了上述标准的磁盘,数据读写的最小单位为4K,即小于4K的,写入时,需要考虑Read-Modify-Write带来的放大 + fdisk -l /dev/sda 可以看到一个logical/phsical sector size 的输出,这些内容实际上也是读取的磁盘上的数据 + 在scsi驱动代码中可以看到 blk_queue_logical_block_size -> read_capacity_16 进而发送SAI_READ_CAPACITY_16的 + scsi命令给磁盘,获取 logical_block_size 和 physical_block_size,这两个值怎么理解呢,logical表示磁盘当前可以 + 寻址的最小单位,而physical则表示真实的可以操作数据的最小单位,其他导出的信息还有minimum_io_size + +12、hdparm -I /dev/sda 的输出中 IORDY 表示一种硬件层面的流控策略,如果不使用,那么在 fast PIO模式下,可能会有 + 数据损坏。 + +13、可以通过命令 dd if=/dev/sda of=/root/mymbr bs=512 count=1 来获取磁盘中第一个sector的数据, + 里面保存有MBR信息,使用 file /root/mymbr 命令可以查看 + +14、MBR 格式的partition table占用64字节,每个partition table entry 占用16字节,所以一个磁盘只能划分出4个parimary partition + 如果要划分多余4个分区,则需要将一个parimary partition格式化为extended partition,然后在这个扩展分区中再划分出 + 多个逻辑分区,且只有逻辑分区可以读写文件 + +15、因为MBR格式中,partition table entry中记录sector数量的是一个4bytes整数,即32bits,那么一个partition最大 + 512 * 2^32 = 512GB,如果有4个partition,那么磁盘最大容量为2TB。 + 所以在当前大容量磁盘广泛使用的今天,MBR格式不再使用,取而代之的是GPT(GUID Partition table) From 859c6f7af901158942ccd8f4b5026ec712ad93fe Mon Sep 17 00:00:00 2001 From: coderall Date: Mon, 7 Nov 2022 09:16:47 +0800 Subject: [PATCH 75/78] add some new notes --- file_system.txt | 5 ++++- gcc_gdb.txt | 2 ++ kernel.txt | 13 +++++++++++-- storage.txt | 17 +++++++++++++++++ tools.txt | 12 ++++++++++++ 5 files changed, 46 insertions(+), 3 deletions(-) diff --git a/file_system.txt b/file_system.txt index 4566dbc..040f904 100644 --- a/file_system.txt +++ b/file_system.txt @@ -348,7 +348,10 @@ 129、I/O polling? (tips:接上一条,如果外部存储设备的延迟够低,那么可以不用现在的基于中断的模式,而是polling,等待直到I/O完成, 减少中断次数;如果采用这种技术,那么应用层应该尽可能的少用Non-blocking,因为这又引入了异步模式,需要额外的操作来 - 确保命令已经执行完) + 确保命令已经执行完, + IO polling 有一个问题就是CPU消耗,试想如果一个IO需要10us完成,在submit_bio之后就立即polling,那么 + 刚开始的几us相当于在做无用功,所以内核引入了 hybrid poll机制,即,在任务提交后,sleep一段时间,然后再 + polling设备,以降低CPU消耗) 130、接上一条,有的SSD本身具有中断聚合功能,即尽可能少的中断CPU执行,批量提交I/O完成信息 diff --git a/gcc_gdb.txt b/gcc_gdb.txt index dfbc0d0..27cb476 100644 --- a/gcc_gdb.txt +++ b/gcc_gdb.txt @@ -67,3 +67,5 @@ 19、使用 LD_DEBUG 环境变量可以查看可执行文件的链接库/符号查找细节。常用命令如下: LD_DEBUG=symbols,files $COMMAND LD_DEBUG环境变量本身支持的取值可以通过 LD_DEBUG=help cat 查看。 + +20、可以通过 cat /proc/${pid}/maps | grep so 的方式来查看进程运行时都加载了哪些so diff --git a/kernel.txt b/kernel.txt index 6e590b4..984ec8c 100644 --- a/kernel.txt +++ b/kernel.txt @@ -300,6 +300,12 @@ 当进程确实用到了浮点数运算时,会触发一个异常,然后下一次的context switch会保存浮点数寄存器 不过这个功能好像有安全风险) +98、应用层使用spinlock需要注意什么? + (tips:应用层的spinlock在lock时,不关中断,这是与内核实现最大的不同;而这也导致用户态的 + 程序在拿到lock后,可能因为外部中断的原因而delay,这时另一个cpu上的程序就陷入了空转,浪费CPU资源, + 解决办法就是拿锁失败后sleep,而sleep又会有上下文切换的开销,与spinlock的高效不符,当前系统mutex基于 + CAS已实现的足够高效) + // 内存管理 mm 1、malloc的实现 @@ -664,8 +670,11 @@ 108、cgroup可以对用户态map的页面进行管理,也可以针对内核使用的内存进行管理, 常见的为tcp,当应用触发limit时,cgroup启动reclaim,如果失败, 则启动OOM(OOM可以配置为不启动,那么进程会hang或者sleep);memory.limit_in_bytes为 - hard limit,对应的有soft limit,超过后cgroup会尽力去回收空间。memsw表示 - memory+swap的空间使用量,在内存空间紧张时,用户态的匿名映射页会swap out。 + hard limit;memory.soft_limit_in_bytes在系统整体内存不紧张时不生效, + 但当系统整体内存紧张后,soft_limit_in_bytes会生效,超额的内存申请会失败sleep。 + memsw表示memory+swap的空间使用量,在内存空间紧张时,用户态的匿名映射页会swap out。 + 在调大memory.limit_in_bytes 之前,需要先把memory.memorysw.limit_in_bytes调大 + 且需要逐级调整,保证整个parent->child链路上的限制都符合预期。 109、内核使用的页面不会swap out到二级存储 (tips:这里还需要明确下具体是哪些页面,例如tcp使用的skb?shm使用的?等, diff --git a/storage.txt b/storage.txt index 945ff82..5d80506 100644 --- a/storage.txt +++ b/storage.txt @@ -48,6 +48,10 @@ 在scsi驱动代码中可以看到 blk_queue_logical_block_size -> read_capacity_16 进而发送SAI_READ_CAPACITY_16的 scsi命令给磁盘,获取 logical_block_size 和 physical_block_size,这两个值怎么理解呢,logical表示磁盘当前可以 寻址的最小单位,而physical则表示真实的可以操作数据的最小单位,其他导出的信息还有minimum_io_size + 业界之所以选择4KB sector主要有以下几点考虑 + (1)大容量磁盘背景下,sector越多元数据越多,管理越复杂 + (2)上层业务使用的文件size也变得越来越大 + (3)4KB的sector可以应用更加高效的数据检测与恢复算法 12、hdparm -I /dev/sda 的输出中 IORDY 表示一种硬件层面的流控策略,如果不使用,那么在 fast PIO模式下,可能会有 数据损坏。 @@ -62,3 +66,16 @@ 15、因为MBR格式中,partition table entry中记录sector数量的是一个4bytes整数,即32bits,那么一个partition最大 512 * 2^32 = 512GB,如果有4个partition,那么磁盘最大容量为2TB。 所以在当前大容量磁盘广泛使用的今天,MBR格式不再使用,取而代之的是GPT(GUID Partition table) + +16、关于块大小的选择,业界有个1%的阈值,即块寻址的时间占整个写入时间的1%;如果块切分的比较小,那么对应的meta数据多, + 查询空闲块的时间消耗大,如果块很大,则又有内碎片问题 + 当前磁盘的寻址时间普遍在 10ms左右,那么以100MB的速度写入的话,可能的最优块大小即为100M,再考虑2的次方对齐,即 + 128MB + +17、hot spare disk(热备盘)在RAID组中个别盘不可服务时,可以快速替换出问题的盘,保证业务连续性 + +18、PMR 和 CMR含义相同,都表示传统的垂直记录磁盘,特点是磁道与磁道独自;但是磁盘写入时需要的磁场强度高于读取,所以 + 一般情况下写磁头的宽度要大于读磁头,而SMR就刚好利用了这一特点,将相隔的两个磁道进行物理上的重叠, + 这样在相同磁盘尺寸的情况下,可以存储更多的数据 + +19、在数据中心成本计算中,设备(包括存储设置)占用的机架空间也需要考虑 diff --git a/tools.txt b/tools.txt index a18aea9..5cd32f8 100644 --- a/tools.txt +++ b/tools.txt @@ -18,3 +18,15 @@ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout privateKey.k #No.5 rpm 解包 rpm2cpio ./xxx.x86_64.rpm | cpio -idmv + +#No.6 tcpdump +抓特定来源的HTTP包 tcpdump -A -s 0 'src example.com and tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' +抓所有HTTP包 tcpdump -A -s 0 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' + +#No.7 ssh +<1>如果使用ssh登录服务器出现长时间的delay,可以查看/etc/ssh/sshd_config文件中UseDNS是否打开 +如果打开,可以考虑关闭 + +#No.8 +在安装了python的机器上,可以使用如下命令行来检查某个json文件格式 +python -m json.tool your_json_file From b0548934f21465b71ab319dc9c2b9ee3749e64f4 Mon Sep 17 00:00:00 2001 From: coderall Date: Fri, 25 Nov 2022 10:53:39 +0800 Subject: [PATCH 76/78] add new question and notes --- file_system.txt | 14 +++++++++++++- kernel.txt | 26 +++++++++++++++++++++++++- storage.txt | 17 +++++++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/file_system.txt b/file_system.txt index 040f904..694cbe4 100644 --- a/file_system.txt +++ b/file_system.txt @@ -233,7 +233,19 @@ 91、SSD 中 wear leveling 作用是? (tips:SSD中每一个cell都有固定的寿命,如果频繁操作某一些cell,会加快这些cell的失效, - wear leveling 的作用就是尽可能的将读写操作分布于整个SSD中,而不是集中于某一些cell) + wear leveling 的作用就是尽可能的将读写操作分布于整个SSD中,而不是集中于某一些cell + 算法实现上有两种 + (1)动态WL + 在一个空白池子中选择待写入的块;但是有一个问题是,空白块往往是PE比较高的块, + 在某种程度上会加剧磨损不均衡 + (2)静态WL + 动态的记录某一个block的PE值,尽可能区分冷热数据,然后进行选择性写入 + 算法实现上的一些问题: + (1)记录的PE值需要动态的去收集,本身就有开销 + (2)底层去分析上层的IO pattern本身就有难度 + (3)注意,WL也可能占用硬件带宽 + 在某些实现中,可能倾向于反磨损均衡(某些固态盘阵列),预期就是这些盘一块块的坏掉替换 + 而不是在某个时刻批量的不可用) 92、SSD中,怎么回收处于stale状态的page? (tips:TODO) diff --git a/kernel.txt b/kernel.txt index 984ec8c..1316b39 100644 --- a/kernel.txt +++ b/kernel.txt @@ -814,6 +814,20 @@ 同时,如果对READ_ONLY的区域,进行写入,则会产生SIGSEGV错误;这与常见的段错误不同;应用层程序尝试写 内核区域的内存时,也会产生SIGSEGV +133、RSS 和 PSS 和 USS + (RSS可以直观的理解为物理内存使用量,PSS在大多数场景和RSS的含义一样,但是在共享库场景,这两个 + 数值不一样,例如一个共享库20K,被20个进程共享,那么PSS的显示就是 1K + USS Unique Set Size则表示进程独享的内存大小) + +134、通过/proc/${pid}/cgroup 可以查看对应进程归属的cgroup组,在对应的cgroup目录下可以查看memory.stat文件 + 确认各项数据分别使用了多少;cgroup限制的内存包括了两部分,RSS和Cache; + 而操作系统的Cache包括了(page cache 、dev buffers、slab,具体数值可以通过/proc/meminfo查看); + 但是需要注意cgroup统计时并不统计slab的使用量 + +135、cgroup内部的回收逻辑在4.19内核之前都是直接回收;但是高版本内核使用了异步回收功能 + 如果回收后,仍然不能满足要求,那么就会触发OOM逻辑 + (在对应进程的memory cgroup目录下查看是否有 wmark* 文件来确认是否支持异步回收功能) + // 其他 1、内核和用户空间通信都有哪些方法? @@ -864,9 +878,19 @@ (tips:使用type命令查看) 5、怎样让系统生成core 文件? - (tips:ulimit -c unlimited) + (tips:ulimit -c unlimited,同时还要关注/proc/sys/kernel/core_pattern是否为空) 6、怎样定制core文件命名规则? (tips:/proc/sys/kernel/core_pattern) 7、Ubuntu系统不再使用/var/log/messages来记录系统事件,现在使用/var/log/syslog来替代 + +8、在core文件中一般不会记录memory-mapped I/O pages,有时coredump file size会比VIRT值还大 + ,有可能是内存中的数据swap到了磁盘 + +9、core file在生成时,具体dump哪些内容受到 /proc/${pid}/coredump_filter 影响, + 这个文件的内容是 16 进制的,具体每一bit的涵义参考man 5 core + +10、/proc/${pid}/task/${thread_id}/stack 可以看到一个进程下的各个线程的内核栈 + +11、/proc/${pid}/smaps 可以看到进程使用的内存区域的详细信息,排查问题时有用 diff --git a/storage.txt b/storage.txt index 5d80506..d43e868 100644 --- a/storage.txt +++ b/storage.txt @@ -79,3 +79,20 @@ 这样在相同磁盘尺寸的情况下,可以存储更多的数据 19、在数据中心成本计算中,设备(包括存储设置)占用的机架空间也需要考虑 + +20、在文章《Flash Reliability in Production: The Expected and the Unexpected》中,作者提出了如下几个观点 + (1)SLC的可靠性并不比MLC高 + (2)RBER比UBER能更好的预测错误 + (3)RBER和UE(uncorrectable errors)的数量会随着PE的增长而增长 + RBER(Raw Bit Error Rate) + UBER(Uncorrectable Bit Error Rate) + +21、影响SSD可靠性的因素有如下几个 + (1)耐久性,随着SSD PE(program/erase)次数的增加,整个盘的持久性会降低 + (2)Data Retention,即数据保持能力,如果发生电荷泄漏,那么就会导致Read Error + (3)Data disturb,目标cell读取多次后,再次读取时,需要对临近的cell同步施加一个电压, + 但这会造成电荷泄漏,导致Read Fail + +22、在使用 smartctl 查询不到对应nvme设备的 smart-log 后,可以尝试使用 sudo nvme smart-log /dev/nvme 查看 + +23、当前3D TLC是企业级固态存储的主要介质选择 From e2f638b8a90fe63f8feba346f8e76c4b67dd2e48 Mon Sep 17 00:00:00 2001 From: coderall Date: Wed, 8 Feb 2023 19:26:58 +0800 Subject: [PATCH 77/78] add daily updates --- file_system.txt | 9 ++++++++- gcc_gdb.txt | 7 +++++++ kernel.txt | 15 ++++++++------- network.txt | 6 +++++- tools.txt | 17 +++++++++++++++++ 5 files changed, 45 insertions(+), 9 deletions(-) diff --git a/file_system.txt b/file_system.txt index 694cbe4..bb131e4 100644 --- a/file_system.txt +++ b/file_system.txt @@ -769,12 +769,19 @@ 如果没有超;那么查看/etc/mtab文件查看对应挂载点的挂载属性中是否有 usrquota/grpquota, 如果有,那么可以使用 edquota -u $USER 或 edquota -u $GROUP 来查看当前为用户/组设置的quota 设置quota可以使用 setquota 命令。 - edquota命令查看不到社会的quota时,可以使用 repquota -g or repquota -u mount_point来确认 + edquota命令查看不到设置的quota时,可以使用 repquota -g or repquota -u mount_point来确认 对应目录是否有设置quota 213、getfattr -d -m '-' /some/file 命令可以获取文件的所有扩展属性,EXT系列文件支持这一属性。 大小限制可以 man 5 attr 查看 +214、什么是 last write win? + (tips:last write win是一种在并发写入场景下的数据版本决策策略,服务端以时间序,选择最后一写入的 + 数据来作为最新版本 + 为什么不是客户端看到的顺序,因为在分布式系统下,很难做到客户端和服务端时钟的一致性(例如,客户端网络卡顿), + 要做到,可能得启用更重的分布式一致性协议,但这又会导致整体QPS低。 + 以分布式对象存储为例,就选择应用lww 原则) + // block layer 1、io_submit调用理论上是非阻塞的,但是如果执行sync写入,或者有meta data I/O,或者,设备中能提供的 request数量有限,如果超过这个限制,也只能阻塞进入等待。 diff --git a/gcc_gdb.txt b/gcc_gdb.txt index 27cb476..94e252d 100644 --- a/gcc_gdb.txt +++ b/gcc_gdb.txt @@ -69,3 +69,10 @@ LD_DEBUG环境变量本身支持的取值可以通过 LD_DEBUG=help cat 查看。 20、可以通过 cat /proc/${pid}/maps | grep so 的方式来查看进程运行时都加载了哪些so + +21、可以通过如下命令获取进程中各个线程栈 + gdb -c -ex "thread apply all bt" -ex "quit" > output.log + 如果运行的进程是个nostripped版本,也可以尝试使用pstack来抓栈 + +22、jump *0x1234 可以做到调到地址为 0x1234地址的指令处; + 这个指令会忽略中间跳过的代码 diff --git a/kernel.txt b/kernel.txt index 1316b39..e7ccefa 100644 --- a/kernel.txt +++ b/kernel.txt @@ -750,7 +750,7 @@ 123、内核会针对每一个page统计MCE(Machine Check Exception),如果超过阈值,那么会进行 soft_offline_page,即将出错的页面内容拷贝到其他物理页面,然后将出错的页面下线, 这一操作对应用透明。 - MCE的相关配置文件位于 /etc/mcelog.conf + MCE的log配置文件位于 /etc/mcelog/mcelog.conf 124、x64程序中,cpu的fs寄存器用于存储stack canary @@ -826,7 +826,13 @@ 135、cgroup内部的回收逻辑在4.19内核之前都是直接回收;但是高版本内核使用了异步回收功能 如果回收后,仍然不能满足要求,那么就会触发OOM逻辑 - (在对应进程的memory cgroup目录下查看是否有 wmark* 文件来确认是否支持异步回收功能) + (在对应进程的memory cgroup目录下查看是否有 wmark* 文件来确认是否支持异步回收功能 + 可以搜搜 memcg异步回收相关文档) + +136、在/var/log/mcelog中可以观察到最近的MCE事件 + +137、'Corrected patrol scrub error' + (tips:Demand scrubbing is the ability to write corrected data back to the memory once a correctable error is detected on a read transaction. Patrol scrubbing proactively searches the system memory, repairing correctable errors. It prevents accumulation of single-bit errors) // 其他 @@ -869,11 +875,6 @@ // shell 1、怎么样使alias永久生效? -2、source 命令有什么作用? - -3、top 命令中CPU使用率高于100,是什么原因? - (tips:机器有多个core,显示的是各个CPU利用率之和) - 4、怎样确定一个shell 命令是builtin的? (tips:使用type命令查看) diff --git a/network.txt b/network.txt index 9d8854b..5beb391 100644 --- a/network.txt +++ b/network.txt @@ -670,7 +670,11 @@ 参数中 mode=4 表示采用 802.3ad标准来组成聚合链路来发送和接收数据包,这个需要 上游交换机支持;miimon 参数表示 mii 监控的时间间隔,用来监听底层硬件是否正常; xmit_hash_policy表示采用的hash规则,常用的有 layer3+4 表示利用ip层的源&目的地址和 - TCP层的源&目的端口) + TCP层的源&目的端口 + mode=0 是rr策略,有容灾能力 + mode=1 是active-backup策略,主备模式,备网卡对外不可见,有容灾能力 + mode=2 是hash策略,具体由xmit_hash_policy决定 + mode=3 是广播模式,每一个包都发给所有网卡,有容灾能力) 13、网络设备中 什么叫 “MAN Core”? diff --git a/tools.txt b/tools.txt index 5cd32f8..91f8082 100644 --- a/tools.txt +++ b/tools.txt @@ -16,8 +16,18 @@ openssl x509 -in certificate.crt -text -noout 生成自签名证书: openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout privateKey.key -out certificate.crt +校验私钥文件正确性 +openssl rsa -check -noout -in key.private + +校验证书文件中的公钥和私钥是否匹配(适用于自签场景) +ssh-keygen -f oss_test.pem -y > key.pub 注意可能需要输入passphrase +openssl x509 -modulus -noout -in key.pub 注意输出 +openssl rsa -modulus -noout -in key.private 查看私钥的module(要和上一条命令输出一致) + #No.5 rpm 解包 rpm2cpio ./xxx.x86_64.rpm | cpio -idmv +rpm -ql [package_name] | head -n 100 可以查看对应包按照目录 +rpm -e [package_name] 删除已安装的包 #No.6 tcpdump 抓特定来源的HTTP包 tcpdump -A -s 0 'src example.com and tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' @@ -30,3 +40,10 @@ rpm2cpio ./xxx.x86_64.rpm | cpio -idmv #No.8 在安装了python的机器上,可以使用如下命令行来检查某个json文件格式 python -m json.tool your_json_file + +#No.9 curl +curl --local-port 12345 可以指定发出去的数据包的源端口,如果是TCP协议,此时会调用bind来完成地址绑定 + + +#No.10 yum +yum whatprovides */c++config.h -b current 可以查询哪个包提供了对应头文件,便于确定需要安装的包 From 57b22035474b135fd9d6741dd41155314e1e5bc4 Mon Sep 17 00:00:00 2001 From: coderall Date: Thu, 10 Aug 2023 22:50:29 +0800 Subject: [PATCH 78/78] 2023-08-10 notes commit --- file_system.txt | 5 +++++ gcc_gdb.txt | 6 ++++++ network.txt | 3 +++ tools.txt | 11 +++++++++++ 4 files changed, 25 insertions(+) diff --git a/file_system.txt b/file_system.txt index bb131e4..4039a9f 100644 --- a/file_system.txt +++ b/file_system.txt @@ -782,6 +782,11 @@ 要做到,可能得启用更重的分布式一致性协议,但这又会导致整体QPS低。 以分布式对象存储为例,就选择应用lww 原则) +215、看文章有人遇到访问/proc下文件慢,先用strace发现耗时长的调用,进而使用公司内部的分析工具确认 + 耗时调用栈。这里有个问题,外部如何确认调用栈(pstack? SystemTap?) + 最后问题怀疑点是 /procy 文件系统实现时有一把全局的mutex,怀疑大并发访问导致锁争用 + sysak 貌似开源了 + // block layer 1、io_submit调用理论上是非阻塞的,但是如果执行sync写入,或者有meta data I/O,或者,设备中能提供的 request数量有限,如果超过这个限制,也只能阻塞进入等待。 diff --git a/gcc_gdb.txt b/gcc_gdb.txt index 94e252d..38badca 100644 --- a/gcc_gdb.txt +++ b/gcc_gdb.txt @@ -76,3 +76,9 @@ 22、jump *0x1234 可以做到调到地址为 0x1234地址的指令处; 这个指令会忽略中间跳过的代码 + +23、在x86架构下进程core 原因为 illegal instruction时,不能忽略,可以gdb disass 看下当前执行到 + 哪条指令报的错,再然后可以去查对应cpu型号是否支持这个指令 + 这两天就遇到一些较老型号的CPU不支持vinsert128 这个指令导致UT core;vinsert128 是avx2指令集中的一个 + 可以 lscpu | grep -i avx2 看对应cpu是否支持 + 谨记,不可大意,还是可以尝试去定位下 diff --git a/network.txt b/network.txt index 5beb391..fea0676 100644 --- a/network.txt +++ b/network.txt @@ -634,6 +634,9 @@ 17、系统本地默认没有DNS cache缓存,即每次使用域名进行访问时,都要进行域名解析;但是libcurl库的 实现中有DNS cache,每个handler中默认保存60s +18、https SNI (Server Name Indacation)机制在TLS客户端握手信息中填入domain,这样在多站点主机中, + 服务端可以正确的下发预期的证书 + // 其他相关 1、iptables实现原理,使用了哪些算法? diff --git a/tools.txt b/tools.txt index 91f8082..524ebe7 100644 --- a/tools.txt +++ b/tools.txt @@ -47,3 +47,14 @@ curl --local-port 12345 可以指定发出去的数据包的源端口,如果 #No.10 yum yum whatprovides */c++config.h -b current 可以查询哪个包提供了对应头文件,便于确定需要安装的包 + +#No.11 make +make -n 只打印make要执行的命令,但不真正执行 + +#No.12 configure +开源软件中的configure脚本依赖 config.guess 和 config.sub;这两个文件需要及时更新,尤其是国产化平台 +需要对应的更新 + +#No.13 gtest +gtest测试框架会catch exception,导致core的堆栈和实际调用栈不匹配,可以在UT binary后加 --gtest_catch_exceptions=0 +参数来禁用exception catch来观察实际问题调用栈,方便定位问题