同学们都知道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

      注意到这里

      linux探秘:netstat中Recv-Q 深究_netstat

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

     linux探秘:netstat中Recv-Q 深究_recv-q_02

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


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

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

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

     linux探秘:netstat中Recv-Q 深究_netstat_03

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

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

     linux探秘:netstat中Recv-Q 深究_linux_04

 

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

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

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

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

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