我希望尽快将支持DMA的PCIe硬件设备中的数据导入用户空间.
问:如何将"使用/和/通过DMA传输直接I/O连接到用户空间"
通过LDD3读取,似乎我需要执行一些不同类型的IO操作!?
dma_alloc_coherent给我一个可以传递给硬件设备的物理地址.但是在传输完成时需要设置get_user_pages并执行copy_to_user类型调用.这似乎是浪费,要求设备DMA进入内核内存(充当缓冲区),然后再将其传输到用户空间.LDD3 p453:/* Only now is it safe to access the buffer, copy to user, etc. */
我理想的是一些记忆:
我是否需要单页流映射,设置映射和用户空间缓冲区映射get_user_pages dma_map_page?
到目前为止,我的代码get_user_pages在用户空间的给定地址设置(我称之为直接I/O部分).然后,dma_map_page用一个页面get_user_pages.我将设备的返回值dma_map_page作为DMA物理传输地址.
我使用一些内核模块作为参考:drivers_scsi_st.c和drivers-net-sh_eth.c.我会看看infiniband代码,但无法找到哪一个是最基本的!
提前谢谢了.
我正在学习用于编写linux设备驱动程序的阻塞I/O函数,我想知道它的用法是什么ERESTARTSYS.考虑以下:
全局变量:
wait_queue_head_t my_wait_q_head;
int read_avail = 0;
Run Code Online (Sandbox Code Playgroud)
device_init():
init_waitqueue_head(&my_wait_q_head);
device_read():
printk("I'm inside driver read!\n");
wait_event_interruptible(&my_wait_q_head, read_avail != 0);
printk("I'm awaken!\n");
Run Code Online (Sandbox Code Playgroud)
device_write():
read_avail = 1;
wake_up_interruptible(&my_wait_q_head);
Run Code Online (Sandbox Code Playgroud)
当我调用read()from用户空间时,命令提示符会挂起,直到我write()按预期调用.的printk消息相应地出现,以及在dmesg.但是,我看到一些像这样编写的驱动程序:
另一个版本的device_read():
printk("I'm inside driver read!\n");
if(wait_event_interruptible(&my_wait_q_head, read_avail != 0))
{return -ERESTARTSYS;}
printk("I'm awaken!\n");
Run Code Online (Sandbox Code Playgroud)
我测试了device_read()在用户空间中使用相同方法的第二个版本,结果完全相同,那么,ERESTARTSYS的用途是什么?
p/s:我已经阅读了这本书上的Linux设备驱动程序,但是我没有得到它,有人可以举例来说明吗?:
一旦我们通过那个电话,有些东西唤醒了我们,但我们不知道是什么.一种可能性是该过程接收到信号.包含wait_event_interruptible调用的if语句将检查此情况.这个陈述确保了对信号的适当和预期的反应,这可能是唤醒过程的原因(因为我们处于可中断的睡眠状态).如果信号已到达并且尚未被进程阻止,则正确的行为是让内核的上层处理事件.为此,驱动程序将-ERESTARTSYS返回给调用者; 此值由虚拟文件系统(VFS)层在内部使用,该层可重新启动系统调用或将-EINTR返回到用户空间.我们使用相同类型的检查来处理每个读写实现的信号处理.
在驱动程序中,我经常看到使用这三种类型的init函数.
module_init()
core_initcall()
early_initcall()
Run Code Online (Sandbox Code Playgroud)
虽然理解每一个(或许不是),但看起来我远远不了解两者之间的实际差异.
根据我的理解,BSP是一个驱动程序和配置设置包,允许内核映像启动板(并且是其中的一部分).单个设备驱动程序在特定组件(HW)上运行,一侧与核心内核连接,另一侧与设备本身连接.
看看Linux内核,我不清楚BSP角色的起源和设备驱动程序角色的结束位置.具体来说,我习惯于每个图像每个板看到一个BSP,但是,通用Linux内核可以加载到具有相同图像的任何架构系列(很明显,对于不同的系列,有不同的图像:x86,amd64,arm, etc ...),其中特定的板和外围设备驱动程序是从initrd按需加载的.
常见的Linux内核发行版是否有BSP?或者BSP是否与特殊案例板相关?
这种行为在其他内核上是否相似?VxWorks的?
最后一个,合并不同的BSP/s以生成适合不同电路板的单个图像是很常见的吗?
我们如何定制内置驱动程序加载顺序(首先加载一些内置驱动程序模块,然后加载依赖模块)?
在Linux设备驱动程序中,创建sysfs属性probe过于活泼 - 特别是,它遇到了与用户空间的竞争条件.建议的解决方法是将属性添加到各种默认属性组,以便在探测之前自动创建它们.对于设备驱动程序,struct device_driver包含const struct attribute_group **groups此目的.
但是,在Linux 3.11中struct attribute_group只有二进制属性的字段.对于较旧的内核(特别是3.4),设备驱动程序如何在探测之前创建sysfs二进制属性?
所以我试图找出哪些内核进程正在调用块驱动程序中的某些函数.我认为在C库中包含backtrace()可以让它变得简单.但是我无法加载回溯.
我复制了这个示例函数来显示回溯:
http://www.linuxjournal.com/files/linuxjournal.com/linuxjournal/articles/063/6391/6391l1.html
所有编译尝试都在一个地方或另一个地方发生错误,导致无法找到文件或未定义函数.
这是最接近的.
在Makefile中我放了编译器指令:
-rdynamic -I/usr/include
Run Code Online (Sandbox Code Playgroud)
如果我省略第二个,-I/usr/include,那么编译器报告它找不到所需的头文件execinfo.h.
接下来,在我想要进行回溯的代码中,我从示例中复制了该函数:
//trying to include the c backtrace capability
#include <execinfo.h>
void show_stackframe() {
void *trace[16];
char **messages = (char **)NULL;
int i, trace_size = 0;
trace_size = backtrace(trace, 16);
messages = backtrace_symbols(trace, trace_size);
printk(KERN_ERR "[bt] Execution path:\n");
for (i=0; i<trace_size; ++i)
printk(KERN_ERR "[bt] %s\n", messages[i]);
}
//backtrace function
Run Code Online (Sandbox Code Playgroud)
我稍后在块驱动程序函数中调用此函数,其中发生错误的第一个符号.只是:
show_stackframe();
Run Code Online (Sandbox Code Playgroud)
所以当我编译它时,会出现以下错误:
user@slinux:~/2.6-32$ make -s
Invoking make againt the kernel at /lib/modules/2.6.32-5-686/build
In file included from /usr/include/features.h:346,
from /usr/include/execinfo.h:22,
from /home/linux/2.6-32/block/block26.c:49:
/usr/include/sys/cdefs.h:287:1: …Run Code Online (Sandbox Code Playgroud) 我有一个流行的绘图板,我用USB连接到我的电脑.连接后,平板电脑会检测手部动作并相应地操纵指针.平板电脑正在某处将这些数据传输到我的电脑.
我的目标是在处理数据后拦截这些传输并操纵鼠标.我发现的流行语是:设备驱动程序和HID,但我还没有能够拼凑到更多.
假设这是可能的,我有几个问题:
我的电脑正在运行Ubuntu(但是非常感谢与任何形式的Linux操作系统相关的答案!).
注意:此问题类似,但适用于Windows.
如果有一个/ dev设备节点及其主要/次要编号,我如何知道导出该节点的内核模块名称?
我有一个modprobe命令问题...我编译了hello world模块并加载它insmod,它工作正常,当我这样做时lsmod,我可以在输出列表中看到它.但是当我使用插入此模块时,我modprobe收到致命错误:
root@okapi:/home/ravi# modprobe ./hello.ko
FATAL: Module ./hello.ko not found.
root@okapi:/home/ravi#
Run Code Online (Sandbox Code Playgroud)
这是模块代码:
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_ALERT "Hello, world\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
Run Code Online (Sandbox Code Playgroud)
和Makefile
obj-m += hello.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Run Code Online (Sandbox Code Playgroud)