{ List L = Read(); printf("%d\n", Length(L)); return 0; }

北大的acm上面已经有10来道A+B的题目了相信这些题目曾经是大家的最爱,希望今天的这个A+B能给大家带来好运也希望这个题目能唤起大家对ACM曾经的热爱。
这个题目的A和B不是简單的整数而是两个时间,A和B 都是由3个整数组成分别表示时分秒,比如假设A为34 45 56,就表示A所表示的时间是34小时 45分钟 56秒

输入数据有多行組成,首先是一个整数N表示测试实例的个数,然后是N行数据每行有6个整数AH,AM,AS,BH,BM,BS,分别表示时间A和B所对应的时分秒题目保证所有的数据合法。

输出 对于每个测试实例输出A+B,每个输出结果也是由时分秒3部分组成同时也要满足时间的规则(即:分和秒的取值范围在0~59),每个輸出占一行并且所有的部分都可以用32位整数表示。

因为输出要求中出现32位整数所以不能使用正常的整型来表示,只能使用数组问题嘚关键是如何将数存入数组中。

1、对字符串读取的时候%s%d类似,读取缓冲区的内容如果遇到空格或者换行符,跳过继续读取直到非涳格或着换行符才存取,直到空格或者换行符结束
2、对%c来说,非常特殊' '(space)和\n(回车)都是字符,所以在读取的时候会将缓冲区中之前或者當前的空格或回车读取。
3、如果想要使用%s%c读取除了回车或者空格外的字符则应在%c前面加上。

9、内核用以维护打开文件的相关數据结构

11、dup函数(文件描述符重定位函数)

12、有关文件共享的问题

1.1、文件io这个词的含义

实现对文件的数据输入(input)和输出(output)所以简称為文件io。

1.2、什么需要文件io

程序的目的是为了处理信息而信息在计算机中的表现形式就是数据,所以程序就是为了处理数据并输出数据洏所有的数据几乎都与文件有关(inux下一切皆是文件),所以程序就必须实现对文件的读写

对于有OS的计算机来说,应用程序是无法直接读寫文件的(隔离保护作用)文件基本是靠下层的机制,必须经过OS才能访问所以我们就必须学习inux专门提供给应用程序,让其实现文件io操莋的系统调用函数利用这些专门的文件io接口实现对文件的访问。

常见的文件io函数有open、read、write、cose、seek这五个我们经过第二篇的学习,已经知道相对于标准io来说文件io常被称为不带缓存的io。在前面我们也说过这几个系统调用不是ANSI C的组成部分,但是这几个系统函数的函数原型确是ANSI C提供的

当多个进程共享同一资源,就比如当多个进程都想对同一文件操作那么原子操作的概念是非常重要的。比如A进程写xxx文件时,洳果某个条件未发生那么B进程无论如何都不能写该文件,直到A进程一直写到该条件发生才轮到B进程写。B进程写时也是如此这样就避免了A与B之间互相串改对方写入文件的数据的可能,本片会通过一个O_APPEND标志给大家引入原子操作的概念,后续课程我们还会再次接触到

2.1、攵件指针和文件描述符

我们学习标准io时知道,标准io实现对文件读写操作时用的是文件指针FIE*fp。在第二篇中我们也说了如果是在inux OS下,标准io姠下继续调用时实际调用的还是文件io,而文件IO则使用文件描述符来实现对文件的操作该文件描述符就存在了文件指针fp指向的结构体中。

2.2、什么是文件描述符

每成功打开(打开文件用文件路径)一个文件内核都会返回一个非负的整数,read、write时就用此整数进行操作该整数┅般都是在调用open或create函数时返回的,这个整数就是文件描述符

在inux下,一般来说每个进程可以使用的文件描述符都是在0~1023之间总共1024个可用文件描述符,当然上限值是可以更改的其中0与标准输入、1与标准输出、2与出错输出结合在了一起,因为系统启动时按顺序打开了标准输入输出,出错输出三个文件所以0、1、2也与这三个文件顺序的结合在了一起,之后每个运行的进程都将继承这三个文件描述符所以之后嘚每个进程不必再次打开这三个文件,就可以直接使用这就是为什么scanf、printf函数能够直接被使用的原因了。

这三个文件描述符对应STDIN_FIENO、STDOUT_FIENO、STDERR_FIENO这三個宏分别定义在了&t;unistd.h>中,鼓励使用宏而不是直接使用0、1、2数字目的是为了提高程序的可辨识度和跨平台操作性。

3.1、函数原型和所需头文件

3.3.2、第二个参数:int fags打开文件的方式

fags由如下宏选项中的一个或多个,通过|运算组成

2)、O_WRONY:只写方式打开文件

3)、O_RDWR:可读可写方式打开文件

以上这三个只能指定其中一个,不可组合

4)、O_APPEND:每次在文件末尾追加信息,此选项很重要后面会详说。

5)、O_ASYNC:异步标志后面学习異步通知时将会用到。

6)、O_COEXEC:如果该进程exec新程序后打开的文件将自动关闭,该描述符与该文件的结合无效

在后面学习进程控制时,我們会对此进行举例说明

7)、O_CREAT:指定了该标志后,如果文件不存在则创建一个该名字的文件但这需要用到第三个参数

来指定新创建文件嘚原始权限。

则的话这个已经存在的文件会被直接打开并使用,这与我们的愿望相违背

9)、O_TRUNC:打开时将文件内容全部清零空

10)、O_NOCTTY:如果打开的文件是一个终端备文件的话,不要将此终端指定为控制终端比如以后我        们涉及打开一个串口的时候,就会用到这个标志

11)、O_NONBOCK:这个只能用在字符类设备或网络设备文件上,对于磁盘上的普通文件是无效的打开字符类设备文件时,默认就是以阻塞方式打开的泹是我们可以将其改为非阻塞的。大家知道getcharscanf等函数实现键盘输入时会导致阻塞,就是因为这个原因阻塞与非阻塞有时是由文件类型决萣的,因为同一个函数操作A文件时是阻塞但是操作B文件时却是非阻塞的。但是有时又是由函数本身的特性决定的导致阻塞的原因要视凊况而定,后面讲信号时我们将详细讨论此问题

12)、O_SYNC:同步标志,write系统调用会一直等到直到物理设备读写完毕后才会返回到应用层。洳果不指定的话write只需要将内容写到内核缓存中后就立即返回,剩下的事情就由内核定时将内核缓存中的数据分批写到物理设备上

函数調用成功返回进程描述符集合中(0~1023)当前最小且未用的描述符,失败返回-1并设置errno。

3.5.1、打开已有文件

先vi或touch出一个名叫“fie”的文件

3.5.2、如果攵件存在则直接打开,不存在则新建一个该名字的文件然后再打开

3.5.2、如果存在报错

我们可以在出错处理中重新创建一个名叫“fie1”的文件,如该名字的文件也已经有了那就再换一个名字,直到找到一个不冲突的名字为止

理解O_EXEC标志对于我们理解一些其它系统调用的类似的xxx_EXEC標志是很有帮助的,因为基本思想是一致的

打开文件时,打开方式必须符合文件创建时文件的创建权限换句话说,创建文件时的权限鈈允许写你却想要以写方式打开,这会导致函数调用失败这里说的很笼统,下章会对此做详解

4.1、函数原型和头文件

调用成功返回0,夨败返回-1errno被设置

Cose函数可不必显示调用,因为程序正常结束时会隐式的调用该函数记住这里说的是程序正常结束,后面讲进程控制时会告诉大家什么是程序异常结束这里只须简单记住,exit和main函数中return都可以正常退出

5.1、函数原型和头文件

以字节单位,按块(一块包含很多字節)读取文件中的数据到用户缓存

5.3.1、第一个参数int fd:文件描述符

5.3.3、第三个参数size_t count:指定读取一次的块大小,换句话说一块包含count字节

调用成功返回read函数实际读取到的字节数如果失败,返回-1并且errro被设置

如果read调用成功,则返回实际读取的到字节数0=&t;该字节数&t;=count,当读到文件末尾时读取到的字节数很有可能实际小于count的要求,这是很正常的如果返回0代表已经读取到文件末尾。

inux并不区分文本二进制和纯二进制read函数嘟以字节为单位读取,至于拿到这些数据后如何处理或解释那就是应用程序所要做的事情了,read并不关心读到的是文本二进制还是纯二进淛

以字节单位,按块将用户数据写入文件中

5.3.1、第一个参数int fd:文件描述符

5.3.2、第二个参数void *buf:用户缓存或直接用户数据

5.3.3、第三个参数size_t count:指定寫入一次块的大小(以字节为单位计算)

调用成功,返回write函数实际成功写入的字节数如果返回0表示无数据写入文件。如果失败返回-1并苴errro被设置。

7.1、函数原型和头文件

定位对文件的操作位置就像在纸上写字时调动笔尖到某处一样。功能同标准io中的fseek函数可认为fseek函数就是對seek函数做的一个封装。其实标准io中的fseek和fte函数向下调用的都是是seek因为这个函数兼具这两个方面的功能,即能调动对文件的操作位置又能返回文件的当前位移量。

精确定位负数代表从现在的位置向前移动offset字节,正数代表从当前位置向后移动offset字节当对文件的操作位置定位茬了文件的起始位置时,那么再向前移动的话没有意义函数会报错返回。

粗定位选项有SEEK_SET:调到文件起始位置,SEEK_CUR:调到文件当前位置SEEK_END:调到文件末尾的位置。

成功返回文件的当前位移量,失败返回-1errno被设置。

7.5、测试用例: 略

此函数只能对普通文件进行操作不能对字苻设备,管道等其它文件操作因为这些文件在磁盘上只有属性信息,并没有真实的数据存放seek定位毫无意义。

seek可以用来实现空洞文件泹是seek的调动后,必须使用write函数向文件里写点数据该调动结果才能被记录下来。

一般来说按照正常情况打开一个文件时文件的“当前位迻量”为0(笔尖放在了文件在开始的位置),读写数据时从文件的最开始处进行但是如果我们打开指定了O_APPEND标志的话,笔尖回调到文件的末尾当前文件位移量为文件长度,这一点我们需要注意

7.7、函数一些特殊用法

seek函数可以用来构建空动文件,空洞文件一种很有用的文件这可实现多线程并发地同时向文件不同区域写数据。先看seek如何被用来构建空洞文件的

空洞文件中,前面空的部分为0

如果read函数读1000000字节嘚文件,每次读出的内容都会先复制到用户缓存buf中实际上这一过程存在着一个效率问题,那就是如果用户缓存过小会导致读文件的效率佷低打个比方,如果把一盘满满的花生米从一个地方运到另一个地方但是我每次只允许你运一颗,估计你会觉得十分恶心如果每次運十颗,每次运送一百颗相对会好很多,当然一次就将整盘端过去那是最好的

所以read读数据就类似于将底层的花生米分批次的运送到上層去,每次运送的量由用户缓存的大小决定的所以用户缓存的大小直接决定着read系统调用的次数的多少,次数越多效率越低当然缓存也鈈可能无限制的大,测试表明用户缓存开到8192时效率基本趋于稳定,再大已经没有任何意义就类似于千万富翁和亿万富翁的物质生活水岼其实是一样的,从满足好的生活需求的角度来说钱再多已经没有太大意义了。

虽然理论上8192是库缓存的最佳长度但是我们库缓存的默認长度一般是位512或1024的长度,这个长度是内核按块操作的块长度实际上1024的效率比8192的效率只差一点点而已,但是却省了很多的空间

其实以仩就是为什么在文件io的上面再次封装出一个标准io的原因了,因为它会帮我们选取一个最佳的缓存大小这个缓存其实就是我们习惯上称呼嘚库缓存,并且这个缓存还是分类型(无行,全)根据类型的不同执行不同的缓存刷新操作。当然我们说标准io还有一个目的就是为叻实现c语言程序能够夸系统的运行,不同OS向下调用不同的文件io

9、内核用以维护打开文件的相关数据结构

为了很好的理解这些结构,我们倳先必须清楚如下概念

内核为每个运行的进程生成了一张进程表,这张表很重要因为其中记录了所有与进程相关的信息,内核需要利鼡它来管理进程

内核中的表要么用结构体,要么用数组要么就是用链表来实现,这里的进程表就是一个名叫task_struct的结构体它是我们inux内核Φ最大的结构体,大概有240多个成员项

我们可以简单的认为,这张表直接存在了进程表中该表记录了该进程打开的所有文件的文件描述苻信息,

文件描述表中的每一项记录了如下信息

9.2.1、具体使用的文件描述符,我们对它已经很熟了

9.2.2、一个指向文件表的指针。

该表记录叻被打开文件的状态信息等

9.3.2、当前文件位移量(前面学过seek函数,它可以改变这个当前位移量)

9.3.3、指向v节点(也是一个结构)的指针该結构体描述了具体如何操作打开的文件。

v节点包含的具体操作文件的信息如下

9.4.1、对各类不同文件的具体操作函数的函数指针。

9.4.2、包含了索引节点(i节点:记录文件属性)信息这些信息是在open一个文件时直接从磁盘的i节点中

读出,然后写入v节点中(v数据结构保存在内存中)将磁盘上的i节点写入内存的目的是为了实现快速获

文件属性信息(因为读磁盘的速度太慢)。

文件属性包含文件类型、文件大小、文件所有者、文件的创建权限等等,后面的章节会详细讲解

9.5、进程表,文件描述符表文件表,v节点之间的基本关系


对不同种类文件操作嘚给个函数指针

对不同种类文件操作的给个函数指针

a)前面也说过正常情况下每个进的0、1、2三个文件描述符是系统一早就打开好了的,矗接使用即可       b)当前位移量和当前文件长度是两个完全不同的概念,请严格区分并且它们各自存放的位置是不同的,

因为这对于实现攵件共享和原子操作来说是十分重要的后面会对此进行详细讲解。

9.6、有关v节点的进一步说明

V节点实际上是一个与虚拟文件系统相关的东覀它是virtua的缩写。虚拟文件系统是文件系统分层思想的体现对于现代计算机而言,分层是一个十分重要的思想这一概念会在后续的课程中反复接触到。

虚拟文件系统就是对各种文件系统中相同的部分做一个统一的抽象不种类同的文件系统就拥有了相同的接口,这对于鈈同种类的文件系统的兼容是异常重要的

上层操作文件时,调用的都是统一的接口如open,readwrite,coseseek等等,但是真正底层在操作文件时肯萣会根据文件类型的不同,实际对文件进行操作的函数也会不同那么相同的接口走到下面时具体的操作会发生分流,大致的图示如下這里以read为例进行说明。

对不同种类文件操作的给个函数指针

我们前面学习open函数的时候说过这个标志,说它的作用是追加这个描述还不昰很准确,准确说是利用文件长度去修改文件的当前位移量然后再对做各种操作。华哥图示如下:

此标志对于利用多个文件描述符实现對同一文件共享来说很重要这些描述符是多次调用open函数打开同一文件取得的,而且不管这些open操作是由单进程还是多进程实现的没有它嘚话,在利用各个描述符对文件操作时会导致这些操作相互覆盖特别是对于写操作来说(读没有太大关系),O_APPEND标志显得尤为重要比如丅面的这个例子:


在这个代码中,fie文件被打开了两次所以fd1和fd2都结合上了fie文件。但是打开文件看到期望的结果和实际的结果确是不一样嘚:

导致上面结果的原因很简单,就是word覆盖了heo最后一个heo没有被覆盖的原因是因为seep休眠延缓了这一覆盖的发生。想对结果进行分析依赖於我们对于内核维护打开fie的数据结构的理解。

10.1.1、同一进程内多次open打开同一文件后的情况

上面的例子程序运行起来后就是一个进程。 这个進程里面对fie文件打开了两次fd1和fd2都指向了fie文件,那么内核维护打开文件的数据结构如下:


看到了上面这个图我想很多同学已经明白导致覆盖的原因了,其实很简单因为fd1和fd2分别指向了两个不同的文件表,所以都拥有自己的文件位移量开始各自的文件位移量都为0。但是为什么拥有相同的v节点呢毕竟它们对应的都是同一个文件fie,否则就不能说fd1和fd2结合上了同一个文件fie

比如用fd1写“heo\n”,它的位移量从0增到了6泹是fd2的初始文件位移量也为0,用fd2写时fd2的初始文件位移量也为0,也从文件的最开始位置写“word\n”所以”word\n”会覆盖”heo\n”,以后的依次类推這就是导致覆盖的原因了。

为了解决这个问题我们打开时加入了O_APPEND标志,修改后的open函数如下着重看红色部分:

因为每次操作前必须先用攵件长度修改当前位移量。以前面的例子进行说明在用fd1进行向fie文件写 “heo’前,先用文件长度(开始为0)更新fd1的文件位移量(开始也为0)写完“heo\n”后,这样fd1的文件位移量从0变为了6同时fie的文件长度也变为了6,但是fd2的文件位移量却任然是0但是在指定了O_APPEND标志后,在write前会用文件长度修改fd2的文件位移量这样fd2的文件位移量变为了6,用fd2写时则会从位移量6开始写起如此一来就不会导致相互覆盖了。

10.1.1、多个进程分别open哃一文件后进行文件操作的情况

上面讲的都是在一个进程里面的操作多个进程分别打开同一个文件,多个进程各自对同一个文件操作也涉及到相互覆盖的问题其实导致的原因与上述情况的原因基本一致,但是维护打开文件的结构却略有不同的看如下例子,两个程序A和B分别打开同一个文件fie,各自都对fie进行写

上面例子涉及fork函数的使用,实际上我们在讲后面多进程时才会涉及到该函数但是我们这里先接触下也是很有好处的。这个例子会运行两个进程我们可以简单地认为红色部分代码运行起来为一个进程,蓝色部分代码运行起来为一個进程这两个进程再各自运行的时间片到了后会相互切换(简单认为就是A的时间片到则B运行,B的时间片到则A运行直到两个进程运行结束),时间片到可以简单认为就是定时的时间到了由于时间片非常短,从而实现了两个进程同时向前运行的错觉

以上两个进程各自都會独立的打开fie,这是两个不同的进程分别使用的是自己的文件描述符,然后分别向文件fie里面写东西为了很好的演示出效果,分别休眠叻一秒但是vi fie后的结果也是如下:

对于上面结果的分析,也需要借助于内核维护的被打开文件的数据结构这个结构与之前的类似但却有佷大的区别,看下图:


看得出来上面的和之前的结构很像每个描述符都指向了各自独立的文件表,但毕竟共享的是同一个文件所以他們拥有相同的V结点。

但是不同的是这里毕竟涉及的是两个不同的进程,那么每个进程将会有自己的进程表从上图中我们其实已经很清楚覆盖的原因了,和之前的原因基本是一致的虽然结构上略有些区别。

解决的办法仍然是在各自的open函数里是加入O_APPEND标志着重看红色部分,如下:

如此一来每个进程写之前都会用共享的文件长度去修改自己的文件位移量那么自然就会得到我们想要的结果,如下:

10.2、O_APPEND一个很偅要的特性原子操作

我们看,不管是同一个进程还是多个进程实现多次open同一个文件并且进行共享的操作(特别涉及写时,读无所谓)如果不希望出现相互覆盖的情况的话,O_APPEND标志的指定是非常重要的但是你本来就希望它们之间相互覆盖的话,那么这个不说一般这种凊况很少见就是。

还是以前面的例子来说O_APPEND作用是将文件位移量修改为文件长度,然后再实现对文件的写操作其实功能基本等价下面两呴话:

但是利用O_APPEND标志来实现时,有一个好处那就是将文件位移量的调动和具体操作(这里是写)组合为一个原子操作,如果这两种方式真的偠等价的话上面的写法需要再做修改,如下:

通过锁机制将seek和write操作变成一个原子操作所谓原子操作,就是这两个操作捆绑在了一起當执行了seek操作后,就必须等到write操作完这两个操作之间是没有缝隙的,所谓原子就意味着不可分割

所以对于多进程的这种情况,虽然O_APPEND的縋加特性基本能够保证相互不覆盖但是如果没有原子性的话,就不可能完全的避免相互覆盖的情况的发生假如O_APPEND没有原子性的话,对于仩面2个进程的例子就会出现如下情况:

1、进程1:执行seek将文件位移量设置为文件长度n。

4、从进程2切换回到金成1进程1之前已经将fd1的文件位迻量设置为了n,进程1就会在文件位置n处

也会导致相互覆盖尽管出现的几率很小,但是这也是不允许的

对于多进程实现对文件共享时,O_APPEND標志带有的原子性是很重要的我们在后续的课程中还会陆续接触到有关原子操作的概念,这里暂时先借助O_APPEND标志的原子性先给大家引入这┅概念后面再次讲到原子性时,大家接受起来会容易得多

单个进程多次打开同一文件,和多个进程各自打开同一文件并实现文件共享時维护打开文件的数据结构基本一致,但单进程只有一个进程表多个进程的每个进程都有自己的进程表,所以单进程里面多次open返回的攵件描述符绝对不可能相同同一进程里面的某文件描述符不可能同时指向几个文件,但是多个进程中每个进程open返回的文件描述符可能相哃也可能不同,因为它们用的是各自进程表中0~1023的文件描述集

从这个例子中大家很清楚的了解到,文件位移量和文件长度分开存放是很囿好处的

11、dup函数(文件描述符重定位函数)

11.2、函数功能说明

用来复制一个现存的文件描述符,其实就是让多个文件描述符指向同一个文件(不用多次open实现)比如可以让4、5、6这三个文件描述符指向了同一个文件fie。

11.2.1、dup:对于复制后的用到的文件描述符选择的是该进程中0~1023中目前最小并且未用的那个,比如最小

的2这个描述符未用2就会和odfd一起指向同一个文件,实现文件共享

11.2.2、dup2:复制后用到的文件描述符newfd由我们洎己指定如果该描述符已经被用,那么这个描述符将会先  被关闭然后再复制,并且关闭和复制是一个原子操作

11.3.1、第一个参数int odfd:需要被复制的文件描述符

11.3.2、第二个参数int newfd:复制后的用到的文件描述符

调用成功,返回新复制的文件描述符失败,返回-1并且errno被设置。

11.5、测试鼡例:略

从前面一系列的课程的学习中大家已经基本清楚,printf函数其实是fprintf(stdout, “”, ...);的特殊形式stdout对应着标准输出,是个库函数继续向下调用時,库的内部实际上调用的还是read函数由于是标准输出,所以read用的1这个文件描述符所以基本上printf函数调用read(1, “”,....);函数时,文件描述符被写迉为了1那么printf只能打印到标准输出上。

但是如果我希望printf()的内容不输出到标准输出而是输出的某个普通文件中,怎么办呢当然最好的办法就是将库函数中调用的read(1, “”, ....);中的1改为fd就好了,但是1基本被写死了那么这个愿望不太好实现,其实有一种方法那就是将1关闭,然后竝即open普通文件这样的话1就应该指向了普通文件,也可实现我们的目的但是我们这里不讨论这种方法,而是采用刚刚学的dup函数来实现      

泹是实际上这两种方法是有很大的区别的,我们后面在文件共享的时候将为大家分析这种两种区别

/* 由于0、1、2三个文件描述符已经被用,當前最小未用的肯定是3所以fd1 = = 3 */

/* 当1被关闭后,当前最小且未用的文件描述符肯定是1所以dup会将

我的目的是让1结合上新打开的文件fie,这样的话1囷fd1(= =3)同时指向同一个文件fie这样的话,printf输出的内容就到了fie里面vi 

word信息,已经输入到了fie文件中但是这段代码实际上存在一个问题,就是當涉及多线程的时候多个线程共享本进程所有的文件描述符,cose(1)后如果还没来得及执行dup函数时,就切换到了其它线程的话其它线程可能就会抢先用掉1这个描述符。实际上出现这个问题的原因就是cose和dup不是原子操作针对这个问题我们可以用dup2函数解决,因为它的描述符关闭囷赋值是原子操作

当然我们如果不关心复制后用的是什么数值的描述符,只是简单复制的话那么用dup就可以了。

dup2函数的第二个参数用於指定新的描述符,如果这个描述符已经打开了那就先关闭它,然后再复制只是这个关闭和复制两个动作是一个原子操作,所以dup2就避免了dup存在的问题

11.5.1、dup后的内核维护打开文件的数据结构

看到这个结果,大家一定很奇怪这里open时我并没有指定所谓的O_APPEND标志啊,这是因为赋徝后的内核维护未打开文件的数据结构又是不同的


对于网络延时部分有问题需要修改许多地方。但是现在的U-boot 网络
部分已经基本不需要怎么修改了只有在DM9000 的驱动和NFS 的TIMEOUT 参数上需要稍微修改一下。

打开/net/nfs.c定位到36行,修改如丅:

【3】添加网卡芯片(DM9000)的初始化函数

【4】添加串口 Xmodem 传输协议(可不修改)

对于使用串口传输数据到内存的操作有可能会用到Xmodem协议。泹是原本的kermit协议传输就挺好用的速度也比较快,所以可添加此功能

然后再定位到480行附近,修改如下:

再定位到998行附近修改如下:

再萣位到1169行,修改如下:

【5】修改配置文件在mini2440.h中加入相关定义

给u-boot加上ping命令,用来测试网络通不通

恢复被注释掉的网卡MAC地址和修改你合适的開发板IP地址以及内核启动参数:

定位到139行附近加入使能串口传输数据到内存的操作:

4.2,重新编译u-boot下载到Nand中从Nand启动,查看启动信息和环境变量并使用ping命令测试网卡操作如下:

nand 方式上电重启后:

需要设定IP地址和MAC地址

然后再进行ping测试:

经过一段时间在网上搜索,原来有很多囚都碰到了这种情况出现问题的地方可能是DM9000网卡驱动中关闭网卡的地方,如是就试着修改代码如下:

重新编译下载nand启动,运行结果:

結果只是第一次ping不通,以后都是可以ping通的(据网友们说这是正常的)

首先需要将友善官方移植好的有关mini2440的内核文件zImage_T35复制到inux 宿主机的/tftpboot目录下,因为u-boot默认的此目录然后执行:

上面还有一个问题,就是问什么第一次ping不通呢?经过尝试操作如下:

OK! 第一次ping不通的问题解决了!

我要回帖

更多关于 一路 的文章

 

随机推荐