关于应用程序打开驱动的read直接返回0的问题

kavy00 2013-06-04 11:32:20
最近学习友善的minis3c2440,写了一个串口的字符设备驱动,串口0已经被用于与PC交互了,我写的驱动是串口1的,
1、在驱动函数的read里,我是这样处理的,直接进入睡眠,只有在串口收到数据的时候我才会去唤醒
static serial_read()
{
wait_event_interruptible(read_waitq,read_wakeup);
...
do something
...
}
2、在应用程序中,我先open 获得句柄,属性是 O_RDWR 可读可写 ,接下来我使用read(f_handle,buf,count)
while(run_read)
{
ret = read(f_handle,buf,count);
...
do something
}
但有时候read会直接返回0,但这时候串口的 RX 是为高电平的,而且我在驱动程序的read里使用printk打印信息,发现应用程序的read 根本就没有调用驱动程序里的read



这样的情况不是一直出现的,有时候串口就是好的,各方面通信都很正常,但一旦出现应用程序里的read返回0的情况,就会一直返回0
一直想不明白,求解啊!!
...全文
6042 22 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
kavy00 2013-06-18
  • 打赏
  • 举报
回复
引用 16 楼 zhanglei042681 的回复:
[quote=引用 11 楼 kavy00 的回复:] [quote=引用 10 楼 xinzha 的回复:] 既然是你自己写的驱动,返回什么是你自己控制的啊。
这个当然了啊。。关键是应用程序的read他直接返回0,完全没有调用驱动程序中read的感觉,因为我在驱动程序的read中(在wait_event_interruptible前面加了 printk ),做了这样的测试,发现printk没有被执行到!! [/quote] 没有走到你的read接口,应该是应用打开的设备句柄已经不可用了,即设备句柄与设备对应出错了。此时close都不起作用了。试试能否在kernel强制close 该设备,然后再open试试。[/quote] 如何强制关闭我不知道,我尝试在出现问题的时候,重新去获得句柄试试
kavy00 2013-06-18
  • 打赏
  • 举报
回复
引用 17 楼 xinzha 的回复:
[quote=引用 15 楼 kavy00 的回复:] [quote=引用 14 楼 xinzha 的回复:] 你看看插拔会不会引起驱动的disconnect和probe,如果会的话,那你以前所打开的fd已经不合适了。
驱动的disconnect与probe怎么理解??出现一直返回0的情况后,我ctrl+c关掉应用程序后,lsmod 依然能看到我加载的驱动啊[/quote] lsmod看到的只是驱动程序本身,设备的拔插会引起驱动中的disconnect或者probe动作,而probe和disconnect的责任就是生成用户空间可见的文件等等。[/quote] 昨天试了一天没有出现那个现象,寒。。现在在程序里加了这个处理,既如果read返回0 则重新打开。不过还不知道这样做行不行。 那么如果是插拔引起的probe或者disconnect 导致了 filehandle不能用的话 那么该如何解决呢??谢谢
kavy00 2013-06-18
  • 打赏
  • 举报
回复
恩,谢谢。。我再尝试尝试
猪头三小队长 2013-06-18
  • 打赏
  • 举报
回复
可以在disconnect的时候检查如果有程序打开文件就给相应程序发消息之类的。 不过这种事一般不由内核驱动来担心,应该是应用程序自己来考虑的,比如说你在read到0之后关闭再重新打开也不失为一种可行的办法,因为在你的read借口中是不会返回0的。
zhanglei042681 2013-06-14
  • 打赏
  • 举报
回复
引用 11 楼 kavy00 的回复:
[quote=引用 10 楼 xinzha 的回复:] 既然是你自己写的驱动,返回什么是你自己控制的啊。
这个当然了啊。。关键是应用程序的read他直接返回0,完全没有调用驱动程序中read的感觉,因为我在驱动程序的read中(在wait_event_interruptible前面加了 printk ),做了这样的测试,发现printk没有被执行到!! [/quote] 没有走到你的read接口,应该是应用打开的设备句柄已经不可用了,即设备句柄与设备对应出错了。此时close都不起作用了。试试能否在kernel强制close 该设备,然后再open试试。
kavy00 2013-06-14
  • 打赏
  • 举报
回复
引用 14 楼 xinzha 的回复:
你看看插拔会不会引起驱动的disconnect和probe,如果会的话,那你以前所打开的fd已经不合适了。
驱动的disconnect与probe怎么理解??出现一直返回0的情况后,我ctrl+c关掉应用程序后,lsmod 依然能看到我加载的驱动啊
猪头三小队长 2013-06-14
  • 打赏
  • 举报
回复
你看看插拔会不会引起驱动的disconnect和probe,如果会的话,那你以前所打开的fd已经不合适了。
kavy00 2013-06-14
  • 打赏
  • 举报
回复
引用 12 楼 xinzha 的回复:
2、然后我就频繁的在插拔(与开发板那端,PC端未连接)、一开始都还好的,可能几次后,就会出现应用程序read一直返回0 这个插拔是个什么操作没看懂,如果pc端未连接都不会引起串口的动作,怎么会有问题呢? 开发板跟pc之间有其他接口相连吗?
开发板与PC之间还有一个串口相连接,是COM0 控制ARM开发板的(通过超级终端,比如 加载驱动等) 而我自己写的驱动是COM1,这个只是为了进行数据的传输(接收与发送,两者不同步),插拔就是相当于4跟线(GND VCC TX RX)的连接于断开啊
猪头三小队长 2013-06-14
  • 打赏
  • 举报
回复
引用 15 楼 kavy00 的回复:
[quote=引用 14 楼 xinzha 的回复:] 你看看插拔会不会引起驱动的disconnect和probe,如果会的话,那你以前所打开的fd已经不合适了。
驱动的disconnect与probe怎么理解??出现一直返回0的情况后,我ctrl+c关掉应用程序后,lsmod 依然能看到我加载的驱动啊[/quote] lsmod看到的只是驱动程序本身,设备的拔插会引起驱动中的disconnect或者probe动作,而probe和disconnect的责任就是生成用户空间可见的文件等等。
猪头三小队长 2013-06-13
  • 打赏
  • 举报
回复
wait_event_interruptible既然是interruptible就会被其他信号中断,这是内核驱动防止等死的一种机制。而如果在这个时候有未知信号进来打断你的等待,你的代码如果不做返回值判断,就会认为是有数据进来了,不管是不是造成这个问题的根本原因,至少从逻辑上说已经出错了。
kavy00 2013-06-13
  • 打赏
  • 举报
回复
引用 4 楼 xinzha 的回复:
wait_event_interruptible(read_waitq,read_wakeup);这句话有出错处理吗? 感谢回答!! 如果没有出错处理,可能在串口没有数据的时候,去读串口fifo,设计不好的硬件和驱动会导致fifo的underflow错误,只有复位硬件才能恢复了。
没有出错的处理,没有数据的时候也不会去读FIFO啊,我采用中断的方式去接收数据的,FIFO触发深度设为最大 32bytes,也只有在接受完数据后,我才会去唤醒read的等待队列。。
kavy00 2013-06-13
  • 打赏
  • 举报
回复
引用 3 楼 weiqing1981127 的回复:
在应用层添加如下代码 options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); options.c_oflag &= ~OPOST; options.c_cflag |= CLOCAL | CREAD; options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
感谢回答!!我先了解下这些控制,再去试验下。。3q!!
猪头三小队长 2013-06-13
  • 打赏
  • 举报
回复
wait_event_interruptible(read_waitq,read_wakeup);这句话有出错处理吗? 如果没有出错处理,可能在串口没有数据的时候,去读串口fifo,设计不好的硬件和驱动会导致fifo的underflow错误,只有复位硬件才能恢复了。
流水恋歌 2013-06-13
  • 打赏
  • 举报
回复
在应用层添加如下代码 options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); options.c_oflag &= ~OPOST; options.c_cflag |= CLOCAL | CREAD; options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
猪头三小队长 2013-06-13
  • 打赏
  • 举报
回复
2、然后我就频繁的在插拔(与开发板那端,PC端未连接)、一开始都还好的,可能几次后,就会出现应用程序read一直返回0 这个插拔是个什么操作没看懂,如果pc端未连接都不会引起串口的动作,怎么会有问题呢? 开发板跟pc之间有其他接口相连吗?
kavy00 2013-06-13
  • 打赏
  • 举报
回复
引用 10 楼 xinzha 的回复:
既然是你自己写的驱动,返回什么是你自己控制的啊。
这个当然了啊。。关键是应用程序的read他直接返回0,完全没有调用驱动程序中read的感觉,因为我在驱动程序的read中(在wait_event_interruptible前面加了 printk ),做了这样的测试,发现printk没有被执行到!!
猪头三小队长 2013-06-13
  • 打赏
  • 举报
回复
既然是你自己写的驱动,返回什么是你自己控制的啊。
kavy00 2013-06-13
  • 打赏
  • 举报
回复
引用 5 楼 kavy00 的回复:
[quote=引用 3 楼 weiqing1981127 的回复:] 在应用层添加如下代码 options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); options.c_oflag &= ~OPOST; options.c_cflag |= CLOCAL | CREAD; options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
感谢回答!!我先了解下这些控制,再去试验下。。3q!![/quote] 实验后,发现还是不能解决原来的问题。。
kavy00 2013-06-13
  • 打赏
  • 举报
回复
引用 7 楼 xinzha 的回复:
wait_event_interruptible既然是interruptible就会被其他信号中断,这是内核驱动防止等死的一种机制。而如果在这个时候有未知信号进来打断你的等待,你的代码如果不做返回值判断,就会认为是有数据进来了,不管是不是造成这个问题的根本原因,至少从逻辑上说已经出错了。
这个你说的是对的,被其他信号打断的话,是会唤醒,并返回一个-ERESTARTSYS ,现在对这个进行了处理,可发现应用程序read还是会一直返回0,而不是-ERESTARTSYS, 1、我是这样操作的才会出现这样的情况:开发板上有串口引出来(VCC、GND、TX、RX),然后我自己做了一个转接口(一端与开发板相连,一端与PC相连,确定转接口没有问题), 2、然后我就频繁的在插拔(与开发板那端,PC端未连接)、一开始都还好的,可能几次后,就会出现应用程序read一直返回0 3、这时,即使我使用ctrl+c强制停止应用后程序后,再重新打开应用,还是出现read一直返回0 4、在网上查到read返回值的情况为3种 :-1 、 0、 读到的字节数 ,返回0的话网上说是达到文件末尾了
kavy00 2013-06-09
  • 打赏
  • 举报
回复
话说大神们能提些意见么。。
加载更多回复(1)

21,616

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 驱动开发/核心开发
社区管理员
  • 驱动开发/核心开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧