当前位置: 技术问答>linux和unix
Linux字符设备驱动疑难问题--printf打印信息发到字符设备write函数中
来源: 互联网 发布时间:2016-09-26
本文导语: 我在开发中遇到一个奇怪的问题: 1、创建了一个字符设备驱动,为其注册了open、read、write、poll等函数; 2、创建了一个用户空间程序,用来打开1中的字符设备驱动,为的是传递命令到用户空间程序进行处理; 3、当...
我在开发中遇到一个奇怪的问题:
1、创建了一个字符设备驱动,为其注册了open、read、write、poll等函数;
2、创建了一个用户空间程序,用来打开1中的字符设备驱动,为的是传递命令到用户空间程序进行处理;
3、当PC端发送一个请求,我们受到后会将其放到请求列表ctrl_list中;
4、字符设备的read函数会循环检测ctrl_list中有没有控制请求,当有控制请求的时候,会通过copy_to_user发送到用户空间程序中;
5、用户空间程序解析4中的请求并执行处理,处理完成后发送结果,在用户空间调用write,我们的请求处理结果最大50字节;
6、在字符设备驱动的write函数中,会出现被写入4096或1024字节数据的情况(依平台不同有所变化),这个是一页的数据;
7、上述一页的数据是我们用户空间程序中所有printf语句的打印信息,并被发送到PC侧,可以从打印log看出;
8、我们通过在内核加panic和在用户空间加指针误操作进行追踪,发现上述4096字节的数据不是我们的用户空间程序调用的,从panic看是文件系统自己调用,并把printf的打印发过去,出现这种情况时,用户空间的打印不会在串口打印出来;
麻烦大家看下有没有遇到过这种问题,为什么会被莫名其妙调到;
不方便贴代码;
谢谢
1、创建了一个字符设备驱动,为其注册了open、read、write、poll等函数;
2、创建了一个用户空间程序,用来打开1中的字符设备驱动,为的是传递命令到用户空间程序进行处理;
3、当PC端发送一个请求,我们受到后会将其放到请求列表ctrl_list中;
4、字符设备的read函数会循环检测ctrl_list中有没有控制请求,当有控制请求的时候,会通过copy_to_user发送到用户空间程序中;
5、用户空间程序解析4中的请求并执行处理,处理完成后发送结果,在用户空间调用write,我们的请求处理结果最大50字节;
6、在字符设备驱动的write函数中,会出现被写入4096或1024字节数据的情况(依平台不同有所变化),这个是一页的数据;
7、上述一页的数据是我们用户空间程序中所有printf语句的打印信息,并被发送到PC侧,可以从打印log看出;
8、我们通过在内核加panic和在用户空间加指针误操作进行追踪,发现上述4096字节的数据不是我们的用户空间程序调用的,从panic看是文件系统自己调用,并把printf的打印发过去,出现这种情况时,用户空间的打印不会在串口打印出来;
麻烦大家看下有没有遇到过这种问题,为什么会被莫名其妙调到;
不方便贴代码;
谢谢
|
你把标准输出 定向的这个字符设备了吧。
比如启动时用 program > /dev/char
比如启动时用 program > /dev/char
|
static ssize_t ***_write_***(struct file * file, const char __user * buf,
size_t count, loff_t *ppos)
在这个write 里把count 打印出来看看.
copied = copy_from_user(dest, buf, sz);
再把这个 copied 值打印出来看看呢?
如果处理数据最多50字节, 即便是缓存在内存里, 也需要好几十次才会分页 .
size_t count, loff_t *ppos)
在这个write 里把count 打印出来看看.
copied = copy_from_user(dest, buf, sz);
再把这个 copied 值打印出来看看呢?
如果处理数据最多50字节, 即便是缓存在内存里, 也需要好几十次才会分页 .
|
如果确定是驱动里面write被调用导致的话,可以在write函数中打印出调用的堆栈信息,并可以打印出调用write函数的进程名称.
|
#include
把调用这个write 的进程打印出来 current->pid
对比一下是哪个进程调用的, 是不是设备号分配冲突?
把调用这个write 的进程打印出来 current->pid
对比一下是哪个进程调用的, 是不是设备号分配冲突?
|
copied值每次都是0 , 那这里就有问题呢
|
是不是程序中,将stdin、stdout、stderr的fd关闭过了呢?导致0、1、2描述符被重用。
使用ps查看一下用户进程的进程号,比如3063。然后通过proc查看一下这个进程所有打开的文件句柄。
localhost:/ > ls -l /proc/3063/fd
total 0
lrwx------ 1 root root 64 Sep 8 04:29 0 -> /dev/pts/3
lrwx------ 1 root root 64 Sep 9 00:49 1 -> /dev/pts/3
lrwx------ 1 root root 64 Sep 9 00:49 2 -> /dev/pts/3
lrwx------ 1 root root 64 Sep 9 00:49 255 -> /dev/pts/3
使用ps查看一下用户进程的进程号,比如3063。然后通过proc查看一下这个进程所有打开的文件句柄。
localhost:/ > ls -l /proc/3063/fd
total 0
lrwx------ 1 root root 64 Sep 8 04:29 0 -> /dev/pts/3
lrwx------ 1 root root 64 Sep 9 00:49 1 -> /dev/pts/3
lrwx------ 1 root root 64 Sep 9 00:49 2 -> /dev/pts/3
lrwx------ 1 root root 64 Sep 9 00:49 255 -> /dev/pts/3