Linux内核网络栈1.2.13-有关tcp/ip协议的基础入门

news/2024/7/7 21:58:08

参考资料

<<linux内核网络栈源代码情景分析>>

Linux内核网络栈的基础内容

主要分析tcp/ip相关的基本构成,概述了socket的系统调用进入内核的一个流程,并了解了协议的执行流程。为后续的理解学习做铺垫。

应用程序调用进入内核的过程

Tcp/ip协议示意图如下;

在这里插入图片描述

在Linux操作系统上面,从用户态进入内核态的方式就是通过系统调用INT $0x80进入内核执行函数,中断处理函数通过不同的系统调用号来选择操作系统初始化时注册的函数,对于socket,bind,connect等函数都是通过该方式来调用的,这些方法就是用户态调用的相关方法,因为linux在启动初始化的过程中会调用trap_init函数注册相关的事件的回调函数,其中就会执行set_system_gate(0x80,&system_call);函数,该函数就是注册调用号为0x80的函数,对应的回调函数为system_call,system_call函数就是汇编函数实现的位于i386/kernel/entry.S中;

.align 4
_system_call:pushl %eax			# save orig_eaxSAVE_ALLmovl $-ENOSYS,EAX(%esp)cmpl $(NR_syscalls),%eaxjae ret_from_sys_callmovl _sys_call_table(,%eax,4),%eaxtestl %eax,%eaxje ret_from_sys_callmovl _current,%ebxandl $~CF_MASK,EFLAGS(%esp)	# clear carry - assume no errorsmovl $0,errno(%ebx)movl %db6,%edxmovl %edx,dbgreg6(%ebx)  # save current hardware debugging statustestb $0x20,flags(%ebx)		# PF_TRACESYSjne 1fcall *%eaxmovl %eax,EAX(%esp)		# save the return valuemovl errno(%ebx),%edxnegl %edxje ret_from_sys_callmovl %edx,EAX(%esp)orl $(CF_MASK),EFLAGS(%esp)	# set carry to indicate errorjmp ret_from_sys_call

从这段汇编代码可知,根据传入的系统调用号会在_sys_call_table中去查找对应位置的系统函数,对应的_sys_call_table列表的初始化位于sparc/kernel/entry.S中,

		.align 4.globl C_LABEL(sys_call_table)
C_LABEL(sys_call_table):.long C_LABEL(sys_setup)		/* 0 */.long C_LABEL(sys_exit).long C_LABEL(sys_fork).long C_LABEL(sys_read).long C_LABEL(sys_write).long C_LABEL(sys_open)			/* 5 */.long C_LABEL(sys_close).long C_LABEL(sys_waitpid)....long C_LABEL(sys_munmap).long C_LABEL(sys_truncate).long C_LABEL(sys_ftruncate).long C_LABEL(sys_fchmod).long C_LABEL(sys_fchown)		/* 95 */.long C_LABEL(sys_getpriority).long C_LABEL(sys_setpriority).long C_LABEL(sys_profil).long C_LABEL(sys_statfs).long C_LABEL(sys_fstatfs)		/* 100 */.long C_LABEL(sys_ni_syscall).long C_LABEL(sys_socketcall) 				// socket相关系统调用处理函数.long C_LABEL(sys_syslog).long C_LABEL(sys_setitimer).long C_LABEL(sys_getitimer)		/* 105 */....align 4

此时查看指向的函数sys_socketcall函数内容;

asmlinkage int sys_socketcall(int call, unsigned long *args)
{int er;switch(call) {case SYS_SOCKET:er=verify_area(VERIFY_READ, args, 3 * sizeof(long));  			// 检查输入参数的合法性if(er)return er; 													// 调用socket初始化执行return(sock_socket(get_fs_long(args+0),get_fs_long(args+1),get_fs_long(args+2)));case SYS_BIND:er=verify_area(VERIFY_READ, args, 3 * sizeof(long)); 		   if(er)return er;return(sock_bind(get_fs_long(args+0),(struct sockaddr *)get_fs_long(args+1),get_fs_long(args+2))); 										// 套接字绑定初始化case SYS_CONNECT:er=verify_area(VERIFY_READ, args, 3 * sizeof(long));if(er)return er;return(sock_connect(get_fs_long(args+0),(struct sockaddr *)get_fs_long(args+1),get_fs_long(args+2))); 									   // 套接字连接case SYS_LISTEN:er=verify_area(VERIFY_READ, args, 2 * sizeof(long));if(er)return er;return(sock_listen(get_fs_long(args+0),get_fs_long(args+1))); 									  // 套接字监听case SYS_ACCEPT:er=verify_area(VERIFY_READ, args, 3 * sizeof(long));if(er)return er;return(sock_accept(get_fs_long(args+0),(struct sockaddr *)get_fs_long(args+1),(int *)get_fs_long(args+2))); 							  // 接受新请求case SYS_GETSOCKNAME:er=verify_area(VERIFY_READ, args, 3 * sizeof(long));if(er)return er;return(sock_getsockname(get_fs_long(args+0),(struct sockaddr *)get_fs_long(args+1),(int *)get_fs_long(args+2))); 							 // 获取host信息case SYS_GETPEERNAME:er=verify_area(VERIFY_READ, args, 3 * sizeof(long));if(er)return er;return(sock_getpeername(get_fs_long(args+0),(struct sockaddr *)get_fs_long(args+1),(int *)get_fs_long(args+2)));case SYS_SOCKETPAIR:er=verify_area(VERIFY_READ, args, 4 * sizeof(long));if(er)return er;return(sock_socketpair(get_fs_long(args+0),get_fs_long(args+1),get_fs_long(args+2),(unsigned long *)get_fs_long(args+3))); 				case SYS_SEND:er=verify_area(VERIFY_READ, args, 4 * sizeof(unsigned long));if(er)return er;return(sock_send(get_fs_long(args+0),(void *)get_fs_long(args+1),get_fs_long(args+2),get_fs_long(args+3))); 									// 发送信息case SYS_SENDTO:er=verify_area(VERIFY_READ, args, 6 * sizeof(unsigned long));if(er)return er;return(sock_sendto(get_fs_long(args+0),(void *)get_fs_long(args+1),get_fs_long(args+2),get_fs_long(args+3),(struct sockaddr *)get_fs_long(args+4),get_fs_long(args+5)));case SYS_RECV:er=verify_area(VERIFY_READ, args, 4 * sizeof(unsigned long));if(er)return er;return(sock_recv(get_fs_long(args+0),(void *)get_fs_long(args+1),get_fs_long(args+2),get_fs_long(args+3))); 									// 接受信息case SYS_RECVFROM:er=verify_area(VERIFY_READ, args, 6 * sizeof(unsigned long));if(er)return er;return(sock_recvfrom(get_fs_long(args+0),(void *)get_fs_long(args+1),get_fs_long(args+2),get_fs_long(args+3),(struct sockaddr *)get_fs_long(args+4),(int *)get_fs_long(args+5)));case SYS_SHUTDOWN:er=verify_area(VERIFY_READ, args, 2* sizeof(unsigned long));if(er)return er;return(sock_shutdown(get_fs_long(args+0),get_fs_long(args+1)));case SYS_SETSOCKOPT:er=verify_area(VERIFY_READ, args, 5*sizeof(unsigned long));if(er)return er;return(sock_setsockopt(get_fs_long(args+0),get_fs_long(args+1),get_fs_long(args+2),(char *)get_fs_long(args+3),get_fs_long(args+4))); 									// 设置套接字配置信息case SYS_GETSOCKOPT:er=verify_area(VERIFY_READ, args, 5*sizeof(unsigned long));if(er)return er;return(sock_getsockopt(get_fs_long(args+0),get_fs_long(args+1),get_fs_long(args+2),(char *)get_fs_long(args+3),(int *)get_fs_long(args+4))); 						   // 获取套接字配置default:return(-EINVAL);}
}

应用程序调用socket的相关的流程就基本完成。

基于TCP/IP的结构图

在这里插入图片描述

整个的基本结构流程图如上所述。在socket.c文件中主要是做了相关检查之后就调用了inet层相关的函数,主要位于af_inet.c文件中,根据不同的协议在继续调用协议层对应的处理函数,然后再处理过ip层相关的信息,再调用相关的驱动的接口程序,讲数据发送。

总结

本文内容整理出于<<linux内核网络栈源代码情景分析>>,主要先概述了解了基本的协议的构成,从用户态到内核态的执行过程,本文只是简单的入门了解,后续内容会继续学习。由于本人才疏学浅,如有错误请批评指正。


http://lihuaxi.xjx100.cn/news/258059.html

相关文章

用C#实现FTP搜索引擎

晚辈最近用C#写了一个教育网FTP搜索引擎&#xff0c;希望能得到高手的指点。 网址&#xff1a;http://soso.ccnu.com.cn http://it.ccnu.edu.cn/soso 部分代码&#xff1a; using System;using softplib;using System.Threading;using System.Collections;using System.Ne…

Python 搭建 AI 健身评分系统

作者|李秋键来源|AI科技大本营&#xff08;ID:rgznai100&#xff09;引言人工智能作为计算机科学的一个分支,其主要是将人的思维与计算机网络相结合,令整个系统在对某一类事物进行处理时实现人工智能化分析,然后结合内部程序的设定,分析出当前事务处理所具备的各类功能如何实现…

终于把XGBoost总结写出来了!

↑↑↑关注后"星标"Datawhale每日干货 & 每月组队学习&#xff0c;不错过Datawhale干货 作者&#xff1a;王茂霖&#xff0c;华中科技大学&#xff0c;Datawhale成员内容概括XGBoost模型及调参总结XGBoost原理XGBoost优势总结XGBoost参数详解XGBoost快速使用XGBo…

使用 StopWatch 优雅打印执行耗时

欢迎关注方志朋的博客&#xff0c;回复”666“获面试宝典0x01&#xff1a;背景有时在做开发的时候需要记录每个任务执行时间&#xff0c;或者记录一段代码执行时间&#xff0c;最简单的方法就是打印当前时间与执行完时间的差值&#xff0c;然后这样如果执行大量测试的话就很麻烦…

Linux内核网络栈1.2.13-网卡设备的初始化流程

参考资料 <<linux内核网络栈源代码情景分析>>网卡设备的初始化 本文主要描述一下网卡设备的整个初始化的过程&#xff0c;该过程主要就是根据设备的硬件信息来获取与传输网络数据&#xff0c;注册相关的网卡中断处理函数&#xff0c;协议的初始化等内容。 初始化…

Matlab与线性代数 -- 矩阵的水平连接和垂直连接

本图文详细介绍了Matlab中矩阵的水平连接和垂直连接。

教大模型自己跳过“无用”层,推理速度×3性能不变,谷歌MIT这个新方法火了...

点击上方“视学算法”&#xff0c;选择加"星标"或“置顶”重磅干货&#xff0c;第一时间送达萧箫 发自 凹非寺量子位 | 公众号 QbitAI大语言模型用着爽&#xff0c;但推理速度实在太慢了&#xff1f;而且&#xff0c;增加模型体积&#xff0c;推理效果也并不一定就比…

android中的回调

1、引子 android中的回调最经典的就是点击事件设置监听&#xff08;一般通过switch&#xff08;v.getId()&#xff09;&#xff09;这里写个最主要的 btn_rigister.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View view) {// TODO log in} }…