随手记之Linux内核Backlog笔记

前言

有些东西总是很容易遗忘,一时记得了,过两天就真正还给周公了。零零碎碎的不如一并记下来,以后可以直接拿过来查询即可。

以下内容基于Linux 2.6.18内核。

一。listen方法传入的backlog参数,net.core.somaxconn
这个参数具体意义,先看看Linux Socket的listen解释

man listen

#include <sys/socket.h>

int listen(int sockfd, int backlog);
int类型的backlog参数,listen方法的backlog意义为,已经完成三次握手、已经成功建立连接的套接字将要进入队列的长度。

一般我们自己定义设定backlog值,若我们设置的backlog值大于net.core.somaxconn值,将被置为net.core.somaxconn值大小。若不想直接硬性指定,跟随系统设定,则需要读取/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;

}
比如经常使用的netty(4.0)框架,在Linux下启动时,会直接读取/proc/sys/net/core/somaxconn值然后作为listen的backlog参数进行调用Linux系统的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
较大内存的Linux,65535数值一般就可以了。

若让其生效,sysctl -p 即可,然后重启你的Server应用即可。

二。网卡设备将请求放入队列的长度,netdev_max_backlog
内核代码中sysctl.c文件解释:

number of unprocessed input packets before kernel starts dropping them, default 300
我所理解的含义,每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的最大数目,一旦超过将被丢弃。

所起作用处,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会在什么时候起作用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值