免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2947 | 回复: 4
打印 上一主题 下一主题

linux驱动中进程调度的问题和多个同类设备的驱动设计问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-07-16 09:58 |只看该作者 |倒序浏览
我在一个字符驱动的write函数中想在设备忙时进行进程调度,主动暂时放弃cpu。但是执行到schedule()函数就调度不回来了,这是怎么回事呢?我的代码如下:

set_current_state(TASK_INTERRUPTIBLE);
schedule();
if(signal_pending(current)){
    return -ERESTARTSYS;
}


另外:

我现在有几个同类的PCI设备,他们的厂商号和设备号是一样的,驱动肯定是只有一个的,但是要在设备文件系统里显示多个相关的设备名。
我该如何区分这几个同类设备呢?我也知道他们用相同的主设备号,不同的次设备号区分。是不是内核中会自动分配不同的次设备号呢?
xxx_probe()函数该如何设计?我自己认为应该给每个设备分配一个设备相关的结构变量并用链表链接。
多个同类设备时,是不是xxx_probe()函数会执行多次,还是执行一次?

论坛徽章:
0
2 [报告]
发表于 2009-07-16 13:14 |只看该作者
应该能调度回来啊。看看每次都是设备比较忙,都执行了sched

你可以参考网卡的驱动,一个设备多个网卡内核会分配此设备号。

论坛徽章:
0
3 [报告]
发表于 2009-07-16 14:35 |只看该作者

回复 #1 pan139com 的帖子

> set_current_state(TASK_INTERRUPTIBLE);
> schedule();
> if(signal_pending(current)){
>     return -ERESTARTSYS;
> }

So where is your wakeup code? process被设为TASK_INTERRUPTIBLE后,除非
1. 别的process给你发signal,kernel会把你唤醒
2. 在条件满足时,去wake_up_process,把process的state设为TASK_RUNNING,kernel才会调度你

而且,一般在driver中,我们都使用wait_queue来实现

> 我现在有几个同类的PCI设备,他们的厂商号和设备号是一样的,驱动肯定是只有一个的,但是
> 要在设备文件系统里显示多个相关的设备名。
> 我该如何区分这几个同类设备呢?我也知道他们用相同的主设备号,不同的次设备号区分。是
> 不是内核中会自动分配不同的次设备号呢?
> xxx_probe()函数该如何设计?我自己认为应该给每个设备分配一个设备相关的结构变量并用链
> 表链接。
> 多个同类设备时,是不是xxx_probe()函数会执行多次,还是执行一次?

每个设备都会执行一次driver的probe()函数,在你的probe()函数中并不需要去管理这些设备,这是kernel相应的subsystem的事。
f.e 假如你有两块一模一样的网卡,在你的probe()中只负责分配net_device并初始化它,然后向kernel的network subsystem注册这个设备。network subsystem会管理这些network device,比如第一块为eth0,第二块为eth1等等。。。

论坛徽章:
0
4 [报告]
发表于 2009-07-16 18:32 |只看该作者
谢谢 eexplorer

>So where is your wakeup code? process被设为TASK_INTERRUPTIBLE后,除非
>1. 别的process给你发signal,kernel会把你唤醒
>2. 在条件满足时,去wake_up_process,把process的state设为TASK_RUNNING,kernel才会调度你

>而且,一般在driver中,我们都使用wait_queue来实现

我现在将set_current_state(TASK_INTERRUPTIBLE);这句去掉就可以了,也就是说该进程调度之后立即成为可以执行的进程,也就是就绪的。这样也就没有等待设备是否已经就绪。

如果不去掉进程就没有就绪。可加入wait_queue中等待,但是这样需要在某处wake_up,进程已经调度出去了,需要等其他进程唤醒。前提是设备可以被多个进程同时访问,否则只能在中断中唤醒了。


>每个设备都会执行一次driver的probe()函数,在你的probe()函数中并不需要去管理这些设备,这是kernel相应的subsystem的事。
>f.e 假如你有两块一模一样的网卡,在你的probe()中只负责分配net_device并初始化它,然后向kernel的network subsystem注册这个设备。network subsystem会管理这些network device,比如第一块为eth0,第二块为eth1等等。。。

可能你们比较熟悉net_device,我是想些成char_device的。

我看的一些代码alloc_chrdev_region()或register_chrdev_region()都是注册一个主设备号的某个次设备号范围,也就是一次性把主次设备号都保留了,这应该是可以实现多设备的。
不知道cdev_add()怎么回事也是一次加一个主次设备号范围,还需要主次设备号。

最郁闷的是现在没有多个设备,不能试验。

我想到了另一个问题,就是驱动加载后自动在设备文件系统/dev显示设备名的问题。

据说在2.4中有devfs这种东西,在2.6中有udev。
我现在是2.6内核,用mknod 创建的设备文件,加载驱动后在/sys中也能看到的设备的信息。不能自动显示设备名可能是因为应用层没有udev这种工具。我试着在2.6中也用devfs但是仍然没有显示设备名。

论坛徽章:
0
5 [报告]
发表于 2009-07-17 10:08 |只看该作者

回复 #4 pan139com 的帖子

> 我现在将set_current_state(TASK_INTERRUPTIBLE);这句去掉就可以了,也就是说该进程调度
> 之后立即成为可以执行的进程,也就是就绪的。这样也就没有等待设备是否已经就绪。

use yield() then.


> 可能你们比较熟悉net_device,我是想些成char_device的。

> 我看的一些代码alloc_chrdev_region()或register_chrdev_region()都是注册一个主设备号的
> 某个次设备号范围,也就是一次性把主次设备号都保留了,这应该是可以实现多设备的。
> 不知道cdev_add()怎么回事也是一次加一个主次设备号范围,还需要主次设备号。

对啊,先通过register_chrdev_region 注册 major number和一段minor number,然后通过cdev_add来添加设备(指定major+minor)

> 据说在2.4中有devfs这种东西,在2.6中有udev。
> 我现在是2.6内核,用mknod 创建的设备文件,加载驱动后在/sys中也能看到的设备的信息。
> 不能自动显示设备名可能是因为应用层没有udev这种工具。我试着在2.6中也用devfs但是仍然
> 没有显示设备名。

devfs没用过,如果没有udev的话,那就只能手动mknod了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP