Understanding Localhost (127.0.0.1) Network I/O in the Linux Kernel
This article explains how Linux handles local network I/O for 127.0.0.1, detailing the differences from cross‑machine communication, the routing decisions, the loopback device driver, soft‑interrupt processing, and the complete kernel execution flow for both sending and receiving packets.
In this article, the author answers a reader’s question about how the loopback address 127.0.0.1 works inside the Linux kernel, comparing it with the previously covered cross‑machine network packet send/receive processes.
一、跨机网路通信过程
Before discussing local communication, the article briefly reviews the cross‑machine network transmission flow, showing how data moves from the send system call to the NIC and back to the kernel.
The article then shows the corresponding kernel source snippets for sending and receiving, emphasizing the role of RingBuffer, hard interrupts, and soft‑interrupt handling.
1.1 跨机数据发送
Key steps include copying user data to kernel space, processing through the protocol stack, entering the RingBuffer, and finally the NIC driver transmitting the packet. After transmission, a hardware interrupt notifies the CPU and the RingBuffer is cleaned.
1.2 跨机数据接收
When a packet arrives on another machine, the NIC raises a hardware interrupt, the kernel’s interrupt handler schedules a soft interrupt, and the packet is processed through the protocol stack before waking the user process.
1.3 跨机网络通信汇总
二、本机发送过程
The local (loopback) send path differs in two main places: routing and the device driver.
2.1 网络层路由
When the packet reaches the IP layer, ip_queue_xmit performs routing. For 127.0.0.1 the route is found in the local routing table, pointing to the lo virtual NIC.
//file: net/ipv4/ip_output.c
int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl) {
// check socket cache
rt = (struct rtable *)__sk_dst_check(sk, 0);
if (rt == NULL) {
// lookup route and cache it
rt = ip_route_output_ports(...);
sk_setup_caps(sk, &rt->dst);
}
}The routing lookup eventually calls fib_lookup , which first searches the RT_TABLE_LOCAL table and finds the entry:
# ip route list table local
local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1Thus the packet is assigned to net->loopback_dev . 2.2 网络设备子系统 The entry point dev_queue_xmit normally queues packets for a physical NIC, but for the loopback device the queue flag is false, so it directly calls dev_hard_start_xmit which invokes the virtual driver’s loopback_xmit . //file: net/core/dev.c int dev_queue_xmit(struct sk_buff *skb) { q = rcu_dereference_bh(txq->qdisc); if (q->enqueue) { rc = __dev_xmit_skb(skb, q, dev, txq); goto out; } if (dev->flags & IFF_UP) { dev_hard_start_xmit(skb, dev, txq, ...); } } //file: net/core/dev.c int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, struct netdev_queue *txq) { const struct net_device_ops *ops = dev->netdev_ops; rc = ops->ndo_start_xmit(skb, dev); ... } The loopback driver is defined in drivers/net/loopback.c : //file: drivers/net/loopback.c static const struct net_device_ops loopback_ops = { .ndo_init = loopback_dev_init, .ndo_start_xmit = loopback_xmit, .ndo_get_stats64 = loopback_get_stats64, }; Its loopback_xmit simply orphanes the skb and hands it to netif_rx : //file: drivers/net/loopback.c static netdev_tx_t loopback_xmit(struct sk_buff *skb, struct net_device *dev) { skb_orphan(skb); if (likely(netif_rx(skb) == NET_RX_SUCCESS)) { // packet received } } 2.3 “驱动”程序 Although the loopback device has no physical hardware, it still follows the driver model, executing the virtual loopback_xmit function. 三、本机接收过程 Local reception skips the hardware interrupt and starts directly with the soft‑interrupt processing. The soft‑interrupt handler net_rx_action invokes process_backlog , which moves skbs from the per‑CPU input_pkt_queue to process_queue and finally calls __netif_receive_skb to hand the packet to the IP stack. //file: net/core/dev.c static void net_rx_action(struct softirq_action *h) { while (!list_empty(&sd->poll_list)) { work = n->poll(n, weight); } } //file: net/core/dev.c static int process_backlog(struct napi_struct *napi, int quota) { while ((skb = __skb_dequeue(&sd->process_queue))) { __netif_receive_skb(skb); } qlen = skb_queue_len(&sd->input_pkt_queue); if (qlen) skb_queue_splice_tail_init(&sd->input_pkt_queue, &sd->process_queue); } After __netif_receive_skb the packet traverses the same IP receive path ( ip_rcv , transport layer, etc.) as in cross‑machine reception. 四、本机网络 IO 总结 The article concludes that local network I/O does not pass through a physical NIC; instead it uses the loopback interface, which avoids hardware‑level overhead but still traverses the full kernel networking stack, including routing, device subsystem, and driver calls. It also notes that eBPF can be used to bypass the kernel stack for side‑car communication.
IT Services Circle
Delivering cutting-edge internet insights and practical learning resources. We're a passionate and principled IT media platform.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.