Vxworks启动代码usrRoot()函数分析(一)

今天到了星期日下午,开始分析usrRoot()函数,看看这个函数实现了哪些功能。

       (1) memInit (pMemPoolStart, memPoolSize);         /* initialize memory pool */

        我们知道在romstart函数中已经对内存进行了清零,这个内存池是干什么用的呢?搜了半天也没有资料具体说到底是如何初始化内存的,根据以前调试QNX的经验来看,我个人觉得这一步很可能为了确保相应内存的清零操作。

         (2) usrMmuInit ();                              /* initialize the mmu */

         初始化MMU单元,这个比较容易理解,MMU就是内存管理单元,负责管理虚拟地址,可以保证每个用户进程都有自己独立的地址空间使用,及时两个不同的进程读写相同的内存虚地址,实际上读写的物理地址是不一样的。这里就初始化MMU单元,打开函数可以看到,针对不同CPU类型加载相应的库函数进行初始化。

         (3)时钟设置

         sysClkConnect ((FUNCPTR) usrClock, 0);         /* connect clock ISR连接系统时钟中断服务程序*/

         我们知道,作为一个多任务操作系统,任务上下文切换是最基础的功能,系统调度用到的就是系统时钟中断,这里的时钟设置就提供了这样的功能。有了这个机制,接下来才可能实现多线程。其中挂接的中断处理程序在什么地方呢?原来VxWorks提供的usrClock()函数是系统缺省时钟中断处理函数,用来调用计数器函数tickAnnounce(),实现系统计数器的作用。

         sysClkRateSet (SYS_CLK_RATE);      /*set system clock rate设置每秒钟系统时钟中断次数,默认中断频率为60,一般在60到100,但不能大于600,也就是1s产生60次中断,大概是16.67ms*/

         这里有一个有意思的话题,就是按照默认的中断频率60次,是不是设置的越高实时性就越高呢?其实并不是这样的,VxWorks手册建议不要将时钟率设得太高,否则它就由硬实时变得趋向于软实时了。因为过高的时钟率使得内核调度频繁进入,更可能导致一些低优先级的硬件中断不能得到及时响应。

          sysClkEnable ();                                  /* start it使能系统时钟中断*/

         (4) selectInit (NUM_FILES);这个函数是干啥的呢?说是_func_selWakeupListInit函数需要其先进行初始化

         (5) iosInit (NUM_DRIVERS, NUM_FILES, "/null");,初始化IO系统,这里面限制了最多同时打开20个设备以及50个文件,也申请一些内存空间,包括设备表,设备的驱动函数表等。

         (6) ttyDrv();                                  /*install console driver */

         ttyDrv是一个字符型设备,负责串口与IO系统之间的交互。设备驱动的初始化过程首先调用系统函数ttyDrv(),该函数通过调用iosDrvInstall()将ttyOpen()、ttyIoctl()、tyRead()、tyRead、tyWrite安装到系统驱动函数表中,供I/O系统调用。其实理解起来一点都不难,就像我之前写的QNX 的SD卡driver的流程一样,负责底层鱼上层的交互。驱动模块初始化成功后,应用程序就可以用标准的I/O函数read()和write()收发数据了。

         有一个问题是,ttyDrv初始化的是哪个串口呢?往下看。

         在下面一些代码中就找到了一个可用的串口,就是sprintf (tyName, "%s%d", "/tyCo/", ix);

于是就找到了/tyCo/0,ttyDrv()实现了驱动函数与IO系统标准POSIX接口的对接,然后通过

(void) ttyDevCreate (tyName, sysSerialChanGet(ix), 512, 512);创建一个串口0的驱动程序,如果是系统CONSOLE_TTY口的话,就打开,并且进行设置。

                   consoleFd =open (consoleName, O_RDWR, 0);

                   (void) ioctl(consoleFd, FIOBAUDRATE, CONSOLE_BAUD_RATE);

                   (void) ioctl(consoleFd, FIOSETOPTIONS, OPT_TERMINAL);

         通过

             ioGlobalStdSet(STD_IN,  consoleFd);

             ioGlobalStdSet (STD_OUT,consoleFd);

             ioGlobalStdSet (STD_ERR,consoleFd);

         将标准输入输出定位到控制台上,就可以实现使用printf实现对控制台的调用了。

          (7)  接下来初始化一些结构、信号、管道、调试信息、标准IO函数库、信号队列、信号量、线程库、消息队列,以及一些POSIX功能支持。

         dosFsLibInit( 0 ) dosFsLibInit中调用iosDrvInstall将7个函数指针填入驱动程序表中,并得到一个驱动号表中各函数的入口对应文件系统提供的相应函数。

          (8)  /*initialize USB components */

         包含了一系列的USB设备初始化,包括USBhost协议栈、鼠标、键盘、打印机、扬声器等等。

         (9) SCSI设备初始化

         什么是SCSI?在Tornado DeviceDriver Workshop一书中解释为Small Computer System Interface,其目的为提供独立的设备接口,其优点在于一个控制器就可以控制多个外设,这就提供了一种驱动编写方法,以后再研究。

         (10)对ideDrvIDE 硬盘的驱动、SATA硬盘的支持、PCMCIA卡、tffs flash文件系统、对于浮点数软件以及硬件计算的支持、任务调度工具、时间工具、设置环境变量、模块管理器、引导设备初始化等。

         (11) usrNetInit()网络设备初始化。

         稍后再仔细对SCSI设备以及usrNetInit()网络初始化进行分析。

你可能感兴趣的:(Vxworks启动代码usrRoot()函数分析(一))