Linux驱动笔记

来源:互联网 发布:淘宝店铺如何上架 编辑:程序博客网 时间:2024/05/18 01:44
一、描述内存分配方式及他们的区别
(1)从静态存储区分配。内存在程序编译时就已经分配好,这块内存在整个程序运行时期都在。例如全局变量,static变量。
(2)在栈上创建。在执行函数时,函数内部局部变量的存储单元都能在栈上创建。函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集。
(3)从堆上分配,称为动态内存分配。程序在运行的时候用malloc或者new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期有程序员决定,使用非常灵活。
二、用户应用程序开发和驱动程序开发的不用点:
1.用户应用程序在用户空间执行(0 - 3G),驱动程序在内核空间执行(3 - 4G)执行。
2.用户程序可以调用C库函数或linux系统调用API,但是驱动程序不能调用这些函数。同样的,驱动能调用的内核函数,应用程序也调用不了,因为它们调用不同的地址空间。
3.用户应用程序的头文件放在/usr/include目录下,驱动程序能调用的函数不同,头文件存放的位置也不同,驱动程序的头文件放在内核源码包下面的include目录下,驱动程序的头文件在内核源码包下的include目录中(它们有多个这样的include目录,分为两大类,平台相关的和平台无关的)。
4.应用程序可以使用各种语言来编写(C、C++、java、pthyon等等),而Linux下的驱动程序只能使用GNU下的C语言来编写。
5.应用程序可以使用浮点数,但是驱动程序不能使用浮点数运算,只能使用整形运算。
6.应用程序使用的栈实际上有两个,当内核创建一个用户进程时,会给它开辟两个栈空间,一个是在用户空间下使用的用户栈(栈空间比较大,而且长度可变,默认大小为8M),另一个是供内核使用的内核栈(大小固定,比较小,只有8K),中断还有自己的中断栈(大小也是固定的,每个CPU提供一个中断栈,中断处理函数在这个CPU上执行时都统一使用这个中断栈,大小为8K)。
7.驱动程序会更加考虑程序的可移植性问题,当然这个问题在开始学习驱动的时候暂时弱化,不用太多考虑。
8.应用程序有内核提供了一套安全保护机制,当应用程序出现致命错误时,内核会杀死用户进程,回收系统资源,但不影响其他用户程序;内核下的驱动程序没有这套保护机制,如果内核出现致命错误,会造成整个操作系统都崩溃掉。
三、区分设备、设备文件、驱动
设备是一个看得见摸的着的硬件实体,也有可能是一个软件模拟出来的虚拟设备(用它来实现相应的硬件功能);设备文件是Linux对硬件设备的一个抽象,通过这个抽象,可以让操作系统上的应用程序像访问普通文件一样的访问硬件设备。它是应用程序调用内核中的设备驱动程序的一个接口。
sudo mknod -m [文件权限] /dev/设备文件名 [设备类型,c为字符设备,b为块设备] 主设备号 次设备号
驱动是内核空间里执行的一段程序,它能够给Linux内核使用,用来访问硬件设备。它通常提供三大类功能(初始化硬件设备,读设备并把设备上读到的数据提交给应用程序,写设备:获取用户程序的数据并把它写到设备上)。驱动程序是操作系统访问硬件设备的中介,没有正确的驱动程序,操作系统也无法响应用户程序的访问硬件设备的请求。驱动自己不会自动执行,它是被应用程序请求执行的,相当于内核中的一段代码库(进程上下文)。如果是硬件设备通过中断请求执行的内核代码,我们称为中断上下文。【进程上下文是可以睡眠的,中断上下问是不同睡眠的】。
四、说出const和#define相比,有何区别?
(1)cosnst常量有数据类型,而宏常量没有数据类型,编译器能对前者进行类型安全检查。而对后者只能进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误。
(2)有些集成化的调试工具能对const常量进行调试,不过不能对宏常量进行调试。
五、虚拟地址:
在Linux驱动中,使用的是虚拟地址,不能使用手册上查到的物理地址。应该以如下方式访问:
把手册中查到的物理地址首先映射得到一个相应的虚拟地址
六、类成员函数的重载、覆盖和隐藏的差别?
a.成员函数被隐藏的特征:
(1)相同的范围(在同一个类中)
(2)函数名字相同
(3)参数不同
(4)virtual关键字可有可无
b.覆盖是指派生类函数覆盖基类的函数
(1)不同的范围(分别位于派生类和基类)
(2)函数名字相同
(3)参数相同
(4)基类函数必须有virtual关键字
c.“隐藏”是指派生类的函数屏蔽了和其同名的基函数
(1)如果派生类的函数和基类的函数同名,不过参数不同。此时,不论是否有virtual关键字,基类的函数都将被隐藏。
(2)如果派生类的函数和基类的函数同名,并且参数也相同,不过,基类函数没有virtual关键字。此时,基类的函数被隐藏。
七、New delete 和 malloc free的联系和区别?
都是在堆上进行动态的内存操作。用malloc函数需要指定内存分配的字节数并且不能呢个初始化对象,new会自动调用对象的构造函数。delete会调用对象的析构函数,而free不会调用对象的析构函数。
八、进程和线程的区别
从概念上:
进程:一个程序对一个数据集的动态执行过程,是分配资源的基本单位。
线程:一个进程内的基本调度单元。线程的划分尺度小于进程,一个进程包含一个或者更多的线程。
从执行过程上来看:
进程:拥有独立的内存单元,而多个线程共享内存,从而提高了应用程序的运行效率。
线程:每一个独立的线程,都有一个程序运行的人口、顺序执行序列、和线程的出口。但是线程不能够独立的执行,必须依存在应用程序当中,由应用程序提供多个线程执行控制。
九、static 和 const关键字的作用
答:static关键字至少有以下n个作用:
(1)函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值。
(2)在模块内的static全局变量可以被模块内所有函数访问,但不能被模块外其他函数访问。
(3)在模块内的static函数只可能被这一模块的其他函数调用,这个函数的使用范围杯限制在声明它的模块内。
(4)在类中的static成员变量属于某个类所拥有,对类的所有对象只有一份拷贝。
(5)在类中的static成员函数属于某个类所拥有,这个函数不接收this指针,因而只能访问同类的static成员变量。
const关键字至少有以下n个作用:
(1)欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化,因为以后就没有机会改变它了。
(2)对指针来说,可以指定指针本身为const,也可以指定指针所指向的数据为const,或者二者均为const.
(3)在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值。
(4)对于类的成员函数,若指定为const类型,则表明其是一个常函数,不能修改类的成员变量。
(5)对于类的成员函数,有时候必须制定其返回值为const类型,以使得其返回值不为“左值”。
#include <asm/io.h>
volatile u32 *V_GPH2CON;
void key_init()
{
    V_GPH2CON = ioremap(0xe29000c0,4);
    V_GPH2DAT = ioremap(0xe29000c4,4);
    *V_GPH2CON &= ~0xff;
    *V_GPH2CON |= 0x2;
}
iounmap(V_GPH2CON)
iounmap(V_GPH2DAT)
或者也可以一次映射多个地址紧挨的寄存器
volatile u8 *V_BASE;
void key_init()
{
    V_BASE = ioremap(0xe29000c0,8);
    V_GPH2CON = V_BASE;
    V_GPH2DAT = V_BASE + 4;
    *V_GPH2CON &= ~0xff;
    *V_GPH2CON |= 0x2;
}
取消地址映射:iounmap(V_BASE)
int k1_is_down()
{
    if(*V_GPH2DAT & (1 << 1))
        return 1;
    else
        return 0;
}




0 0