Linux内核--网络栈实现分析(一)--网络栈初始化
本文分析基于内核Linux Kernel 1.2.13
原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7488828
更多请看专栏,地址http://blog.csdn.net/column/details/linux-kernel-net.html
以后的系列博文将深入分析Linux内核的网络栈实现原理,这里看到曹桂平博士的分析后,也决定选择Linux内核1.2.13版本进行分析。
3.复杂度相对新的内核版本较小,复杂度低,更容易把握网络内核的实质
经过系统加电后执行的bootsect.S,setup.S,head.S,可以参考以前分析的0.11内核。原理相同。
进行前期的准备工作后,系统跳转到init/main.c下的start_kernel函数执行。
网络栈的层次结构如下图:(注:该图片摘自《Linux内核网络栈源代码情景分析》)
链路层主要指的是提供对物理层进行访问的各种接口卡的驱动程序,如网卡驱动等;
网路层的作用是负责将网络数据包传输到正确的位置,最重要的网络层协议当然就是IP协议了,其实网络层还有其他的协议如ICMP,ARP,RARP等,只不过不像IP那样被多数人所熟悉;
传输层的作用主要是提供端到端,说白一点就是提供应用程序之间的通信,传输层最着名的协议非TCP与UDP协议末属了;
1,系统调用接口层,实质是一个面向用户空间应用程序的接口调用库,向用户空间应用程序提供使用网络服务的接口。
3,网络协议实现层,毫无疑问,这是整个协议栈的核心。这一层主要实现各种网络协议,最主要的当然是IP,ICMP,ARP,RARP,TCP,UDP等。这一层包含了很多设计的技巧与算法,相当的不错。
5,驱动程序层,这一层的目的就很简单了,就是建立与硬件的接口层。
start_kernel函数经过平台初始化,内存初始化,陷阱初始化,中断初始化,进程调度初始化,缓冲区初始化等,然后执行socket_init(),最后开中断执行init()。
内核的网络战初始化函数socket_init()函数的实现在net/socket.c中
- void sock_init(void)//网络栈初始化
- {
- int i;
- printk("Swansea University Computer Society NET3.019\n");
- /*
- * Initialize all address (protocol) families.
- */
- for (i = 0; i < NPROTO; ++i) pops[i] = NULL;
- /*
- * Initialize the protocols module.
- */
- proto_init();
- #ifdef CONFIG_NET
- /*
- * Initialize the DEV module.
- */
- dev_init();
- /*
- * And the bottom half handler
- */
- bh_base[NET_BH].routine= net_bh;
- enable_bh(NET_BH);
- #endif
- }
其中的地址族协议初始化语句for (i = 0; i < NPROTO; ++i) pops[i] = NULL;
这里文件中定义的NPROTO为16
#define NPROTO 16 /* should be enough for now.. */
而pop[i]是如何定义的呢?
static struct proto_ops *pops[NPROTO];
proto_ops结构体是什么呢?该结构体的定义在include/linux/net.h中,该结构体是具体的操作函数集合,是联系BSD套接字和INET套接字的接口,可以把BSD套接字看做是INET套接字的抽象,结构示意图如下:
具体定义在net.h中
- struct proto_ops {
- int family;
- int (*create) (struct socket *sock, int protocol);
- int (*dup) (struct socket *newsock, struct socket *oldsock);
- int (*release) (struct socket *sock, struct socket *peer);
- int (*bind) (struct socket *sock, struct sockaddr *umyaddr,
- int sockaddr_len);
- int (*connect) (struct socket *sock, struct sockaddr *uservaddr,
- int sockaddr_len, int flags);
- int (*socketpair) (struct socket *sock1, struct socket *sock2);
- int (*accept) (struct socket *sock, struct socket *newsock,
- int flags);
- int (*getname) (struct socket *sock, struct sockaddr *uaddr,
- int *usockaddr_len, int peer);
- int (*read) (struct socket *sock, char *ubuf, int size,
- int nonblock);
- int (*write) (struct socket *sock, char *ubuf, int size,
- int nonblock);
- int (*select) (struct socket *sock, int sel_type,
- select_table *wait);
- int (*ioctl) (struct socket *sock, unsigned int cmd,
- unsigned long arg);
- int (*listen) (struct socket *sock, int len);
- int (*send) (struct socket *sock, void *buff, int len, int nonblock,
- unsigned flags);
- int (*recv) (struct socket *sock, void *buff, int len, int nonblock,
- unsigned flags);
- int (*sendto) (struct socket *sock, void *buff, int len, int nonblock,
- unsigned flags, struct sockaddr *, int addr_len);
- int (*recvfrom) (struct socket *sock, void *buff, int len, int nonblock,
- unsigned flags, struct sockaddr *, int *addr_len);
- int (*shutdown) (struct socket *sock, int flags);
- int (*setsockopt) (struct socket *sock, int level, int optname,
- char *optval, int optlen);
- int (*getsockopt) (struct socket *sock, int level, int optname,
- char *optval, int *optlen);
- int (*fcntl) (struct socket *sock, unsigned int cmd,
- unsigned long arg);
- };
可以看到,这里实际上就是一系列操作的函数,有点类似于文件系统中的file_operations。通过参数传递socket完成操作。
接下来是proto_init()协议初始化。
- void proto_init(void)
- {
- extern struct net_proto protocols[]; /* Network protocols 全局变量,定义在protocols.c中 */
- struct net_proto *pro;
- /* Kick all configured protocols. */
- pro = protocols;
- while (pro->name != NULL)
- {
- (*pro->init_func)(pro);
- pro++;
- }
- /* We're all done... */
- }
全局的protocols定义如下:
- struct net_proto protocols[] = {
- #ifdef CONFIG_UNIX
- { "UNIX", unix_proto_init },
- #endif
- #if defined(CONFIG_IPX)||defined(CONFIG_ATALK)
- { "802.2", p8022_proto_init },
- { "SNAP", snap_proto_init },
- #endif
- #ifdef CONFIG_AX25
- { "AX.25", ax25_proto_init },
- #endif
- #ifdef CONFIG_INET
- { "INET", inet_proto_init },
- #endif
- #ifdef CONFIG_IPX
- { "IPX", ipx_proto_init },
- #endif
- #ifdef CONFIG_ATALK
- { "DDP", atalk_proto_init },
- #endif
- { NULL, NULL }
- };
而结构体net_proto的定义net.h中为
- struct net_proto {
- char *name; /* Protocol name */
- void (*init_func)(struct net_proto *); /* Bootstrap */
- };
以后注重讨论标准的INET域
让我们回到proto_init()函数
接下来会执行inet_proto_init()函数,进行INET域协议的初始化。该函数的实现在net/inet/af_inet.c中
其中的
(void) sock_register(inet_proto_ops.family, &inet_proto_ops);
- int sock_register(int family, struct proto_ops *ops)
- {
- int i;
- cli();//关中断
- for(i = 0; i < NPROTO; i++) //查找一个可用的空闲表项
- {
- if (pops[i] != NULL)
- continue;//如果不空,则跳过
- pops[i] = ops;//进行赋值
- pops[i]->family = family;
- sti();//开中断
- return(i);//返回用于刚刚注册的协议向量号
- }
- sti();//出现异常,也要开中断
- return(-ENOMEM);
- }
参数中的inet_proto_ops定义如下:
- static struct proto_ops inet_proto_ops = {
- AF_INET,
- inet_create,
- inet_dup,
- inet_release,
- inet_bind,
- inet_connect,
- inet_socketpair,
- inet_accept,
- inet_getname,
- inet_read,
- inet_write,
- inet_select,
- inet_ioctl,
- inet_listen,
- inet_send,
- inet_recv,
- inet_sendto,
- inet_recvfrom,
- inet_shutdown,
- inet_setsockopt,
- inet_getsockopt,
- inet_fcntl,
- };
其中AF_INET宏定义为2,即INET协议族号为2,后面是函数指针,INET域的操作函数。
然后
- printk("IP Protocols: ");
- for(p = inet_protocol_base; p != NULL;) //将inet_protocol_base指向的一个inet_protocol结构体加入数组inet_protos中
- {
- 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();//对IP层进行初始化
协议初始化完成后再执行dev_init()设备的初始化。
这是大体的一个初始化流程,讨论的不是很详细,后续会进行Linux内核网络栈源代码的详细分析。
转载于:https://www.cnblogs.com/hehehaha/archive/2013/04/12/6332919.html
Linux内核--网络栈实现分析(一)--网络栈初始化相关推荐
- Linux内核抢占实现机制分析【转】
Linux内核抢占实现机制分析 转自:http://blog.chinaunix.net/uid-24227137-id-3050754.html [摘要]本文详解了Linux内核抢占实现机制.首先介 ...
- linux内核中链表代码分析---list.h头文件分析(二)【转】
转自:http://blog.chinaunix.net/uid-30254565-id-5637598.html linux内核中链表代码分析---list.h头文件分析(二) 16年2月28日16 ...
- 第十期-Linux内核补丁源码分析(2)
作者:罗宇哲,中国科学院软件研究所智能软件研究中心 在上一期中,我们通过CAKE系统的实例介绍了一种对Linux内核补丁的初步分析方法,这一期我们将继续通过CAKE系统的例子介绍一种对补丁文件源码的分 ...
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】Linux内核抢占实现机制分析
Linux内核抢占实现机制分析 Sailor_forever sailing_9806@163.com 转载请注明 http://blog.csdn.net/sailor_8318/archive/ ...
- linux内核中链表代码分析---list.h头文件分析(一)
linux内核中链表代码分析---list.h头文件分析(一) 16年2月27日17:13:14 在学习数据结构时,有一个重要的知识点就是链表.对于链表的一些基本操作,它的最好学习资料就是内核中的li ...
- Linux内核深入理解系统调用(1):初始化-入口-处理-退出
Linux内核深入理解系统调用(1):初始化-入口-处理-退出 rtoax 2021年3月 1. Linux 内核系统调用简介 这次提交为 linux内核解密 添加一个新的章节,从标题就可以知道, 这 ...
- 【内核】linux内核启动流程详细分析【转】
转自:http://www.cnblogs.com/lcw/p/3337937.html Linux内核启动流程 arch/arm/kernel/head-armv.S 该文件是内核最先执行的一个文件 ...
- 【内核】linux内核启动流程详细分析
Linux内核启动流程 arch/arm/kernel/head-armv.S 该文件是内核最先执行的一个文件,包括内核入口ENTRY(stext)到start_kernel间的初始化代码, 主要作用 ...
- 嵌入式Linux内核移植相关代码分析(转)
本文通过整理之前研发的一个项目(ARM7TDMI +uCLinux),分析内核启动过程及需要修改的文件,以供内核移植者参考.整理过程中也同时参考了众多网友的帖子,在此谢过.由于整理过程匆忙,难免 错误 ...
- 【华为云技术分享】Linux内核补丁源码分析(1)
在上一期中,我们介绍了Linux内核编程环境,在这一期中,我们将通过实例来介绍如何分析Linux内核的补丁. 一.Linux内核补丁 在"Linux内核发展史"中,我们简要介绍了L ...
最新文章
- 汇编和python-PyAsm-在python中嵌入汇编 | 学步园
- JZOJ 4822. 【NOIP2016提高A组集训第1场10.29】完美标号
- 数据结构探险——图篇
- 10 个理由让你继续干 IT
- 数组任意取三个数中乘积最大值
- 我以为内卷是外包的反义词!
- if or函数套用_excel常用函数用法解析第二篇——SUMPRODUCT、AND、OR、IF函数
- STAR:转录组数据比对工具简介
- oracle库客户端完整卸载,卸载Oracle数据库或客户端​
- seaweedfs入门
- 互联网集体下沉,PKQ后又一匹下沉黑马出现了
- JavaScript 剪贴板
- GitHub与微信开启“秘密扫描”计划,来确保数据安全
- 通过伴随矩阵怎么求逆矩阵
- (附源码)springboot基于JAVA的电影推荐系统的开发与实现 毕业设计112306
- 容器化 中国5000年 历史时间轴
- html如何添加多个视频教程,html多格式视频教程
- 华硕B85M-E BIOS NVME m.2 mmtool4.5 硬盘提速25倍
- Android 计步器开发
- pink老师前端入门视频教程笔记(中)
热门文章
- nginx 带宽_你知道服务器的带宽怎样设置吗?
- 现代通信原理5.2:带通信号的(复包络)低通表示
- hdu acm2549
- t14m4t:一款功能强大的自动化暴力破解工具
- 获取北京时间 日开始时间戳
- Mysql报错(必解决):The user specified as a definer (‘mysql.infoschema‘@‘localhost‘) does not exist
- lnmp mysql 哪个好_[LNMP]Mysql生产环境配置
- cv python 画直线_Python进阶之Matplotlib入门(一)
- 根据缺口的模式选股买股票,python 学习代码
- 解决linux 运行自动化脚本浏览器无法启动问题