vislee / leevis.com

Blog
87 stars 13 forks source link

linux-1.2.0 tcp/ip实现 #182

Open vislee opened 2 years ago

vislee commented 2 years ago

概述

linux-0.98可能是最早支持tcp/ip的linux内核版本,该版本由Ross Biro开发,随着内核版本变迁,tcp/ip实现也跟着进行了升级迭代, 随后,Fred N. van Kempen在Ross Biro的基础上,改写了代码的主要部分,发不了Net-2版本。后来Alan Cox等人又对Net-2版本的代码进行了重构和扩充,发布了Net-3版本。而linux-1.2.0(net代码中的版本是1.1.93)应该已经是Net-3版本的代码的最早实现了。

代码

在Linux0.98的代码里,通过fd查找socket时,还需要遍历sockets数组。该版本已经做了优化,不再遍历了。 并且,支持的协议族也是通过调用函数注册的,而不是硬编码到代码里了。 还是先来串一下代码调用流程。 在init/main.c文件的start_kernel函数中调用net/socket.c文件中的sock_init初始化网络子系统。 unix socket 则调用的是net/unix/sock.c文件中的unix_proto_init函数。 inet协议则是调用的net/inet/af_inet.c文件的inet_proto_init函数。


void inet_proto_init(struct net_proto *pro)
{
    struct inet_protocol *p;
    int i;

    printk("Swansea University Computer Society TCP/IP for NET3.019\n");

    /*
     *  Tell SOCKET that we are alive... 
     */

        // 注册网络协议族回调函数
    (void) sock_register(inet_proto_ops.family, &inet_proto_ops);

    seq_offset = CURRENT_TIME*250;

    /*
     *  Add all the protocols. 
     */

    for(i = 0; i < SOCK_ARRAY_SIZE; i++) 
    {
               // tcp协议
        tcp_prot.sock_array[i] = NULL;
               // udp协议
        udp_prot.sock_array[i] = NULL;
               // 原始套接字
        raw_prot.sock_array[i] = NULL;
    }
    tcp_prot.inuse = 0;
    tcp_prot.highestinuse = 0;
    udp_prot.inuse = 0;
    udp_prot.highestinuse = 0;
    raw_prot.inuse = 0;
    raw_prot.highestinuse = 0;

    printk("IP Protocols: ");
        // net/inet/protocol.c文件中,定义了TCP、UDP、IMCP等协议
    for(p = inet_protocol_base; p != NULL;) 
    {
        struct inet_protocol *tmp = (struct inet_protocol *) p->next;
        inet_add_protocol(p);
        printk("%s%s",p->name,tmp?", ":"\n");
        p = tmp;
    }
    /*
     *  Set the ARP module up
     */
    arp_init();
    /*
     *  Set the IP module up
     */
    ip_init();
}

当应用程序调用socket函数创建socket套接字fd时,实际上是调用了sock_socket函数,该函数根据协议族(domain)又调用了af_inet 文件中inet_proto_ops结构体中的inet_create函数。

应用程序调用bind时,实际调用了sock_bind 函数, 该函数根据协议族(domain)又调用了af_inet 文件中inet_proto_ops结构体中的inet_bind函数。

c文件组织:net/socket.c -> net/inet/af_inet.c -> net/inet/tcp.c 头文件组织:net.h -> sock.h

总结