setsockopt的工作流程(从用户空间到内核)
来源:互联网 发布:mac xampp设置htdoc 编辑:程序博客网 时间:2024/05/22 13:59
一、用户空间
获取套接口选项:
1. int getsockopt ( int sockfd, int level, int optname, void * optval, socklen_t *opteln ) 设置套接口选项:
2. int setsockopt ( int sockfd, int level, int optname, const void * optval, socklen_t *opteln )
二、内核空间
系统调用setsockopt是通过内核sys_setsockopt函数实现的
- asmlinkage long sys_setsockopt(int fd,int level, int optname, char __user *optval, int optlen)
- {
- ……
- if ((sock = sockfd_lookup_light(fd,&err,&fput_needed))!= NULL)
- {
- ……
- if (level == SOL_SOCKET)//基本套接口
- 套接口类型(linux/socket.h):
- /* Setsockoptions(2) level. Thanks to BSD these must match IPPROTO_xxx */
- #define SOL_IP 0
- /* #define SOL_ICMP 1 No-no-no! Due to Linux :-) we cannot use SOL_ICMP=1 */
- #define SOL_TCP 6
- #define SOL_UDP 17
- ……
- err=sock_setsockopt(sock,level,optname,optval,optlen);
- else
- err=sock->ops->setsockopt(sock, level, optname, optval, optlen);
- ……
- }
- return err;
- }
假如我们定义的套接口是IPPROTO_IP=0,所以我们将调用SOL_IP套接口,err=sock->ops->setsockopt(sock, level, optname, optval, optlen),该钩子为proto_ops类型,所以它指向了我们注册的inet_stream_ops钩子,所以setsockopt指向了sock_common_setsockopt函数(net/core/sock.c)
在net/ipv4/af_inet.c文件中,函数inet_init注册了inetsw_array数组
- for(q = inetsw_array; q< &inetsw_array[INETSW_ARRAY_LEN];++q)
- inet_register_protosw(q);
- static struct inet_protosw inetsw_array[]=
- {
- {
- .type= SOCK_STREAM,
- .protocol= IPPROTO_TCP,
- .prot= &tcp_prot,
- .ops= &inet_stream_ops,
- .capability= -1,
- .no_check= 0,
- .flags= INET_PROTOSW_PERMANENT |
- INET_PROTOSW_ICSK,
- },
- ……
- };
譬如它注册了inet_stream_ops针对tcp协议
- const struct proto_ops inet_stream_ops= {
- .family = PF_INET,
- .owner = THIS_MODULE,
- ……
- .setsockopt = sock_common_setsockopt,
- .getsockopt = sock_common_getsockopt,
- ……
- };
现在我们看接口函数sock_common_setsockopt
- int sock_common_setsockopt(struct socket*sock, int level, int optname,
- char __user *optval, int optlen)
- {
- struct sock *sk= sock->sk;
- return sk->sk_prot->setsockopt(sk, level, optname, optval, optlen);
- }
由于sk->sk_prot是指向协议的钩子,如果它指向了tcp协议钩子,setsockopt指向了tcp_setsockopt函数(net/ipv4/tcp.c)
- struct proto tcp_prot= {
- .name ="TCP",
- .owner = THIS_MODULE,
- ……
- .setsockopt = tcp_setsockopt,
- .getsockopt = tcp_getsockopt,
- ……
- }
- int tcp_setsockopt(struct sock*sk, int level, int optname, char __user *optval,
- int optlen)
- {
- struct inet_connection_sock *icsk = inet_csk(sk);
- if (level != SOL_TCP)//显然我们注册的是SOL_IP所以执行下面语句
- return icsk->icsk_af_ops->setsockopt(sk, level, optname,
- optval, optlen);
- return do_tcp_setsockopt(sk, level, optname, optval, optlen);//如果注册时SOL_TCP就执行
- }
如果注册时SOL_IP则由于isck->isck_af_ops是inet_connection_sock_af_ops类型的钩子,此钩子的注册为
- struct inet_connection_sock_af_ops ipv4_specific= {
- ……
- .setsockopt = ip_setsockopt,
- .getsockopt = ip_getsockopt,
- ……
- };
注册ip_setsockopt(net/ipv4/tcp_ipv4.c)接口
- int ip_setsockopt(struct sock*sk, int level,
- int optname, char __user*optval, int optlen)
- {
- int err;
- if (level != SOL_IP)
- return -ENOPROTOOPT;
- err = do_ip_setsockopt(sk, level, optname, optval, optlen);//注册是IPPROTO_IP执行
- #ifdef CONFIG_NETFILTER
- /* we needto exclude all possible ENOPROTOOPTs except defaultcase */
- if (err ==-ENOPROTOOPT && optname!= IP_HDRINCL&&
- optname != IP_IPSEC_POLICY&& optname != IP_XFRM_POLICY
- #ifdef CONFIG_IP_MROUTE
- &&(optname < MRT_BASE|| optname > (MRT_BASE + 10))
- #endif
- ) {
- lock_sock(sk);
- err = nf_setsockopt(sk, PF_INET, optname, optval, optlen);//如果编译选项中设置了CONFIG_NETFILTER,就调用nf_setsockopt函数
- release_sock(sk);
- }
- #endif
- return err;
- }
到此我们知道了如果注册时IPPROTO_IP最终会调用do_ip_setsockopt和nf_setsockopt函数
如果注册了IPPROTO_TCP最终会调用do_tcp_setsockopt函数
0 0
- setsockopt的工作流程(从用户空间到内核)
- 从用户空间的open到内核空间的open
- 从用户空间传递到内核中字符串的长度
- 从用户态的open到内核驱动实现流程
- 从用户态的open到内核驱动实现流程
- 从用户态的open到内核驱动实现流程
- 从用户态的open到内核驱动实现流程
- 从用户态的open到内核驱动实现流程
- Linux Malloc分析-从用户空间到内核空间
- Linux Malloc分析-从用户空间到内核空间
- Linux Malloc分析-从用户空间到内核空间
- Linux Malloc分析-从用户空间到内核空间
- Linux Malloc分析-从用户空间到内核空间
- 热插拔时间从内核空间到用户空间的传递过程
- 热插拔时间从内核空间到用户空间的传递过程
- 1 - 热插拔时间从内核空间到用户空间的传递过程
- 详细讲解从用户空间申请内存到内核如何为其分配内存的过程
- Linux内核源码分析—从用户空间复制数据到内核空间
- 未能加载文件或程序集"Microsoft.Web.Infrastructure 的解决方案
- CSS固定背景的图片
- MySQL数据导入导出命令
- 九度OJ 1113 二叉树
- 【NSBD】——二维码的生成与打印
- setsockopt的工作流程(从用户空间到内核)
- MySQL:MHA测试
- CSS设置背景图片
- C#类型基础(值类型and引用类型)
- 各种软件常用下载地址(更新中~~~
- 【Java并发编程】深入分析AtomicInteger(二)
- C++ Primer 第13章 知识点回顾
- java中的冒泡排序
- 【Java并发编程】深入分析synchronized(三)