10.内核的分离和分层-linux-component-《计算机知识》

admin 2025-11-02 22:20:27 系统网络 来源:ZONE.CI 全球网 0 阅读模式
  • 内容和参考
    • 内容
    • 参考
  • component框架
    • component的作用
    • component的组成
    • component软件
    • 设备驱动框架
    • master驱动框架
  • 软件测试

    内容和参考

    内容

    如何加载驱动?insmod xxx.ko 或者 modprobe xxx.ko驱动中如何匹配? 设备树 / platform_device 匹配 platform_driver

    那么引来一个问题:如何有顺序的完整的安装驱动? 有顺序的安装驱动方式可以有:

    • initcall级别修改(如果initcall级别一样,那么静态编译进内核时 Makefile的顺序影响了加载顺序,

    因为编译后 模块按照顺序依次放在init 代码段中, 内核启动后会依次加载驱动);

    • initcall级别不一致,比如device_initcall 和 device_initcall_late
    • component组件

    component组件不只可以确定启动顺序, 而且可以在模块内所有模块准备好后,依次安装;

    参考

    • linux kernel component框架分析

    component框架

    component的作用

    component系统架构的提出就是出于这样一种现实需求:按顺序完整的构建功能系统!

    所以component架构构建功能系统就包括两方面的作用:

    • 保证系统安装了所有的组件。
    • 规定了系统各组件初始化的顺序。

    component架构在linux内核中现在主要的应用是用来构建display-subsystem (drm子系统中)

    系统就是各种功能单元(组件)的有序结合。一个系统,只有集齐了它的所有组件才能正常工作。

    可以打个比方:

    • 一辆车,只装上发动机,或变速箱。是不能工作的,必须安装了所有的组件,才能开始发动。
    • 而发动的过程,也是有顺序要求的,如先采离合,再挂当(变速箱初始化),再踩油门(发动机初始化),车轮再开始转动。(有序)

    component的组成

    在component中,包含两个基本概念,master和component。

    • master是设备树中的“超级设备(superdevice)”,负责管理该超级设备下的普通设备。component是由master管理的普通设备,要先初始化。
    • component是普通的设备节点,其下有与master的prots属性值一样的节点

    component软件

    初始化分为两部分:master即超级设备,执行probe函数时使用component_master_add_with_match函数注册自己到component框架中。component即普通设备,执行probe函数时使用component_add函数注册自己到component框架中。两种流程先后顺序并无要求,可随意顺序。每一个设备加入到框架中,框架就尝试进行匹配,当master匹配上所有component后,会调用master的bind回调,开始按顺序进行初始化。保证了当所有子设备全部probe成功后再执行初始化操作

    1. // include/linux/component.h
    2. // driver/base/compponent.c
    3. #include <linux/component.h>
    4. // 设备接口 : 在设备的probe/remove函数执行,将自己注册到component中
    5. int component_add(struct device *, const struct component_ops *);
    6. void component_del(struct device *, const struct component_ops *);
    7. // master接口
    8. int component_bind_all(struct device *master, void *master_data);
    9. void component_unbind_all(struct device *master, void *master_data);
    10. void component_master_del(struct device *,
    11. const struct component_master_ops *);
    12. int component_master_add_with_match(struct device *,
    13. const struct component_master_ops *, struct component_match *);
    14. void component_match_add_release(struct device *master,
    15. struct component_match **matchptr,
    16. void (*release)(struct device *, void *),
    17. int (*compare)(struct device *, void *), void *compare_data);
    18. static inline void component_match_add(struct device *master,
    19. struct component_match **matchptr,
    20. int (*compare)(struct device *, void *), void *compare_data);

    设备驱动框架

    1. struct component_ops {
    2. int (*bind)(struct device *comp, struct device *master,
    3. void *master_data);
    4. void (*unbind)(struct device *comp, struct device *master,
    5. void *master_data);
    6. };
    7. struct component_ops xxx_comp_ops {
    8. bind = xxx_comp_bind;
    9. unbind = xxx_comp_unbind;
    10. };
    11. static int xxx_probe(struct platform_device *pdev)
    12. {
    13. return component_add(&pdev->dev, &xxx_comp_ops);
    14. }
    15. static int xxx_remove(struct platform_device *pdev)
    16. {
    17. component_del(&pdev->dev, &xxx_comp_ops);
    18. return 0;
    19. }

    参考:linux-4.14/drivers/gpu/drm/armada/armada_crtc.c

    master驱动框架

    1. static const struct component_master_ops xxx_master_ops = {
    2. .bind = xxx_master_bind,
    3. .unbind = xxx_master_unbind,
    4. };
    5. // 自定义匹配函数方法
    6. static int compare_dev_name(struct device *dev, void *data)
    7. {
    8. const char *name = data;
    9. return !strcmp(dev_name(dev), name);
    10. }
    11. // component_master_add_with_match函数注册自己到component框架中
    12. static int xxx_drm_probe(struct platform_device *pdev)
    13. {
    14. struct component_match *match = NULL;
    15. // 将所有子设备挂载到当前master中,
    16. for (xxx);
    17. component_match_add(&pdev->dev, &match, compare_dev_name, port);
    18. return component_master_add_with_match(&pdev->dev, &armada_master_ops,
    19. match);
    20. }
    21. // 当所有设备匹配成功后,会先调用master的bind接口来 回调所有component接口
    22. static int xxx_master_bind(struct device *dev)
    23. {
    24. ...
    25. /* Now try and bind all our sub-components */
    26. ret = component_bind_all(dev, xxx); // 这时回调所有子设备的bind接口
    27. if (ret)
    28. goto err_kms;
    29. ...
    30. }

    参考:linux-4.14/drivers/gpu/drm/armada/armada_drv.c

    软件测试

    参考: test_componet代码中先注册了一堆虚拟平台总线设备,然后使用component来加载和使用; 当前使用非设备树环境;

    01-shell脚本介绍-《shell脚本》 系统网络

    01-shell脚本介绍-《shell脚本》

    一、shell脚本是什么二、为什么要学shell,而不是其他计算机语言三、学习这门课程的优势四、学了能干什么五、学习什么内容六、学习的技巧七、成长路径八、学习环
    评论:0   参与:  14