聶永的博客

          記錄工作/學習的點點滴滴。

          隨手記之Linux內(nèi)核Backlog筆記

          零。前言

          有些東西總是很容易遺忘,一時記得了,過兩天就真正還給周公了。零零碎碎的不如一并記下來,以后可以直接拿過來查詢即可。

          以下內(nèi)容基于Linux 2.6.18內(nèi)核。

          一。listen方法傳入的backlog參數(shù),net.core.somaxconn

          這個參數(shù)具體意義,先看看Linux Socket的listen解釋

          man listen

             #include <sys/socket.h>
          
             int listen(int sockfd, int backlog);
          

          int類型的backlog參數(shù),listen方法的backlog意義為,已經(jīng)完成三次握手、已經(jīng)成功建立連接的套接字將要進入隊列的長度。

          一般我們自己定義設定backlog值,若我們設置的backlog值大于net.core.somaxconn值,將被置為net.core.somaxconn值大小。若不想直接硬性指定,跟隨系統(tǒng)設定,則需要讀取/proc/sys/net/core/somaxconn。

          net\Socket.c :

          /*
           *  Perform a listen. Basically, we allow the protocol to do anything
           *  necessary for a listen, and if that works, we mark the socket as
           *  ready for listening.
           */
          
          int sysctl_somaxconn = SOMAXCONN;
          
          asmlinkage long sys_listen(int fd, int backlog)
          {
              struct socket *sock;
              int err, fput_needed;
          
              if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) {
                  if ((unsigned) backlog > sysctl_somaxconn)
                      backlog = sysctl_somaxconn;
          
                  err = security_socket_listen(sock, backlog);
                  if (!err)
                      err = sock->ops->listen(sock, backlog);
          
                  fput_light(sock->file, fput_needed);
              }
              return err;
          }
          

          比如經(jīng)常使用的netty(4.0)框架,在Linux下啟動時,會直接讀取/proc/sys/net/core/somaxconn值然后作為listen的backlog參數(shù)進行調(diào)用Linux系統(tǒng)的listen進行初始化等。

          int somaxconn = 3072;
          BufferedReader in = null;
          try {
              in = new BufferedReader(new FileReader("/proc/sys/net/core/somaxconn"));
              somaxconn = Integer.parseInt(in.readLine());
              logger.debug("/proc/sys/net/core/somaxconn: {}", somaxconn);
          } catch (Exception e) {
              // Failed to get SOMAXCONN
          } finally {
              if (in != null) {
                  try {
                      in.close();
                  } catch (Exception e) {
                      // Ignored.
                  }
              }
          }
          
          SOMAXCONN = somaxconn;
          ......
          private volatile int backlog = NetUtil.SOMAXCONN;
          

          一般稍微增大net.core.somaxconn值就顯得很有必要。

          設置其值方法:

          sysctl -w net.core.somaxconn=65535
          

          較大內(nèi)存的Linux,65535數(shù)值一般就可以了。

          若讓其生效,sysctl -p 即可,然后重啟你的Server應用即可。

          二。網(wǎng)卡設備將請求放入隊列的長度,netdev_max_backlog

          內(nèi)核代碼中sysctl.c文件解釋:

          number of unprocessed input packets before kernel starts dropping them, default 300
          

          我所理解的含義,每個網(wǎng)絡接口接收數(shù)據(jù)包的速率比內(nèi)核處理這些包的速率快時,允許送到隊列的最大數(shù)目,一旦超過將被丟棄。

          所起作用處,net/core/Dev.c:

          int netif_rx(struct sk_buff *skb)
          {
              struct softnet_data *queue;
              unsigned long flags;
          
              /* if netpoll wants it, pretend we never saw it */
              if (netpoll_rx(skb))
                  return NET_RX_DROP;
          
              if (!skb->tstamp.off_sec)
                  net_timestamp(skb);
          
              /*
               * The code is rearranged so that the path is the most
               * short when CPU is congested, but is still operating.
               */
              local_irq_save(flags);
              queue = &__get_cpu_var(softnet_data);
          
              __get_cpu_var(netdev_rx_stat).total++;
              if (queue->input_pkt_queue.qlen <= netdev_max_backlog) {
                  if (queue->input_pkt_queue.qlen) {
          enqueue:
                      dev_hold(skb->dev);
                      __skb_queue_tail(&queue->input_pkt_queue, skb);
                      local_irq_restore(flags);
                      return NET_RX_SUCCESS;
                  }
          
                  netif_rx_schedule(&queue->backlog_dev);
                  goto enqueue;
              }
          
              __get_cpu_var(netdev_rx_stat).dropped++;
              local_irq_restore(flags);
          
              kfree_skb(skb);
              return NET_RX_DROP;
          }
          

          以上代碼看一下,大概會明白netdev_max_backlog會在什么時候起作用。

          posted on 2014-07-30 17:22 nieyong 閱讀(15489) 評論(5)  編輯  收藏 所屬分類: Socket

          評論

          # re: 隨手記之Linux內(nèi)核Backlog筆記 2014-07-30 18:01 旺達鎖業(yè)

          支持博主更新、、、、、、、、、、、  回復  更多評論   

          # re: 隨手記之Linux內(nèi)核Backlog筆記 2014-07-30 22:06 月小升技術博客

          玩內(nèi)核的高手,我現(xiàn)在只能用Linux,還不能玩內(nèi)核。  回復  更多評論   

          # re: 隨手記之Linux內(nèi)核Backlog筆記 2014-08-02 16:11 創(chuàng)業(yè)初期

          技術男.支持一下  回復  更多評論   

          # re: 隨手記之Linux內(nèi)核Backlog筆記 2014-08-02 16:12 互聯(lián)網(wǎng)博客

          學習一下  回復  更多評論   

          # re: 隨手記之Linux內(nèi)核Backlog筆記 2014-08-08 11:48 喜歡研究的人類

          記得以前在
          http://www.duanmeiwen.com/
          是有相關介紹的,不過現(xiàn)在變成了什么美文網(wǎng)了,可惜了!  回復  更多評論   

          公告

          所有文章皆為原創(chuàng),若轉載請標明出處,謝謝~

          新浪微博,歡迎關注:

          導航

          <2014年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          統(tǒng)計

          常用鏈接

          留言簿(58)

          隨筆分類(130)

          隨筆檔案(151)

          個人收藏

          最新隨筆

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 承德县| 营口市| 龙口市| 常熟市| 兖州市| 霍山县| 克山县| 兴国县| 裕民县| 凤城市| 柘荣县| 博野县| 尼勒克县| 石楼县| 宁都县| 石城县| 北票市| 娄烦县| 芷江| 香格里拉县| 长海县| 连云港市| 黄浦区| 嘉义市| 禄丰县| 昌宁县| 伊春市| 镇巴县| 苍南县| 凤翔县| 平定县| 泗水县| 亚东县| 寿光市| 楚雄市| 阜平县| 西丰县| 高青县| 日照市| 太湖县| 叙永县|