1.字符设备驱动程序概念介绍

落日映苍穹つ 2022-08-20 02:24 247阅读 0赞

u-boot的任务是启动内核,内核的任务是启动应用程序。应用程序会涉及很多文件和硬件操作(当然不会直接操作硬件), 比如读写文件,点灯、获取按键值。

对于应用程序的开发人员不要求去阅读芯片手册,了解硬件的构造。应用程序的开发人员在用户空间直接使用open、read、 write等等这些被称为系统调用的函数,通过这些函数进入内核空间,进而调用内核空间的驱动程序。

比如对于控制led灯的用户程序与驱动程序,最简单的实现方法是,应用程序中需要打开led灯,就需要open函数,在内核中的驱动 程序中也有对应的led_open函数,这个led_open函数负责直接操作硬件,应用程序中要调用read函数读取led灯的状态的时候,内核中的驱动程序也有led_read函数。这是 应用程序与内核中驱动程序一种最简单的对应方式。

那么应用程序中的open、read函数最终怎样调用到驱动程序中的led_open、led_read呢,中间有哪些东西。

我们首先写一个简单的应用程序。

int main()

{

  1. int fd1; fd2;
  2. int val = 1;
  3. fd1 = open("/dev/led", O\_RDWR);
  4. write(fd1, &val, 4);
  5. fd2 = open("/home/xxx/hello.txt", O\_RDWR);
  6. write(fd2, &val, 4);

}

这些open、write函数在Linux中称为系统调用,是用户态进入内核态的门户。当处于用户空间的应用程序调用这些系统调用的时候, 会进入内核空间执行。这些系统调用怎样进入内核态呢?这些系统调用会调用一条汇编指令:swi 。在swi指令后面会跟着一个值。这 个值用来表明是哪一条系统调用调用了该swi汇编指令,也就是说不同的系统调用调用swi指令,swi后面跟着的值都是不同的。这条汇 编指令会引发一个叫做内核陷入的异常。引发内核异常会进入到一个内核异常处理函数中。 内核异常处理函数会根据异常发生的原因,调 用不同的处理函数。异常发生的原因是根据swi后面跟着的值来决定的,比如说open函数执行swi,swi后面跟着的值是val1,read函数执 行swi,swi后面跟着的值是val2。内核中一个称为虚拟文件系统的东西会根据swi后面不同的值去调用system_open或者system_read等

函数。

再看上面的应用程序,我们点灯与打开文本文件,都是用的同样的函数。但是点灯与打开文本文件的行为显然不一样。那么谁来实现

这些不一样的行为呢?

对于LED灯,有led_open驱动程序。对于文本文件存在于flash设备上,也有对于的驱动程序。system_open、system_read最终会根据 打开的不同文件,找到底层的不同驱动程序的,然后调用驱动程序中的硬件操作函数比如led_open来实现对具体硬件设备的操作。

这就是整个的字符设备驱动程序框架。

发表评论

表情:
评论列表 (有 0 条评论,247人围观)

还没有评论,来说两句吧...

相关阅读