博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux 内核面向对象思想及实现
阅读量:3561 次
发布时间:2019-05-20

本文共 20043 字,大约阅读时间需要 66 分钟。

面向对象, 并不一定需要C++, JAVA语言才能实现。 C语言也能实现, 比如Linux内核。

 

C语言实现面向对象的思想, 

1. 封装,  将数据和方法都封装在数据结构中, 其中方法可以使用函数指针来实现。

2. 继承, 

3. 多态, 即具体的函数调非编译器决定, 而是程序运行期间决定, 即所谓的晚绑定(Late Binding)。

    即封装中的函数指针,  可根据具体的实际对象选择函数调用。

    

    看些代码, 比如常见的比如platform_driver,

1671 static struct platform_driver dwc3_driver = {                                                                                                                      1672 ›   .probe› ›   = dwc3_probe,                                                                                                                                      1673 ›   .remove››   = dwc3_remove,                                                                                                                                     1674 ›   .driver››   = {                                                                                                                                                1675 ›   ›   .name›  = "usb",                                                                                                                                           1676 ›   ›   .of_match_table›= of_match_ptr(of_dwc3_match),                                                                                                             1677 ›   ›   .acpi_match_table = ACPI_PTR(dwc3_acpi_match),                                                                                                             1678 ›   ›   .pm›= &dwc3_dev_pm_ops,                                                                                                                                    1679 ›   },                                                                                                                                                             1680 };                                                                                                                                                                 1681                                                                                                                                                                    1682 module_platform_driver(dwc3_driver);

该dwc3_driver驱动注册成ko模式, 当该ko加载时, 内核会调用probe函数, 即dwc3_probe函数, 

驱动卸载时,  会调用dwc3_remove函数。

有点类和封装的味道...


dwc3_probe函数会去做某些初始化, 如dwc3_core_init_mode->dwc3_gadget_init, 并初始选一些gadget操作集。

3267 ›   dwc->gadget.ops››   ›   = &dwc3_gadget_ops;                                                                                                                    3268 ›   dwc->gadget.speed›  ›   = USB_SPEED_UNKNOWN;                                                                                                                   3269 ›   dwc->gadget.sg_supported›   = true;                                                                                                                            3270 ›   dwc->gadget.name›   ›   = "dwc3-gadget";                                                                                                                       3271 ›   dwc->gadget.is_otg› ›   = dwc->dr_mode == USB_DR_MODE_OTG;    2074 static const struct usb_gadget_ops dwc3_gadget_ops = {                                                                                                             2075 ›   .get_frame› ›   = dwc3_gadget_get_frame,                                                                                                                       2076 ›   .wakeup››   ›   = dwc3_gadget_wakeup,                                                                                                                          2077 ›   .set_selfpowered›   = dwc3_gadget_set_selfpowered,                                                                                                             2078 ›   .pullup››   ›   = dwc3_gadget_pullup,                                                                                                                          2079 ›   .udc_start› ›   = dwc3_gadget_start,                                                                                                                           2080 ›   .udc_stop›  ›   = dwc3_gadget_stop,                                                                                                                            2081 ›   .udc_set_speed› ›   = dwc3_gadget_set_speed,                                                                                                                   2082 };

ok, 此处dwc3_gadet_ops即为dwc3这个具体udc控制器的一些行为,  比如启动,  关闭, 上拉, 设置速度,  唤醒, 设置自供电模式, get_frame等。

而这些行为都是所有UDC控制器需要实现的功能, 即所有usb控制器抽象出来的一种行为。 故UDC算是父类, dwc3控制器算个具体的子类, 该子类封装了它的属性及行为。

我们看下udc_start行为的流程, 即udc core框架如何调用udc_start的。

一种usb composite复合设备的流程如下:

usb_gadget_probe_driver->udc_bind_to_driver->usb_gadget_udc_start->udc->gadget->ops->udc_start(udc->gadget, udc->driver); -> dwc3_gadget_start

1038 /**                                                                                                                                                                1039  * usb_gadget_udc_start - tells usb device controller to start up                                                                                                  1040  * @udc: The UDC to be started                                                                                                                                     1041  *                                                                                                                                                                 1042  * This call is issued by the UDC Class driver when it's about                                                                                                     1043  * to register a gadget driver to the device controller, before                                                                                                    1044  * calling gadget driver's bind() method.                                                                                                                          1045  *                                                                                                                                                                 1046  * It allows the controller to be powered off until strictly                                                                                                       1047  * necessary to have it powered on.                                                                                                                                1048  *                                                                                                                                                                 1049  * Returns zero on success, else negative errno.                                                                                                                   1050  */                                                                                                                                                                1051 static inline int usb_gadget_udc_start(struct usb_udc *udc)                                                                                                        1052 {                                                                                                                                                                  1053 ›   return udc->gadget->ops->udc_start(udc->gadget, udc->driver);                                                                                                  1054 }

看下udc_bind_to_driver函数, 

1317 static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)

参数分别为, udc指针和gadget_driver指针,  即绑定具体的udc控制器和当前的gadget驱动。

这里udc控制器是dwc3, gadget驱动就是具体的function驱动, 如g_zero, g_serial, g_dnl(fastboot)等等。

 


看下udc_bind_to_driver绑定的流程。

1352 int usb_gadget_probe_driver(struct usb_gadget_driver *driver)                                                                                                      1353 {                                                                                                                                                                  1354 ›   struct usb_udc› ›   *udc = NULL;                                                                                                                               1355 ›   int››   ›   ret = -ENODEV;                                                                                                                                     1356                                                                                                                                                                    1357 ›   if (!driver || !driver->bind || !driver->setup)                                                                                                                1358 ›   ›   return -EINVAL;                                                                                                                                            1359                                                                                                                                                                    1360 ›   mutex_lock(&udc_lock);                                                                                                                                         1361 ›   if (driver->udc_name) {                                                                                                                                        1362 ›   ›   list_for_each_entry(udc, &udc_list, list) {                                                                                                                1363 ›   ›   ›   ret = strcmp(driver->udc_name, dev_name(&udc->dev));                                                                                                   1364 ›   ›   ›   if (!ret)                                                                                                                                              1365 ›   ›   ›   ›   break;                                                                                                                                             1366 ›   ›   }                                                                                                                                                          1367 ›   ›   if (ret)                                                                                                                                                   1368 ›   ›   ›   ret = -ENODEV;                                                                                                                                         1369 ›   ›   else if (udc->driver)                                                                                                                                      1370 ›   ›   ›   ret = -EBUSY;                                                                                                                                          1371 ›   ›   else                                                                                                                                                       1372 ›   ›   ›   goto found;                                                                                                                                            1373 ›   } else {                                                                                                                                                       1374 ›   ›   list_for_each_entry(udc, &udc_list, list) {                                                                                                                1375 ›   ›   ›   /* For now we take the first one */                                                                                                                    1376 ›   ›   ›   if (!udc->driver)                                                                                                                                      1377 ›   ›   ›   ›   goto found;                                                                                                                                        1378 ›   ›   }                                                                                                                                                          1379 ›   }                                                                                                                                                              1380                                                                                                                                                                    1381 ›   if (!driver->match_existing_only) {                                                                                                                            1382 ›   ›   list_add_tail(&driver->pending, &gadget_driver_pending_list);                                                                                              1383 ›   ›   pr_info("udc-core: couldn't find an available UDC - added [%s] to list of pending drivers\n",                                                              1384 ›   ›   ›   driver->function);                                                                                                                                     1385 ›   ›   ret = 0;                                                                                                                                                   1386 ›   }                                                                                                                                                              1387                                                                                                                                                                    1388 ›   mutex_unlock(&udc_lock);                                                                                                                                       1389 ›   return ret;                                                                                                                                                    1390 found:                                                                                                                                                             1391 ›   ret = udc_bind_to_driver(udc, driver);                                                                                                                         1392 ›   mutex_unlock(&udc_lock);                                                                                                                                       1393 ›   return ret;                                                                                                                                                    1394 }                                                                                                                                                                  1395 EXPORT_SYMBOL_GPL(usb_gadget_probe_driver);

可以看到, 是遍历udc_list, 并根据名称进行匹配, 匹配到空闲的udc,  绑定该udc和驱动。(由于usb端点硬件资源的限制, 通常一个时间只能使能一种usb gadget驱动。 例如安卓手机, 同一时间只能选择MTP, PTP, ADB等其中一种。 所以对于想同时使用多种功能的需求, 需使用composite复合设备,  如g_multi那种多功能复合设备。)

 


继续看下什么时机调用该绑定的操作。

其中一种复合设备流程如下:

module_usb_composite_driver->usb_composite_probe->usb_gadget_probe_driver->udc_bind_to_driver

查看g_zero驱动(zero.c)

416 static struct usb_composite_driver zero_driver = {                                                                                                                  417 ›   .name›  ›   = "zero",                                                                                                                                           418 ›   .dev›   ›   = &device_desc,                                                                                                                                     419 ›   .strings›   = dev_strings,                                                                                                                                      420 ›   .max_speed› = USB_SPEED_SUPER,                                                                                                                                  421 ›   .bind›  ›   = zero_bind,                                                                                                                                        422 ›   .unbind››   = zero_unbind,                                                                                                                                      423 ›   .suspend›   = zero_suspend,                                                                                                                                     424 ›   .resume››   = zero_resume,                                                                                                                                      425 };                                                                                                                                                                  426                                                                                                                                                                     427 module_usb_composite_driver(zero_driver);

即ko加载的时机就是绑定的时机。

modprobe g_zero后,  内核就会绑定一个可用的udc控制器和g_zero驱动, 配置并开启udc控制器, 拉高相应D+/D- 引脚。使主机端能识别到usb设备插入, 并发起枚举。


关于系统udc控制器, 我们在代码中找下udc_list列表的维护。

可以找到相应的list_add_tail(&udc->list, &udc_list); 处。

调用顺序为:

usb_add_gadget_udc->usb_add_gadget_udc_release->list_add_tail(&udc->list, &udc_list); 

cscope搜索下usb_add_gadget_udc的调用。

Cscope tag: usb_add_gadget_udc                                                                                                                                             #   line  filename / context / line                                                                                                                                     1   1929  ./kernel-4.14/drivers/usb/chipidea/udc.c <
> retval = usb_add_gadget_udc(dev, &ci->gadget); 2 4724 ./kernel-4.14/drivers/usb/dwc2/gadget.c <
> ret = usb_add_gadget_udc(dev, &hsotg->gadget); 3 3298 ./kernel-4.14/drivers/usb/dwc3/gadget.c <
> ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget); 4 1943 ./kernel-4.14/drivers/usb/gadget/udc/at91_udc.c <
> retval = usb_add_gadget_udc(dev, &udc->gadget); 5 2380 ./kernel-4.14/drivers/usb/gadget/udc/atmel_usba_udc.c <
> ret = usb_add_gadget_udc(&pdev->dev, &udc->gadget); 6 2412 ./kernel-4.14/drivers/usb/gadget/udc/bcm63xx_udc.c <
> rc = usb_add_gadget_udc(dev, &udc->gadget); 7 552 ./kernel-4.14/drivers/usb/gadget/udc/bdc/bdc_udc.c <
> ret = usb_add_gadget_udc(bdc->dev, &bdc->gadget); 8 1078 ./kernel-4.14/drivers/usb/gadget/udc/dummy_hcd.c <
> rc = usb_add_gadget_udc(&pdev->dev, &dum->gadget); 9 1178 ./kernel-4.14/drivers/usb/gadget/udc/fotg210-udc.c <
> ret = usb_add_gadget_udc(&pdev->dev, &fotg210->gadget); 10 1478 ./kernel-4.14/drivers/usb/gadget/udc/fusb300_udc.c <
>

可以看到, 有很多具体的UDC控制器, 和该具体的产品及内核配置有关。 如果内部有集成dwc2, dwc3, chipidea等多种控制器, 你当然可以通过make menuconfig使能他们, 或者编译成ko, 加载具体的驱动模块。

 


综上, 用户可以于程序运行时选在加载的gadget驱动及控制器模块, 程序进项相应的绑定/匹配,  并最终能使用该驱动。

这就是一种多态的思想。。


ok, 摘录两篇lwn.net的文章, 后续继续学些。

转载地址:http://wpcrj.baihongyu.com/

你可能感兴趣的文章
hadoop3.0+spark2.0两台云服务器集群环境配置。
查看>>
网站实现qq登录(springboot后台)
查看>>
简单的用户头像修改功能(springboot后台)
查看>>
springboot+mybatis实现分页
查看>>
leetcode332. 重新安排行程
查看>>
为什么局域网网段不同不能通信?
查看>>
itchat微信助手,kaggle 电影数据集分析,基于内容的电影推荐
查看>>
认识和使用JWT
查看>>
通过springboot框架,自己动手实现oauth2.0授权码模式认证
查看>>
条件表达式于运算符的点点滴滴的积累
查看>>
最短路径最基本的三种算法【此后无良辰】
查看>>
class的点点滴滴的总结
查看>>
vector 的点点滴滴的总结
查看>>
测试用例
查看>>
自动化测试学习步骤
查看>>
自动化测试需要掌握的知识
查看>>
HTTP协议
查看>>
Python小程序——冒泡排序
查看>>
cmd中输入net start mysql 提示:服务名无效或者MySQL正在启动 MySQL无法启动
查看>>
LeetCode 206反转链表 [javsScript]
查看>>