android 对linux 内核的使用

1  arch,processor和mach的关系

arch:内核目录里面有专用的目录,代表了一种架构。arch是硬件里面最大的分类,那些硬件可以归到同一个arch里面呢?这个取决于指令集。 采用相同硬件指令集的处理器属于同一个arch。同时arch的种类决定了gcc的种类,不同的arch目录必须采用不同的gcc编译。编译arm架构, 采用arm-linux-gcc。编译ppc则需要ppc-linux-gcc。
processor:processor隶属于arch的一个分支,代表了一个处理器家族。即使采用相同的指令集,由于指令集存在版本的差异,这促生了处理器家族的概念。举例来说,x86代表了一种指令集,而286,386,486则分别使用了该指令集的不同版本,分别属于不同的处理器家族。arm 也代表了一种指令集,而arm7,arm9等等分别也是不同的处理器家族。

mach:他通常指某一款特定的处理器。属于processor的实体化。

mach

 processor

 arch

 说明

 sa1100

 arm920

 arm

 

 s3c44b0

 arm7

 arm

 

 P4

 i686

 x86

 

 AMD_64

 althon_64

 x86_64

以上规则是在内核的组织中用到的。然而这些信息是如何传递给gcc的呢?

查看arch/xxx/Makefile march代表了arch

-march=armv3  -march=armv4  -march=armv5  -march=pentium-mmx

mtune代表了processor

-mtune=arm7tdmi   -mtune=arm9tdmi   -mtune=strongarm1100

mcpu代表了mach

-mcpu=860 -mcpu=ev5 -mcpu=pentium-mmx

2 内核驱动程序 与用户空间驱动程序

内核驱动程序是内核空间实现的驱动程序,它使用内核资源,内核栈。它包括可加载的内核驱动模块。用户空间驱动程序就是指在用户空间实现的驱动程序。可以认为,它跟普通的用户程序没有什么两样,它使用用户进程空间和栈。这里说下,我不是讨论接到串口,并口上什么设备!

大家不要以为在用户空间写驱动程序“不过瘾!”。其实,作为设备驱动程序,其主要做的事就是配置设备寄存器(一家之言)。所以也不用把驱动程序看得那么“神秘”。当然,有些设备是不合适在用户空间实现驱动的。个人认为,使用中断的设备不宜在用户空间驱动,除此外,都有办法在用户空间来驱动。在用户空间实现驱动的一个好处就是,方便用GDB调试。

怎么写
上面说到,驱动程序主要做的事情就是配置设备寄存器。那么,只要在用户空间,我能获得到寄存器地址(或是映像地址)那就可以驱动这个设备了。
以PCI设备为例,假设你的PCI设备主芯片的配置寄存器在PCI配置头的0x14位置:
首 先:通过/proc文件系统的pci文件,及/proc/bus/pci目录下的文件,可以获取到你的设备PCI配置头的信息,当然,也可以读出0x14 偏移的值。假设其值为0xE0080000;这个就是你的PCI设备主芯片的配置寄存器的物理地址。在有MMU的处理器里,直接使用这个地址是不允许的。 我们都知道,在用户进程空间寻址一个物理地址,首先要把这个物理地址映射到进程空间内。

怎么映射呢?
我们知道,在Linux的/dev目录下,有一个mem的设备。我们简单认为它 就是管理0x00000000-0xFFFFFFFF(32位处理器)物理地址的一个设备(不单指物理内存,它的空间也含盖了PCI地址空间)。将PCI 配置寄存器空间映射到进程空间的逻辑如下:

fd = open("/dev/mem",O_RDWR);
reg_addr = mmap(NULL,0x100,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0xE0080000);
之后,你就可以使用reg_addr这个地址,在0x100大小空间范围内配置你的PCI设备了。

3 PCI设备驱动

要弄清楚Linux PCI设备驱动,首先要明白,所谓的Linux PCI设备驱动实际包括Linux PCI设备驱动和设备本身驱动两部分。不知道读者理不理解这句话,本人觉得这句话很重要,对于PCI、USB这样的驱动来说,必须要理解这个概念,才能明白该如何看待Linux下的PCI和USB以及类似的总线型的驱动。理由也很简单,就是Linux PCI驱动是内核自带的,或者说内核帮你写好了!而我们需要完成的就是设备本身的驱动,比如网卡驱动等。当然,并不是说内核帮咱们写好了Linux PCI驱动我们什么就不用做了,至少你要明白内核大致都干了些什么,这样你才能明白你该干什么,如何完成设备本身的驱动。这跟我们学习操作系统时要学习很多系统调用接口一样的道理,不知道这些接口,怎么用操作系统或者说操作系统给你提供的功能呢? 所以这里我们就来研究下Linux PCI驱动到底都干了些什么,以便我们在此基础上完成我们设备本身的驱动。

参考

4  系统调用、用户编程接口(API)、系统命令和内核函数的关系

系统调用并非直接和程序员或系统管理员打交道,它仅仅是一个通过软中断机制(我们后面讲述)向内核提交请求,获取内核服务的接口。而在实际使用中程序员调用的多是用户编程接口——API,而管理员使用的则多是系统命令。

用户编程接口其实是一个函数定义,说明了如何获得一个给定的服务,比如read( )、malloc( )、free( )、abs( )等。它有可能和系统调用形式上一致,比如read()接口就和read系统调用对应,但这种对应并非一一对应,往往会出现几种不同的API内部用到同一个系统调用,比如malloc( )、free( )内部利用brk( )系统调用来扩大或缩小进程的堆;或一个API利用了好几个系统调用组合完成服务。更有些API甚至不需要任何系统调用——因为它并不是必需要使用内核服务,如计算整数绝对值的abs()接口。

另外要补充的是Linux的用户编程接口遵循了在Unix世界中最流行的应用编程界面标准——POSIX标准,这套标准定义了一系列API。在Linux中(Unix也如此),这些API主要是通过C库(libc)实现的,它除了定义的一些标准的C函数外,一个很重要的任务就是提供了一套封装例程(wrapper routine)将系统调用在用户空间包装后供用户编程使用。

下一个需要解释一下的问题是内核函数和系统调用的关系。大家不要把内核函数想像的过于复杂,其实它们和普通函数很像,只不过在内核实现,因此要满足一些内核编程的要求。系统调用是一层用户进入内核的接口,它本身并非内核函数,进入内核后,不同的系统调用会找到对应到各自的内核函数——换个专业说法就叫:系统调用服务例程。实际上针对请求提供服务的是内核函数而非调用接口。

比如系统调用 getpid实际上就是调用内核函数sys_getpid。

asmlinkage long sys_getpid(void)

{

    return current->tpid;

}

Linux系统中存在许多内核函数,有些是内核文件中自己使用的,有些则是可以export出来供内核其他部分共同使用的,具体情况自己决定。

参考




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值