lwip协议栈在linux运行,LwIP协议栈在uCOS II下的实现

1、概述:

LwIP协议栈在设计时就考虑到了将来的移植问题,因此把所有与硬件、OS、编译器相关的部份独立出来,放在ucosii&LwIPsource etlwiparch目录下。因此LwIP在uCOS II上的实现就是修改这个目录下的文件,其它的文件一般不应该修改。下面分几部份分别说明相应文件的实现原理和过程。

2、与CPU或编译器相关的include文件:

ucosii&LwIPsource etlwiparchucosIIincludearch目录下cc.h、cpu.h、perf.h中有一些与CPU或编译器相关的定义,如数据长度,字的高低位顺序等。这应该与用户实现µC/OS II时定义的数据长度等参数是一致的。

#define BYTE_ORDER LITTLE_ENDIAN  //C33209默认为小端存储系统

//数据类型长度的定义

typedef unsigned char   u8_t;

typedef signed char     s8_t;

typedef unsigned short  u16_t;

typedef signed short    s16_t;

typedef unsigned int    u32_t;

typedef signed int      s32_t;

此外还有一点:一般情况下C语言的结构体struct是4字节对齐的,但是在处理数据包的时候,LwIP使用的是通过结构体中不同数据的长度来读取相应的数据的,所以,一定要在定义struct的时候使用_packed关键字,让编译器放弃struct的字节对齐。LwIP也考虑到了这个问题,所以,在它的结构体定义中有几个PACKED_FIELD_xxx宏,默认的时候这几个宏都是空的,可以在移植的时候添加不同的编译器所对应的_packed关键字。比如在Skyeye(C33209)上对应gcc编译器的定义:

#define PACK_STRUCT_FIELD(x) x __attribute__((packed))

#define PACK_STRUCT_STRUCT __attribute__((packed))

#define PACK_STRUCT_BEGIN

#define PACK_STRUCT_END

3、sys_arch操作系统相关部份:

sys_arch.[ch]中的内容是与OS相关的一些结构和函数,主要可以分为四个部份:

(1)    sys_sem_t 信号量

LwIP中需要使用信号量通信,所以在sys_arch中应实现信号量结构体和处理函数:

struct  sys_sem_t

sys_sem_new()            //创建一个信号量结构

sys_ sem _free()            //释放一个信号量结构

sys_ sem _signal()        //发送信号量

sys_ arch_sem _wait()    //请求信号量

由于µC/OSII已经实现了信号量OS_EVENT的各种操作,并且功能和LwIP上面几个函数的目的功能是完全一样的,所以只要把µC/OSII的函数重新包装成上面的函数,就可以直接使用了。

(2)    sys_mbox_t 消息

LwIP使用消息队列来缓冲、传递数据报文,因此要在sys_arch中实现消息队列结构sys_mbox_t,以及相应的操作函数:

sys_mbox_new()          //创建一个消息队列

sys_mbox_free()          //释放一个消息队列

sys_mbox_post()          //向消息队列发送消息

sys_arch_mbox_fetch()      //从消息队列中获取消息

µC/OSII同样实现了消息队列结构OSQ及其操作,但是µC/OS-II没有对消息队列中的消息进行管理,因此不能直接使用,必须在µC/OS-II的基础上重新实现。为了实现对消息的管理,我们定义了以下结构:

typedef struct {

OS_EVENT*   pQ;

void* pvQEntries[MAX_QUEUE_ENTRIES];

} sys_mbox_t;

在以上结构中,包括OS_EVENT类型的队列指针(pQ)和队列内的消息(pvQEntries)两部分,对队列本身的管理利用µC/OS-II自己的OSQ操作完成,然后使用µC/OS-II中的内存管理模块实现对消息的创建、使用、删除回收,两部分综合起来形成了LwIP的消息队列功能。

(3)    sys_arch_TImeout 函数

LwIP中每个与外界网络连接的线程都有自己的TImeout属性,即等待超时时间。这个属性表现为每个线程都对应一个sys_TImeout结构体队列,包括这个线程的TImeout时间长度,以及超时后应调用的timeout函数,该函数会做一些释放连接,回收资源的工作。如果一个线程对应的sys_timeout为空(NULL),说明该线程对连接做永久的等待。

timeout结构体已经由LwIP自己在sys.h中定义好了,而且对结构体队列的数据操作也由LwIP负责,我们所要实现的是如下函数:

struct sys_timeouts * sys_arch_timeouts(void)

这个函数的功能是返回目前正处于运行态的线程所对应的timeout队列指针。timeout队列属于线程的属性,因此是OS相关的函数,只能由用户实现。

(4)    sys_thread_new 创建新线程

LwIP可以是单线程运行,即只有一个tcpip线程(tcpip_thread),负责处理所有的tcp/ucp连接,各种网络程序都通过tcpip线程与网络交互。但LwIP也可以多线程运行,以提高效率,降低编程复杂度。这时就需要用户实现创建新线程的函数:

void sys_thread_new(void (* thread)(void *arg), void *arg);

在µC/OS II中,没有线程(thread)的概念,只有任务(Task)。它已经提供了创建新任务的系统API调用OSTaskCreate,因此只要把OSTaskCreate封装一下,就可以实现sys_thread_new。需要注意的是LwIP中的thread并没有µC/OS II中优先级的概念,实现时要由用户事先为LwIP中创建的线程分配好优先级。

4、lib_arch中库函数的实现:

LwIP协议栈中用到了8个外部函数,这些函数通常与用户使用的系统或编译器有关,因此留给用户自己实现。如下:

u16_t htons(u16_t n);     //16位数据高低字节交换

u16_t ntohs(u16_t n);

u32_t htonl(u32_t n);      //32位数据大小头对调

u32_t ntohl(u32_t n);

int strlen(const char *str);    //返回字符串长度

int strncmp(const char *str1, const char *str2, int len);  //字符串比较

void bcopy(const void *src, void *dest, int len);    //内存数据块之间的互相拷贝

void bzero(void *data, int n);        //内存中指定长度的数据块清零

前四个函数通常由用户自己实现。在我的系统中,由于使用了gcc编译器,gcc的lib库里已经有了两个字符串操作函数。若用户的编译器的库中没有这些函数,需要自己编写。

5、网络设备驱动程序:

在我的系统中使用的网络芯片为RealTek的8019as芯片,这是ISA 10BASE-T的以太网芯片,与Ne2k兼容。所以目前实现的网络设备驱动是针对Ne2k的,其它类型的网络芯片驱动可以在LwIP的网站上找到。LwIP的网络驱动有一定的模型,ucosii&LwIPsource etlwiparchucosII etif 中的ne2kif.c文件即为驱动的模板,用户为自己的网络设备实现驱动时应参照此模板。

在LwIP中可以有多个网络接口,每个网络接口都对应了一个struct netif,这个ne2kif包含了相应网络接口的属性、收发函数。LwIP调用ne2kif的方法netif->input()及netif->output()进行以太网packet的收、发等操作。在驱动中主要做的,就是实现网络接口的收、发、初始化以及中断处理函数。驱动程序工作在IP协议模型的网络接口层,它提供给上层(IP层)的接口函数如下:

//网卡初始化函数

void low_level_init (struct netif *netif)

//网卡接收函数,从网络接口接收以太网数据包并把其中的IP报文向IP层发送

//在中断方式下由网卡ISR调用

void ne2k_recv_packet (struct netif *netif)

//网卡发送函数,给IP层传过来的IP报文加上以太网包头并通过网络接口发送

err_t ne2k_send_packet (struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)

//网卡中断处理函数ISR

void ne2k_isr (void);

以上的函数都可以分为协议栈本身的处理和对网络接口硬件的操作两部份,但硬件操作是对上层屏蔽的,具体参见RTL8019as、DM9008等Ne2k网络芯片的数据手册。驱动程序可以到LwIP的网站下载。

6、应用实例的建立和测试

做完上面的移植修改工作以后,就可以在uCOS II中初始化LwIP,并创建TCP或UDP任务进行测试了。这部份完全是C语言的实现,因此这部份在ez80和ARM7上基本都是一样的。值得注意的是LwIP的初始化必须在uCOS II完全启动之后也就是在任务中进行,因为它的初始化用到了信号量等OS相关的操作。关键部份的代码和说明如下:

void start_kernel(void)

{

int     LineNo10 = 0;

int     LineNo11 = 1;

int     LineNo12 = 2;

int     LineNo13 = 3;

int     LineNo14 = 4;

OSInit();

OSTaskCreate(lwip_init_task, &LineNo10, &lwip_init_stk[TASK_STK_SIZE-1], 0);

OSTaskCreate(usr_task,&LineNo14,&usr_stk[TASK_STK_SIZE-1],20);

vRTCStart();

OSStart();

/* NEVER EXECUTED */

while(1);

}

主程序中创建了lwip_init_task初始化LwIP任务(优先级0)和usr_task用户任务(优先级20)。lwip_init_task任务中除了初始化硬件时钟和LwIP之外,还创建了tcpip_thread(优先级5)和tcpecho_thread(优先级6)。实际上tcpip_thread才是LwIP的主线程,多线程的Berkley API也是基于这个线程实现的,即上面的tcpecho_thread线程也要依靠tcpip_thread线程来与外界通信,这样做的好处是编程简单,结构清晰。

实用Berkley API实现的tcpecho_thread是一个TCP echo服务器,监听7号端口,程序框架如下:

void tcpecho_thread(void *arg){

conn = netconn_new(NETCONN_TCP);  //创建新的连接标识

netconn_bind(conn, NULL, 7);        //绑定到7号端口

netconn_listen(conn);                //开始监听端口

while(1){

newconn = netconn_accept(conn);        //接收外部到来的连接

buf = netconn_recv(newconn)        //获取数据

…….                            //处理数据

netconn_write(newconn, data, len, NETCONN_COPY); //发送数据

netconn_delete(newconn);            //释放本次连接

}

}

编译运行后,用ping ip地址命令可以得到ICMP reply响应。用telnet ip地址 7(登录7号端口)命令可以看到echo server的回显效果。说明ARP、ICMP、IP、TCP协议都已正确运行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/501503.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux离线安装redmine_Feem:免流量跨平台文件传输工具,支持离线分享

Feem 是一款在文件传输领域打拼多年的产品,目前是基于 Wifi 局域网直连模式的文件传输服务,跨平台,在 Mac、PC、iOS、Android、Linux 皆有客户端。安装不同平台的客户端设备只要在同一无线网络,可以实现无提前配置式的自动配对&am…

JAVA入门级教学之(abstract抽象类)

目录 JAVA入门级教学之(abstract抽象类) 1.如何定义抽象类? 2.抽象类无法被实例化 3.虽然抽象类没有办法实例化,但是抽象类也有构造方法,该构造方法是给子类创建对象用的 4.抽象类中可以定义抽象方法 5.如果一个类…

linux 内核裁剪不当 死机,Linux編譯x86架構內核出現_stack_chk_guard未定義錯誤

背景android模擬器運行於virtualbox中,而virtualbox運行於x86架構的pc端,所以android及其Linux內核都編譯成x86架構。當virtualbox的vt未開啟的情況下android系統會出現各種問題,如arm庫游戲不能運行,桌面平凡掛死重啟。通過查看日…

a*算法流程图_光伏逆变器MPPT基本算法介绍李星硕

欢迎加入技术交流QQ群(2000人):电力电子技术与新能源 905723370高可靠新能源行业顶尖自媒体在这里有电力电子、新能源干货、行业发展趋势分析、最新产品介绍、众多技术达人与您分享经验,欢迎关注我们,搜索微信公众号:电力电子技术…

JAVA入门级教学之(接口)

目录 JAVA入门级教学之(接口) 接口也是一种引用类型,可以等同看做类 1.如何定义接口,语法: 2.接口中只能出现: 3.接口其实是一个特殊的抽象类,特殊在接口是完全抽象的 4.接口中没有构造方…

java 线程状态_浅析Java中的线程状态

一、线程的5种状态众所周知,Java的线程状态有5种,分别对应上图中五种不同颜色,下面对这5种状态及状态间的转化做相应的解释: 1. 初始化状态:新建一个线程对象 2. 可运行状态:其他线程调用了该线程对象的sta…

Linux7添加syslog,请教linux下安装syslog的方法.是安装,不是配置

、安装JDK从sun网站上直接下载JDK:http://java.sun.com/j2se/1.4.2/download.html 提供了两个下载:1、RPM in self-extracting file (j2sdk-1_4_2_04-linux-i586.bin, 32.77 MB) 这个是自解压的文件,在linux上安装如下:# chmod ux…

如何在jieba分词中加自定义词典_Pyspark Word2Vec + jieba 训练词向量流程

摘要:用商品描述为语料库训练商品词向量为例,分享一下用pyspark自带word2vecjieba分词训练词向量的流程.工具:python,pyspark,jieba,pandas,numpy数据格式:自定义词典,语料库均为pyspark dataframe,停用辞典不大,直接使用txt.1 create spark我的pyspark参数设置如下:def create…

linux底行模式显示信息,14天linux命令加强

linux命令加强linux命令加强.jpg复习cd./ 当前目录../ 上级目录/ 代表根目录 or 代表目录和文件之间的分隔符 ..pwd 查看当前路径LS 查看当前目录下的文件ls ./a/ 查看目标路径下的文件tab 自动补全grep 文件外部根据关键字搜索文件内容 grep -n 关键字 *(文件名)more 以分页的…

字节和位 B和b的区别

“B”不是最小的单位,“B”是Byte的意思,一个Byte等于8个bit(位),bit是最小的单位。 就好像你用宽带上网,1M、2M、10M、100M都是用bit来作为单位的,实际上以上的速度换算到B是都要除上8。 bit一…

AndroidManifest.xml详解

我们在进行APP开发的时候都会遇到一个文件:AndroidManifest.xml。从刚开始进行Android开发,到现在已经过去了几个月,还是对这个文件一知半解,只知道它是配置用的。但是这文件里的东西具体有什么用,该怎么用一直都没有理…

a标签传值到另一个页面_vue-router页面传值及接收值

前端写页面&#xff0c;我们经常需要从A页面传值给B页面&#xff0c;比如下面的场景点击“充值中”跳转到下一个页面&#xff0c;使tabbar中的页面与其对应需要上个页面传值下面来实现下&#xff1a;A页面——My.vue在去“order”页面的方法中通过params传值current1<B页面—…

本机ping不通虚拟机linux,Windows本地Linux虚拟机ping不通的解决办法

安装linux操作系统安装双操作系统; 1 0. 介绍: 1 1 实验环境: 2 2. 实验准备: 2 3.开始安装: 2 1 制作U盘启动工具: 2 2.安装LinuxOS. 3 2.1在windowOS中划分60G空间 ...VS2008编译bat工程文件为AirCode,批处理文件为bulit.bat(与*.sln文件在同级目录). 以下是批处理的代码: ec…

如何实现文件互拖-VMware Tools (ubuntu系统)安装详细过程与使用

VMware Tools &#xff08;ubuntu系统&#xff09;安装详细过程与使用 1、打开虚拟机VMware Workstation&#xff0c;启动Ubuntu系统&#xff0c;菜单栏 - 虚拟机 - 安装VMware Tools&#xff0c;不启动Ubuntu系统是无法点击“安装VMware Tools”选项的&#xff0c;如下图&…

c++ 中文乱码_Visual Studio Code 中 CodeRunner 插件的输出窗口中文乱码

原来我一直用 Pycharm 写代码&#xff0c;Pycharm 写代码虽然很方便&#xff0c;但是Pycharm 有点重&#xff0c;我转到了Vscode了&#xff0c;真香。在 Visual Studio Code 中安装 CodeRunner 插件后&#xff0c;直接运行 Python 代码的时候&#xff0c;输出窗口中的中文出现了…

linux 下 java md5值,MD5值的简介和查看

MD5即Message-Digest Algorithm 5(信息-摘要算法第5版)&#xff0c;用于确保信息传输完整一致。每个文件都可以用MD5验证程序算出一个固定的MD5码来。MD5在论坛上、软件发布时经常用&#xff0c;是为了保证文件的正确性&#xff0c;防止一些人盗用程序&#xff0c;加些木马或者…

解决为什么导入了tomcat进入myeclipse却在server中找不到

有时候在servers中找不到刚刚在preferences搜索框中&#xff0c;输入tomcat等等等一系列的操作后却还是找不到在哪里 其实需要在servers窗口中右键new一个新的tomcat出来&#xff0c;这时候再在里面选择刚刚新建的tomcat即可

三菱modbusRTU通讯实例_实例 | 三菱PLC接线图干货,FX5U模块硬件

点击箭头处“工业之家”&#xff0c;选择“关注公众号”&#xff01;三菱PLC接线图干货此次主要描述的是关于三菱FX5U 模块硬件的接线实例&#xff0c;主要有以下几个方面&#xff1a;电源AC、DC接线、输入输出接线、模拟量接线。不同原理不同的接线方式&#xff0c;现在来给大…

linux共享文件系统sy,Linux使用Samba实现文件共享

Samba服务是现在Linux系统与Windows系统之间共享文件的最佳选择。[rootstudy ~]# yum install samba -y  #安装samba服务[rootstudy ~]# cat -n /etc/samba/smb.conf  #查看samba主配置文件Samba服务程序中的参数以及作用[global]参数作用workgroup MYGROUP#工作组名称ser…

recycleviewitem 列表加载动画_用vue实现一个虚拟列表

上次分享了超长列表分片加载的方式&#xff0c;这种方式现在一般不会使用&#xff0c;因为dom会变的无比庞大&#xff0c;页面会很卡&#xff0c;今天分享用vue实现一个虚拟列表的简易实现&#xff0c;本来是想用原生实现一个&#xff0c;后来觉得直接使用computed&#xff0c;…