目次
1 つの Linux 環境変数、デバイス ドライバー モデル 1. Linux デバイス ドライバー モデルの起源
まず、デバイスドライバーのコンパイルの通常のプロセスを確認してください
【1】エントリー関数 module_init() とモジュールアンロード関数 module_exit();を実装する
【2】デバイス番号の申請 register_chrdev();-----> (カーネル関連)
【3】udev/mdev機構を利用してデバイスファイルノードを作成する class_create(), device_create();------>(カーネル関連)
【4】ハードウェアの初期化: 1.io リソース マッピング ioremap()、カーネルは gpio ライブラリ関数を提供します。 2. 割り込みを登録します。 ------->(ハードウェア関連)
【5】file_operation構造体を構築する-------->(カーネル関連)
[6] ハードウェア操作メソッドの実装 xxx_open(), xxx_write()...
推論: プロセス全体の 4 番目の部分だけがハードウェアに関連しているわけではなく、残りの部分も同様の操作です (車輪の再発明なしで) デバイス ドライバーを便利にコンパイルし、労力を節約するために、デバイスを簡素化するデバイス ドライバー モデルが提案されています。ドライバーのコンパイルプロセス。
2. デバイスドライバーモデルフレームワーク
sysfs仮想ファイルシステムを通じてバスオブジェクトを表示できます(例としてUSB)
二Linuxドライバープログラミング、BUSバスモデルプログラミング
コンセプトマップ
1.バスオブジェクト
【1】structbus_type: バス オブジェクト Linux トレーニング機関。バスを記述し、デバイスとドライバーを管理します Linux ドライバー プログラミング、完全に一致します。
リーリー
【2】バスの登録とログアウト
リーリー
【3】バスを作ろう
リーリー
2.デバイスオブジェクト
【1】デバイスオブジェクト: アドレス、割り込み、その他のデータを含むデバイス情報を記述するデバイスオブジェクト
リーリー
【2】バスの登録とログアウト
リーリー
【3】デバイスオブジェクトの書き込み
定义一个描述设备的信息的结构体,匹配成功以后让driver对象在总线中领到device对象的信息,实现分离。
<span class="token macro property">#<span class="token directive keyword">include</span> <span class="token string"></span></span> <span class="token macro property">#<span class="token directive keyword">include</span> <span class="token string"></span></span> <span class="token macro property">#<span class="token directive keyword">include</span> <span class="token string"></span></span> <span class="token keyword">extern</span> <span class="token keyword">struct</span> bus_type mybus<span class="token punctuation">;</span> <span class="token keyword">struct</span> mydev_desc<span class="token punctuation">{</span> <span class="token keyword">char</span><span class="token operator">*</span> name<span class="token punctuation">;</span> <span class="token keyword">int</span> irqno<span class="token punctuation">;</span> <span class="token keyword">unsigned</span> <span class="token keyword">long</span> addr<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">struct</span> mydev_desc deviofo <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">"hqs"</span><span class="token punctuation">,</span> <span class="token punctuation">.</span>irqno <span class="token operator">=</span> <span class="token number">8877</span><span class="token punctuation">,</span> <span class="token punctuation">.</span>addr <span class="token operator">=</span> <span class="token number">0x12345678</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">void</span> <span class="token function">mydev_release</span><span class="token punctuation">(</span><span class="token keyword">struct</span> device<span class="token operator">*</span> dev<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"------%s---------n"</span><span class="token punctuation">,</span>__FUNCTION__<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//构建一个device对象</span> <span class="token keyword">struct</span> device mydev <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token punctuation">.</span>init_name <span class="token operator">=</span> <span class="token string">"fsdev_drv"</span><span class="token punctuation">,</span> <span class="token punctuation">.</span>bus <span class="token operator">=</span> <span class="token operator">&</span>mybus<span class="token punctuation">,</span> <span class="token punctuation">.</span>release <span class="token operator">=</span> mydev_release<span class="token punctuation">,</span> <span class="token punctuation">.</span>platform_data <span class="token operator">=</span> <span class="token operator">&</span>deviofo<span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">static</span> <span class="token keyword">int</span> __init <span class="token function">mydev_init</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"------%s---------n"</span><span class="token punctuation">,</span>__FUNCTION__<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">int</span> ret<span class="token punctuation">;</span> <span class="token comment">//将device注册到总线中</span> ret <span class="token operator">=</span> <span class="token function">device_register</span><span class="token punctuation">(</span><span class="token operator">&</span>mydev<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span><span class="token punctuation">(</span>ret <span class="token operator"><</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"device_register errorn"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> ret<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">static</span> <span class="token keyword">void</span> __exit <span class="token function">mydev_exit</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"------%s---------n"</span><span class="token punctuation">,</span>__FUNCTION__<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">device_unregister</span><span class="token punctuation">(</span><span class="token operator">&</span>mydev<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">module_init</span><span class="token punctuation">(</span>mydev_init<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">module_exit</span><span class="token punctuation">(</span>mydev_exit<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">MODULE_LICENSE</span><span class="token punctuation">(</span><span class="token string">"GPL"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
3.driver对象
【1】driver对象:描述设备驱动发的方式
<span class="token keyword">struct</span> device_driver <span class="token punctuation">{</span><span class="token comment">//只列举重要成员</span> <span class="token keyword">const</span> <span class="token keyword">char</span> <span class="token operator">*</span>name<span class="token punctuation">;</span><span class="token comment">//在/sys/bus/mybus/driver的名字,用于在总线中匹配</span> <span class="token keyword">struct</span> bus_type <span class="token operator">*</span>bus<span class="token punctuation">;</span><span class="token comment">//指向该device对象依附的总线对象</span> <span class="token keyword">int</span> <span class="token punctuation">(</span><span class="token operator">*</span>probe<span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token keyword">struct</span> device <span class="token operator">*</span>dev<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//device和driver匹配之后要做的事情</span> <span class="token keyword">int</span> <span class="token punctuation">(</span><span class="token operator">*</span>remove<span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token keyword">struct</span> device <span class="token operator">*</span>dev<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//device和driver分离之后要做的事情</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
【2】注册和注销总线
<span class="token keyword">int</span> <span class="token function">driver_register</span><span class="token punctuation">(</span><span class="token keyword">struct</span> device_driver <span class="token operator">*</span>drv<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">void</span> <span class="token function">driver_unregister</span><span class="token punctuation">(</span><span class="token keyword">struct</span> device_driver <span class="token operator">*</span>drv<span class="token punctuation">)</span><span class="token punctuation">;</span>
【3】编写driver对象
匹配成功以后可以在总线中领到device对象的数据,具体实现在probe函数里。
<span class="token macro property">#<span class="token directive keyword">include</span> <span class="token string"></span></span> <span class="token macro property">#<span class="token directive keyword">include</span> <span class="token string"></span></span> <span class="token macro property">#<span class="token directive keyword">include</span> <span class="token string"></span></span> <span class="token macro property">#<span class="token directive keyword">include</span> <span class="token string"></span></span> <span class="token keyword">extern</span> <span class="token keyword">struct</span> bus_type mybus<span class="token punctuation">;</span> <span class="token keyword">struct</span> mydev_desc<span class="token punctuation">{</span> <span class="token keyword">char</span><span class="token operator">*</span> name<span class="token punctuation">;</span> <span class="token keyword">int</span> irqno<span class="token punctuation">;</span> <span class="token keyword">unsigned</span> <span class="token keyword">long</span> addr<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">struct</span> mydev_desc<span class="token operator">*</span> pdesc<span class="token punctuation">;</span> <span class="token keyword">int</span> <span class="token function">mydrv_probe</span><span class="token punctuation">(</span><span class="token keyword">struct</span> device <span class="token operator">*</span>dev<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"------%s---------n"</span><span class="token punctuation">,</span>__FUNCTION__<span class="token punctuation">)</span><span class="token punctuation">;</span> pdesc <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">struct</span> mydev_desc<span class="token operator">*</span><span class="token punctuation">)</span>dev<span class="token operator">-></span>platform_data<span class="token punctuation">;</span> <span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"name =%sn"</span><span class="token punctuation">,</span>pdesc<span class="token operator">-></span>name<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"irqno = %dn"</span><span class="token punctuation">,</span>pdesc<span class="token operator">-></span>irqno<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">unsigned</span> <span class="token keyword">long</span> <span class="token operator">*</span> paddr <span class="token operator">=</span> <span class="token function">ioremap</span><span class="token punctuation">(</span>pdesc<span class="token operator">-></span>addr<span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">int</span> mydrv_remove <span class="token punctuation">(</span><span class="token keyword">struct</span> device <span class="token operator">*</span>dev<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"------%s---------n"</span><span class="token punctuation">,</span>__FUNCTION__<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//构建一个driver对象</span> <span class="token keyword">struct</span> device_driver mydrv <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">"fsdev_drv"</span><span class="token punctuation">,</span> <span class="token punctuation">.</span>bus <span class="token operator">=</span> <span class="token operator">&</span>mybus<span class="token punctuation">,</span> <span class="token punctuation">.</span>probe <span class="token operator">=</span> mydrv_probe<span class="token punctuation">,</span> <span class="token punctuation">.</span>remove <span class="token operator">=</span> mydrv_remove<span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">static</span> <span class="token keyword">int</span> __init <span class="token function">mydrv_init</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"------%s---------n"</span><span class="token punctuation">,</span>__FUNCTION__<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">int</span> ret<span class="token punctuation">;</span> <span class="token comment">//将device注册到总线中</span> ret <span class="token operator">=</span> <span class="token function">driver_register</span><span class="token punctuation">(</span><span class="token operator">&</span>mydrv<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span><span class="token punctuation">(</span>ret <span class="token operator"><</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"driver_register errorn"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> ret<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">static</span> <span class="token keyword">void</span> __exit <span class="token function">mydrv_exit</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"------%s---------n"</span><span class="token punctuation">,</span>__FUNCTION__<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">driver_unregister</span><span class="token punctuation">(</span><span class="token operator">&</span>mydrv<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">module_init</span><span class="token punctuation">(</span>mydrv_init<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">module_exit</span><span class="token punctuation">(</span>mydrv_exit<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">MODULE_LICENSE</span><span class="token punctuation">(</span><span class="token string">"GPL"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
4.device对象和driver对象匹配
【1】实现BUS对象中的match方式(按device对象的名子和driver对象中的名子相匹配)
要注意的是不能直接用device对象中的init_name,而要用device对象中继承的structkobjectkobj;上面的成员name不然会报错
<span class="token keyword">int</span> <span class="token function">mybus_match</span><span class="token punctuation">(</span><span class="token keyword">struct</span> device <span class="token operator">*</span>dev<span class="token punctuation">,</span> <span class="token keyword">struct</span> device_driver <span class="token operator">*</span>drv<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//如果匹配成功,match方法一定要返回一个1,失败返回0</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span> <span class="token function">strncmp</span><span class="token punctuation">(</span>drv<span class="token operator">-></span>name<span class="token punctuation">,</span>dev<span class="token operator">-></span>kobj<span class="token punctuation">.</span>name<span class="token punctuation">,</span><span class="token function">strlen</span><span class="token punctuation">(</span>drv<span class="token operator">-></span>name<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"match okn"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token number">1</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token function">printk</span><span class="token punctuation">(</span><span class="token string">"match failedn"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//实例化一个bus对象</span> <span class="token keyword">struct</span> bus_type mybus <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">"mybus"</span><span class="token punctuation">,</span> <span class="token punctuation">.</span>match <span class="token operator">=</span> mybus_match<span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
【2】保证device对象和driver对象的名子一样:例如这儿都使用"fsdev_drv"才能保证能匹配成功
<span class="token comment">//构建一个device对象</span> <span class="token keyword">struct</span> device mydev <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token punctuation">.</span>init_name <span class="token operator">=</span> <span class="token string">"fsdev_drv"</span><span class="token punctuation">,</span> <span class="token punctuation">.</span>bus <span class="token operator">=</span> <span class="token operator">&</span>mybus<span class="token punctuation">,</span> <span class="token punctuation">.</span>release <span class="token operator">=</span> mydev_release<span class="token punctuation">,</span> <span class="token punctuation">.</span>platform_data <span class="token operator">=</span> <span class="token operator">&</span>deviofo<span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token comment">//构建一个driver对象</span> <span class="token keyword">struct</span> device_driver mydrv <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">"fsdev_drv"</span><span class="token punctuation">,</span> <span class="token punctuation">.</span>bus <span class="token operator">=</span> <span class="token operator">&</span>mybus<span class="token punctuation">,</span> <span class="token punctuation">.</span>probe <span class="token operator">=</span> mydrv_probe<span class="token punctuation">,</span> <span class="token punctuation">.</span>remove <span class="token operator">=</span> mydrv_remove<span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
以上がLinuxデバイスドライバーモデルの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。