Nouveau源码分析(二):Nouveau结构体的基本框架

本文介绍了Nouveau驱动中如何通过C语言模拟面向对象特性,包括继承和虚拟函数的概念,以此来管理复杂的GPU设备,并提供了具体的代码示例。

Nouveau源码分析(二)

在讨论Nouveau对Nvidia设备的初始化前,我准备先说一下Nouveau结构体的基本框架

Nouveau的很多结构体都可以看作是C++中的类,之间有很多相似的东西,比如继承关系,virtual成员函数等.

模拟继承

先尝试阅读一下这个代码:

  1. #include <stdlib.h>  
  2.   
  3. struct abc  
  4. {  
  5.    int a;  
  6.    int b;  
  7.    int c;  
  8. };  
  9.   
  10. struct def  
  11. {  
  12.    struct abc base;  
  13.    int d;  
  14.    int e;  
  15.    int f;  
  16. };  
  17.   
  18. #define abc_create(a,b,c,pabc) \  
  19.    abc_create_(a,b,c,sizeof(**pabc),(void **)pabc)  
  20.   
  21. int abc_create_(int a,int b,int c,  
  22.                  size_t size,void **pabc)  
  23. {  
  24.    struct abc *abc_ = (struct abc *)malloc(size); //按传入的size分配空间  
  25.   
  26.    abc_->a = a;  
  27.    abc_->b = b;  
  28.    abc_->c = c; //初始化自身  
  29.   
  30.    *pabc = abc_;  
  31.    return 0;  
  32. }  
  33.   
  34. #define def_create(a,b,c,d,e,f,pdef) \  
  35.    def_create_(a,b,c,d,e,f,sizeof(**pdef),(void **)pdef) //获得实际应分配空间大小  
  36.   
  37. int def_create_(int a,int b,int c,int d,int e,int f,  
  38.                  size_t size,void **pdef)  
  39. {  
  40.    struct def *def_;  
  41.    abc_create_(a,b,c,size,pdef); //先初始化基类  
  42.    def_ = (struct def *)*pdef;  
  43.   
  44.    def_->d = d;  
  45.    def_->e = e; //然后初始化自身  
  46.    def_->f = f;  
  47.    return 0;  
  48. }  
  49.   
  50. int main(void)  
  51. {  
  52.     struct def *d;  
  53.     def_create(1,2,3,4,5,6,&d);  
  54.     return 0;  
  55. }  
Nouveau中大部分的结构体都是这种模式的,模拟C++的继承关系

当然一般还会有配套使用的宏,比如这个例子中可以有:

  1. #define nv_abc(a) ((struct abc *)a)  
  2.   
  3. //使用方法:  
  4.   
  5. struct def *b;  
  6. //初始化b,做一些事情  
  7. nv_abc(b)->a = 7;  


[注意:实际在nouveau代码中,还有一种关系是parent关系,这和此处讨论的继承关系无关]

模拟virtual函数

改造一下上面写的程序,改成这样:

  1. #include <stdlib.h>  
  2. #include <stdio.h>  
  3.   
  4. struct oclass  
  5. {  
  6.     int (*test)(int); //类的test函数  
  7. };  
  8.   
  9. /****************abc****************/  
  10. struct abc  
  11. {  
  12.    struct oclass *oclass;  
  13.    int a;  
  14.    int b;  
  15.    int c;  
  16. };  
  17.   
  18. int abc_test(int a)  
  19. {  
  20.     return a * a;  
  21. }  
  22.   
  23. struct oclass abc_oclass = {abc_test}; //abc的test函数  
  24.   
  25. #define nv_abc(a) ((struct abc *)a)  
  26.   
  27. #define abc_create(a,b,c,pabc) \  
  28.    abc_create_(&abc_oclass, \  
  29.        a,b,c,sizeof(**pabc),(void **)pabc)  
  30.   
  31. int abc_create_(struct oclass *oclass,int a,int b,int c,  
  32.                  size_t size,void **pabc)  
  33. {  
  34.    struct abc *abc_ = (struct abc *)malloc(size);  
  35.   
  36.    abc_->a = a;  
  37.    abc_->b = b;  
  38.    abc_->c = c;  
  39.    abc_->oclass = oclass;  
  40.   
  41.    *pabc = abc_;  
  42.    return 0;  
  43. }  
  44.   
  45. /****************def****************/  
  46. struct def  
  47. {  
  48.    struct abc base;  
  49.    int d;  
  50.    int e;  
  51.    int f;  
  52. };  
  53.   
  54.   
  55. int def_test(int a)  
  56. {  
  57.     return a;  
  58. }  
  59.   
  60. struct oclass def_oclass = {def_test}; //def的test函数  
  61.   
  62. #define nv_def(a) ((struct def *)a)  
  63.   
  64. #define def_create(a,b,c,d,e,f,pdef) \  
  65.    def_create_(a,b,c,d,e,f,sizeof(**pdef),(void **)pdef)  
  66.   
  67. int def_create_(int a,int b,int c,int d,int e,int f,  
  68.                  size_t size,void **pdef)  
  69. {  
  70.    struct def *def_;  
  71.    abc_create_(&def_oclass,a,b,c,size,pdef);  
  72.    def_ = (struct def *)*pdef;  
  73.   
  74.    def_->d = d;  
  75.    def_->e = e;  
  76.    def_->f = f;  
  77.    return 0;  
  78. }  
  79.   
  80. int main(void)  
  81. {  
  82.     struct def *d;  
  83.     struct abc *a;  
  84.     def_create(1,2,3,4,5,6,&d);  
  85.     abc_create(1,2,3,&a);  
  86.   
  87.     printf("%d %d\n",nv_abc(d)->oclass->test(3),  
  88.                      nv_abc(a)->oclass->test(3)); //尝试执行  
  89.     return 0;  
  90. }  

利用这个,就可以用同一个接口nouveau_object,实现对很多不同设备模块的访问

使用标识符获得oclass

还有一种情况,传递参数时传递的是"u32 oclass",而不是"struct nouveau_oclass *oclass",这种情况就要依照parent向上搜索,得到具体的oclass

此处不展开讨论,等看到那部分代码再详细说明

### Nouveau DRM Driver Issue on GPU 0000:01:00.0 Solution For addressing the Nouveau DRM driver issue specifically with the GPU identified as `0000:01:00.0`, several strategies can be employed based on previous experiences and solutions found within similar contexts. #### Disabling Kernel Mode Setting Temporarily During Boot To temporarily disable kernel mode setting (KMS), which is often responsible for display issues related to the Nouveau driver, one should add a boot parameter when starting up the system. This involves accessing the GRUB menu by pressing Shift during startup or using Ctrl+Alt+F1-F6 keys depending upon the setup[^2]. Once at the GRUB screen: - Navigate to the line that begins with 'linux' or 'linux16'. - Add `nomodeset` after any existing parameters like `quiet splash`. - Press F10 or Ctrl+X to continue booting into the operating system with these temporary changes applied. This method allows bypassing potential graphical glitches caused by KMS until more permanent fixes are implemented. #### Permanently Adjusting Grub Configuration File Permanently altering how the system handles graphics drivers requires editing `/etc/default/grub`. By modifying this configuration file, it's possible to ensure that every time the machine boots, certain settings take effect automatically without manual intervention each reboot. ```bash sudo nano /etc/default/grub ``` Within this text editor session, locate the line containing `GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"` and append `nomodeset` so it reads something akin to `"quiet splash nomodeset"`. After saving modifications (`Ctrl+O`) and exiting (`Ctrl+X`): ```bash sudo update-grub ``` Executing this command updates all necessary files ensuring new configurations will apply from next boot onwards[^4]. #### Preventing Nouveau Module Loading via Blacklisting Another approach entails preventing Linux from loading the problematic Nouveau module altogether through blacklisting techniques. Editing another critical configuration file achieves this goal effectively while allowing alternative proprietary NVIDIA drivers installation later if desired. ```bash echo "blacklist nouveau" | sudo tee -a /etc/modprobe.d/blacklist.conf echo "options nouveau modeset=0" | sudo tee -a /etc/modprobe.d/nouveau-kms-off.conf ``` After applying such commands, regenerate initramfs images to incorporate recent alterations before restarting your computer normally. ```bash sudo update-initramfs -u ``` These actions collectively contribute towards mitigating common challenges associated with incompatible open-source graphic card drivers under various distributions of GNU/Linux systems including Debian-based ones where Nouveau conflicts arise frequently due to hardware incompatibilities[^3]. --related questions-- 1. What other methods exist besides disabling KMS for troubleshooting display problems? 2. How does adding `nomodeset` impact overall performance compared to default behavior? 3. Can installing proprietary NVIDIA drivers resolve ongoing issues better than tweaking Nouveau options? 4. Is there an optimal way to switch between different video drivers seamlessly post-installation?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值