linux系统原理中的一些理解D

来源:互联网 发布:mysql中timestampdiff 编辑:程序博客网 时间:2024/06/06 04:03

程序的局部性原理   

1. %esp指向内核堆栈中,为啥当屏蔽掉%esp的后13有效位屏蔽后,才得到这个两个连续的物理页面的开头,而这个开头正好是task_struct的开始,从而得到了指向task_struct的指针。

     答:进程结构task_struct的起始地址必须保证指针地址的低13位全为0,因为由于linux内核分配进程任务结构空间时,是以8KB(2个页面空间,即2^1*4KB,linux对物理内存空间和虚拟内存空间管理时,均规定其页面单位的尺寸为4KB)为单位来分配的,所以内存应用地址是8KB(2^13)的整数倍,即指针地址的低13位全为0。


2. keobject 是什么?

答:kobject--对应sysfs下的一个目录
kobj_type--对应该目录(kobject)的一些属性(包括释构时的执行的方法,读写操作,文件列表)

struct attribute{
        char* name;
        struct module* owner;
        mode_t mode;
 }---对应sysfs下的一个文件

kobj_type.sysfs_ops描述了如何读写kobj_type.default_attrs列出的文件


3.如何学习函数指针
函数指针的学习:参数的来龙去脉(那些是系统穿进去的,那些传出来的,那些是要你传的;返回值是什么),什么时候调用,用来做什么


4.为什么页的起始地址都是4k字节对齐?
答:分页的基本原理是把内存划分成大小固定的若干单元,每个单元称为一页(page),每页包含4k字节的地址空间。
这样每一页的起始地址都是4k字节对齐的。


5 slab解决了什么问题呢?

答:我们知道在内核里有些数据结构是很常用的,
例如inode,这些数据结构会频繁初始化和销毁。但是初始化数据结构是有开销的啊,更好的办法是把它存下来,然后下次创建的时候,直接拿一个现成的,改改内容,就可以用了!
slab又译作“板坯”,这样子是不是好理解一点呢?
在实现上,slab会为一类对象开辟一段空间,存储多个这样的对象,然后创建和销毁,其实只是在这片空间里指针移动一下的事情了!我们其实可以叫它“对象池”或者“结构池”吧!
slab的代码实现在LKD中有非常详细的描述,不再赘述了。




6.段式管理解决的是什么问题?
目的是让位少的(16位)CUP能够访问多位的地址(20位的地址)


7.为什么一个进程占用4G空间呀?但是现在电脑一般就2G内存?
程序的运行并不是一下子全部加载,而是用到什么地方加载什么地方。好处显而易见,程序实际使用的物理内存很少


6.进行应用程序编程的一些基础编程知识有那些?

答:(来自国嵌)文件编程,时间编程,多进程程序设计,进程间通信,多线程程序设计,网络编程(6个)。

文件编程:(系统调用的方式)打开,读出一个文件的内容,写入文件

时间编程:读取系统时间,打印出来

多进程程序设计:

进程间的通信:(管道,信号,共享内存,信号灯,消息队列)的方式实现进程通信。

线程编程:线程等待;多线程互斥操作一个整数并打印出来

网络编程:TCP/UDP服务器的设计


7.为什么中断不能进行上下文切换
答:应该是不能在中断处理到一半的时候进行上下文切换。那如果非要这么做,会带来什么后果呢?
我想大约有这么几点:
第一,被中断的任务会收到无端的牵连,因为如果中断不发生,它本来有机会继续运行的,现在这种切换反而会导致cpu调度的不公平,但是不会紊乱;
第二,嵌套的中断也会因为cpu无端的上下文切换没有得到及时地处理,从而性能大幅度下降,某些硬件行为甚至变得不可测;
第三,中断上下文切换花费时间较长,影响cpu处理其他中断,及时性有损失。


8.pthread_join的应用的用途:
pthread_join使一个线程等待另一个线程结束。
代码中如果没有pthread_join主线程会很快结束从而使整个进程结束,从而使创建的线程没有机会开始执行就结束了。
加入pthread_join后,主线程会一直等待直到等待的线程结束自己才结束,使创建的线程有机会执行。


9.为什么管道不能同时读写
答:由于管道是一段特殊的内存区域,所以它不肯能同时进行读写的操作。
多进程中,管道的使用不一定要关闭一些读写端口,但是为了防止同时读写的情况,一般读线程要关闭写,写线程先关闭读。
管道可以被看作是打开的文件(但在已安装的文件系统中没有相应的映像),所以很多使用管道的系统调用和文件操作是相同的
(比如,pipe()返回的是一对文件描述符,读,写,关闭等)


10 linux的思想是什么?
1) 程序应该小而专一,程序应该尽量的小,且只专注于一件事上,不要开发那些看起来有用但是90%的情况都用不到的特性; 
2) 程序不只要考虑性能, 程序的可移植性更重要,shell和perl,python等脚本相比c有更好的移植性;
3)一切皆文件,尽量使用文本文件来存储数据,避免使用二进制文件,因为文本文件可读性强,且已经有跟多的工具来处理,例如awk,sed,grep等;
4)让每个程序都成为过滤器,程序需要与其他的工具一起配合使用,管道的支持是非常的重要的;
from http://www.cnblogs.com/itech/archive/2012/06/18/2554124.html

1、一切皆文件;
2、单一目的的小程序;
3、组合小程序完成复杂任务;
4、文本文件保存配置信息;
5、尽量避免捕获用户接口;
6、提供机制,而非策略。
from http://szyangxiao.blog.51cto.com/8022664/1348162

11看门狗的作用:
开门狗的作用在于监控CPU的运行,保证在诸如噪音和系统错误等这样的故障干扰情况下能尽快回复正常工作。
与PWM定时器都能实现定时的功能。两者的区别是:看门狗能发出复位信号而PWM定时器不能。


12 为什么CUP上电之后,都要执行一段汇编程序,再执行C程序
答:因为c语言的运行是需要堆栈等环境的。所以这段汇编程序要先配置好内存,堆栈,初始化好c语言环境等等。


13.ARM寄存器如何记忆:
1.R0--R12通用寄存器,放通用数据,32bit.
2.各个模式的R0-R12与USR模式是共享的(除了FIR,R8-R12是自己的),PC、CPSR共享的
3.User模式先没有SPSR


R0--R12称为通用寄存器,放通用数据,32bit.
R13--SP(stack pointer )栈寄存器,存储栈地址,将要运行程序的地址标识(用于快速切换进程)。
R14--(Link Register)是链接寄存器,保存了返回地址,用于快速切换子程序。
R15--(Program counter Register)程序计数寄存器(是用来计数的,指示指令在存储器的存放位置,也就是个地址信息)
A/CPSR--应用/当前程序状态寄器 Application/Current Program Status Register
SPSC--已存储程序状态寄存器 Saved Program Status Register


系统模式与用户模式共享寄存器,只不过访问级别和权限不一样而已。
user模式称为非特权模式,其他模式称为特权模式。




14. 寄存器的作用:
模式切换数据恢复,子程序的调用和返回,转移到相应的异常处理,程序切换状态保存等都用到寄存器。




15.判断是否是立即数?
%4 整除且在0至255之间


伪指令只是在汇编之前作用,汇编之后会翻译为标准的的汇编指令集


16.常见存储结构有哪些?
iRom也是一种SRom(也是静态的Rom,程序可以直接在它运行,可以用来启动),
iRam是一种SRam(也是静态的,像NorFlash一样,代码可以在上面直接运行,可以用来启动的)
DRam是常说的内存
Flash --相当于硬盘
能够直接执行程序的存储器:iRom,iRam,NorFlash




sudo dd iflag=dsync oflag=dsync if=210.bin of=/dev/sdb seek=1
seek=1是指要跳过第一个block,因为第一个block里面含有磁盘到区信息。


17 区别运行地址和链接地址 


运行地址<--->链接地址:他们两个是等价的,只是两种不同的说法。
运行地址:程序在RAM中执行时的地址。就是执行这条指令时,PC应该等于这个地址,
          换句话说,PC等于这个地址时,这条指令应该保存在这个地址内.
          简单的理解就是就是计算机认为程序运行时应该处于的地址.
arm-linux-ld –Ttext 直接指定链接地址(也就是代码段的地址)。

加载地址<--->存储地址:他们两个是等价的,也是两种不同的说法。
加载地址:程序保存在Nand flash中的地址

位置无关码:B、BL、MOV都是位置位置无关码。  
位置有关码:LDR PC,=LABEL等类似的代码都是位置有关码



1

、运行地址

<--->

链接地址:他们两个是等价的,只是两种不同的说法。

 

2

、加载地址

<--->

存储地址:他们两个是等价的,也是两种不同的说法。

18 -Ttext 0x00表示什么意思

-Ttext 0x00这种指定方式仅仅是指定了一下代码段的运行地址,后面的数据段并不会在后面接着存放。
现在看视频,好像程序地址,运行地址是队Arm来说,Arm认得的是MEMORY ADDRESS MAP后的地址,应该站在
Arm的角度看,才看到比较本质的东西(我们的程序还没有运行起来,这时候必须在ARM硬件角度看了)。
(MEMORY ADDRESS MAP 是指地址映射[分布]xxx--xxxx这段地址给谁的)


19 芯片理解memory address map的一些理解
在CPU内部运行的程序(例如,我们运行与编写的程序),其内存地址是逻辑的(logical)
 必须在使用总线获取该地址之前,通过CPU转换为物理内存地址。

内存地址映射(memory address map)的地址,是供底板总线使用的物理内存地址

需要记忆的关键点是:CPU并不知道它连接着什么东西。CPU通过针脚(pin)与外界(outside world)通信,但并不关心外界是什么。
                    也许是一个烤面包机(toaster),网络路由器等等。
当北桥(northbridge)收到物理内存请求后,它决定向何处转发该请求:应该送至(go to)RAM么?或许是视频卡(Video Card)?
该转发过程(routing)是通过内存地址映射(memory address map)完成的。对于每一块物理内存地址空间,
内存映射(memory map)知道哪个设备拥有该内存区域。

程序中汇编之后的最终地址是逻辑地址,需要转换成线性地址,再经过MMU(CPU中的内存管理单元)转换成物理地址才能够被访问到。
"逻辑地址" 在学术文献中的解释:
这样该存储单元的地址就可以用段基值和段内偏移量来表示,段基值确定它所在的段居于整个存储空间的位置,偏移量确定它在段内的位置。
段式管理和页式管理,是MMU里面的东西。

以下是启动代码中的一段


我猜想:
因为内存使用是动态变化的,程序运行地址是变化,所以逻辑地址中的段基地址是变化的。
引起程序中对象获得的逻辑地址,线性地址也是变化。但是程序内对象之间的偏移不变。
后面CUP访问的时候,也就是根据这次运行获得的逻辑地址,在通过MMU访问内存。
memory address map的作用:用于启动,用于内存管理(MMU)


20.什么叫做输入输出
硬件操作的过程中,写寄存器的时候叫做输出,读取寄存器就设置为输入。
(芯片管脚---核心板管脚---外部硬件)






21.拿到一款开发版,如何用?
答:找CPU,用什么样的架构,为了找到上电后第一条执行的代码是放在那里。找异常向量表中reset向量
    对应的地址是什么。 如何找,根据现在所有的芯片都是这样思路:SOC =CPU+Controller,看block框图.
(所有ARM的复位异常向量地址都是0x00,所有0x00地址处应该接一个可读可保存的存储器(是否可执行,应情况而定),如no-flash,ROM等)


    地址都被芯片公司重新定义,去芯片公司的datasheet中寻找memory map这样的章节。这些存储器资源,从大的范围来看,
分片内资源和片外资源(一般除了SFR和iRom,iRam外的都是片外资源)。之所这样划分,是因为这两种资源的访问方式是不一样。


   芯片跟外围控制器怎么样连,可以通过IO章节看。selection signed(片选) 对于片外资源的分析非常重要,很多外围芯片都有一个总开关叫nCE(chip enable)或nCS(chip select).
控制这个芯片是否工作。cup收到地址,先发给地址选择器,地址选择器,根据memory map判断该地址所在的块,然后发给相应的地址控制器(如果是片内资源地址,就不会触发外部的地址总线了) 
这时候只有地址所在的bank是有效的(程序访问的地址,落在那个分块区间上,CPU就自动对该分块的片选信号置为有效)。


22.怎么样找片外资源(如SDRAM)的地址范围?
答:硬件工程师的话,根据IO description确定各片外资源挂到芯片那个引脚。
但是,对于软件工程师,反过来用即可,步骤如下:
找到该外部芯片的类似于cs/enable这样的引脚,看该芯片接到cpu的那个片选信号上。
这样子,该片选信号对应分块的地址范围,就是这个片外资源的地址范围。
   到底这个片选信号(引脚)归那个块管呢,就根据和各个IO description的片选信号信息来确定是属于那个块。然后根据memory map种块的
范围就知道了这个片外资源的启始地址。(结束地址由实际接的物理硬件定)


23.ARM底层开发中的时钟有那些?
答:脉冲宽度调制PWM,带复位功能的看门狗watchdog,RTC.


24.硬件上如何做到定时器的?
答:cpu是根据脉冲来计数计时的。
芯片使用了一个叫做递减计数器的功能块,每来一个时钟缘,递减计数器减1,当减到0是,就会触发相应的输出
引脚,发生跳变(PCLK基本时钟缘,CLK--频率引脚,output输出引脚)。在看任何一个timer的时候,首先要关心这个timer的位数,
因为位数的不同就会导致程序在设计的时候不同的设置。


25.PWM是怎么样实现的?常用场合有那些? (重点)
答:使用的时候,重点是波形的控制(脉冲宽度和产生频率)。


26.watchdog的工作原理是什么?
答:和pwm相比,除了发出跳变外,还会发出一个复位信号。主要用于解决硬件引起程序"跑飞"的问题。




27.RTC的基本操作:获取时间,矫时  (重点)


28重定位实验

核心:

要理解这段代码主要是搞清楚LDR的两种用法。

ldr r0, =SMRDATA的作用是让r0等于U-BOOT编译时已经确定下来的SMRDATA这块内存缓冲池的起始地址。

ldr r1, _TEXT_BASE的作用则是让r1等于_TEXT_BASE这个标号所在的内存里面的内容,


ldr r3, [r0], #4 ;从r0这个地址里取一个32bit的数据,放到r3,并将r0+4,指向下一个内存池里的数据。
str r3, [r1], #4 ;这条指令实现了把r3里的数据赋值给r1所标示的地址,并将r1+4

LDR说的定义为:大范围地址读取伪指令,LDR伪指令用于加载32们的立即数或一个地址值到指定寄存器。在汇编编译源程序时,LDR伪指令被编译 器替换成一条合适的指令。若加载的常数未超出MOV或者MVN的范围,刚使用MOV或MVN指令代替该LDR伪指令,否则汇编器将常量放入字池,并使用一 条程序相对偏移的LDR指令从文字池读出常量。


此外对adr的理解:

ADR的定义为:小范围的地址读取伪指令,ADR指令将基于PC相对偏移的地址值读取到寄存器中,在编译源程序时ADR伪指令被编译器 替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能,若不能用一条指令实现,刚产生错误。

比如,如果在汇编程序中使用ADR R1,ResetHandel语句,其中ResetHandel是汇编程序中的一个标签,此条伪指令的作用是把ResetHandel标签所在的指令地址 读取到寄存器R1中,编译器在编译的时候把ADR伪指令编译成一个ADD R1,PC,Immediate指令,其中Immediate是一个立即数,数值是ResetHandel语句和此条伪指令之间的差值,由编译器自动算 出。由于立即数寻址的约束,这个Immediate存在一定的约束,所以会出现定义中所说的不能用一条指令实现。

http://blog.csdn.net/colder2008/article/details/5848215


29与位置无关代码的理解

答:这个是bootloader代码重定位用到的。

     连接器脚本xxx.lds文件中指定的地址,就是链接地址,程序运行时必须位于它的链接地址处,汇编文件中的各个标号或者c文件中的各个函数名(函数的入口地址)对应的链接地址就是由链接脚本中的起始链接地址和各个目标文件(.s或.c文件编译但还为链接的文件)的排放顺序有关。这些链接地址可以通过查看可执行文件的反汇编文件即xxx.dis文件来获得.      如果你不使用全局变量或者静态变量,访问这些变量时要使用到链接地址,重定位完成之前不能使用这些类型的变量,adr、b和bl指令都是属于相对跳转指令,即在当前pc值的基础上加减一个偏移值,跳转去执行。如果只使用adr、b或者bl指令,并且不访问全局变量或者静态变量,这类代码被称为“位置无关码”,即代码的存储位置可以不在其链接地址处。如果当使用全局跳转指令ldr时就只能使用链接地址了,如ldr pc,_reset。程序运行时,pc指针的内容是不区分原本地址(存储地址)或链接地址的,只要是”位置无关码“,存储地址可以与链接地址不同,不是位置无关码就要使用到链接地址,即存储地址与链接地址必须相同。即使用之前必须完成代码的重定位。
   http://wenku.baidu.com/link?url=Z94e8n0Lb4m-GcX-8enhs5OWsB0csNh-IOHxLDAtw-3qYDGnkssRyj19OItI0Y9MXUDa8alcu-UC0B-7lg-G3Ze-dkCGDClpuTKHIOwxHLS
 http://zhidao.baidu.com/link?url=9NSorjyqfd-Fs8zBQn3oGC2CmDKSlEQHeIKLjWtLT8Jna8AQzuyu86GTK-SQ1aynikfppvt7uwoe9l4-WbrYURCB4xJ-E4VWP6h15W1JI6i


30理解bootloader

boot的目的:调到c语言中 bl main

关闭看门狗,关闭中断(因为还没进入C,有中断来了也不懂怎么处理;进入Main再启动中断处理),也可以关闭MMU(因为MMU一般有操作系统的时候才用),数据CACHE(一般不看,因为开了之后数据的完整性可能有影响,给后期调试有很多麻烦)

配置系统时钟(时钟来源,LockTime, PLL ,DIV ,cup工作模式(快速模式,还是同步模式)等)
配置SDRAM的控制器(行数,列数,块数,周期性充电)
(SDRAM的特性:1.SDRAM看做三维 2.BA告诉控制器有多少块;nRAS,nCAS,有效的时候告诉DRMAM发出的是什么信号。
故要告诉控制器:行地址数,列地址数,有多少块。告诉多久充一次充电来让RAM工作。)
 
让sp执行可读可写的设备区间中,满足递减栈(SP往下走)的规则.

  --用那些模式,就要初始化那些模式下的SP  

  --每个模式值不能覆盖其他模式


代码搬移

       执行速度问题,把程序从存储器(no-flash)搬移到快速的内存

      只把存储器的一部分代码执行处理,把存储在其他位置上的代码搬移到内存,(在代码搬移之前,要做)对应存储器的控制器的初始化。

bl main


S5PV210的启动流程说明:http://www.51hei.com/bbs/dpj-25281-1.html

                                                http://www.360doc.com/content/13/0313/10/7775902_271194344.shtml


31 如何学习时钟体系:

  有哪些PLL和DIV,产生了那些频率(CLK),用来做什么?

时钟相关概念:
时钟:同步工作系统(特点:有个节拍)的同步节拍,是个时钟(而不是生活中的时钟,时分秒之类的)
时钟脉冲:脉冲信号是一个按一定电压幅度,一定时间间隔连续发出的脉冲信号。

为什么要有它?
Soc内部有很多器件,譬如cup,串口控制器,DRAM控制器,定时器,GPIO等内部外设,这些东西要彼此协同工作,需要
同步的时钟系统来指挥。这个就是我们Soc的时钟系统。

SOC的时钟一般如何获得::
外部直接输入时钟信号,Soc有个引脚用来输入外部时钟信号(一般多个CUP同步工作的时候,很少)
外部晶振+内部时钟发送器(引出引脚外接晶振),大部分低频单片机都是这么工作的。
外部晶振+内部时钟发送器(引出引脚外接晶振)+内部PLL产生高频时钟+内部分配器分频得到各种频率的时钟(S5PV210)

时钟和外设编程的关联:
每个外设工作都需要一定频率的时钟,这些时钟由芯片的时钟系统提供的。程序员可以为每个外设指定
时钟来源、时钟分频系数等参数,从而制定这个外设的工作时钟。
soc内部有很多外设,这些外设不用的时候最好关掉(从发热,待机时间等考虑),开关外设不是通过开光,
而是通过时钟。也就是说我们给某个外设断掉时钟,这个外设就不工作了。

时钟初始化流程如下:


(有些芯片有默认值,入lock time默认值,有些芯片不用设置cup的工作模式的。具体根据芯片来看。具体指也可以参考uboot的设置和芯片手册的推荐值)

32如何理解CUP的运行

ldr cup excute cache,[pc]
run cup excute cache
流程:向地址总线发出pc指针所指地址,硬件接到地址把数据通过数据总线传到cup excute cache,cup执行。
给芯片中的DRAM CONTROLLER(是个寄存器)发送地址后,DRAM CONTROLLER根据行和列的特性,
由DRAM CONTROLLER自己决定,什么时候发送行地址,什么时候发送列地址,什么时候发送块地址。


33 set_svc的理解

set_svc:
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0xd3
msr cpsr, r0
mov pc, lr



34R14链接寄存器的理解

from:http://blog.sina.com.cn/s/blog_491f02870100hxna.html



35 ARM处理器各个模式之间是如何切换的?

答:除用户模式外的其他6种模式称为特权模式,这些模式中,程序可以访问所有系统资源,也可以任意进行处理器模式的切换。处理器模式可以通过软件控制进行切换(直接设置CPSR寄存器的后五位就可以在6种特权模式之间互相切换),也可以通过外部中断或异常处理过程进行切换(例如,在USR模式下,发生中断后切换到IRQ模式)。


36ARM各个模式之间切换时,上下文的保存哪些是硬件在做?哪些软件做的?

答:



37.识别中断源的方法包括那些?

答:


38中断处理流程



39 How to use ARM's data-abort exception

答: http://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece763105392230e54f734638787432983c55f93130a1c187bb5ec66794558ce873c3a47f20f17a8ab6a27200356e4c79e9f4aabedc56c78d67a762f4bda070fd51badcf422ec63dea07acb81991fcad2593d89592884353bc20650597f0fd1b1714bc39a35262f4a6ef1b450250fcfa3013a813267edd651beb1beda56f2e518eb68a0917826c87215080af44ef6344e252b31f6a7718f65bb179066c61b70d61a419614585ea2df02b0a5722c60ee9ee9af6fc48fd98bd60dea78bee389511b599bc&p=85759a46d1c416be00b6c7710f08cd&newp=882a9642d18713f10be2963a4c089c231601d13523808c0a3b8fd12590625a051538&user=baidu&fm=sc&query=registers%2Cmodes+and+exceptions%3Atheir+vectors+and&qid=f0c1e9a500010c0a&p1=17


40 一些异常相关的图片



41处理器模式切换

答:1)除用户模式外的其他6种模式称为特权模式,这些特权模式中,程序可以访问所有系统资源,也可以修改CPSR的模式位使处理器进入相应模式(注:用户模式下无权这样做)。2)进入相应的异常中断,处理器自动进入相应的模式。


42如何设置各个模式下的栈指针

答:http://blog.csdn.net/mr_raptor/article/details/6556172


42 我们说的初始化内存,实际上是对芯片的存储控制器进行初始化


43 ARM保存中断时,为什么使用“sub lr, lr, #4”

答案:http://blog.csdn.net/comwise/article/details/10490203

1. )首先要谈流水线,在arm执行过程中一般分为取指,译码,执行阶段

  也就是假设当前 第一条指令在执行阶段,则,此时第二条指令在译码阶段,第三条指令在取指阶段

  当前正在执行的指令地址为pc-8,第二条就为pc-4,而pc现在真正指向已处于pc位置

2) 一般pc在发生中断时lr保存的是当前的pc值,这里pc值是多少呢?

     当发生中断肯定保存的pc是第三条指令,而我们从中断返回肯定不是执行第三条指令,而是紧接着的第二条指令,所以应该保存的 lr = pc - 4,但是当执行到此位置时pc值已经改变,肯定不对,还好发生中断时 mov lr,pc 所以这里就可以直接使用 sub lr,lr,#4


44 如何确定内存的bank数目,每个bank中的行数chip_row,列数chip_row

答案: 列子 http://www.07net01.com/program/658225.html


根据:电路图+内存芯片手册  注意公式


0

0 0
原创粉丝点击