问题提出
让我们来带着问题来跟踪代码:
- 根据什么来保证执行顺序的?
- 执行bind()的时机是什么?
- 能否多级执行? 比如说,A执行前需要保证B先执行,但B执行前需要保证C先执行
代码流程
根据实例解析
将上面的图片用文字发出来:
假如有 A_master驱动,需要等A_component驱动中的bind()先执行完;然后还有B_master驱动,需要等B_comonent中的bind()先执行完。假如这四个驱动加载的顺序是 B_master -> A_component -> B_comonent ->A_master
流程梳理:
1. 先执行B_master 的probe,在我们的示例程序中就是类似于testdrm_platform_probe(),先根据dts配置,找到“ports”下的子节点,申请用于匹配/比较的资源struct component_match *match,并将“ports”节点的device_node地址(dts编译成dtb之后每个节点都会生成一个phandle,这个device_node就会包含这个phandle)和比较方法存在match中。然后申请master资源 master = kzalloc(sizeof(*master), GFP_KERNEL),将刚才的match存放到master->match 中,并通过list_add(&master->node, &masters)将当前master加入到全局链表masters中去。然后调用try_to_bring_up_master()进入到find_components中,在调用component_master_add_child()中因为component_list中没有元素,所以会返回-ENXIO,然后在try_to_bring_up_master()中直接退出。
2. 执行A_component 的probe,在我们的示例程序中就是类似于testsub1_platform_probe(),先申请资源component = kzalloc(sizeof(*component),然后将此component加入到内核文件component.c中的全局链表component_list中,调用try_to_bring_up_masters()在内核文件component.c全局链表masters中去遍历。当调用到component_master_add_child()的if (compare(c->dev, compare_data)),因为A_component 和B_master(具体是master->match->compare[match->num].data)的device_node匹配不上,所以会返回-ENXIO,然后在try_to_bring_up_master()中直接退出。
3. 执行B_comonent 的probe,在我们的示例程序中就是类似于testsub1_platform_probe(),先申请资源component = kzalloc(sizeof(*component),然后将此component加入到内核文件component.c中的全局链表component_list中,调用try_to_bring_up_masters()在全局链表masters中去遍历。当调用到component_master_add_child()的if (compare(c->dev, compare_data)),因为B_component 和B_master的device_node可以匹配的上,所以会调用component_attach_master()并component->master = master,这在try_to_bring_up_master()中会用到。之后会返回0,回到try_to_bring_up_master()中,会执行master->ops->bind(master->dev),(在我们的示例程序中就是master_test.c中的rockchip_test_drm_bind())然后会再调用component_bind_all(dev, "hello") (这里的“hello”是随便去的一个字符串,会把这个参数传个component端,在这里我们没用到此参数),最终会调用到component->ops->bind(),此时就是执行B_component的bind(),等它执行完之后,会返回,然后接着执行B_master的bind()。 这样,就达到了控制顺序的目的。
4. 执行B_component 的probe。和上一步差不多,就不作分析了。
解答文章开头的问题
- 前两个问题我们在分析过程中已经解答了
- 能否多级执行的问题,根据分析是可以的,在component_test.c中的bind()中再包一层。具体代码我就不实现了,有兴趣的同学可以试试。
图片是用visio画的,上传一份word,安装有visio的可以直接在visio中双击打开
链接: https://pan.baidu.com/s/1SHWpKhd0R8qNRbNydHMu6w
提取码: rexw