与Linux内核有关,"内核"页面是否会被换出?此外,用户空间页面是否会驻留在ZONE_NORMAL中?
linux arm memory-management linux-device-driver linux-kernel
我编写了一个linux驱动程序,ioremaps将特定设备的PCI BAR0导出到sysfs二进制属性,允许用户空间直接控制它.
当我尝试在属性之上进行MMAP以直接访问该位内存(来自userland程序)时,问题就出现了.读取成功并返回预期值,但是当我写入该内存时,它似乎缓存在内核和内存之间的某处,而不是传递给GMCH根复合体(因此也就是设备).我想做的是每次访问后都有一个隐含的写内存屏障.
跟进:
我最近在自定义Linux内核(2.6.31.5,x86)驱动程序中遇到了一个问题,其中copy_to_user会定期不将任何字节复制到用户空间.它将返回传递给它的字节数,表明它没有复制任何东西.代码检查后,我们发现代码在调用copy_to_user时禁用了中断,这违反了它的合同.纠正此问题后,问题就停止了.因为问题很少发生,我需要证明禁用中断会导致问题.
如果你从arch/x86/lib/usercopy_32.c rep看下面的代码片段; movsl通过CX中的计数将单词复制到用户空间.退出时使用CX更新大小.如果movsl正确执行,CX将为0.因为CX不是零,所以movs?为了符合copy_to_user的定义和观察到的行为,指令不得执行.
/* Generic arbitrary sized copy. */
#define __copy_user(to, from, size) \
do { \
int __d0, __d1, __d2; \
__asm__ __volatile__( \
" cmp $7,%0\n" \
" jbe 1f\n" \
" movl %1,%0\n" \
" negl %0\n" \
" andl $7,%0\n" \
" subl %0,%3\n" \
"4: rep; movsb\n" \
" movl %3,%0\n" \
" shrl $2,%0\n" \
" andl $3,%3\n" \
" .align 2,0x90\n" \
"0: rep; movsl\n" \
" movl %3,%0\n" \
"1: rep; …Run Code Online (Sandbox Code Playgroud) 模块名称:params.ko
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/stat.h>
MODULE_LICENSE("Dual BSD/GPL");
static char *mystring = "this is my char string";
module_param(mystring, charp, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(mystring, "A char string");
static int __init params_init(void)
{
printk("Driver is loaded\n");
printk(" My char string(mystring): %s\n", mystring);
return 0;
}
static void __exit params_exit(void)
{
printk("Driver is unloaded\n");
}
module_init(params_init);
module_exit(params_exit);
当我使用默认设置时,我可以在加载驱动程序时看到"这是我的字符串".
但是,如果我使用命令行来传递带空格的字符串,它将显示以下错误:
EX1:
# insmod ./params.ko mystring="Hello World"
insmod: error inserting './params.ko': -1 Unknown symbol in module
dmesg显示以下信息:
params: Unknown parameter …
我看到内核代码中使用的u8 u16 u64 u64数据类型.我想知道为什么会出现需要使用u8或u16或u32或u64不unsigned int?
我正在编写我的第一个Linux内核模块,它实际上是一个RAM磁盘驱动程序以及一些附加功能.当我尝试insmod模块时,发生了"分段错误".
这里是相应的内核日志,实际上是两条内核oops消息.在阅读了很多相关的教程后,我仍然对这个日志有一些疑问:
1)在通话跟踪列表中,有一些带有问号和没有问号的功能,问号"?"的特殊含义是什么?那个功能?
2)我对调用跟踪的理解是:除了底部函数之外的每个函数都应该由它下面的函数调用.但为此:
[ 397.855035] [<c05a603b>] ? exact_lock+0x0/0x16
[ 397.855035] [<f787c252>] ? diag_init+0x252/0x4bd [b2bntb_diag]
[ 397.855035] [<c0451e35>] ? __blocking_notifier_call_chain+0x42/0x4d
[ 397.855035] [<f787c000>] ? diag_init+0x0/0x4bd [b2bntb_diag]
Run Code Online (Sandbox Code Playgroud)
diag_init我编写的模块init函数.它不会调用任何命名的函数,exact_lock或者__blocking_notifier_call_chain这两个函数如何在调用跟踪中出现?
3)错误是什么以及如何解决?
顺便说一下,我正在运行的Linux内核有2.6.35.6版本.
[ 397.850955] ------------[ cut here ]------------
[ 397.851544] WARNING: at lib/kobject.c:168 kobject_add_internal+0x3a/0x1e2()
[ 397.851601] Hardware name: VirtualBox
[ 397.851639] kobject: (f4580258): attempted to be registered with empty name!
[ 397.851678] Modules linked in: b2bntb_diag(+) fuse vboxvideo drm sunrpc ip6t_REJECT nf_conntrack_ipv6 …Run Code Online (Sandbox Code Playgroud) 我在使用mdev规则运行busybox的嵌入式Linux中编写了一个简单的UART串行驱动程序.我在驱动程序代码中提供.dev_name了" ttyC2C".
static struct uart_driver serial_omap_reg = {
.owner = THIS_MODULE,
.driver_name = "Omap-C2C-Serial",
.dev_name = "ttyC2C",
.nr = OMAP_MAX_HSUART_PORTS,
.cons = NULL,
};
Run Code Online (Sandbox Code Playgroud)
但是,节点正在创建中
./sys/devices/platform/omap_c2c_uart.0/tty/ttyC2C0
./sys/class/tty/ttyC2C0
/ # ls -l ./sys/class/tty/ttyC2C0
lrwxrwxrwx 1 root 0 0 Jan 1 00:14 ./sys/class/tty/ttyC2C0 -> ../../devices/platform/omap_c2c_uart.0/tty/ttyC2C0
/ # ls -l ./sys/devices/platform/omap_c2c_uart.0/tty/ttyC2C0
-r--r--r-- 1 root 0 4096 Jan 1 00:14 dev
lrwxrwxrwx 1 root 0 0 Jan 1 00:14 device -> ../../../omap_c2c_uart.0
drwxr-xr-x 2 root 0 0 Jan 1 00:14 power …Run Code Online (Sandbox Code Playgroud) 为什么大多数设备驱动程序中的每个功能都是静态的?由于静态函数在文件范围之外不可见.那么,这些驱动程序函数如何被用户空间应用程序调用?
strerror内核中是否存在类似的功能?我找不到一个,所以我的想法是否定的,但更重要的是,他们有没有讨论过这个问题?我认为它可以减少故障排除时间,因为您不必查找错误代码(并非每个人都记住了),并且可能使系统管理员和普通的日常用户(通过dmesg)更容易.
我想在邮寄LKML之前问这里.我的想法是一个双重机制,一个用于错误名称(例如,EINVAL),另一个用于描述.此外,%mglibc扩展可以添加到printk,除了它必须读取错误代码,因为glibc扩展读取errno.也许%m可以打印错误名称,同时%M可以打印错误描述?
无论如何,如果它被添加,它应该是.config选项,因为它会膨胀文本大小.只需将错误名称(当前为1到133)存储在单个字符串中,并且每个字符串之间只有一个空终止符并且只是一个慢速strerror(强制遍历字符串并计算空终止符),因为速度可以缩小.这应该不重要.内部错误512-529必须在单独的字符串中.然后,可以返回指向以null结尾的字符串的直接指针,而无需复制任何内容.根据我的计算,错误名称大约需要1322个字节,描述需要3540个字节(根据每个错误的#define之后的注释中的内容以及当前缺少的那些添加"no description").
然后,当配置禁用时,printk %m可以被解释为%d并且%M可以只打印(或者一些这样的).
总结(我们做了什么,我们尝试了什么):
基本上,目的是通过使用adb源代码在两台Linux计算机之间通过usb建立adb协议.
Envinronment是Ubuntu 16.0.4.有一个android-tools-adbd(adb守护程序)包准备在池中使用,其源可用.
此链接上的源(adbd)可与gcc选项-stc = c ++ 14兼容,默认情况下(或gcc 5.2)在16.0.4中受支持.
我们可以使用adb connect(依赖于TCP/IP)从源代码构建软件包或使用已构建的软件包成功构建软件包.如果两台计算机连接到同一网络,则通过TCP/IP进行adb连接没有问题.
不幸的是,我们无法使用A到A(两个都是)电缆在两台计算机之间设置USB连接.ADB小工具无法正常工作,并且所有设备都无法识别其他设备.除了ADB小工具之外,我们无法确定是否需要显式驱动程序.
问题是(真正的问题需要回答):
如何在两台Linux计算机之间设置USB协议,以便通过USB完成adb通信?
它有什么解决方案吗?
[ - -编辑 - -]
笔记:
日复一日,小问题离开了.对于那些想要参与的人; 我们正在遵循本指南.
(内核版本4.4.0-38-通用)
运行正确的udc(USB设备控制器)驱动程序时遇到问题.激活ConfigFS后modprobe usb_f_fs,xdg-adbd (可从源链接执行,adbd)正常工作,直到if(...)检测到udc驱动程序.我们尝试了运行,modprobe musb_hdrc但没有看到明确的驱动程序名称/sys/class/udc.
(2016年9月27日)
linux-kernel ×6
linux ×5
c ×4
adb ×1
adb-drivers ×1
android ×1
arm ×1
interrupt ×1
kernel ×1
mmap ×1
page-fault ×1
serial-port ×1
static ×1
uart ×1
usb ×1
x86 ×1