0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何让自己创建的tcp协议栈为其他应用程序提供网络服务?

FPGA之家 来源:embed linux share 作者:embed linux share 2021-03-22 11:07 次阅读

一般来说,使用套接字进行网络编程时,默认使用linux内核提供的网络服务。但是,现在我们自己在用户空间构建了一个tcp协议栈,并且让它为其他应用程序提供网络服务,这势必要求我们自己实现一套新的套接字接口,并且提供给其他应用程序指定使用。

但是,我们并不希望把该tcp协议栈封装成动态库的形式,因为这样一来,应用程序的编译是必须要把库一起连接进去的。那么原生网络编程开发的程序就不能基于我们tcp协议栈来运行了。

一种较好的设计思路是,把tcp协议栈剥离出来作为一个独立的组件来运行,然后通过一个中间件,把网络程序与tcp协议栈协同工作起来。这个中间件的主要工作就是负责偷龙换凤,也就是把网络程序中的内核网络服务转换成独立运行的tcp协议栈的网络服务。

核心思路:网络程序(curl)+自定义套接字库(liblevel.so)+tcp协议栈(level-ip),如下图:

curl小工具

curl是一种命令行工具,作用是发出网络请求,然后得到和提取数据,显示在"标准输出"(stdout)上面。我们直接在curl命令后加上网址和端口,就可以看到网页源码。比如抓取www.sina.com网址:

curl www.sina.com 80

下面我们来看一个curl工具的简易实现,如下图:

第3行:判断目标主机名是否合法

第11行:判断目标端口好是否合法

第16行:完成主机名到地址解析

第21行:使用socket申请一个套接字描述符

第23行:使用connect函数发起tcp连接

第30行:按照http 1.1协议来填充要发送的内容,此处为http协议的get请求

第33行:调用write来发送网络数据

第41行:在while循环中重复接收服务器返回来的网页数据,并且打印在当前控制台终端上。

这是标准的网络应用程序,使用gcc命令编译后即可运行。

gcc curl.c -o curl

liblevelip.so库

level-ip脚本

liblevelip.so库重新封装了常用的socket套接字,并借助socket原生的本地套接字接口来与tcp协议栈(level-ip)进行数据通信。以后在curl程序使用socket套接字时,优先使用该库的服务接口,而不是内核的网络服务。这是通过level-ip这个shell脚本完成的,具体命令如下:

./level-ip curl www.sina.com 80

我们来分析一下level-ip这个shell脚本的原理,如下图:

第1行:执行该shell脚本由/bin/sh程序来执行。

第3行:指定脚本如果发生错误,或者遇到不存在的变量就报错,并停止执行。

第5行:保存脚本的第一个参数到prog变量中。

第6行:去掉一个参数,即原来的1,2,依此类推。

第8行:LD_PRELOAD是一个环境变量,其指定的动态库加载等级最高。@表示第二个参数之后的全部参数。

综上所述,我们就可以确定curl程序是优先加载liblevelip.so库来使用了,通过这种打桩技术,我们可以在加载阶段替换部分系统函数的调用,比如我们常用的socket接口。

liblevelip.c文件

liblevelip.so库由liblevellip.c文件编译而来,该文件在tools文件夹中,我们逐步来分析一下这个c文件。

__libc_start_main函数

首先是__libc_start_main函数,该函数原本是glibc库里面的函数,curl程序里面的main函数就是从这里开始被调用。但是我们在liblevelip.c里面实现了这个函数,并且liblevelip.so的库加载顺序优先于glibc的动态库加载。因此在执行curl程序中的main函数之前,此函数先被执行。如下图:

第3行:dlsym函数里的第一个参数为RTLD_NEXT,这意味着我们将从其他动态库去加载__libc_start_main函数符号(比如glibc库),然后把函数句柄赋值给__start_main变量。

第7~22行:从glibc库中加载一部分linux系统原生提供的系统调用接口。因为我们的网络服务还是要依赖于一些更底层的系统调用接口的。

第24行:初始化一个链表节点lvlip_socks。

第26行:调用glibc的原生__libc_start_main接口。

socket函数

接下来就是liblevelip.so对外提供的第一个网络编程接口--socket函数了。该函数实现如下:

第3~5行:检查网络通信协议族是否为tcp协议,如果不是tcp协议,则调用内核提供的网络服务。

第9行:借助tcp本地套接字接口,与tcp协议栈建立连接,用于通信的本地文件为/tmp/lvlip.socket

第11行:申请一个lvlip_sock类型的buff用于管理socket信息。结构体类型如下:

struct lvlip_sock { struct list_head list; int lvlfd; /* For Level-IP IPC */ int fd;};

list成员变量为链表结点

lvlfd记录与tcp协议栈通信的网络文件描述符

fd记录tcp协议栈的返回状态发送socket消息给tcp协议栈第12行:记录与tcp协议栈通信的网络文件描述符到sock->lvlfd第13行:把这次的网络通信消息加入lvlip_socks链表中第14行:网络通信消息数量加1第16行:获取当前线程的pid号

第17~18行:申请ipc_msg+ipc_socket结构体长度的buff,用于发送详细的socket信息到tcp协议栈。结构体定义如下:

struct ipc_msg { uint16_t type; pid_t pid; uint8_t data[];} __attribute__((packed));

type:记录此次socket信息的具体类型

pid:记录请求网络服务的进程pid号

data:存放具体的通信内容

struct ipc_socket { int domain; int type; int protocol;} __attribute__((packed));

实际上就是soket函数的三个参数。

第23~29行:把ipc_socket作为通信的具体内容填充到ipc_msg的data区域中去

第31行:调用transmit_lvlip()函数真正给tcp协议栈发送消息,并且等待协议栈的数据回复。

此处我们就把liblevelip.so中的socket函数给剖析清楚了,其他诸如close、connect、write、read、send、sendto、recv、此处我们就把liblevelip.so中的socket函数给剖析清楚了,其他诸如close、connect、write、read、send、sendto、recv、此处我们就把liblevelip.so中的socket函数给剖析清楚了,其他诸如close、connect、write、read、send、sendto、recv、recvfrom、poll、select等函数,原理都是一样的,此处不再展开分析。

tcp协议栈(level-ip)

用户空间的level-ip协议栈,在运行之初,就已经在main函数里面创建了一系列线程。如下图:

其中第9行,在run_threads()函数里创建了一系列线程,如下图:

在这里,我们重点关注第5行创建的start_ipc_listener线程

该线程的实现如下:

第5行:指定tcp本地通信的路径文件为"/tmp/lvlip.socket",与我们前面liblevelip.so库的本地通信文件一致,这就说明它们之间确实是通过tco本地通信接口来通信的

第10行:调用socket接口开始进行tcp本地通信

第24行:调用bind函数绑定本地通信路径

第31行:调用listen函数监听指定端口,等待liblevelip.so库发起连接

第46行:如果liblevelip.so库发起连接,则调用accept函数准备开始收发信息。

第54行:每监听到一个新的连接,新创建一个socket_ipc_open函数来进行数据的具体收发。

socket_ipc_open函数主要是负责通信信息的读取,然后根据通信消息的类型不同,来进一步调用具体的处理函数,其实现如下:

第7行:调用read函数进行数据的读取

第8行:调用具体指令的回调信息

demux_ipc_socket_call的函数非常简单,实现如下:

前面我们在liblevelip.so库中调用socket()函数的时候,发送的消息类型为IPC_SOCKET,所以在此处我们进一步分析ipc_socket()这个函数。

它的具体实现如下:

我们重点是关注第7行的_socket函数,该函数就是tcp协议栈的核心接口之一了,它是整个tcp协议栈的真正入口,我们以后再来专门分析这个接口。然后第9行,ipc_write函数负责把tcp协议栈的处理结果返回给liblevelip.so库,代码较为简单,此处不再分析。

原文标题:Linux系统中间件的巧妙实现--以用户空间的tcp协议栈为例

文章出处:【微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    87

    文章

    11196

    浏览量

    208659

原文标题:Linux系统中间件的巧妙实现--以用户空间的tcp协议栈为例

文章出处:【微信号:zhuyandz,微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    什么是socket编程 socket与tcp/ip协议的关系

    基于TCP/IP协议族,这是一组用于网络通信的协议,包括传输控制协议TCP)和互联网
    的头像 发表于 11-01 16:01 95次阅读

    TCP协议是什么

    ,应用层之下,各种应用提供可靠的、面向连接的、基于字节流的传输服务。本文将详细解析TCP协议的定义、工作原理、主要特点及其在各种应用场景中
    的头像 发表于 10-09 13:54 264次阅读

    Linux网络协议的实现

    网络协议是操作系统核心的一个重要组成部分,负责管理网络通信中的数据包处理。在 Linux 操作系统中,网络
    的头像 发表于 09-10 09:51 228次阅读
    Linux<b class='flag-5'>网络</b><b class='flag-5'>协议</b><b class='flag-5'>栈</b>的实现

    串口服务器和TCP/IP协议是什么关系

    串口服务器与TCP/IP协议之间存在着紧密而复杂的关系。这种关系主要体现在串口服务器如何利用TCP
    的头像 发表于 08-25 17:35 1342次阅读

    嵌入式学习-常见的shell命令之网络相关命令

    提供了很好的参考模型。在OSI七层结构中,每一层规定了不同的特性,负责不同的功能:应用层(Application Layer):用户接口,应用程序提供访问
    发表于 08-21 09:41

    常见的shell命令之网络相关命令

    提供了很好的参考模型。在OSI七层结构中,每一层规定了不同的特性,负责不同的功能:应用层(Application Layer):用户接口,应用程序提供访问
    发表于 08-20 09:50

    TCP/IP协议的设计与实现_中文

    电子发烧友网站提供TCP/IP协议的设计与实现_中文.pdf》资料免费下载
    发表于 07-03 11:28 4次下载

    LwIP协议源码详解—TCP/IP协议的实现

    电子发烧友网站提供《LwIP协议源码详解—TCP/IP协议的实现.pdf》资料免费下载
    发表于 07-03 11:22 3次下载

    Microchip TCP/IP 协议应用笔记

    电子发烧友网站提供《Microchip TCP/IP 协议应用笔记.pdf》资料免费下载
    发表于 04-17 14:16 1次下载

    使用LwIP协议浅析实战分析(i.MX RT)

    LWIP协议网络分层 LwIP(Light weight IP),是一种轻量化且开源的TCP/IP协议,它可以在有限的RAM和ROM条件
    的头像 发表于 02-02 17:05 1464次阅读
    使用LwIP<b class='flag-5'>协议</b><b class='flag-5'>栈</b>浅析实战分析(i.MX RT)

    通信网络协议之UDP协议技术解析

    在通常的网络协议中,TCP/IP协议是一个常见的示例,其中UDP和
    发表于 02-01 11:00 853次阅读
    通信<b class='flag-5'>网络</b><b class='flag-5'>协议</b><b class='flag-5'>栈</b>之UDP<b class='flag-5'>协议</b>技术解析

    TCP源码,和注释,及应用

    许多应用程序(如Web浏览器和电子邮件客户端)提供可靠的数据传输服务。以下是一个简化的TCP源代码示例,并带有注释,以帮助您更好地理解TCP
    发表于 11-19 12:31

    linux重启网络服务

    网络服务是现代计算机系统中不可或缺的一部分,而Linux作为开源的操作系统,其网络服务的管理和维护也成为系统管理员的一项重要工作。本文将详细介绍Linux下网络服务的重启方法以及重启过程中需要
    的头像 发表于 11-17 09:53 1151次阅读

    TCP 协议深度解析

    头部信息,此处是 TCP 协议 Hypertext Transfer Protocol:应用层 HTTP 的信息 网络分层 应用层(Application Layer) 应用层的本质是规定了
    的头像 发表于 11-09 11:19 861次阅读
    <b class='flag-5'>TCP</b> <b class='flag-5'>协议</b>深度解析

    基于Http和Tcp协议自主实现的WebServer

    项目介绍 该项目是一个基于Http和Tcp协议自主实现的WebServer,用于实现服务器对客户端发送过来的GET和POST请求的接收、解析、处理,并返回处理结果给到客户端。该项目主要背景知识涉及
    的头像 发表于 11-09 11:11 653次阅读
    基于Http和<b class='flag-5'>Tcp</b><b class='flag-5'>协议</b>自主实现的WebServer