Linux 内核设备驱动程序或用户空间程序

Linux 内核设备驱动程序或用户空间程序,linux,linux-device-driver,embedded-linux,Linux,Linux Device Driver,Embedded Linux,我目前正在使用运行Linux 3.10.0+的SAMA5D31-EK板来控制一些硬件设备。我使用的GPIOs,I2C,PWM和UART可在该董事会。一些设备仅通过GPIO线控制,而其他设备则需要UART、PWM和3 GPIO。到目前为止,我正在使用一个用户空间程序来控制这些硬件设备——基本上是一个步进电机、一个ADC和一个字母数字LCD显示器 开发内核设备驱动程序来控制这些设备有什么好处?到目前为止(使用用户空间程序),我发现的唯一限制是速度:因为我必须对一些GPIO进行位击,结果有点慢。我假设

我目前正在使用运行Linux 3.10.0+的SAMA5D31-EK板来控制一些硬件设备。我使用的GPIOs,I2C,PWM和UART可在该董事会。一些设备仅通过GPIO线控制,而其他设备则需要UART、PWM和3 GPIO。到目前为止,我正在使用一个用户空间程序来控制这些硬件设备——基本上是一个步进电机、一个ADC和一个字母数字LCD显示器


开发内核设备驱动程序来控制这些设备有什么好处?到目前为止(使用用户空间程序),我发现的唯一限制是速度:因为我必须对一些GPIO进行位击,结果有点慢。

我假设您的主板上有可用于I2C/GPIO/PWM/UART接口的平台特定驱动程序(它应该是BSP[主板支持包]的一部分)

只是您不想使用内核设备驱动程序框架,而是想从用户空间做一些事情。我一直处于这种情况,因此我知道,这可能是多么诱人,特别是如果您不熟悉内核设备驱动程序的话

a速度:你提到过。但是,你可能没有完全理解原因

速度效率来自于避免内核和用户空间进程之间的上下文切换。以下是一个例子:

/* A loop in kernel code which reads a register 100 time */
for (i = 0 ; i < 100 ; i++ )
{
  __kernel_read_reg(...);
}

/* A loop in User-space code which reads a register 100 time */
for ( i= 0 ; i < 100; i++)
{
   __user_read_reg(...);
}
/*内核代码中的一个循环,它读取寄存器100次*/
对于(i=0;i<100;i++)
{
__内核读取注册表(…);
}
/*用户空间码中的一种循环,它将寄存器读取100次*/
对于(i=0;i<100;i++)
{
__用户读取注册表(…);
}
就功能而言,这两个*\u read\u reg()是相同的。假设_user_read_reg()将经历一个典型的系统调用过程,它必须为每个_user_read_reg(…)执行上下文切换,这代价太高

您可能会说,“我们可以对硬件寄存器进行mmap(),并避免对此类操作进行系统调用”。 当然,你可以这么做,但我想说的是: 接近硬件的操作(例如:寄存器读取或写入或处理中断)应尽可能快地完成。上下文切换中涉及的延迟将影响性能

b现有/测试/构建良好的子系统:

如果您在Linux内核中看到I2C子系统,那么它提供了一个经过良好测试的健壮框架,可以轻松重用。您不必在用户空间中写入完整的I2C子系统(处理所有设备类型、速度、各种配置等)。 在开发内核设备驱动程序时,重复使用“已经完成的工作”可能是一大优势

c、 从基于轮询的方法转向基于中断的机制

如果您没有在内核驱动程序中处理中断,那么您必须在用户空间进程中使用某种轮询机制。根据系统的不同,这可能不是处理硬件更改的非常可靠的方法。对于快速设备来说,绝对不准确/可靠

通常,基于中断的机制是处理设备更可靠的方式,在这种机制中,您可以尽可能快地处理关键更改(硬件中断上下文),并将非关键工作负载移动到用户空间或其他一些内核机制

当然,除了上述三点之外,可能还有更多的论点和反驳

您可能感兴趣的另一条线索是: