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

 u-boot的任务是启动内核,内核的任务是启动应用程序。应用程序会涉及很多文件和硬件操作(当然不会直接操作硬件), 比如读写文件,点灯、获取按键值。
   对于应用程序的开发人员不要求去阅读芯片手册,了解硬件的构造。应用程序的开发人员在用户空间直接使用open、read、 write等等这些被称为系统调用的函数,通过这些函数进入内核空间,进而调用内核空间的驱动程序。
  比如对于控制led灯的用户程序与驱动程序,最简单的实现方法是,应用程序中需要打开led灯,就需要open函数,在内核中的驱动 程序中也有对应的led_open函数,这个led_open函数负责直接操作硬件,应用程序中要调用read函数读取led灯的状态的时候,内核中的驱动程序也有led_read函数。这是 应用程序与内核中驱动程序一种最简单的对应方式。
  那么应用程序中的open、read函数最终怎样调用到驱动程序中的led_open、led_read呢,中间有哪些东西。
  我们首先写一个简单的应用程序。

  int main()
  {
          int fd1; fd2;
          int val = 1;

          fd1 = open("/dev/led", O_RDWR);
          write(fd1, &val, 4);

          fd2 = open("/home/xxx/hello.txt", O_RDWR);
          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来实现对具体硬件设备的操作。
  这就是整个的字符设备驱动程序框架。

你可能感兴趣的:(linux,驱动开发)