提交 d5ffaf97 编写于 作者: 鸿蒙内核源码分析's avatar 鸿蒙内核源码分析

从ifconfig netstat 等常用网络命令的实现来理解lwip协议栈

搜索 @note_pic 可以查看全部字符图
搜索 @note_why 是注者尚未看明白的地方,如果您看明白了,请告诉注者完善
搜索 @note_thinking 是注者的思考和吐槽的地方
上级 bb99c88e
......@@ -56,7 +56,7 @@ VOID LOS_BitmapSet(UINT32 *bitmap, UINT16 pos)
*bitmap |= 1U << (pos & OS_BITMAP_MASK);//在对应位上置1
}
//对应位上置0
VOID LOS_BitmapClr(UINT32 *bitmap, UINT16 pos)
{
if (bitmap == NULL) {
......
......@@ -128,7 +128,7 @@ VOID OsSetMainTask()
LITE_OS_SEC_TEXT WEAK VOID OsIdleTask(VOID)
{
while (1) {//只有一个死循环
#ifdef LOSCFG_KERNEL_TICKLESS
#ifdef LOSCFG_KERNEL_TICKLESS //低功耗模式开关, idle task 中关闭tick
if (OsTickIrqFlagGet()) {
OsTickIrqFlagSet(0);
OsTicklessStart();
......@@ -1191,7 +1191,7 @@ EXIT:
SCHEDULER_UNLOCK(intSave);
return errRet;
}
//删除任务,回归任务池
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskDelete(UINT32 taskID)
{
UINT32 intSave;
......@@ -1215,10 +1215,10 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskDelete(UINT32 taskID)
}
processCB = OS_PCB_FROM_PID(taskCB->processID);
if (processCB->threadNumber == 1) {
if (processCB == OsCurrProcessGet()) {
if (processCB->threadNumber == 1) {//此任务为进程的最后一个任务的处理
if (processCB == OsCurrProcessGet()) {//是否为当前任务
SCHEDULER_UNLOCK(intSave);
OsProcessExit(taskCB, OS_PRO_EXIT_OK);
OsProcessExit(taskCB, OS_PRO_EXIT_OK);//进程退出
return LOS_OK;
}
......@@ -1226,7 +1226,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskDelete(UINT32 taskID)
OS_GOTO_ERREND();
}
return OsTaskDeleteUnsafe(taskCB, OS_PRO_EXIT_OK, intSave);
return OsTaskDeleteUnsafe(taskCB, OS_PRO_EXIT_OK, intSave);//任务以非安全模式删除
LOS_ERREND:
SCHEDULER_UNLOCK(intSave);
......@@ -1512,7 +1512,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskInfoGet(UINT32 taskID, TSK_INFO_S *taskInf
taskInfo->uwBottomOfStack = TRUNCATE(((UINTPTR)taskCB->topOfStack + taskCB->stackSize),//这里可以看出栈底地址是高于栈顶
OS_TASK_STACK_ADDR_ALIGN);
taskInfo->uwCurrUsed = (UINT32)(taskInfo->uwBottomOfStack - taskInfo->uwSP);//当前已使用了多少
taskInfo->uwCurrUsed = (UINT32)(taskInfo->uwBottomOfStack - taskInfo->uwSP);//当前任务栈已使用了多少
taskInfo->bOvf = OsStackWaterLineGet((const UINTPTR *)taskInfo->uwBottomOfStack,//获取栈的使用情况
(const UINTPTR *)taskInfo->uwTopOfStack, &taskInfo->uwPeakUsed);
......
......@@ -36,13 +36,13 @@
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
// 文件作用:统计多CPU core下运行情况,打开开关必然消耗大量的性能
#if (LOSCFG_KERNEL_SCHED_STATISTICS == YES)
#define HIGHTASKPRI 16
#define HIGHTASKPRI 16 //界定高优先级任务的标准
#define NS_PER_MS 1000000
#define DECIMAL_TO_PERCENTAGE 100
typedef struct {
typedef struct { //每个cpu core 运行参数描述体
UINT64 idleRuntime;
UINT64 idleStarttime;
UINT64 highTaskRuntime;
......@@ -304,7 +304,7 @@ LITE_OS_SEC_TEXT_MINOR VOID OsShellMpStaticStop(VOID)
if (cpuid == (UINT32)(OS_TASK_INVALID_CPUID)) {
continue;
}
if (!strcmp(taskCB->taskName, "Idle")) {
if (!strcmp(taskCB->taskName, "Idle")) { //空闲任务情况下
runtime = mpStaticStopTime - g_mpStatPercpu[cpuid].idleStarttime;
g_mpStatPercpu[cpuid].idleRuntime += runtime;
g_mpStatPercpu[cpuid].idleStarttime = 0;
......
......@@ -175,7 +175,7 @@ typedef struct {
#define IPC_THREAD_STATUS_STOP 0x0008U
#if (LOSCFG_KERNEL_TRACE == YES)
#define LOS_TRACE_IPC 3
#define LOS_TRACE_IPC 3 //IPC 对应..\kernel\include\los_trace.h TraceType 理解
typedef enum {
WRITE,
......
......@@ -41,7 +41,7 @@
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
//在多CPU系统上,如果当前的CPU没有任务或者只有一个任务的前提下,系统将不向该CPU发送timer tick
STATIC BOOL g_ticklessFlag = FALSE;
STATIC BOOL g_tickIrqFlag[LOSCFG_KERNEL_CORE_NUM] = {FALSE};
STATIC volatile UINT32 g_sleepTicks[LOSCFG_KERNEL_CORE_NUM] = {0};
......
......@@ -42,11 +42,11 @@ extern "C" {
#endif /* __cplusplus */
#if (LOSCFG_KERNEL_TRACE == YES)
LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_traceSpin);
LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_traceSpin); //定义trace自旋锁
#define TRACE_LOCK(state) LOS_SpinLockSave(&g_traceSpin, &(state))
#define TRACE_UNLOCK(state) LOS_SpinUnlockRestore(&g_traceSpin, (state))
STATIC SPIN_LOCK_S g_traceCpuSpin[LOSCFG_KERNEL_CORE_NUM];
STATIC SPIN_LOCK_S g_traceCpuSpin[LOSCFG_KERNEL_CORE_NUM];//定义每个CPU单独的自旋锁
#define TRACE_CPU_LOCK(state, cpuID) LOS_SpinLockSave(&g_traceCpuSpin[(cpuID)], &(state))
#define TRACE_CPU_UNLOCK(state, cpuID) LOS_SpinUnlockRestore(&g_traceCpuSpin[(cpuID)], (state))
......@@ -64,7 +64,7 @@ STATIC VOID OsTracePosAdj(UINT16 bufferSize)
g_traceBuf[cpu].tracePos = 0;
}
}
//任务上下文切换时的触发函数,由trace初始化时注册 LOS_TRACE_SWITCH
STATIC UINT16 OsTaskTrace(UINT8 *inputBuffer, UINT32 newTaskID, UINT32 oldTaskID)
{
TaskTraceFrame *taskInfo = NULL;
......@@ -74,15 +74,15 @@ STATIC UINT16 OsTaskTrace(UINT8 *inputBuffer, UINT32 newTaskID, UINT32 oldTaskID
}
taskInfo = (TaskTraceFrame *)inputBuffer;
taskInfo->currentTick = LOS_TickCountGet();
taskInfo->srcTaskId = oldTaskID;
taskInfo->destTaskId = newTaskID;
taskInfo->currentTick = LOS_TickCountGet();//记录切换任务上下文的时间
taskInfo->srcTaskId = oldTaskID; //源任务ID
taskInfo->destTaskId = newTaskID; //目标任务ID
return sizeof(TaskTraceFrame);
}
//中断产生时触发函数,由trace初始化时注册 LOS_TRACE_INTERRUPT
STATIC UINT16 OsIntTrace(UINT8 *inputBuffer, UINT32 newIrqNum, UINT32 direFlag)
{
{//函数详细记录了中断发生时的现场
IntTraceFrame *interruptInfo = NULL;
UINT16 useSize = 0;
......@@ -90,26 +90,26 @@ STATIC UINT16 OsIntTrace(UINT8 *inputBuffer, UINT32 newIrqNum, UINT32 direFlag)
return 0;
}
/* ignore tick and uart interrupts */
/* ignore tick and uart interrupts */ //忽略掉tick和UART硬中断
if ((newIrqNum != OS_TICK_INT_NUM) && (newIrqNum != NUM_HAL_INTERRUPT_UART)) {
useSize = sizeof(IntTraceFrame);
interruptInfo = (IntTraceFrame *)inputBuffer;
interruptInfo->currentTick = LOS_TickCountGet();
interruptInfo->currentTick = LOS_TickCountGet();//中断发生时的时间
interruptInfo->irqNum = newIrqNum;
interruptInfo->irqDirection = direFlag;
}
return useSize;
}
//trace模块注册不同类型trace下的处理函数
UINT32 OsTraceReg(TraceType traceType, WriteHook inHook)
{
TraceHook *traceInfo = NULL;
if (g_traceInfo[traceType]) {
if (g_traceInfo[traceType]) {//已经注册过的就更新
/* The Buffer has been alocated before */
traceInfo = g_traceInfo[traceType];
} else {
} else { //未注册过的分配空间
/* First time allocate */
traceInfo = (TraceHook *)LOS_MemAlloc(m_aucSysMem0, sizeof(TraceHook));
if (traceInfo == NULL) {
......@@ -119,12 +119,12 @@ UINT32 OsTraceReg(TraceType traceType, WriteHook inHook)
g_traceInfo[traceType] = traceInfo;
}
traceInfo->type = traceType;
traceInfo->type = traceType;
traceInfo->inputHook = inHook;
return LOS_OK;
}
//trace 初始化 ,trace是内核系统极为重要的模块,trace模块是解决,定位问题的基础工具.
UINT32 LOS_TraceInit(VOID)
{
UINT32 ret;
......@@ -142,14 +142,14 @@ UINT32 LOS_TraceInit(VOID)
}
g_frameSize[LOS_TRACE_SWITCH] = sizeof(TaskTraceFrame);
ret = OsTraceReg(LOS_TRACE_SWITCH, OsTaskTrace);
ret = OsTraceReg(LOS_TRACE_SWITCH, OsTaskTrace);//注册任务上下文切换时的触发函数
if (ret != LOS_OK) {
TRACE_UNLOCK(intSave);
return ret;
}
g_frameSize[LOS_TRACE_INTERRUPT] = sizeof(IntTraceFrame);
ret = OsTraceReg(LOS_TRACE_INTERRUPT, OsIntTrace);
ret = OsTraceReg(LOS_TRACE_INTERRUPT, OsIntTrace);//注册trace中断时触发处理函数
if (ret != LOS_OK) {
TRACE_UNLOCK(intSave);
return ret;
......@@ -158,7 +158,7 @@ UINT32 LOS_TraceInit(VOID)
return LOS_OK;
}
//供外部调用,注册trace处理函数
UINT32 LOS_TraceUserReg(TraceType traceType, WriteHook inHook, UINT16 useSize)
{
UINT32 intSave;
......@@ -183,7 +183,7 @@ UINT32 LOS_TraceUserReg(TraceType traceType, WriteHook inHook, UINT16 useSize)
return ret;
}
//记录两个任务 切换或通讯时的日志
VOID LOS_Trace(TraceType traceType, UINT32 newID, UINT32 oldID)
{
TraceHook *traceInfo = NULL;
......
......@@ -480,9 +480,9 @@ typedef VOID *(*TSK_ENTRY_FUNC)(UINTPTR param1,
*/
typedef struct {
UINTPTR userArea;//用户区域
UINTPTR userSP; //用户模式下栈指针
UINTPTR userMapBase;//用户模式下映射基地址
UINT32 userMapSize;//用户模式下映射大小
UINTPTR userSP; //用户下栈指针
UINTPTR userMapBase;//用户下映射基地址
UINT32 userMapSize;//用户下映射大小
} UserTaskParam;
/**
......@@ -499,13 +499,13 @@ typedef struct tagTskInitParam {//Task的初始化参数
UINT32 uwStackSize; /**< Task stack size */ //任务栈大小
CHAR *pcName; /**< Task name */ //任务名称
#if (LOSCFG_KERNEL_SMP == YES)
UINT16 usCpuAffiMask; /**< Task cpu affinity mask */ //任务cpu关联掩码
UINT16 usCpuAffiMask; /**< Task cpu affinity mask */ //任务cpu亲和力掩码
#endif
UINT32 uwResved; /**< It is automatically deleted if set to LOS_TASK_STATUS_DETACHED.
It is unable to be deleted if set to 0. */ //如果设置为LOS_TASK_STATUS_DETACHED,则自动删除。如果设置为0,则无法删除
UINT16 consoleID; /**< The console id of task belongs */ //任务的控制台id所属
UINT32 processID; //进程ID
UserTaskParam userParam; //用户参数
UserTaskParam userParam; //在用户态运行时栈参数
} TSK_INIT_PARAM_S;
/**
......@@ -520,7 +520,7 @@ typedef struct tagTskInitParam {//Task的初始化参数
* Task information structure.
*
*/
typedef struct tagTskInfo {
typedef struct tagTskInfo { //主要用于 shell task -a 使用
CHAR acName[LOS_TASK_NAMELEN]; /**< Task entrance function */
UINT32 uwTaskID; /**< Task ID */
UINT16 usTaskStatus; /**< Task status */
......
......@@ -118,12 +118,12 @@ typedef UINT16 (*WriteHook)(UINT8 *inBuf, UINT32 newID, UINT32 oldID);
/**
* @ingroup los_trace
* Stands for the trace type can be registered.
* Stands for the trace type can be registered. //表示可以注册的跟踪类型
*/
typedef enum {
LOS_TRACE_SWITCH = 0, /**< trace for task switch, 0 is reserved for taskswitch */ //任务切换的跟踪,0是为taskswitch保留的
LOS_TRACE_INTERRUPT = 1, /**< trace for Interrrupt, 1 is reserved for interrupt */ //中断,1表示为中断保留
LOS_TRACE_TYPE_NUM = 5, /**< num for the register type, user can use 2~ LOS_TRACE_TYPE_NUM-1 */
LOS_TRACE_TYPE_NUM = 5, /**< num for the register type, user can use 2~ LOS_TRACE_TYPE_NUM-1 *///寄存器数量,用于控制中断范围
} TraceType;
/**
......@@ -133,7 +133,7 @@ typedef enum {
typedef struct {
UINTPTR tracePos; /**< Data buffer current index position */ //数据缓冲区当前索引位置
UINTPTR traceWrapPos; /**< Data buffer last loop end position */ //数据缓冲区最后一个循环结束位置
UINT8 dataBuf[LOS_TRACE_BUFFER_SIZE]; /**< Data buffer */ //数据缓存区
UINT8 dataBuf[LOS_TRACE_BUFFER_SIZE]; /**< Data buffer */ //数据缓存区 2K
} TraceBuffer;
/**
......
......@@ -193,14 +193,14 @@ int netstat_udp_sendq(struct udp_pcb *upcb);
int netstat_netconn_sendq(struct netconn *conn);
/* Forward Declarations [END] */
#define IFCONFIG_OPTION_SET_IP (1)
#define IFCONFIG_OPTION_SET_NETMASK (1 << 1)
#define IFCONFIG_OPTION_SET_GW (1 << 2)
#define IFCONFIG_OPTION_SET_HW (1 << 3)
#define IFCONFIG_OPTION_SET_UP (1 << 4)
#define IFCONFIG_OPTION_SET_DOWN (1 << 5)
#define IFCONFIG_OPTION_SET_MTU (1 << 6)
#define IFCONFIG_OPTION_DEL_IP (1 << 7)
#define IFCONFIG_OPTION_SET_IP (1) //ifconfig add 命令之设置IP地址
#define IFCONFIG_OPTION_SET_NETMASK (1 << 1) //ifconfig netmask 命令 之设置子网掩码
#define IFCONFIG_OPTION_SET_GW (1 << 2) //ifconfig gateway 命令 之设置网关
#define IFCONFIG_OPTION_SET_HW (1 << 3) //ifconfig hw ether 命令 之设置板子硬件mac地址
#define IFCONFIG_OPTION_SET_UP (1 << 4) //ifconfig up 命令 之设置启用网卡数据处理,需指定网卡名
#define IFCONFIG_OPTION_SET_DOWN (1 << 5) //ifconfig down 命令 之设置关闭网卡数据处理,需指定网卡名
#define IFCONFIG_OPTION_SET_MTU (1 << 6) //ifconfig mtu 命令 之设置网络最大传输单元。
#define IFCONFIG_OPTION_DEL_IP (1 << 7) //ifconfig del 命令 之删除IP
#define NETSTAT_ENTRY_SIZE 120
#define MAX_NETSTAT_ENTRY (NETSTAT_ENTRY_SIZE * (MEMP_NUM_TCP_PCB + MEMP_NUM_UDP_PCB + MEMP_NUM_TCP_PCB_LISTEN + 1))
......@@ -235,7 +235,7 @@ int netstat_netconn_sendq(struct netconn *conn);
} while(0)
#define LWIP_MSECS_TO_SECS(time_in_msecs) (time_in_msecs / 1000)
struct ifconfig_option {
struct ifconfig_option { //shell ifconfig 命令所需内容结构体
char iface[IFNAMSIZ];
unsigned int option;
ip_addr_t ip_addr;
......@@ -255,13 +255,13 @@ struct netstat_data {
s8_t *netstat_out_buf;
u32_t netstat_out_buf_len;
u32_t netstat_out_buf_updated_len;
sys_sem_t cb_completed;
sys_sem_t cb_completed;//call back 信号量
};
struct if_cmd_data {
char *if_name;
err_t err;
sys_sem_t cb_completed;
sys_sem_t cb_completed;//call back 信号量
};
#ifndef LWIP_TESTBED
......@@ -678,8 +678,44 @@ LWIP_STATIC void lwip_ifconfig_usage(const char *cmd)
"\n[interface up|down]\n",
cmd);
}
/*******************************************************
https://gitee.com/openharmony/docs/blob/master/kernel/ifconfig.md
命令功能
ifconfig命令用来查询和设置网卡的IP地址、网络掩码、网关、硬件mac地址等参数。并能够启用/关闭网卡。
命令格式
ifconfig
[-a]
<interface> <address> [netmask <mask>] [gateway <address>]
[hw ether <address>] [mtu <size>]
[inet6 add <address>]
[inet6 del <address>]
[up|down]
参数 参数说明 取值范围
不带参数 打印所有网卡的IP地址、网络掩码、网关、硬件mac地址、MTU、运行状态等信息。
-a 打印协议栈收发数据信息。
interface 指定网卡名,比如eth0。
address 设置IP地址,比如192.168.1.10,需指定网卡名。
netmask 设置子网掩码,后面要掩码参数,比如255.255.255.0。
gateway 设置网关,后面跟网关参数,比如192.168.1.1。
hw ether 设置mac地址, 后面是MAC地址,比如00:11:22:33:44:55。目前只支持ether硬件类型。
mtu 设置mtu大小,后面是mtu大小,比如1000。 仅支持ipv4情况下的范围为[68,1500]。支持ipv6情况下的范围为[1280,1500]。
add 设置ipv6的地址,比如2001:a:b:c:d:e:f:d,需指定网卡名和inet6。
del 删除ipv6的地址,需指定网卡名和inet6。
up 启用网卡数据处理,需指定网卡名。
down 关闭网卡数据处理,需指定网卡名。
u32_t lwip_ifconfig(int argc, const char **argv)
使用指南
命令需要启动TCP/IP协议栈后才能使用。
由于IP冲突检测需要反应时间,每次使用ifconfig设置IP后会有2S左右的延时。
使用实例
ifconfig eth0 192.168.100.31 netmask 255.255.255.0 gateway 192.168.100.1 hw ether 00:49:cb:6c:a1:31
ifconfig -a
ifconfig eth0 inet6 add 2001:a:b:c:d:e:f:d
ifconfig eth0 inet6 del 2001:a:b:c:d:e:f:d
*******************************************************/
u32_t lwip_ifconfig(int argc, const char **argv)//一个400多行代码的函数
{
int i;
static struct ifconfig_option ifconfig_cmd;
......@@ -1141,21 +1177,21 @@ ifconfig_error:
SHELLCMD_ENTRY(ifconfig_shellcmd, CMD_TYPE_EX, "ifconfig", XARGS, (CmdCallBackFunc)lwip_ifconfig);//采用shell命令静态注册方式
#endif /* LOSCFG_SHELL */
/* add arp entry to arp cache */
#define ARP_OPTION_ADD 1
#define ARP_OPTION_ADD 1 //向arp缓存添加arp条目
/* delete arp entry to arp cache */
#define ARP_OPTION_DEL 2
#define ARP_OPTION_DEL 2 //向arp缓存删除arp条目
/* print all arp entry in arp cache */
#define ARP_OPTION_SHOW 3
#define ARP_OPTION_SHOW 3 //打印所有arp条目
struct arp_option {
/* see the ARP_OPTION_ above */
int option;
/* descriptive abbreviation of network interface */
char iface[IFNAMSIZ];
/* descriptive abbreviation of network interface */
char iface[IFNAMSIZ];//表示该ARP表项使用的接口名。
/* ip addr */
unsigned int ipaddr;
unsigned int ipaddr;//如192.168.1.35 ipaddr记录是 35
/* hw addr */
unsigned char ethaddr[6];
unsigned char ethaddr[6];//表示网络设备的MAC地址。
/* when using telnet, printf to the telnet socket will result in system */
/* deadlock.so don't do it.cahe the data to prinf to a buf, and when */
/* callback returns, then printf the data out to the telnet socket */
......@@ -1339,6 +1375,13 @@ LWIP_STATIC void lwip_arp_usage(const char *cmd)
cmd, cmd, cmd);
}
/****************************************************************
地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议。
主机发送信息时将包含目标IP地址的ARP请求广播到局域网络上的所有主机,并接收返回消息,
以此确定目标的物理地址;收到返回消息后将该IP地址和物理地址存入本机ARP缓存中并保留一定时间,
下次请求时直接查询ARP缓存以节约资源。地址解析协议是建立在网络中各个主机互相信任的基础上的,
局域网络上的主机可以自主发送ARP应答消息,其他主机收到应答报文时不会检测该报文的真实性就会将
其记入本机ARP缓存;
命令功能
在以太网中,主机之间的通信是直接使用MAC地址(非IP地址)来通信的,所以,对于使用IP通信的协议,
必须能够将IP地址转换成MAC地址,才能在局域网(以太网)内通信。解决这个问题的方法就是主机存储
......@@ -1566,7 +1609,7 @@ LWIP_STATIC unsigned int get_hostip(const char *hname)
}
#endif
#if LWIP_EXT_POLL_SUPPORT
#if LWIP_EXT_POLL_SUPPORT // 使用poll实现 I/O多路复用
static int ping_taskid = -1;
static int ping_kill = 0;
#define PING_ZERO_DATA_LEN 8
......@@ -1796,8 +1839,27 @@ static void ping_cmd(unsigned int p0, unsigned int p1, unsigned int p2, unsigned
ping_taskid = -1;
}
//shell ping 用于测试网络连接是否正常 ping_ [-n cnt_] [-w interval] [-l data_len]_ <IP>_
u32_t osShellPing(int argc, const char **argv)
/**********************************************************
https://gitee.com/openharmony/docs/blob/master/kernel/ping.md
命令功能
ping命令用于测试网络连接是否正常。
命令格式
ping_ [-n cnt_] [-w interval] [-l data_len]_ <IP>_
ping [-t] [-w interval] <IP>
ping -k
使用指南
ping命令用来测试到目的IP的网络连接是否正常,参数为目的IP地址。
如果目的IP不可达,会显示请求超时。
如果显示发送错误,说明没有到目的IP的路由。
命令需要启动TCP/IP协议栈后才能使用。
使用实例
举例:输入ping 169.254.60.115
**********************************************************/
u32_t osShellPing(int argc, const char **argv)
{
int ret;
u32_t i = 0;
......@@ -2088,7 +2150,26 @@ SHELLCMD_ENTRY(ping_shellcmd, CMD_TYPE_EX, "ping", XARGS, (CmdCallBackFunc)osShe
#endif /* LWIP_EXT_POLL_SUPPORT*/
#if LWIP_IPV6
#if LWIP_IPV6 //鸿蒙默认支持ipv6,物联网时代那是必须滴
/**********************************************************
https://gitee.com/openharmony/docs/blob/master/kernel/ping.md
命令功能
ping6用于测试IPv6网络连接是否正常。
命令格式
ping6 [-c count] [-I interface / sourceAddress] destination
使用指南
如果目的IPv6地址不可达,会显示请求超时。
如果显示发送错误,说明没有到目的IPV6的路由。
命令需要启动TCP/IP协议栈后才能使用。
使用实例
ping6 2001:a:b:c:d:e:f:b
ping6 -c 3 2001:a:b:c:d:e:f:b
ping6 -I eth0 2001:a:b:c:d:e:f:b
ping6 -I 2001:a:b:c:d:e:f:d 2001:a:b:c:d:e:f:b
**********************************************************/
u32_t osShellPing6(int argc, const char **argv)
{
u16_t icmpv6_id;
......@@ -2346,7 +2427,7 @@ usage:
PRINTK("\tping6 [-c count] [-I interface/sourceAddress] destination\n");
return LOS_NOK;
}
//创建一个 ping ipv6 的socket
LWIP_STATIC int create_ping6_socket(u8_t type, const void *param)
{
int sfd;
......@@ -3456,7 +3537,16 @@ out:
sys_sem_signal(&ndata->cb_completed);
return;
}
/************************************************
https://gitee.com/openharmony/docs/blob/master/kernel/netstat.md
命令功能
netstat是控制台命令,是一个监测TCP/IP网络的非常有用的工具,
它可以显示实际的网络连接以及每一个网络接口设备的状态信息。
netstat用于显示与TCP、UDP协议相关的统计数据,一般用于检验本设备(单板)各端口的网络连接情况。
命令格式
netstat
************************************************/
u32_t osShellNetstat(int argc, const char **argv)
{
struct netstat_data ndata;
......
......@@ -389,20 +389,27 @@ u32_t lwip_tftp_put_file_by_filename(u32_t ulHostAddr,
{
return 0;
}
/****************************************************************
著名的tcp 11种状态表述,参考博文:https://blog.csdn.net/zzhongcy/article/details/38851271
状态迁移过程:
  a、客户端:
    CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
  b、服务端
    CLOSED->LISTEN->SYN_RECEIVED->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSE
****************************************************************/
const char *const tcp_state_str[] = {
"CLOSED",
"LISTEN",
"SYN_SENT",
"SYN_RCVD",
"ESTABLISHED",
"FIN_WAIT_1",
"FIN_WAIT_2",
"CLOSE_WAIT",
"CLOSING",
"LAST_ACK",
"TIME_WAIT"
"CLOSED", //没有使用这个套接字[netstat 无法显示closed状态]
"LISTEN", //套接字正在监听连接[调用listen后]
"SYN_SENT", //套接字正在试图主动建立连接[发送SYN后还没有收到ACK]
"SYN_RCVD", //正在处于连接的初始同步状态[收到对方的SYN,但还没收到自己发过去的SYN的ACK]
"ESTABLISHED", //连接已建立,表示两台机器正在传输数据。
"FIN_WAIT_1", //套接字已关闭,正在关闭连接[发送FIN,没有收到ACK也没有收到FIN]
"FIN_WAIT_2", //套接字已关闭,正在等待远程套接字关闭[在FIN_WAIT_1状态下收到发过去FIN对应的ACK],从远程TCP等待连接中断请求,主动关闭端接到ACK后,就进入了FIN-WAIT-2 .
"CLOSE_WAIT", //远程套接字已经关闭:正在等待关闭这个套接字[被动关闭的一方收到FIN]
"CLOSING", //套接字已关闭,远程套接字正在关闭,暂时挂起关闭确认[在FIN_WAIT_1状态下收到被动方的FIN],等待远程TCP对连接中断的确认,处于此种状态比较少见。
"LAST_ACK", //远程套接字已关闭,正在等待本地套接字的关闭确认[被动方在CLOSE_WAIT状态下发送FIN],等待原来的发向远程TCP的连接中断请求的确认,被动关闭端一段时间后,接收到文件结束符的应用程序将调用CLOSE关闭连接,TCP也发送一个 FIN,等待对方的ACK.进入LAST-ACK。
"TIME_WAIT" //套接字已经关闭,正在等待远程套接字的关闭传送[FIN、ACK、FIN、ACK都完毕,这是主动方的最后一个状态,在过了2MSL时间后变为CLOSED状态]
};
volatile int tcpip_init_finish = 1; // needed by api_shell.c
......
......@@ -78,11 +78,13 @@
#define DRV_STS_DEBUG LWIP_DBG_ON
#endif
//select、poll、epoll之间的区别 可以看 https://www.cnblogs.com/aspirant/p/9166944.html
// Options only in new opt.h
#define LWIP_SOCKET_SELECT 0
#define LWIP_SOCKET_POLL 1
#define LWIP_SOCKET_SELECT 0 //O(n),它仅仅知道了,有I/O事件发生了,却并不知道是哪那几个流(可能有一个,多个,甚至全部),我们只能无差别轮询所有流,找出能读出数据,或者写入数据的流,对他们进行操作。所以select具有O(n)的无差别轮询复杂度,同时处理的流越多,无差别轮询时间就越长。
#define LWIP_SOCKET_POLL 1 //O(n),poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态, 但是它没有最大连接数的限制,原因是它是基于链表来存储的.
//鸿蒙liteos并不支持 epoll(event poll),其不同于忙轮询和无差别轮询,epoll会把哪个流发生了怎样的I/O事件通知。
//所以epoll实际上是事件驱动(每个事件关联上fd)的,复杂度降低到了O(1)
// Options in old opt.h that differs from new opt.h
#define MEM_ALIGNMENT __SIZEOF_POINTER__
......
......@@ -450,7 +450,7 @@ int SysSetUserID(int uid)
SCHEDULER_LOCK(intSave);
User *user = OsCurrUserGet();//获取当前用户
if (IsCapPermit(CAP_SETUID)) { //是否定义了设置用户ID的能力
if (IsCapPermit(CAP_SETUID)) { //是否设置用户ID的能力
user->userID = uid; //改变UID
user->effUserID = uid;
/* add process to a user */
......
git add -A
git commit -m '对chmod chown chgrp几个命令的实现注解
git commit -m '从ifconfig netstat 等常用网络命令的实现来理解lwip协议栈
搜索 @note_pic 可以查看全部字符图
搜索 @note_why 是注者尚未看明白的地方,如果您看明白了,请告诉注者完善
搜索 @note_thinking 是注者的思考和吐槽的地方
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册