之前讲了uboot,它的任务是启动内核;
内核的任务是启动应用程序;
应用程序,里面肯定会涉及很多文件操作,比如读写文件,还有很多硬件操作,比如点灯,获取按键值等。
对于写应用程序的人,他们通常不会去查看芯片手册看这些硬件要怎么操作,而是直接调用open,read,write这些接口来调用底层驱动。
最简单的一种对应方法就是,open函数,read函数,write函数分别会来调用底层驱动的led_open函数,led_read函数,led_write函数。
现在我们来看一下,应用程序的open,read这些函数,是怎么最终调用我们底层驱动的led_open,led_read这些函数的,中间有哪些东西。
假如我们写一个应用程序如下:
int main(void)
{
int fd1, fd2;
int val = 1;
fd1 = open("/dev/led", O_RDWR);
write(fd1, &val, 4);
fd2 = open("hello.txt", O_RDWR);
write(fd2, &val, 4);
}
这里面的open,write这些函数,都不是我们实现的,那是谁实现的吗?
答:C库。它一样属于应用层,当我们的应用程序调用这些open,read,write这些系统调用接口的时候就会进入到内核,驱动也属于内核的一部分。
那么C库是怎么进入内核的呢?
答:open,read,write这些系统调用,实质上都是执行一条swi指令,后面加上某个值val(swi val),这样就会进入到内核的异常处理函数。
有一个system call interface系统调用接口,它会根据发生中断的原因调用不同的处理函数(sys_open,sys_read,sys_write等),这一层叫做VFS(virtual file system虚拟文件系统)。
我们点灯和写文件都使用了open,write函数,但是这两个行为显然不一样,那么,谁来实现这些不同的操作呢?
显然,LED灯有一套它自己的驱动程序,Flash文件也有另一套它自己的驱动程序。
sys_xxx函数就会根据打开的不同文件,找到不同的底层驱动程序,然后调用这些驱动程序来实现底层的write,read,open功能。
app里面的open,read,write这些函数怎么找到底层驱动的对应的xxx_open,xxx_read这些函数,就是通过驱动框架,怎么对应起来的,这个就是下一节的内容。