1. 程式人生 > >linux net子系統-套介面層

linux net子系統-套介面層

套介面層框圖

核心資料結構

struct socket
struct proto_ops
struct sock
struct proto

結構體之間的關係

結構體之間的關係

socket建立

註冊struct net_proto_family與struct inet_protosw

static const struct net_proto_family inet_family_ops = {
    .family = PF_INET,
    .create = inet_create,
    .owner  = THIS_MODULE,
};

static struct inet_protosw inetsw_array[] =
{
    {
        .type
= SOCK_STREAM, .protocol = IPPROTO_TCP, .prot = &tcp_prot, .ops = &inet_stream_ops, .no_check = 0, .flags = INET_PROTOSW_PERMANENT | INET_PROTOSW_ICSK, }, { .type = SOCK_DGRAM, .protocol
= IPPROTO_UDP, .prot = &udp_prot, .ops = &inet_dgram_ops, .no_check = UDP_CSUM_DEFAULT, .flags = INET_PROTOSW_PERMANENT, }, { .type = SOCK_DGRAM, .protocol = IPPROTO_ICMP, .prot = &ping_prot, .ops
= &inet_dgram_ops, .no_check = UDP_CSUM_DEFAULT, .flags = INET_PROTOSW_REUSE, }, { .type = SOCK_RAW, .protocol = IPPROTO_IP, /* wild card */ .prot = &raw_prot, .ops = &inet_sockraw_ops, .no_check = UDP_CSUM_DEFAULT, .flags = INET_PROTOSW_REUSE, } }; fs_initcall(inet_init); (void)sock_register(&inet_family_ops); for (q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q) inet_register_protosw(q);

在struct inet_protosw inetsw_array[]陣列中的每個元素的struct proto_ops和struct proto都會被初始化,並且通過inet_register_protosw將陣列中的每個元素註冊到全域性static struct list_head inetsw[SOCK_MAX];

sys_socket

sys_socket
    sock_create
        __sock_create
            struct socket *sock = sock_alloc
            //下面這個inet_create是之前通過sock_register註冊的inet_family_ops中的create函式
            pf->create(net, sock, protocol) == inet_create
                //在inet_create這個函式中會將之前通過inet_register_protosw
                //註冊的inetsw_array陣列中的struct proto_ops和struct proto
                //分別賦值給struct socket和struct sock
                sock->ops = answer->ops
                struct sock *sk = sk_alloc
                sk->sk_prot = sk->sk_prot_create = answer->prot

struct proto_ops

對應tcp的struct proto_ops位於net/ipv4/af_inet.c

const struct proto_ops inet_stream_ops = {
    .family        = PF_INET,
    .owner         = THIS_MODULE,
    .release       = inet_release,
    .bind          = inet_bind,
    .connect       = inet_stream_connect,
    .socketpair    = sock_no_socketpair,
    .accept        = inet_accept,
    .getname       = inet_getname,
    .poll          = tcp_poll,
    .ioctl         = inet_ioctl,
    .listen        = inet_listen,
    .shutdown      = inet_shutdown,
    .setsockopt    = sock_common_setsockopt,
    .getsockopt    = sock_common_getsockopt,
    .sendmsg       = inet_sendmsg,
    .recvmsg       = inet_recvmsg,
    .mmap          = sock_no_mmap,
    .sendpage      = inet_sendpage,
    .splice_read       = tcp_splice_read,
};

sock_sendmsg

sock_sendmsg位於net/socket.c檔案

sock_sendmsg
    __sock_sendmsg
        struct socket *sock;
        sock->ops->sendmsg //這個ops是struct socket結構體中的struct proto_ops
            inet_sendmsg
                struct sock *sk = sock->sk;
                sk->sk_prot->sendmsg //這個ops是struct sock結構體中的struct proto

sock_recvmsg

sock_recvmsg位於net/socket.c檔案

sock_recvmsg
    __sock_recvmsg
        struct socket *sock;
        sock->ops->recvmsg //這個ops是struct socket結構體中的struct proto_ops
            sock_common_recvmsg
                struct sock *sk = sock->sk;
                sk->sk_prot->recvmsg //這個ops是struct sock結構體中的struct proto