/*************************************************/
/* 本贴记录自己项目开发过程中遇到的一些问题,水平一般,有错误或者不足欢迎指正,感谢!*/
一、Linux基础
1.1 linux常用命令
- top命令
linux的top命令相当于windows得任务管理器,用来监测系统CPU、内存等的使用情况。
%Cpu(s): 76% usr, 23% sys, 0% nic, 99.0 idle, 0.0 wa, 0.0 hi, 0.0sirq
- usr:用户空间占CPU时间的百分比
- sy: 内核空间占CPU的百分比(所有进程要使用的系统资源都是由Linux内核处理的,对于操作系统的设计来说,消耗在内核态的时间应该是越少越好,在实践中有一类典型的情况会使sy变大,那就是大量的IO操作,因此在调查IO相关的问题时需要着重关注它)
- ni:用户进程空间改变过优先级(ni是nice的缩写,可以通过nice值调整进程用户态的优先级,这里显示的ni表示调整过nice值的进程消耗掉的CPU时间,如果系统中没有进程被调整过nice值,那么ni就显示为0)
- id: 空闲CPU占用率
- wa: 等待输入输出的CPU时间百分比(和CPU的处理速度相比,磁盘IO操作是非常慢的,有很多这样的操作,比如,CPU在启动一个磁盘读写操作后,需要等待磁盘读写操作的结果。在磁盘读写操作完成前,CPU只能处于空闲状态。Linux系统在计算系统平均负载时会把CPU等待IO操作的时间也计算进去,所以在我们看到系统平均负载过高时,可以通过wa来判断系统的性能瓶颈是不是过多的IO操作造成的)
- hi: 硬中断占用百分比(硬中断是硬盘、网卡等硬件设备发送给CPU的中断消息,当CPU收到中断消息后需要进行适当的处理(消耗CPU时间)。)
- si:软中断占用百分比(软中断是由程序发出的中断,最终也会执行相应的处理程序,消耗CPU时间 来源传送门
进程信息
PID 进程ID
PPID 进程父ID
USER 进程所有者
STAT 进程运行状态(S:睡眠、R:运行、T:停止、Z:僵尸进程)VSZ 进程所用的虚拟内存空间(kb),同VIRT
%VSZ 进程所用的虚拟内存空间占比
%CPU 进程占CPU占比
COMMAND 进程命令-----------------------------------------------------------------
SHR 进程使用共享内存大小(kb)
%MEM 进程使用的物理内存百分比
- awk命令
awk命令用于将输入的字符串分割为多个字段,这里的输入可以是一行,也可以是多行。
awk的完整命令格式为:awk ‘BEGIN {commands} pattern {commands} END{commands}' file1
BEGIN : 处理数据前执行的命令
END :处理数据后执行的命令
pattern :模式,每一行都执行的命令
BEGIN和END里的命令只是执行一次
pattern里的命令会匹配每一行去处理
直接上例子就懂了
解释:
-
cat read.txt
的输出作为awk
的输入。 -
-F
后面的:
表示输入的分割条件,默认为空格、制表符、换行符。 -
后面为数据处理命令,使用BEGIN 和 END 中的命令只执行一次。 pattern 中的命令则是在读取每行时均会执行,图中的
{print $2}
表示选择分隔后的第二列进行打印。
这是第二个例子 每行以”//“作为分隔符,输入文件方到最后面。
通过这三个例子,即可完全掌握awk用法。
二、linux目录
三、Linux内核
四、 文件IO
4.1 socket编程
1. close()函数使用注意事项
- 使用close()关闭一个已经建立连接的套接字,会导致对端接收到一个长度为0的空包
- 关闭服务器的监听套接字不会影响其他套接字的工作。
- close()函数不经会关闭该套接字,还会将占用的文件描述符资源释放掉,内核可以重新使用。
- 当代码中有多线程是,close()函数并不会直接关掉socket,而是使其对应的引用计数减一,应用计数为0是,关闭sock_fd。
2. shutdown()函数使用注意事项以及与close()函数的对比
- shutdown(fd,state)函数可以更加精细的控制socket,可以选择关闭sock的都通道、写通道、读写通道,而close()则是关闭读写通道。
3. TCP套接字使用注意事项
- 一个TCP套接字是全双工的,即一个已建立的套接字可以同时双向传数据,因此这类socket关闭也是独立进行。
- TCP套接字的关闭流程(A和B):A执行close()函数会,会将自己剩余的数据全部发送出去(此处是发送到发送缓存区),然后向对方发送一个FIN帧来终止这个方向,当B收到FIN帧以后,内核会让read()函数返回0,此时B的应用从返回结果可以知道A中止了向自己的数据发送。
TCP状态说明
CLOSED:表示初始状态。对服务端和客户端双方都一样。
LISTEN:表示监听状态。服务端调用了listen函数,可以开始accept连接了
。SYN_SENT:表示客户端已经发送了SYN报文。当客户端调用connect函数发起连接时,首先发SYN给服务端,然后自己进入SYN_SENT状态,并等待服务端发送ACK+SYN。
SYN_RCVD:表示服务端收到客户端发送SYN报文。服务端收到这个报文后,进入SYN_RCVD状态,然后发送ACK+SYN给客户端。
ESTABLISHED:表示连接已经建立成功了。服务端发送完ACK+SYN后进入该状态,客户端收到ACK后也进入该状态。
FIN_WAIT_1:表示主动关闭连接。无论哪方调用close函数发送FIN报文都会进入这个这个状态。
FIN_WAIT_2:表示被动关闭方同意关闭连接。主动关闭连接方收到被动关闭方返回的ACK后,会进入该状态。
TIME_WAIT:表示收到对方的FIN报文并发送了ACK报文,就等2MSL后即可回到CLOSED状态了。如果FIN_WAIT_1状态下,收到对方同时带FIN标志和ACK标志的报文时,可以直接进入TIME_WAIT状态,而无须经过FIN_WAIT_2状态。
CLOSING:表示双方同时关闭连接。如果双方几乎同时调用close函数,那么会出现双方同时发送FIN报文的情况,此时就会出现CLOSING状态,表示双方都在关闭连接。
CLOSE_WAIT:表示被动关闭方等待关闭。当收到对方调用close函数发送的FIN报文时,回应对方ACK报文,此时进入CLOSE_WAIT状态。
LAST_ACK:表示被动关闭方发送FIN报文后,等待对方的ACK报文状态,当收到ACK后进入CLOSED状态。
4.2 I/O复用之select()
1. select()使用
select函数使用很简单,无非是FD_ZERO、FD_SET、以及遍历fdset,但select函数本身有一个bug需要注意。select的原理,日后学到内核再来补充。
2. select()使用注意事项
- ret = -1
int clit_fd = 10;
void thread1()
{
.....
close(clit_fd);
clit_fd = 11;
}
int main()
{
....
while(1){
FD_ZERO(&fdset);
FD_SET(clit_fd, &fdset);
ret = select(fd_max + 1, &fdset, NULL, NULL, &tv_wait);
....
}
....
return 0;
}
此时,ret会返回-1,因为select委托内核监控的描述符在线程中已经释放了,而内核去检测一个Bad descriptor 会返回-1,使用时要注意。