linux net子系統-套介面層
阿新 • • 發佈:2019-01-09
核心資料結構
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