GIT ADD
- git add -A 提交所有变化
- git add -u 提交被修改(modified)和被删除(deleted)文件,不包括新文件(new)
- git add . 提交新文件(new)和被修改(modified)文件,不包括被删除(deleted)文件
golang GMP
- https://mp.weixin.qq.com/s/4gMdGH4ssgeYwQi34mEzhg
- https://studygolang.com/articles/28572
linux 不同用户环境变量
- /etc/profile文件是bash shell默认的主启动文件。只要你登录了Linux系统,bash就会执行/etc/profile启动文件的命令。
- $HOME下的启动文件都是用户专属的启动文件,定义该用户的环境变量。而/etc/profile则是系统的,所有用户的环境变量。
- shell会按照下列顺序,运行第一个找到的文件,余下被忽略:
- $HOME/.bash_profile
- $HOME/.bash_login
- $HOME/.profile
- .bashrc通过.bash_profile来调用。
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/.local/bin:$HOME/bin:/home/windows/go/bin
export LD_LIBRARY_PATH=/usr/local/lib
export PATH
- file-max 表示系统级别的能够打开的文件句柄的数量。是对整个系统的限制,并不是针对用户的。
- ulimit -n 控制进程级别能够打开的文件句柄的数量。提供对shell及其启动的进程的可用文件句柄的控制。这是进程级别的。
- lsof -p 29015 | wc -l 查询某个进程打开的文件数量
- lsof | wc -l 查询系统打开的文件数量
linux常用命令
-
netstat -ntulp | grep 3306 获取占用端口的进程信息 n=(don’t resolve names 禁用域名解析) t=(tcp) u=(udp) l=(listening) p=(display PID/Program name for sockets)
-
用ps -ef |grep xxxxx 得到该进程的pid
-
lsof -i:端口号 端口被哪个进程占用
-
输入ls -l ,结果中 exe链接对应的就是可执行文件的路径
-
ls -l /proc/18283
-
以下是/proc目录中进程18283的信息
-
/proc/18283 pid为N的进程信息
-
/proc/18283/cmdline 进程启动命令
-
/proc/18283/cwd 链接到进程当前工作目录
-
/proc/18283/environ 进程环境变量列表
-
/proc/18283/exe 链接到进程的执行命令文件
-
/proc/18283/fd 包含进程相关的所有的文件描述符
-
/proc/18283/maps 与进程相关的内存映射信息
-
/proc/18283/mem 指代进程持有的内存,不可读
-
/proc/18283/root 链接到进程的根目录
-
/proc/18283/stat 进程的状态
-
/proc/18283/statm 进程使用的内存的状态
-
/proc/18283/status 进程状态信息,比stat/statm更具可读性
-
cat /proc/cpuinfo| grep “physical id”| sort| uniq| wc -l 查看机器几个CPU
-
cat /proc/cpuinfo| grep “cpu cores”| uniq 查看每个物理CPU中core的个数(即核数)
-
cat /proc/cpuinfo| grep “processor”| wc -l 查看逻辑CPU的个数
-
ps -eo pid,args,psr | grep 29015 查看进程ID在哪个逻辑CPU上执行
linux加载动态库
ldconfig是一个动态链接库管理命令,其目的为了让动态链接库为系统所共享。
ldconfig的主要用途:
默认搜寻/lilb和/usr/lib,以及配置文件/etc/ld.so.conf内所列的目录下的库文件。
搜索出可共享的动态链接库,库文件的格式为:lib***.so.**,进而创建出动态装入程序(ld.so)所需的连接和缓存文件。
缓存文件默认为/etc/ld.so.cache,该文件保存已排好序的动态链接库名字列表。
ldconfig通常在系统启动时运行,而当用户安装了一个新的动态链接库时,就需要手工运行这个命令。
ldconfig需要注意的地方:
1、往/lib和/usr/lib里面加东西,是不用修改/etc/ld.so.conf文件的,但是添加完后需要调用下ldconfig,不然添加的library会找不到。
2、如果添加的library不在/lib和/usr/lib里面的话,就一定要修改/etc/ld.so.conf文件,往该文件追加library所在的路径,然后也需要重新调用下ldconfig命令。比如在安装MySQL的时候,其库文件/usr/local/mysql/lib,就需要追加到/etc/ld.so.conf文件中。命令如下:
echo “/usr/local/mysql/lib” >> /etc/ld.so.conf
ldconfig -v | grep mysql
3、如果添加的library不在/lib或/usr/lib下,但是却没有权限操作写/etc/ld.so.conf文件的话,这时就需要往export里写一个全局变量LD_LIBRARY_PATH,就可以了。
go test
- 运行当前目录及所有子目录下的测试用例
go test ./… - 运行指定目录及所有子目录下的测试用例
go test foo/… - 运行指定前缀的测试用例
go test foo… - 运行GOPATH下的所有测试用例
go test …
tcpdump TCP抓包
- 抓包本地回环网络接口 tcpdump -i lo port 6381
- 抓包本地回环UDP指定端口数据报 tcpdump -nn -vv -X udp -i lo port 9101
- 查看个端口占用情况 lsof -i
- tcpdump的Flags代表了这个数据包的用途,这些标记是TCP首部的内容
-
[S]:SYN同步标识
[.]:.
表示ACK确认标识
[S.]:SYN同步标识,以及确认[S]的ACK
[P.]:PSH,push推送,数据传输
[R.]:RST,连接重置
[F.]:FIN结束连接
[DF]:Don't Fragment(不要碎裂),当DF=0时,表示允许分片,一般-v
时才有这个标识
[FP.]:标记FIN、PUSH、ACK组合,这样做是为了提升网络效率,减少数据来回确认等
TIME_WAIT & 长连接 & 短连接
- https://jishuin.proginn.com/p/763bfbd25a93
TCP保活连接
- TCP 虽然有 Keepalive,但它只有在连接有异常的时候才会关闭连接具体来说,在 客户主机始终正常运行,并且从服务器端可达的 情况下,TCP 的保活定时器会不断以固定的时间间隔(默认7200s)触发,发送探查报文这种状况只能知道对方是正常的,并不会将连接关闭而当客户端可能处于 已经崩溃、已经崩溃并重启了、由于中间链路问题不可达 的情况下时,TCP 会将连接断开
- tcp自己的检测时间是2个小时,如果你要修改这个时间需要重新编译内核,但会对所有应用有影响。一般是需要自己实现心跳包的,不要依赖tcp的实现
LINUX & 机器负载
-
平均负载是指单位时间内,系统处于可运行状态和不可中断状态的平均进程数,也就是平均活跃进程数,它和 CPU 使用率并没有直接关系
-
可运行状态的进程,是指正在使用 CPU 或者正在等待 CPU 的进程,也就是我们常用ps 命令看到的,处于 R 状态(Running 或 Runnable)的进程
-
不可中断状态的进程则是正处于内核态关键流程中的进程,并且这些流程是不可打断的,比如最常见的是等待硬件设备的 I/O 响应,也就是我们在 ps 命令中看到的 D 状态(Uninterruptible Sleep,也称为 Disk Sleep)的进程
-
比如,当一个进程向磁盘读写数据时,为了保证数据的一致性,在得到磁盘回复前,它是不能被其他进程或者中断打断的,这个时候的进程就处于不可中断状态。如果此时的进程被打断了,就容易出现磁盘数据与进程数据不一致的问题。所以,不可中断状态实际上是系统对进程和硬件设备的一种保护机制。
-
平均负载其实就是平均活跃进程数。平均活跃进程数,直观上的理解就是单位时间内的活跃进程数,但它实际上是活跃进程数的指数衰减平均值。
-
比如当平均负载为 2 时,意味着什么呢?
-
在只有 2 个 CPU 的系统上,意味着所有的 CPU 都刚好被完全占用。
-
在 4 个 CPU 的系统上,意味着 CPU 有 50% 的空闲。
-
而在只有 1 个 CPU 的系统中,则意味着有一半的进程竞争不到 CPU
进程调度,线程调度,上下文消耗
- 在系统进程和线程调度的时候,需要保存之前线程的执行现场,和加载新的线程的执行现场(cpu的PC和SP要加载新线程的寄存器和栈)
- 进程的执行现场即上下文:进程的上下文不仅包括了虚拟内存、栈、全局变量等用户空间的资源,还包括了内核堆栈、寄存器等内核空间的状态
- 线程的执行现场即上下文:当进程拥有多个线程时,这些线程会共享相同的虚拟内存和全局变量等资源。这些资源在上下文切换时是不需要修改的。另外线程也有自己的私有数据,比如栈和寄存器等,这些在上下文切换时也时需要保存的。
- 更多了解:深入理解Linux的CPU上下文切换
- 用户态主动调用系统调用,陷入内核态 ( https://www.cnblogs.com/xshun/p/12069643.html )
函数调用过程探究,汇编堆栈详解
- GDB调试corefile???堆栈信息
- 函数调用过程探究,汇编堆栈详解
- 分析info frame 每个栈帧的信息解读
- rbp 栈基地址,函数起始地址 高地址,rsp栈顶指针,函数栈顶位置 低地址
- gdb disassemble 可以分析每个栈帧的RIP执行到哪行指令了
Redis
- 原生批量命令与Pipeline对比
可以使用Pipeline模拟出批量操作的效果,但是在使用时需要质疑它与原生批量命令的区别,具体包含几点:
原生批量命令是原子性,Pipeline是非原子性的.
原生批量命令是一个命令对应多个key,Pipeline支持多个命令.
原生批量命令是Redis服务端支持实现的,而Pipeline需要服务端与客户端的共同实现.
multi和pipeline的区别在于multi会将操作都即刻的发送至redis服务端queued起来,每条指令queued的操作都有一次通信开销,执行exec时redis服务端再一口气执行queued队列里的指令,pipeline则是在客户端本地queued起来,执行exec时一次性的发送给redis服务端,这样只有一次通信开销。比如我有5个incr操作,multi的话这5个incr会有5次通信开销,但pipeline只有一次。
pileline其实就是在客户端换成multi和exec多个命令,一次请求发给服务端
multi在事务结束的时候,也会删除对应客户端watch的所有key, A客户端watch key1的时候,然后开启multi事务后,在执行EXEC的时候,如果其他客户端有改过这个key1的话,c->flags |= CLIENT_DIRTY_CAS会打上一致性标记,在exec的时候会判断,其他客户端执行写命令的时候会在signalModifiedKey() 为之前watch的客户端打上标记.
- Pipeline总结
Pipeline虽然好用,但是每次Pipeline组装的命令个数不能没有节制,否则一次组装Pipeline数据量过大,一方面会增加客户端的等待时机,另一方面会造成一定的网络阻塞,可以将一次包含大量命令的Pipeline拆分成多次较小的Pipeline来完成.
Pipeline只能操作一个Redis实例,但即使在分布式Redis场景中,也可以作为批量操作的重要优化方法. - 事务
为了保证多条命令组合的原子性,Redis提供了简单的事务以及集成Lua脚本来解决这个问题. - 事务是原子性的,Pipeline不是原子性的
- redis通信协议
EPOLL ET|LT
- 在使用epoll时,在函数 epoll_ctl中如果不设定,epoll_event 的event默认为LT(水平触发)模式。
设置ET -》 event.events= EPOLLIN | EPOLLET ;
使用LT模式意味着只要fd处于可读或者可写状态,每次epoll_wait都会返回该fd,这样的话会带来很大的系统开销,且处理时候每次都需要把这些fd轮询一遍,如果fd的数量巨大,不管有没有事件发生,epoll_wait都会触发这些fd的轮询判断。
在ET模式下,当有事件发生时,系统只会通知你一次,即在调用epoll_wait返回fd后,不管这个事件你处理还是没处理,处理完没有处理完,当再次调用epoll_wait时,都不会再返回该fd,这样的话程序员要自己保证在时间发生时要及时有效的处理完该事件。例如:fd发生了IN事件,在调用epoll_wait后发现了该事件,程序员要保证在本次轮询中对该fd做了读操作,且还要循环调用recv操作,直到读到的recv的返回值小于请求值,或者遇到EAGAIN错误,否则,在下次轮询时,如果该fd没有再次触发事件,你就没有机会知道这个fd需要处理。这样就会增加程序员的负担和出错的机会(可能有些数据没有来得及处理,丢失数据)。
在LT模式下,无论fd是否有事件发生,或者还有一些事件没有处理完,每次调用epoll_wait时,总会得到该fd让你处理(只要有没事件没有处理,会一直通知你处理,直到你处理完为止,这样就保证了数据的不丢失)。
操作系统在LT模式下维护的就绪队列大小相对于ET模式肯定大,且LT轮询所有的fd总比ET轮询的fd大。自然在性能上LT不如ET,但是在使用ET模式的时,需要循环调用recv,send等处理函数,得保证其事件处理完毕,这样也会带来开销且容易出错。
从 kernel 代码来看,ET/LT模式的处理逻辑几乎完全相同,差别仅在于 LT模式在 event 发生时不会将其从 ready list 中移除,略为增大了event 处理过程中 kernel space 中记录数据的大小。
总结:
- epoll 的 ET和 LT 模式处理逻辑差异极小,性能测试结果表明常规应用场景中二者性能差异可以忽略。
- 使用 ET 的程序比使用LT 的逻辑复杂,出错概率更高。
- ET 和LT 的性能差异主要在于 epoll_wait 系统调用的处理速度,是否是程序的性能瓶颈需要视应用场景而定,不可一概而论,参数timeout是超时时间(毫秒,0会立即返回,-1将不确定,也有说法说是永久阻塞)
运算符小记
- 表达式10&15表示(1010 & 1111),它将返回表示1010的值10。因为真真得真,或者是11得1,同位全是1结果也是1
- 表达式10|15表示(1010 | 1111),它将返回表示1111的值15。假假得假。全零得零
- 表达式10^15表示(1010 ^ 1111), 它将返回表示0101的值5。此时是同性相斥,相同的就为假
- 表达式~10表示(~1010),它将返回表示0101的值 5。此号好理解,按位取反
shell中各种括号的作用()、(())、[]、[[]]、{}
- https://www.cnblogs.com/qlqwjy/p/8684630.html
linux c/c++后台开发知识体系图
- https://www.0voice.com/uiwebsite/html/courses/v9.2.html