ping命令执行过程一 ping命令过程

一、简介

这里打算从U-Boot的ping命令说起。ping命令是用于测试网络是否和目标网络畅通简单工具,

在U-Boot中ping命令的使用方法是:

ping 比如我电脑的IP地址为192.168.1.10,ping命令使用如下:

ping192.168.1.10,如果开发板和目标IP之间的通信畅通的话,将输出如下信息:

host 192.168.1.100 is alive

否则显示:

ping failed;

host 192.168.1.100 is notalive

二、ping命令介绍

U-Boot中加入ping命令的代码如下:

U_BOOT_CMD(ping,// 命令名称

2, //参数个数

1,

do_ping, //命令执行函数

"sendICMP ECHO_REQUEST to network host",//长帮助说明

"pingAddress" );//短帮助说明

显然,我们需要分析do_ping函数

三、ping函数

int do_ping (cmd_tbl_t *cmdtp,

int flag,

int argc,//参数3和参数4是和main函数一样的参数

char *argv[])//我们在使用ping命令的时候的格式如下:ping 192.168.1.10

//因此这里的argv[1]就是我们的IP地址的字符串格式了

{

if (argc < 2)该命令的参数至少应该为2,如果参数个数小于2则直接返回

return-1;

NetPingIP =string_to_ip(argv[1]);//该函数将主机的字

//符串ip地址转换成点分ip地址

if (NetPingIP ==0)//NetPingIP是一个全局变量,定义在net/net.c中,

//如:IPaddr_tNetPingIP;

//而IPaddr_t在include/net.h文件中定义,

//定义如下:typedefulongIPaddr_t;也就是说他是一个长整形变量

{

cmd_usage(cmdtp);

return -1;

}

if(NetLoop(PING)<0)//若NetLoop函数返回值小于0,则网络不通;

{

printf("pingfailed;host%sisnotaliven",argv[1]);

return1;

}

printf("host%sisaliven",argv[1]);网络通畅。

return0;

}

一个ip地址占用32位,具体怎么转换的需要看看相关书籍,推荐TCP/IP协议簇,很不错的书

我们在PC机上执行如下操作:

ping www.baidu.com

正在 PING www.a.shifen.com (61.135.169.105) 具有32字节的数据:

来自61.135.169.105 的回复:字节=32 时间=31ms TTL=55

......

后面的就不看了,

我们看到一个IP地址:61.135.169.105

由于IP地址是点分十进制格式的。比如百度的这个IP地址61.135.169.105,他的意思就是把

一个32位的数分成4个字节,每个字节八位,用三个点分开的四个数分别占据这四个字节

当中的一个。因此百度的这个IP地址实际上可以转换成下面的格式:

61 ----0x3D

135----0x87

169----0xA9

105----0x69

那么这个整数就是0x3D87A969,转换为十进制就是1032300905。

在dos命令提示符下输入:ping 1032300905

正在 ping 61.135.169.105 具有32字节的数据:

......

我们在浏览器的地址栏里面输入: http://1032300905 也能打开百度搜索网页。这其实就

说明了一个问题: NetPingIP =string_to_ip(argv[1]); 这行代码把我们输入的IP地址

解析成了后面代码需要使用的IP地址,现在记住这一条就行了。

解析了IP地址,后面就是调用具体的工作函数NetLoop了。调用的时候

给了一个参数:PING。在include/net.h文件中有如下定义:

typedef enum

{ BOOTP, RARP, ARP, TFTP, DHCP, PING, DNS, NFS, CDP, NETCONS,SNTP } proto_t;

proto_t是一个枚举型的变量,我们可以凭此猜测这个NetLoop函数还可以接受

这个枚举定义的其他参数。准备工作就做到这里,下面接着看NetLoop函数。

这个函数比较庞大,在net/net.c文件中,我们分成若干部分来看:

intNetLoop(proto_t protocol)

{

bd_t *bd =gd->bd;

#ifdefCONFIG_NET_MULTI

NetRestarted =0;

NetDevExists = 0;

#endif

NetArpWaitPacketMAC =NULL;

NetArpWaitTxPacket = NULL;

NetArpWaitPacketIP =0;

NetArpWaitReplyIP =0;

NetArpWaitTxPacket =NULL;

NetTxPacket =NULL;

NetTryCount = 1;

if (!NetTxPacket)//因为在前边这个变量定义为NULL,那么该部分肯定会执行,这里有点冗余

{

int i;// Setup packetbuffers,alignedcorrectly.

//NetTxPacket是一个unsignedchar类型的指针,通过该语句,该指针指向PktBuf的第32个位置

NetTxPacket= &PktBuf[0] + (PKTALIGN -1);

NetTxPacket -= (ulong)NetTxPacket %PKTALIGN;//32字节对齐,这两句的意思是,首先加

//31,相当于指针指向数组的第31个位置,除以32,然后减去该地址除以32的余数,这这两

//句执行完毕后NetTxPacket指向的PtkBuf地址肯定能被32整除,有可能导致数组一些位置不

//在使用之所以要先加后除是因为不过不先加的话,可能导致操作时超出数组的边界.

for (i = 0; i < PKTBUFSRX; i++)

{

NetRxPackets[i] = NetTxPacket +(i+1)*PKTSIZE_ALIGN;

}

}

NetTxPacket = &PktBuf[0] + (PKTALIGN -1); //PktBuf是一个字符数组,

// 定义如下: volatileuchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN+ PKTALIGN];

//这上面的三个宏定义分别如下:

//# define PKTBUFSRX4

//#definePKTSIZE_ALIGN1536

//#definePKTALIGN32

//所以这里定义的是一个大概5个1536字节大的数组。继续看下面:

NetTxPacket-= (ulong)NetTxPacket % PKTALIGN;

//NetTxPacket先是获得了一个地址,然后把这个地址减去一个值,减去的这个值

//是地址本身和32的余数,那么实际上就是把NetTxPacket进行32字节对齐了。

for (i = 0; i < PKTBUFSRX; i++)

{

NetRxPackets[i] = NetTxPacket +(i+1)*PKTSIZE_ALIGN;

}

//实际上就是把NetRxPackets数组进行赋值,这个数组定义如下:

//volatile uchar *NetRxPackets[PKTBUFSRX]; 说明它也是指向字符串的数组,

//可以知道这个数组都被赋予了PktBuf当中的某个地址,并且这些地址都是

//32位对其的。

if (!NetArpWaitTxPacket)//传输包不为空执行以下操作

{//以下两句仍然是32字节对齐

NetArpWaitTxPacket=&NetArpWaitPacketBuf[0]+(PKTALIGN-1);

NetArpWaitTxPacket-=(ulong)NetArpWaitTxPacket%PKTALIGN;

NetArpWaitTxPacketSize =0;

}

//同样,这里这个判断貌似也是多余,因为前面已经直接把

//NetArpWaitTxPacket设置为了NULL,这个后面的代码肯定会执行的。

//继续后面的代码:

NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN -1);

//先给它一个值,这个值就是数组当中的一个地址,数组定义如下:

//ucharNetArpWaitPacketBuf[ PKTSIZE_ALIGN + PKTALIGN];

//然后和上面的一样,进行一个地址对齐,32位:

//NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket %PKTALIGN;

//到这里,一些housekeeping的代码就完成了,然后是一些和硬件相关的:

eth_halt();

#ifdefCONFIG_NET_MULTI

eth_set_current();

#endif

if (eth_init(bd) < 0)

{

eth_halt();

return(-1);

}

首先是eth_halt()函数,定义在net/eth.c文件中:

void eth_halt(void)

{

if(!eth_current)

return;

eth_current->halt(eth_current);

eth_current->state = ETH_STATE_PASSIVE;

}

//实际上它只是调用了具体网卡驱动的halt函数,然后把网卡状态设置为

//passive。由于网卡驱动的halt函数只是进行了网卡的硬件操作,不是我们这

//里关心的重点,因此这里就不分析了。同样,后面的eth_init函数也调用

//的是网卡驱动的init函数,对网卡硬件进行一个初始化,接着看下面的代码:

restart:

#ifdefCONFIG_NET_MULTI

memcpy (NetOurEther, eth_get_dev()->enetaddr, 6);

#else

eth_getenv_enetaddr("ethaddr",NetOurEther);//该行执行完毕后,NetOurEther的值等于我在

//fs2410.h定义的MAC地址值

#endif

//实际上执行的是第一个函数,可以看出我们实际上是把本机的mac

//地址拷贝到了NetOurEther中。本机的mac地址是在调用eth_init函

//数的时候从网络控制器中读取到当前网络设备的enetaddr中的,和

//具体硬件相关。

NetState = NETLOOP_CONTINUE

//然后设置网络状态,初始化循环。

switch (protocol) {//protocol =3 =ping
#if (CONFIG_COMMANDS & CFG_CMD_NFS)
case NFS:
#endif
#if (CONFIG_COMMANDS & CFG_CMD_PING)
case PING:
#endif
#if (CONFIG_COMMANDS & CFG_CMD_SNTP)
case SNTP:
#endif
case NETCONS:
case TFTP:
NetCopyIP(&NetOurIP,&bd->bi_ip_addr);//程序执行后,NetOurIP=192.168.1.5
NetOurGatewayIP =getenv_IPaddr ("gatewayip");//NetOurGatewayIP=NULL,因为gatewayip为空
NetOurSubnetMask=getenv_IPaddr ("netmask");//该命令执行后NetOurSubnetMask=255.255.255.0
NetOurVLAN =getenv_VLAN("vlan"); //该命令执行后 NetOurVLAN的结果为NULL
NetOurNativeVLAN= getenv_VLAN("nvlan");//同上

switch(protocol) {//protocol =3 =ping
#if (CONFIG_COMMANDS & CFG_CMD_NFS)
case NFS:
#endif
caseNETCONS:
case TFTP:
NetServerIP= getenv_IPaddr ("serverip"); //该命令执行后NetServerIP=192.168.1.10.该值在

//fs2410.h中定义
break;
#if (CONFIG_COMMANDS & CFG_CMD_PING)
case PING:

break;
#endif
#if (CONFIG_COMMANDS & CFG_CMD_SNTP)
case SNTP:

break;
#endif
default:
break;
}

break;
case BOOTP:
case RARP:

NetOurIP =0;
NetServerIP =getenv_IPaddr ("serverip");
NetOurVLAN =getenv_VLAN("vlan");
NetOurNativeVLAN= getenv_VLAN("nvlan");
case CDP:
NetOurVLAN =getenv_VLAN("vlan");
NetOurNativeVLAN= getenv_VLAN("nvlan");
break;
default:
break;
}

switch (net_check_prereq (protocol)){//这个函数返回0
case 1:

eth_halt();
return (-1);

#ifdef CONFIG_NET_MULTI
case 2:

break;
#endif

case 0:
#ifdef CONFIG_NET_MULTI
NetDevExists =1;//存在一个网络设备
#endif
switch (protocol){//protocol =3 =ping执行ping命令
case TFTP:

TftpStart();
break;

#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
case DHCP:

BootpTry= 0;
NetOurIP= 0;
NetServerIP= getenv_IPaddr ("serverip");
DhcpRequest();
break;
#endif

caseBOOTP:
BootpTry= 0;
BootpRequest();
break;

caseRARP:
RarpTry= 0;
RarpRequest();
break;
#if (CONFIG_COMMANDS & CFG_CMD_PING)
casePING://执行这一部分
PingStart();
break;
#endif
#if (CONFIG_COMMANDS & CFG_CMD_NFS)
case NFS:
NfsStart();
break;
#endif
#if (CONFIG_COMMANDS & CFG_CMD_CDP)
case CDP:
CDPStart();
break;
#endif
#ifdef CONFIG_NETCONSOLE
caseNETCONS:
NcStart();
break;
#endif
#if (CONFIG_COMMANDS & CFG_CMD_SNTP)
case SNTP:
SntpStart();
break;
#endif
default:
break;
}

NetBootFileXferSize= 0;
break;
}

//以下下划线之间的部分不执行,因为那些宏我们没定义

----------------------------------------------------------------------------------------------

#if defined(CONFIG_MII) || (CONFIG_COMMANDS &CFG_CMD_MII)
#if defined(CFG_FAULT_ECHO_LINK_DOWN) &&defined(CONFIG_STATUS_LED) && defined(STATUS_LED_RED)

if(miiphy_link(eth_get_dev()->name,CFG_FAULT_MII_ADDR)) {
status_led_set(STATUS_LED_RED, STATUS_LED_OFF);
} else {
status_led_set(STATUS_LED_RED, STATUS_LED_ON);
}
ping命令执行过程一 ping命令过程
#endif
#endif

------------------------------------------------------------------------------------------------

//*Main packet receptionloop. Loop receiving packets until
//someonesets `NetState' to a state that terminates.
for (;;) {
WATCHDOG_RESET();
#ifdef CONFIG_SHOW_ACTIVITY
{
externvoid show_activity(int arg);
show_activity(1);
}
#endif

eth_rx();


if (ctrlc()){
eth_halt();
puts("nAbortn");
return(-1);
}

ArpTimeoutCheck();


if (timeHandler&& ((get_timer(0) - timeStart) > timeDelta)) {
thand_f*x;

#if defined(CONFIG_MII) || (CONFIG_COMMANDS &CFG_CMD_MII)
# if defined(CFG_FAULT_ECHO_LINK_DOWN)&&
defined(CONFIG_STATUS_LED)&&
defined(STATUS_LED_RED)

if(miiphy_link(eth_get_dev()->name,CFG_FAULT_MII_ADDR)) {
status_led_set(STATUS_LED_RED, STATUS_LED_OFF);
}else {
status_led_set(STATUS_LED_RED, STATUS_LED_ON);
}
# endif
#endif
x= timeHandler;
timeHandler= (thand_f *)0;
(*x)();
}


switch (NetState){

caseNETLOOP_RESTART:
#ifdef CONFIG_NET_MULTI
NetRestarted= 1;
#endif
gotorestart;

caseNETLOOP_SUCCESS:
if(NetBootFileXferSize > 0) {
charbuf[10];
printf("Bytestransferred = %ld (%lx hex)n",
NetBootFileXferSize,
NetBootFileXferSize);
sprintf(buf,"%lx", NetBootFileXferSize);
setenv("filesize",buf);

sprintf(buf,"%lX", (unsigned long)load_addr);
setenv("fileaddr",buf);
}
eth_halt();
returnNetBootFileXferSize;

caseNETLOOP_FAIL:
return(-1);
}
}
下一节,我们将分析PingStart这个函数

  

爱华网本文地址 » http://www.aihuau.com/a/25101014/229944.html

更多阅读

学习领导科学与艺术提升领导力与执行力一

学习领导科学与艺术提升领导力与执行力(一)彭向刚(根据听课记录整理,未经本人审阅)不是前言的前言听彭教授的同一个专题讲座有两次,每一次讲座都是深深吸引导着大家,讲座思想深刻、内容翔实、逻辑严密、析理透彻、语言风趣,我很想看到他

学习执行力的心得体会

“执行力”一词最早出现在企业,近年来逐步向政府延伸。从执行力的延伸动态可以看出,政府的土壤在一定程度上适合企业的执行力的移植。因此我们对于执行力的思考,可以从企业的角度出发,加上政府的元素来进行。一、何为执行力执行力包含三

PDPC过程决策程序图法 pdpc图

PDPC过程决策程序图法■文/李士福http://blog.sina.com.cn/lishifu过程决策程序图PDPC(Process Decision ProgramChart)是在策划过中,针对可能出现的风险因素分别提出预防对策、应急方案,当执行过程中遇到不利情况时,仍能有条不紊地按计

ping命令执行过程一 ping命令过程

一、简介这里打算从U-Boot的ping命令说起。ping命令是用于测试网络是否和目标网络畅通简单工具,在U-Boot中ping命令的使用方法是:ping 比如我电脑的IP地址为192.168.1.10,ping命令使用如下:ping192.168.1.10,如果开发板和目标IP之间

声明:《ping命令执行过程一 ping命令过程》为网友不甜薄荷叶分享!如侵犯到您的合法权益请联系我们删除