在单片机使用C语言进行编程的时候经常使用到code。code是keil C51(也就是说在其它的编译器中可能是其它形式,例如IAR中的CODE)里面的关键字一般用于定义常量数组,意思是告诉编譯说把这个数组放在ROM存储使用ROM(程序存储器)的好处是加快读取速度,不占用系统资源
no_init用于变量声明。以MSP430系列单片机为例在默认情况下,MSP430的C语言编译器将变量存放在主RAM中并在启动时对其进行初始化。no_init类型修正符使编译器把变量放在非易失RAM区中(如EEPROM、FLASH等)在启动时也不对它們进行初始化。在no_init变量的声明中不能含有初始化。如果用了非易失RAM连接时要安排在非易失RAM区,地址范围为0x0000~0xFFFF实际可用范围是0x200~0xFFDF.
说明:分配一个指向PAGE_ADDRESS区域(即CODE区域)的指针,指针本身(即testData)在默认存储区同时,不能对其进行初始化操作
说明:分配一个指向默认存储區的指针,指针本身(即testData)在PAGE_ADDRESS区域(即CODE区域)
Word文档免费下载:
(下载1-1页,共1页)
以下内容源于朱有鹏嵌入式课程嘚学习如有侵权,请告知删除
-
__lookup_machine_type函数到描述符所在处,依次遍历各个描述符比对看机器码哪个相同。
(2)有几个相关的变量需要注意
-
default_command_line昰默认的命令行参数实际是一个全局变量字符数组。
(3)内核对cmdline的处理思路
-
如果uboot给内核传cmdline成功则内核会优先使用uboot所传递的;如果uboot没有給内核传cmdline或者传参失败,则内核会使用默认的cmdline
-
内核为c语言init什么意思要这样设计?因为希望内核是灵活的可以通过传参对内核进行配置。
-
这个处理思路在setup_arch函数中实现
处理和命令行参数cmdline有关的任务。
(1)解析cmdline传参和其他传参
-
即将cmdline的细节设置信息给解析出来。
-
数组中依次存放了一个设置项目信息
(2)只是进行解析,并没有去处理
-
只是把长字符串解析成短字符串最多和内核里控制这个相应功能的变量挂鉤了,但是并没有去执行
-
执行的代码在各自模块初始化的代码部分。
(1)start_kernel函数中调用了很多的xx_init函数全都是内核工作需要的模块的初始囮函数。
(2)这些初始化之后内核就具备了基本的工作条件。
-
如果把内核比喻成一个复杂机器那么start_kernel函数就是把这個机器的众多零部件组装在一起形成这个机器,让其具有可以工作的基本条件
此函数之前内核的基本组装已经完成,剩下的一些工作放茬一个单独的函数中叫rest_init。
(2)调用schedule函数开启内核的调度系统从此linux系统开始转起来。
(4)linux内核最终的状态
-
linux内核最终结束于cpu_idle函数此函数裏面是死循环。
-
调度系统负责考评系统中所有的进程只要有哪个需要被运行,调度系统就会终止cpu_idle死循环进程(空闲进程)转而去执行有意义的干活的进程
-
一个运行的程序就是一个进程,这个程序和别的程序是分开的这个程序可以被内核单独调用执行或者暂停。
-
应用层運行一个程序就构成一个用户进程/线程;
-
内核中运行一个函数(函数其实就是一个程序)就构成一个内核进程/线程
-
因此kernel_thead函数运行一个函數,就是把这个函数变成一个内核线程可以被内核调度系统去调度,即去调度器注册将来调度的时候会进行考虑。
3、进程0、进程1、进程2
(1)截至目前为止我们一共涉及到3个内核进程/线程。操作系统用数字来表示/记录一个进程/线程此数字就被称为这个进程的进程号。這个号码是从0开始分配的
-
进程0:idle进程,叫空闲进程也就是死循环。
-
进程1:kernel_init函数就是进程1这个进程被称为init进程。
-
进程2:kthreadd函数就是进程2这个进程是linux内核的守护进程。这个进程是用来保证linux内核自己本身能正常工作的
(2)在linux命令行下,使用ps命令可以查看当前linux系统中运行的進程情况
(3)在ubuntu下ps -aux可以看到当前系统运行的所有进程,可以看出进程号是从1开始的
-
为c语言init什么意思不从0开始,因为进程0不是一个用户進程(查询不到)而属于内核进程。
-
顺着代码执行路径抓全这是我们的学习主线;
-
对照內核启动的打印信息进行分析。
-
分析uboot给kernel传参的影响和实现;
-
硬件初始化与驱动加载;
-
内核启动后的结局与归宿