linux探秘:netstat中Recv-Q 深究

同学们都知道netstat是查看网络连接状况的有力工具,倒是不知道大家有没有仔细注意其中一些细节的东西,比如我在运维时就遇到:

Active Internet connections (servers and established)
Proto  Recv-Q  Send-Q Local Address               Foreign Address             State      
udp   1894912      0 127.0.0.1:53                0.0.0.0:*

这个问题,维护过服务器的同学一看都知道,哦这个是接收的队列满了,服务器出问题了,重启吧。

但是我有个习惯,喜欢打破砂锅问到底。就在想这个怎么会这样呢,这个具体是什么问题,Revc-Q的数字的单位是什么,这个数字是从何处来的,于是有了下面的探索。

1.  这是Recv-Q 是什么意思?

首先找到了man,man netstat,官方是这样说的:

Recv-Q

The count of bytes not copied by the user program connected to this socket.

单位是字节,是表示程序总共还有多少字节的数据没有从内核空间的套接字缓存拷贝到用户空间。

2   netstat是怎样得到Recv-Q这个值的呢?

我们使用strace -e open netstat,来看看netstat都打开了什么文件

open("/proc/30419/attr/current", O_RDONLY|O_LARGEFILE) = 5

open("/proc/30419/attr/current", O_RDONLY|O_LARGEFILE) = 5

...

open("/proc/net/tcp", O_RDONLY)         = 3

open("/proc/net/tcp6", O_RDONLY)        = -1 ENOENT (No such file or directory)

open("/proc/net/udp", O_RDONLY)         = 3

open("/proc/net/udp6", O_RDONLY)        = -1 ENOENT (No such file or directory)

有没有很眼熟呢,这个/proc/..我们在调优系统的时候通常会用到,里面都写了些什么

既然我们是udp,就看看udp的吧:cat /proc/net/udp

sl  local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt  uid  timeout inode

46: 0100001B:0035 00000000:0000 07 00000000:001CEA00 00:00000000 00000000    70  0 7349

好了,我们注意到红色部分,接收队列rx_queue,对应大小:001CEA00。原来netstat是从这里将数据读出来的,这个001CEA00是十六进制的,换算成十进制就是1894912

3  rx_queue的值是从哪来的?

这里涉及到内核的一些东西,我在搜索rx_queue找到了一些线索

https://github.com/hiboma/hiboma/blob/master/kernel/net/netstat%E3%81%AERecv-Q.md

注意到这里

rx_queue是sk_rmem_alloc_get函数得到的,继续看

程序通过返回sk结构体中的sk_rmem_alloc(sk即socket的简写,记录此sock使用了多少内存)来得到这个值.

4  既然是函数,要触发执行才能显示,这个函数是怎么调用的?

我们注意到每次cat /proc/net/udp,得到的值都可能不一样,也就是说在操作这个“文件”时,后面一定做了什么,于是我们继续挖

参考网站http://lxr.free-electrons.com/source/net/ipv4/udp.c#L2414

/proc这个伪文件系统就是内核和用户对话的平台,当我们cat(open)/proc/net/udp这个文件时,系统帮我们做了open这个对应函数的调用udp_seq_open,

接下来由它调用了udplite4_seq_afinfo结构体的seq_ops.show对应的函数,而udp4_seq_show就正式调用了udp4_format_sock这个函数。

PS:以上是本人的看法,不免有遗漏和错误,如有问题,还望读者指正.

另外,对于问题一,是一般做运维的都要了解的;

对于问题二,是对做运维自动化的一点想法,不必要使用工具,有时在了解原理后也可以自己重写或者加深理解,提取自己需要的那一块来做监控;

对于问题三,是因为公司有一个服务偶尔出现问题,每次都要重启,随着业务的增大,这个问题希望能解决;

对于问题四,则是本人对这个问题的一点其他想法,可以偷窥系统内部的一点实现,纯属个人爱好

时间: 2024-10-03 22:42:17

linux探秘:netstat中Recv-Q 深究的相关文章

必看|Linux运维中必用的工具,让你轻松10倍

A:"A办公区的网络不太好咦" B:"今天C区这边网速好快呀" C:"上传这么快,咋下载这么慢呢?" 以上场景,作为Linux运维刚入门的同学来讲,这些问题应该会经常遇到.那有什么方法可以方便快捷的了解情况呢? 以上情况可能跟系统资源.网络状态.网络流量都有关系,也有可能就跟其中一个有关系. 在Linux系统中 top可以查看系统资源.进程.内存占用等信息. netstat.nmap可以查看网络状态. Iftop可以用来查看实时的网络流量,监控T

Linux设备驱动中的阻塞和非阻塞I/O

[基本概念] 1.阻塞 阻塞操作是指在执行设备操作时,托不能获得资源,则挂起进程直到满足操作所需的条件后再进行操作.被挂起的进程进入休眠状态(不占用cpu资源),从调度器的运行队列转移到等待队列,直到条件满足. 2.非阻塞 非阻塞操作是指在进行设备操作是,若操作条件不满足并不会挂起,而是直接返回或重新查询(一直占用CPU资源)直到操作条件满足为止. 当用户空间的应用程序调用read(),write()等方法时,若设备的资源不能被获取,而用户又希望以阻塞的方式来访问设备,驱动程序应当在设备驱动层的

linux设备驱动程序中的阻塞、IO多路复用与异步通知机制

一.阻塞与非阻塞 阻塞与非阻塞是设备访问的两种方式.在写阻塞与非阻塞的驱动程序时,经常用到等待队列. 阻塞调用是指调用结果返回之前,当前线程会被挂起,函数只有在得到结果之后才会返回. 非阻塞指不能立刻得到结果之前,该函数不会阻塞当前进程,而会立刻返回. 函数是否处于阻塞模式和驱动对应函数中的实现机制是直接相关的,但并不是一一对应的,例如我们在应用层设置为阻塞模式,如果驱动中没有实现阻塞,函数仍然没有阻塞功能. 二.等待队列 在linux设备驱动程序中,阻塞进程可以使用等待队列来实现. 在内核中,

[转] linux下shell中使用上下键翻出历史命名时出现^[[A^[[A^[[A^[[B^[[B的问题解决,Linux使用退格键时出现^H解决方法

[From] https://www.zmrbk.com/post-2030.html https://blog.csdn.net/suifengshiyu/article/details/40952771 我的理解是,如果出现如题所描述的问题,这是因为使用了不同的shell程序和对应的stty设置对应关系所综合作用的结果. 这是/bin/sh里面stty -a命令输出的信息: $ stty -a speed 38400 baud; rows 43; columns 209; line = 0;

在共享文件夹中解压到linux其他目录中,千万注意软连接的问题

这几天一直在练习驱动,搭建一个简单的交叉编译环境,交叉编译工具链和开发板的源码都导进去linux的目录中,并且解压,但是执行一个简单的交叉编译命令总会出现一个奇怪的错误提示: as:unrecongnized option 'mcpu=XXX'; 百思不得其解,后来经过一个实验室的师兄的提示,终于明白了.这里有一个背景需要交代一下: 我是在windows下面的unbuntu虚拟机中进行的驱动开发练习. 首先,我建立了一个共享文件夹,将交叉编译链的压缩文件拷贝进去,这里我的压缩文件的名字为XXX.

浅析Linux驱动模型中的底层数据结构kobject和kset

1.kobject Linux内核用kobject来表示一个内核对象.它和Sysfs文件系统联系密切,在内核中注册到系统中的每个kobject对象在sysfs文件系统中对对应着一个文件目录.kobject数据结构通常的用法是嵌入到其对他的数据结构中(即容器,比如cdev结构),用于实现内核对该类数据结构对象的管理.这些数据结构(容器)通过kobject连接起来,形成了一个树状结构. 它在源码中的定义为: /*<include/linux/kobject.h>*/ struct kobject

Linux使用netstat命令查看并发连接数

本文和大家分享的主要是linux使用netstat命令查看并发连接数的相关内容,一起来看看吧,希望对大家学习linux有所帮助. netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' 解释: 返回结果示例: LAST_ACK 5 (正在等待处理的请求数) SYN_RECV 30 ESTABLISHED 1597 (正常数据传输状态) FIN_WAIT1 51 FIN_WAIT2 504 TIME_WAIT 105

Linux shell脚本中shift的用法说明

Linux shell脚本中shift的用法说明 shift命令用于对参数的移动(左移),通常用于在不知道传入参数个数的情况下依次遍历每个参数然后进行相应处理(常见于Linux中各种程序的启动脚本). 示例1:依次读取输入的参数并打印参数个数: run.sh: #!/bin/bash while [ $# != 0 ];do echo "第一个参数为:$1,参数个数为:$#" shift done 输入如下命令运行:run.sh a b c d e f 结果显示如下: 第一个参数为:a

[书接上一回]在Oracle Enterprise Linux (v5.7) 中安装DB - (4/4)

选择自己创建的安装数据库路径. Sample Schemas 打钩. 调整内存大小. 选择官方建议的字符集编码. 是否创建创建的脚本,如需要请打钩. 脚本生成成功. 创建成功,如需要,则可以管理数据库中用户的密码. 使用数据库. 此时,从虚拟机中,安装OEL系统到安装Oracle数据库全部完结. 以上的资料都从网络寻找,如查询未果,请联系我,我可以发以上需要的资源. [好好学习]在VMware中安装Oracle Enterprise Linux (v5.7) - (1/5)http://www.