目录
Windows 、Linux、下查看符号表,dumpbin、readelf、objdump用法
SVN基本操作,checkin \check out\ update\add
处理器
常用处理器架构、指令集
CISC:x86、x86_64-litte
RISC:Arm、MIPS(龙芯)、PowerPC-big
国产处理器
mips阵营:龙芯
arm阵营: 飞腾,海思麒麟
IBM powerpc阵营:
宏芯x86:兆芯,申威
字长和处理器类型的关系
计算机字长(机器字长)取决于数据总线的宽度,通常就是CPU一次能处理的数据的位数(CPU位数)。
不同处理器的大小端
Big Endian:低字节存储在高地址
eg:PowerPC、IBM、Sun
Little Endian:低字节存放在低地址
eg:x86、DEC.
查看处理器类型
uname -m
核与线程之间的关系
总的逻辑 cpu 数 = 物理 cpu 数 * 每颗物理 cpu 的核心数 * 每个核心的超线程数
如何绑定处理器
cat /proc/cpuinfo|grep "physical id"|sort -u|wc -l
查看物理CPU个数
cat /proc/cpuinfo|grep "cpu cores"|uniq
查看每个物理CPU中core的个数(即核数)
cat /proc/cpuinfo|grep "processor"|wc -l
查看逻辑CPU的个数
cat /proc/cpuinfo|grep "name"|cut -f2 -d:|uniq
查看CPU的名称型号
ps -eo pid,args,psr
查看进程运行的逻辑CPU
taskset -c [CPU NUMBER] -p PID
指定cpu
基本的汇编原子操作
加减
mov ecx, Addend;
mov eax, 0FFFFFFFFh;//-1 (mov eax, 1;)//+1
lock xadd [ecx], eax; //加-1
dec eax;
比较后交换
mov ecx, Destination;
mov edx, Exchange;
mov eax, Comperand;
lock cmpxchg [ecx], edx;
交换
mov ecx, Target;
mov edx, Value;
label:
lock cmpxchg [ecx], edx;//加
jnz short label;
操作系统
操作系统接口标准,名称,厂商
操作系统 提供了3类型的接口供用户使用:
- 命令接口. 提供一组命令供用户直接或间接操作。. 根据作业的方式不同,命令接口又分为联机命令接口和脱机命令接口。
- 程序接口. 程序接口 由一组系统调用命令组成,提供一组系统调用命令供 用户程序 使用。
- 图形界面接口.
名称 | 厂商 |
posix | IEEE |
有哪些国产操作系统
中标麒麟(NeoKylin) | 银河麒麟操作系统 | inux(Deepin) | 普华操作系统 | 中科方德操作系统 |
中兴新支点操作系统 | 一铭操作系统 | 优麒麟(UbuntuKylin) | 湖南麒麟 Kylinsec | startOS(起点操作系统) |
共创Linux桌面操作系统 | 威科乐恩Linux(WIOS) | 恩普操作系统 | UOS 统一操作系统 | 红旗Linux |
哪些是实时、哪些是非实时操作系统
实时操作系统的实时性是第一要求,需要调度一切可利用的资源完成实时任务。根据响应时间在微秒、毫秒和秒级的不同,可分为强实时、准实时和弱实时三种。强实时系统必须是对即时的事件作出反应,绝对不能错过事件处理时限。
实时操作系统:VxWorks、mC/OS-II、RT-Linux、QNX
非实时操作系统:Linux/Windows
设置时间、时区
查看时间:date
设置时间(年月日):date -s 3/29/2021 (其中-s 指的是set)
设置时间(时分秒):date -s 15:52:36
设置时间(年月日时分秒) :date -s "2022-3-29 18:44:02"
查看时区: date -R
关闭网络时间协议同步时间:sudo timedatectl set-ntp false
修改时区:timedatectl set-timezone “Asia/Shanghai”
修改时区:timedatectl set-time '16:10:40 2015-11-20'
设置用户、密码和文件读、写、运行权限
# useradd 用户名称 // 添加用户
# passwd 用户名称 // 修改用户密码
# chmod [who] [+ | - | =] [mode] 文件名
查找文件、字符串及管道操作
将当前目录及其子目录下所有文件后缀为 .c 的文件列出来:
find . -name "*.c"
将当前目录及其子目录中的所有文件列出:
find . -type f
将当前目录及其子目录下所有最近 20 天内更新过的文件列出:
find . -ctime 20
远程连接
ssh
ssh user@remote -p port
// 保证对端机器打开sshd服务,使用 systemctl status sshd.service 查看
vnc,winscp
桌面工具,粘贴两个链接
VNC的安装与使用(Windows环境下使用VNC进行远程桌面控制) - 简书
不过使用vnc client要注意,一定不能让目标主机磁盘占用过大,不然会导致 vnc server服务无法启动从而连接失败
命令行,查看内存、磁盘、进程、线程资源使用情况
磁盘:df -h
内存:sar -r
进程:ps -elf
线程:ps -T -p 20756、top -H -p 20756或者 top 一键搞定
查看操作系统、Glibc、GCC版本
uname -r // 操作系统
ldd --version // glibc
gcc --version // gcc
// 跨平台交叉编译时需要
如何杀死进程
kill -9 PID
如何查看系统日志
Windows:
程序-查看事件日志
Linux:
/var/log/message 系统启动后的信息和错误日志,是Red Hat Linux中最常用的日志之一
/var/log/secure 与安全相关的日志信息
/var/log/cron 与定时任务相关的日志信息
/var/log/spooler 与UUCP和news设备相关的日志信息
/var/log/boot.log 守护进程启动和停止相关的日志消息
/var/log/wtmp 该日志文件永久记录每个用户登录、注销及系统的启动、停机的事件
编写批处理和Shell脚本
程序必须以下面的行开始(必须方在文件的第一行):
#!/bin/sh
符号#!用来告诉系统它后面的参数是用来执行该文件的程序。在这个例子中我们使用/bin/sh来执行程序。 (能写一些shell普通命令,命令用分号隔开)
#!bin/sh
echo "==============================================="
echo "================启动 ***==================="
echo "==============================================="
start-all.sh;
Tty切换
chvt N
输出stdout\stderror的意义,会重定向
cout的输出可以重定向到一个文件中,而cerr必须输出在显示器上。cerr不经过缓冲区,直接向显示器输出信息,而clog中的信息存放在缓冲区,缓冲区满或者遇到endl 时才输出。缓冲区的的,就是减少访问文件的次数。
编译器
编译器选项,头文件包含方式、库连接方式、优化选项
常用编译选项
- -E 预处理,生成.i的文件[预处理器cpp]
- -S 将预处理后的文件不转换成汇编语言,生成文件.s[编译器egcs]
- -s 有汇编变为目标代码(机器代码)生成.o的文件[汇编器as]
- -l 连接目标代码,生成可执行程序[链接器ld]
头文件包含和库链接
-nostdinc 使编译器不再系统默认的头文件目录里面找头文件, 一般和 -I 联合使用,明确限定头文件的位置。
-llibrary 制定编译的时候使用的库
优化选项
-O0 、-O1 、-O2 、-O3
编译器的优化选项的 4 个级别,-O0 表示没有优化, -O1 为默认值,-O3 优化级别最高。
类型未定义、缺少引用解决办法
- 检查头文件包含
- 库文件符号表
- 头文件包含覆盖
优化级别设置
gcc中指定优化级别的参数有:-O0、-O1、-O2、-O3、-Og、-Os、-Ofast。
- 在编译时,如果没有指定上面的任何优化参数,则默认为 -O0,即没有优化。
- 参数 -O1、-O2、-O3 中,随着数字变大,代码的优化程度也越高,不过这在某种意义上来说,也是以牺牲程序的可调试性为代价的。
- 参数 -Og 是在 -O1 的基础上,去掉了那些影响调试的优化,所以如果最终是为了调试程序,可以使用这个参数。不过光有这个参数也是不行的,这个参数只是告诉编译器,编译后的代码不要影响调试,但调试信息的生成还是靠 -g 参数的。
- 参数 -Os 是在 -O2 的基础上,去掉了那些会导致最终可执行程序增大的优化,如果想要更小的可执行程序,可选择这个参数。
- 参数 -Ofast 是在 -O3 的基础上,添加了一些非常规优化,这些优化是通过打破一些国际标准(比如一些数学函数的实现标准)来实现的,所以一般不推荐使用该参数。
gcc -Q --help=optimizers -O3
查寻O3参数具体做了哪些优化
编码方式配置
- 源码字符集:源码存储在计算机磁盘上所采用的编码方式。
- 执行字符集:运行的程序中的字符在内存中存储所使用的编码方式。
- 内部字符集:编译器内部使用的字符集。
以gcc为例:
-finput-charset 设置输入字符集,用于从输入的字符集转换,默认为utf8。
-fexec-charset=charset 设置执行字符集。决定了字符串常量在内存中的编码。默认为utf8。
输入字符集决定了源码到内部字符集的转换方式。源码存储方式如果为gbk,且编译器指定的输入字符集为gbk。在将c语言编译为汇编时,会将源码字符集转换为内部utf-8。
执行字符集决定了由内部字符集到执行字符集的转换方式。如果设置为gbk,在将汇编语言翻译成机器语言时,会将字符串常量从内部字符集utf-8向gbk转换。
如果二者都为utf-8,由于gcc内部字符集也为utf-8,不会发生转换。内存中的字符串常量的编码直接取决于源码的编码。
并行编译选项
VS
- 选取某项目的“Properties(属性)
- 在打开的对话框中,左侧选择 “C/C++”->“General(常规)”中将“ Multi-processor Compilation(多处理器编译)”打开
- “C/C++”->“Code Generation(代码生成)”中将“Enable Minimal Rebuild(启用最小重新生成)”关闭
- 在“Debug(调试)”中选取项目的“Options and Settings (选项和设置)”->“Projects and Solutions (项目和解决方案)”->“ Build and Run (编译与运行)”中设置“ maximum number of parallel project builds(最大并发C++编译数)”(即开发项目机器本身的CPU所包含的核数)
Windows 、Linux、下查看符号表,dumpbin、readelf、objdump用法
dumpbin
dumpbin.exe /SYMBOLS <file(.lib)>
readelf
readelf -s <file>
objdump
objdmp -t <file(.so)>
nm
nm -D <file> // 查村符号并支持反译为函数名
用denpends和ldd查看依赖关系
ldd <filename> // linux
denpends 软件打开可执行文件或者动态库查看依赖 // windows
如何设置导出调试信息
# gdb <file> // 进入到gdb命令行中
# set logging file <filename> // 设置输出文件
# set logging on // 开始拷贝
# thread apply all bt // 查看所有线程堆栈并输出到文件中
# set logging off // 停止拷贝
调试器
设置调试断点
GDB
break | b | 添加断点
tbreak | tb | 添加临时断点
delete | d | 删除断点
enable | enable | 启用某个断点
disable | disable | 禁用某个断点
使用快捷键操作
GDB
run | r | 运行一个待调试的程序
continue | c | 让暂停的程序继续运行
next | n | 运行到下一行
step | s | 单步执行,遇到函数会进入
until | u | 运行到指定行停下来
finish | fi | 结束当前调用函数,回到上一层调用函数处
return | return | 结束当前调用函数并返回指定值,到上一层函数调用处
jump | j | 将当前程序执行流跳转到指定行或地址
print | p | 打印变量或寄存器值
backtrace | bt | 查看当前线程的调用堆栈
frame | f | 切换到当前调用线程的指定堆栈
thread | thread | 切换到指定线程
break | b | 添加断点
tbreak | tb | 添加临时断点
delete | d | 删除断点
enable | enable | 启用某个断点
disable | disable | 禁用某个断点
watch | watch | 监视某一个变量或内存地址的值是否发生变化
list | l | 显示源码
info | i | 查看断点 / 线程等信息
ptype | ptype | 查看变量类型
disassemble | dis | 查看汇编代码
set args | set args | 设置程序启动命令行参数
show args | show args | 查看设置的命令行参数
查看内存信息
GDB
print | p | 打印变量或寄存器值
backtrace | bt | 查看当前线程的调用堆栈
watch | watch | 监视某一个变量或内存地址的值是否发生变化
远程调试
gdbserver、VsCode、qtcreator、VS2010、VisualGDB
附加部分代码调试
qtcreator
直接将想要调试的文件拖进qt中,但必须保证代码版本一致(带界面)
调试时更改内存值
GDB
(gdb) whatis tmp
type = double
(gdb) p tmp
$4 = 13
(gdb) set var tmp=47
不能直接使用set tmp=47,因为set的子命令可能跟变量名冲突导致运行错误
set {int}0x83040 = 4
设置调试断点条件
GDB
(gdb) b N if i == 8
使用GDB调试基本程序
GDB调试主要有三种方式
- 直接调试目标程序:gdb ./hello_server
- 附加进程id:gdb attach pid
- 调试core文件:gdb filename corename
查看和调试软件锁死原因
方法1:
- attach pid
- bt
- 定位到 pthread_mutex_lock()
方法2:
- attach pid
- thread apply all bt
- 定位到 thread_proc (arg=0x0)
方法3:
- gdb test 进程号 | 启动gdb attach 进程
- info threads | 显示所有线程信息
- thread 2 | 调到第2个线程(查看线程中带有 __111_lock_wait() 的线程)
- bt | 查看第2个线程的堆栈,即可可以看到线程死锁的地方
语言和工具
SVN基本操作,checkin \check out\ update\add
拉取代码:
svn checkout svn://192.168.0.1/runoob01 --username=user01
提交代码:cat readme // 在库本版中需要增加一个readme的说明文件。
svn status // 查看工作副本中的状态,此时 readme的状态为?,说明它还未加到版本
控制中。
svn add readme // 将文件readme加到版本控制,等待提交到版本库。
svn status // 查看工作副本中的状态,此时 readme的状态为A,它意味着这个文件已经被成功地添加到了版本控制中。
svn commit -m "SVN readme" // 为了把 readme 存储到版本库中,使用 commit -m加上注释信息来提交。
如果你忽略了 -m 选项, SVN会打开一个可以输入
多行的文本编辑器来让你输入提交信息。
更新代码:
svn update
与SVN特定版本比较,revert到某一个版本
# svn revert readme // 文件 readme 回归到未修改状态
# svn revert -R trunk // 目录 trunk 回归到未修改状态
# svn merge -r 22:21 readme // 恢复一个已经提交的版本:现版本22,旧版本21。
内存对齐
默认对齐数可以通过预编译命令#pragma pack(n),n = 1,2,4,8,16来改变。
#pragma pack(4)
#pragma pack(1)
#pragma pack(2)
需要特别注意的有几点
- 对齐数时变化的
- 不同的处理器默认对齐数不同,跨平台通信要特别注意
- 对其原则是在当前对齐数倍数的空间内是否能放下我下一个类型,可以直接放,不可以进行填充对齐
- 结构体中有其他结构体,各自计算然后相加
不同语言的接口实现
C++插入C代码
extern "C" {
void funcA(int x);
}
不同语言版本的主要差异
C++11 && C++98
- 自动类型推导auto
- 列表初始化
- 变量类型推导
- 范围for循环
- 返回类型后置语法
- final和override
- =default和=delete
- lambda表达式
- std::move
- std::array
- std::forward_list
- std::unordered_map和std::unordered_set
- 智能指针
- 右值引用&线程库
c98 && c99
- 增加restrict指针
- inline(内联)关键字
- 新增数据类型
- 对数组的增强
- 单行注释
- 分散代码与声明
- 预处理程序的修改
- for语句内的变量声明
- 复合赋值
- 柔性数组结构成员
- 指定的初始化符
- printf()和scanf()函数系列的增强
- C99新增的库
- __func__预定义标识符
网络
网络地址、MAC地址查看、配置
查看IP/MAC
$ ifconfig
设置IP和掩码
# ifconfig eth0 192.168.5.40 netmask 255.255.255.0
设置网关
# route add default gw 192.168.5.1
Route路由查看
centos7
$ route / $netstat -rn
Ubuntu20.04
$ route / $netstat -rn
Destination | 目标网络/主机 |
Gateway | 网关地址,*表示目标和本机在同一网络,不需要路由 |
Genmask | 网络掩码 |
Flags | 路由项标志,常见标志有如下 U 该路由项是活动的 |
Metric | 路由距离,即到达指定网络所需的中转数 Ref 路由项被引用的次数(Linux未使用) |
Use | 该路由项被使用的次数 |
Iface | 该路由项对应的输出网卡接口 |
TCP基本原理
TCP头
- URG:紧急比特(urgent)。当URG=1时,表明紧急指针字段有效,代表该封包为紧急封包。它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据), 且上图中的 Urgent Pointer 字段也会被启用。
- ACK:确认比特(Acknowledge)。只有当ACK=1时确认号字段才有效,代表这个封包为确认封包。当ACK=0时,确认号无效。
- PSH:(Push function)。若为1时,代表要求对方立即传送缓冲区内的其他对应封包,而无需等缓冲满了才送。
- RST:复位比特(Reset) 。当RST=1时,表明TCP连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。
- SYN:同步比特(Synchronous)。SYN置为1,就表示这是一个连接请求或连接接受报文,通常带有 SYN 标志的封包表示『主动』要连接到对方的意思。
- FIN:终止比特(Final)。用来释放一个连接。当FIN=1时,表明此报文段的发送端的数据已发送完毕,并要求释放运输连接。
三次握手
- 第一次握手:建立连接时,客户端A发送SYN包[SYN=1,seq=x]到服务器B,并进入SYN_SEND状态,等待服务器B确认。
- 第二次握手:服务器B收到SYN包,必须确认客户A的SYN,同时自己也发送一个SYN包,即SYN+ACK包[SYN=1,ACK=1,seq=y,ack=x+1],此时服务器B进入SYN_RECV状态。
- 第三次握手:客户端A收到服务器B的SYN+ACK包,向服务器B发送确认包ACK[ACK=1,seq=x+1,ack=y+1],此包发送完毕,客户端A和服务器B进入ESTABLISHED状态,完成三次握手。 完成三次握手,客户端与服务器开始传送数据。
四次挥手
- 首先A B端的TCP进程都处于established状态, 当A的应用程序传送完报文段,就会去主动关闭连接。A会停止发送报文段(但是还会接收),并向B发送[FIN = 1,seq=u]数据,之后进入FIN-WAIT-1状态;
- B接收到A发送的请求之后,会通知应用进程,A已经不再发送数据,同时B会向A发送ACK确认数据[ACK=1,seq=v,ack=u+1 ],B进入CLOSE-WAIT状态,A接收到B发送的数据之后,A进入FIN-WAIT-2状态;此时A到B方的连接已经关闭了(即半连接状态)。
- 当B的应用进程发现自己也没有数据需要传送,B应用进程就会发出被动关闭的请求,B此时向A发送[FIN=1,ACK=1,seq=w,ack=u+1]数据,并且进入LAST-ACK状态;
- A接收到B发送的数据之后,向B发送ACK确认数据[ACK =1,seq=u+1,ack=w+1],进入TIME-WAIT状态,等待2MSL之后正常关闭连接进入CLOSED状态;B接收到A发送的确认之后进入CLOSED状态。B到A方的连接关闭!至此,TCP连接才真正全部关闭!
UDP基本原理
UDP头
设置不同防火墙
centos7
启动防火墙:# systemctl start firewalld
查看防火墙状态:# systemctl status firewalld
停止防火墙:# systemctl disable firewalld
禁用防火墙:# systemctl stop firewalld
Ubuntu20.04
开启/关闭防火墙:$ sudo ufw enable|disable
允许 53 端口
$ sudo ufw allow 53
禁用 53 端口
$ sudo ufw delete allow 53
允许 80 端口
$ sudo ufw allow 80/tcp
禁用 80 端口
$ sudo ufw delete allow 80/tcp
允许 smtp 端口
$ sudo ufw allow smtp
删除 smtp 端口的许可
$ sudo ufw delete allow smtp
允许某特定 IP
$ sudo ufw allow from 192.168.254.254
删除上面的规则
$ sudo ufw delete allow from 192.168.254.254
常用软件默认端口
HTTP:80/8080/3128/8081/9080
HTTP:443
FTP(文件传输):21
Telnet(远程登录):23
ssh(VNC 安全登录):22
DNS:53
Wireshark查看过滤网络包
过滤源ip、目的ip:
- 查找目的地址为192.168.101.8的包
- ip.dst==192.168.101.8
- 查找源地址为
- ip.src==1.1.1.1
端口过滤:
- tcp.port==80,
- 源端口和目的端口为80
- tcp.dstport==80
- 只过滤目的端口为80的
- tcp.srcport==80
- 只过滤源端口为80的
协议过滤:
- 在Filter框中直接输入协议名即可,如过滤HTTP的协议
http模式过滤:
- 如过滤get包,http.request.method=="GET",过滤post包,http.request.method=="POST"
连接符and
- 过滤两种条件时,使用and连接,如过滤ip为192.168.101.8并且为http协议的,ip.src==192.168.101.8 and http。
netstat查看应用绑定的端口
windows
netstat -ano
Linux
TCP:netstat -ntlp<br>
UDP:netstat -nulp
iperf3测试不同协议下的网络可用带宽
服务端
iperf3 -s -i 1 -p 5201
客户端
TCP
iperf3 -c 192.168.1.120 -i 1 -t 60 -p 5201
UDP
iperf3 -u -c 192.168.1.120 -b 1000m -t 60 -p 5201
调整操作系统和网卡的工作模式、缓冲区大小
工作模式
查看:mii-tool -v ens33
调整:mii-tool -F 10baseT-HD ens33
恢复自适应:mii-tool -r ens33
// HD:半双工 FD:全双工
缓冲区大小
查看:ethtool -g ens33
调整:ethtool -G ens33 rx 4096 tx 4096
不同协议包头大小
以太头 14 尾 4
IP头 20
TCP头 20
UDP头 8
后续补充
- 操作系统
- 调整线程、进程优先级
- 用户线程和处理器线程之间的关系
- 锁的原理,连接读写锁和自旋锁的原理
- 系统资源和文件句柄数、系统锁等的关系
- 查看不同操作系统定时器误差,由此引起线程切换时间范围
- 编译器
- 编译的基本工程,能够手动通过命令行操作程序
- 编译运行和解释运行的区别
- 哪些主流语言是解释运行,哪些是编译运行
- Java语言虚拟机基本原理
- 如何判断编译器版本
- 附加部分代码调试
这篇文章呢主要是搜索和整理,欢迎大家留言补充和纠正。后面关于网络和 rtps 我会单独开一两篇去详讲我碰到的一些问题和查看处理办法。共勉。