Linux 中的所有驱动程序都运行在相同的上下文中(内核空间的地址空间),还是各自运行在不同的环境中(类似于不同进程在用户空间的不同地址空间中的工作方式)?
1 回答
在 32 位 x86-Linux 中,所有驱动程序都在所谓的内核模式下运行(有时称为 Ring 0 模式,因为 Intel 组织其 CPU 保护方案的方式)。当一个驱动程序被进程调用时(例如,您read()
向设备驱动程序发出系统调用),驱动程序内部有一个函数会被执行。据说该函数在该进程的上下文中执行。
这意味着驱动函数在调用进程的内存映射中执行。这意味着驱动函数不仅可以访问存储在内核保留地址(虚拟地址 0xC0000000 及以上)中的自己的变量和结构,还可以访问用户调用进程的变量和代码。这允许类似copy_to_user()
或copy_from_user()
能够与用户调用进程交换信息的函数。
回想一下,Linux 中任何进程的内存映射都有两部分:一大部分是用户进程可用的最大 3GB 内存。该内存对于该进程是私有的。1GB 的另一部分用于内核。这部分在所有用户进程的内存映射之间共享。驱动程序的代码、堆栈和全局变量驻留在这 1GB 空间内。
还有另一个上下文:中断上下文。Linux 驱动程序可以为硬件中断安装处理程序。触发此中断时,将执行处理程序,但这一次,它将在当时正在执行的任何进程的上下文中执行(即尚未从用户进程调用处理程序)
典型的驱动程序是函数的集合,它们中的大多数是在用户进程发出系统调用的请求时执行的,所以大多数时候,驱动程序正在上下文中执行(实际上是它的一个实例)特定用户进程(但与用户进程中的代码不同,驱动程序以所有权限执行)。驱动程序的某些部分可能被其他内核函数异步调用,因此它们可能在另一个上下文中执行,与属于使用驱动程序的进程的上下文无关。
还要记住,多个用户进程可能正在使用驱动程序,因此每个进程在其自己的上下文中执行相同的代码。应该编写驱动程序以便可以重新输入,从而避免副作用。