本文分析基于内核Linux Kernel 1.2.13

以后的系列博文将深入分析Linux内核的网络栈实现原理,这里看到曹桂平博士的分析后,也决定选择Linux内核1.2.13版本进行分析。

原因如下:

1.功能和网络栈层次已经非常清晰

2.该版本与其后续版本的衔接性较好

3.复杂度相对新的内核版本较小,复杂度低,更容易把握网络内核的实质

4.该内核版本比较系统资料可以查询

下面开始零基础分析Linux内核网络部分的初始化过程。

经过系统加电后执行的bootsect.S,setup.S,head.S,可以参考以前分析的0.11内核。原理相同。

进行前期的准备工作后,系统跳转到init/main.c下的start_kernel函数执行。

网络栈的层次结构如下图:(注:该图片摘自《Linux内核网络栈源代码情景分析》)

start_kernel函数经过平台初始化,内存初始化,陷阱初始化,中断初始化,进程调度初始化,缓冲区初始化等,然后执行socket_init(),最后开中断执行init()。

内核的网络战初始化函数socket_init()函数的实现在net/socket.c中

下面是该函数的实现

voidsock_init(void)//网络栈初始化

{

inti;

printk("Swansea University Computer Society NET3.019\n");

/*

*  Initialize all address (protocol) families.

*/

for(i = 0; i

/*

*  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 NPROTO16/* 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中

structproto_ops {

intfamily;

int(*create)   (structsocket *sock,intprotocol);

int(*dup)      (structsocket *newsock,structsocket *oldsock);

int(*release)  (structsocket *sock,structsocket *peer);

int(*bind)     (structsocket *sock,structsockaddr *umyaddr,

intsockaddr_len);

int(*connect)  (structsocket *sock,structsockaddr *uservaddr,

intsockaddr_len,intflags);

int(*socketpair)   (structsocket *sock1,structsocket *sock2);

int(*accept)   (structsocket *sock,structsocket *newsock,

intflags);

int(*getname)  (structsocket *sock,structsockaddr *uaddr,

int*usockaddr_len,intpeer);

int(*read)     (structsocket *sock,char*ubuf,intsize,

intnonblock);

int(*write)    (structsocket *sock,char*ubuf,intsize,

intnonblock);

int(*select)   (structsocket *sock,intsel_type,

select_table *wait);

int(*ioctl)    (structsocket *sock, unsignedintcmd,

unsignedlongarg);

int(*listen)   (structsocket *sock,intlen);

int(*send)     (structsocket *sock,void*buff,intlen,intnonblock,

unsigned flags);

int(*recv)     (structsocket *sock,void*buff,intlen,intnonblock,

unsigned flags);

int(*sendto)   (structsocket *sock,void*buff,intlen,intnonblock,

unsigned flags,structsockaddr *,intaddr_len);

int(*recvfrom) (structsocket *sock,void*buff,intlen,intnonblock,

unsigned flags,structsockaddr *,int*addr_len);

int(*shutdown) (structsocket *sock,intflags);

int(*setsockopt)   (structsocket *sock,intlevel,intoptname,

char*optval,intoptlen);

int(*getsockopt)   (structsocket *sock,intlevel,intoptname,

char*optval,int*optlen);

int(*fcntl)    (structsocket *sock, unsignedintcmd,

unsignedlongarg);

};可以看到,这里实际上就是一系列操作的函数,有点类似于文件系统中的file_operations。通过参数传递socket完成操作。

接下来是proto_init()协议初始化。

voidproto_init(void)

{

externstructnet_proto protocols[];/* Network protocols 全局变量,定义在protocols.c中 */

structnet_proto *pro;

/* Kick all configured protocols. */

pro = protocols;

while(pro->name != NULL)

{

(*pro->init_func)(pro);

pro++;

}

/* We're all done... */

}全局的protocols定义如下:

structnet_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中为

structnet_proto {

char*name;/* Protocol name */

void(*init_func)(structnet_proto *);/* Bootstrap */

};以后注重讨论标准的INET域

让我们回到proto_init()函数

接下来会执行inet_proto_init()函数,进行INET域协议的初始化。该函数的实现在net/inet/af_inet.c中

其中的

(void) sock_register(inet_proto_ops.family, &inet_proto_ops);

intsock_register(intfamily,structproto_ops *ops)

{

inti;

cli();//关中断

for(i = 0; i

{

if(pops[i] != NULL)

continue;//如果不空,则跳过

pops[i] = ops;//进行赋值

pops[i]->family = family;

sti();//开中断

return(i);//返回用于刚刚注册的协议向量号

}

sti();//出现异常,也要开中断

return(-ENOMEM);

}

参数中的inet_proto_ops定义如下:

staticstructproto_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中

{

structinet_protocol *tmp = (structinet_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内核网络栈源代码的详细分析。

linux内核网络初始化,Linux内核--网络栈实现分析相关推荐

  1. linux恢复硬盘初始状态,初始化Linux数据盘(fdisk)

    初始化Linux数据盘(fdisk)TkV南京数据恢复-西数科技: 硬盘/手机/SSD数据恢复专家. 025-83608636 18913825606 查看PDFTkV南京数据恢复-西数科技: 硬盘/ ...

  2. linux 字符串数组初始化,Linux命令行 – 数组

    在上一章中,我们查看了 shell 怎样操作字符串和数字的.目前我们所见到的数据类型在计算机科学圈里被 称为标量变量:也就是说,只能包含一个值的变量. 在本章中,我们将看看另一种数据结构叫做数组,数组 ...

  3. Linux内核--网络栈实现分析(二)--数据包的传递过程--转

    转载地址http://blog.csdn.net/yming0221/article/details/7492423 作者:闫明 本文分析基于Linux Kernel 1.2.13 注:标题中的&qu ...

  4. linux内核网络协议栈--linux bridge(十九)

    1 . 前言 本文是参考附录上的资料整理而成,以帮助读者更好的理解kernel中brdige 模块代码. 2. 网桥的原理 2.1 桥接的概念 简单来说,桥接就是把一台机器上的若干个网络接口" ...

  5. linux内核网络协议栈--linux网络设备理解(十三)

    网络层次 linux网络设备驱动与字符设备和块设备有很大的不同. 字符设备和块设备对应/dev下的一个设备文件.而网络设备不存在这样的设备文件.网络设备使用套接字socket访问,虽然也使用read, ...

  6. 浅析linux内核网络协议栈--linux bridge

    1 . 前言 本文是参考附录上的资料整理而成,以帮助读者更好的理解kernel中brdige 模块代码. 2. 网桥的原理 2.1 桥接的概念 简单来说,桥接就是把一台机器上的若干个网络接口" ...

  7. 调试linux内核前的多虚拟机网络配置(图文教程)

    需求: Linux源代码的分析中重要的一部分,是网络管理内核.最基本的内核调试平是两台联网的机器.内核调试平台由开发机和目标机两台机器构成,并要为他们配置网络.内核调试平台分为硬件物理结构和软件虚拟结 ...

  8. linux 网络瘫痪,Linux内核发现TCP漏洞,小流量也能DoS瘫痪设备

    卡内基梅隆大学的 CERT/CC 发出一个 Linux 内核漏洞警告,称 Linux 4.9 内核或者更高版本中出现一个 TCP 漏洞,该漏洞可使攻击者通过极小流量对系统发动 DoS (Denial- ...

  9. 【树莓派学习笔记】树莓派4B上运行uboot并从网络启动linux内核(上)

    [树莓派学习笔记]树莓派4B上运行uboot并从网络启动linux内核(上) 文章目录 [树莓派学习笔记]树莓派4B上运行uboot并从网络启动linux内核(上) 前言 1. 硬件需求与软件版本汇总 ...

最新文章

  1. 计算机房装修对门的要求,防火门尺寸要求有哪些 防火门尺寸规范
  2. 如何把class里的vector结构体memcpy出来_面试官:请说出线程安全的 ArrayList 有哪些,除了Vector...
  3. structs2文件下载
  4. JSON 解析的两种方法
  5. C++ Primer 有感(重载操作符)
  6. mysql课程表学时_Mysql 巩固提升 (学生表_课程表_成绩表_教师表)
  7. Java7和8在虚拟机上的差异:Perm Generation vs. Metaspace
  8. python链接MySQL数据库
  9. Mozilla推荐的CSS属性书写顺序及命名规则
  10. 使用STL标准模板库实现的个人通讯录
  11. awk命令详解+示例
  12. ba无标度网络python_python绘制BA无标度网络示例代码
  13. 笔记本电脑Haswell黑苹果opencore睡眠实战
  14. HTML+CSS网页设计期末课程大作业 【茶叶文化网站设计题材】web前端开发技术 web课程设计 网页规划与设计
  15. 你和语言模型,谁的填空能力更强?
  16. 对100层楼两个玻璃球测试问题的理解
  17. 【Android】自定义View的位置参数
  18. abstract(抽象)的定义和使用
  19. queue和deque的区别
  20. 获取微信小程序的昵称和手机号

热门文章

  1. golang Receiver has generic name 问题解决
  2. javascript 编码规范 用更合理的方式写 javascript
  3. linux c warning: implicit declaration of function 'strtok_r'解决方案
  4. Nmap源码分析(主机发现)
  5. centos安装 ping 命令 ( yum provides )
  6. Vivotek 摄像头远程栈溢出漏洞分析及利用
  7. 工控系统的指纹识别技术
  8. smarty实例教程
  9. 深入理解 C 指针阅读笔记 -- 第五章
  10. Ubuntu安装google拼音输入法