隨手記之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