在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

電子發(fā)燒友App

硬聲App

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示
創(chuàng)作
電子發(fā)燒友網(wǎng)>電子資料下載>嵌入式開發(fā)>module 概述以及如何寫一個(gè)module

module 概述以及如何寫一個(gè)module

2017-11-07 | rar | 0.3 MB | 次下載 | 1積分

資料介紹

 不知道在什幺時(shí)候,Linux 出現(xiàn)了 module 這種東西,的確,它是 Linux 的一大革新。有了 module 之后,寫 device driver 不再是一項(xiàng)惡夢(mèng),修改 kernel 也不再是一件痛苦的事了。因?yàn)槟悴恍枰看我獪y(cè)試 driver 就重新 compile kernel 一次。那簡直是會(huì)累死人。Module 可以允許我們動(dòng)態(tài)的改變 kernel,加載 device driver,而且它也能縮短我們 driver development 的時(shí)間。在這篇文章里,我將要跟各位介紹一下 module 的原理,以及如何寫一個(gè) module。
  module 翻譯成中文就是模塊,不過,事實(shí)上去翻譯這個(gè)字一點(diǎn)都沒意義。在講模塊之前,我先舉一個(gè)例子。相信很多人都用過 RedHat。在 RedHat 里,我們可以執(zhí)行 sndconfig,它可以幫我們 config 聲卡。config 完之后如果捉得到你的聲卡,那你的聲卡馬上就可以動(dòng)了,而且還不用重新激活計(jì)算機(jī)。這是怎幺做的呢 ? 就是靠module。module 其實(shí)是一般的程序。但是它可以被動(dòng)態(tài)載到 kernel 里成為 kernel的一部分。載到 kernel 里的 module 它具有跟 kernel 一樣的權(quán)力。可以 access 任何 kernel 的 data structure。你聽過 kdebug 嗎 ? 它是用來 debug kernel 的。它就是先將它本身的一個(gè) module 載到 kernel 里,而在 user space 的 gdb 就可以經(jīng)由跟這個(gè) module 溝通,得知 kernel 里的 data structure 的值,除此之外,還可以經(jīng)由載到 kernel 的 module 去更改 kernel 里 data structure。
  我們知道,在寫 C 程序的時(shí)候,一個(gè)程序只能有一個(gè) main。Kernel 本身其實(shí)也是一個(gè)程序,它本身也有個(gè) main,叫 start_kernel()。當(dāng)我們把一個(gè) module 載到 kernel 里的時(shí)候,它會(huì)跟 kernel 整合在一起,成為 kernel 的一部分。請(qǐng)各位想想,那 module 可以有 main 嗎 ? 答案很明顯的,是 No。理由很簡單。一個(gè)程序只能有一個(gè) main。在使用 module 時(shí),有一點(diǎn)要記住的是 module 是處于被動(dòng)的角色。它是提供某些功能讓別人去使用的。
  Kernel 里有一個(gè)變量叫 module_list,每當(dāng) user 將一個(gè) module 載到 kernel 里的時(shí)候,這個(gè) module 就會(huì)被記錄在 module_list 里面。當(dāng) kernel 要使用到這個(gè) module 提供的 function 時(shí),它就會(huì)去 search 這個(gè) list,找到 module,然后再使用其提供的 function 或 variable。每一個(gè) module 都可以 export 一些 function 或變量來讓別人使用。除此之外,module 也可以使用已經(jīng)載到 kernel 里的 module 提供的 function。這種情形叫做 module stack。比方說,module A 用到 module B 的東西,那在加載 module A 之前必須要先加載 module B。否則 module A 會(huì)無法加載。除了 module 會(huì) export 東西之外,kernel 本身也會(huì) export 一些 function 或 variable。同樣的,module 也可以使用 kernel 所 export 出來的東西。由于大家平時(shí)都是撰寫 user space 的程序,所以,當(dāng)突然去寫 module 的時(shí)候,會(huì)把平時(shí)寫程序用的 function 拿到 module 里使用。像是 printf 之類的東西。我要告訴各位的是,module 所使用的 function 或 variable,要嘛就是自己寫在 module 里,要嘛就是別的 module 提供的,再不就是 kernel 所提供的。你不能使用一般 libc 或 glibc所提供的 function。像 printf 之類的東西。這一點(diǎn)可能是各位要多小心的地方。(也許你可以先 link 好,再載到 kernel,我好象試過,但是忘了)
  剛才我們說到 kernel 本身會(huì) export 出一些 function 或 variable 來讓 module 使用,但是,我們不是萬能的,我們?cè)蹒壑?kernel 有開放那里東西讓我們使用呢 ? Linux 提供一個(gè) command,叫 ksyms,你只要執(zhí)行 ksyms -a 就可以知道 kernel 或目前載到 kernel 里的 module 提供了那些 function 或 variable。底下是我的系統(tǒng)的情形:
  c0216ba0 drive_info_R744aa133
  c01e4a44 boot_cpu_data_R660bd466
  c01e4ac0 EISA_bus_R7413793a
  c01e4ac4 MCA_bus_Rf48a2c4c
  c010cc34 __verify_write_R203afbeb
  。 . 。 . 。
  在 kernel 里,有一個(gè) symbol table 是用來記錄 export 出去的 function 或 variable。除此之外,也會(huì)記錄著那個(gè) module export 那些 function。上面幾行中,表示 kernel 提供了 drive_info 這個(gè) function/variable。所以,我們可以在 kernel 里直接使用它,等載到 kernel 里時(shí),會(huì)自動(dòng)做好 link 的動(dòng)作。由此,我們可以知道,module 本身其實(shí)是還沒做 link 的一些 object code。一切都要等到 module 被加載 kernel 之后,link 才會(huì)完成。各位應(yīng)該可以看到 drive_info 后面還接著一些奇怪的字符串。_R744aa133,這個(gè)字符串是根據(jù)目前 kernel 的版本再做些 encode 得出來的結(jié)果。為什幺額外需要這一個(gè)字符串呢 ?
  Linux 不知道從那個(gè)版本以來,就多了一個(gè) config 的選項(xiàng),叫做 Set version number in symbols of module。這是為了避免對(duì)系統(tǒng)造成不穩(wěn)定。我們知道 Linux 的 kernel 更新的很快。在 kernel 更新的過程,有時(shí)為了效率起見,會(huì)對(duì)某些舊有的 data structure 或 function 做些改變,而且一變可能有的 variable 被拿掉,有的 function 的 prototype 跟原來的都不太一樣。如果這種情形發(fā)生的時(shí)候,那可能以前 2.0.33 版本的 module 拿到 2.2.1 版本的 kernel 使用,假設(shè)原來 module 使用了 2.0.33 kernel 提供的變量叫 A,但是到了 2.2.1 由于某些原因必須把 A 都設(shè)成 NULL。那當(dāng)此 module 用在 2.2.1 kernel 上時(shí),如果它沒去檢查 A 的值就直接使用的話,就會(huì)造成系統(tǒng)的錯(cuò)誤。也許不會(huì)整個(gè)系統(tǒng)都死掉,但是這個(gè) module 肯定是很難發(fā)揮它的功能。為了這個(gè)原因,Linux 就在 compile module 時(shí),把 kernel 版本的號(hào)碼 encode 到各個(gè) exported function 和 variable 里。
  所以,剛才也許我們不應(yīng)該講 kernel 提供了 drive_info,而應(yīng)該說 kernel 提供了 driver_info_R744aa133 來讓我們使用。這樣也許各位會(huì)比較明白。也就是說,kernel 認(rèn)為它提供的 driver_info_R744aa133 這個(gè)東西,而不是 driver_info。所以,我們可以發(fā)現(xiàn)有的人在加載 module 時(shí),系統(tǒng)都一直告訴你某個(gè) function 無法 resolved。這就是因?yàn)?kernel 里沒有你要的 function,要不然就是你的 module 里使用的 function 跟 kernel encode 的結(jié)果不一樣。所以無法 resolve。解決方式,要嘛就是將 kernel 里的 set version 選項(xiàng)關(guān)掉,要嘛就是將 module compile 成 kernel 有辦法接受的型式。
  那有人就會(huì)想說,如果 kernel 認(rèn)定它提供的 function 名字叫做 driver_info_R744aa133 的話,那我們寫程序時(shí),是不是用到這個(gè) funnction 的地方都改成 driver_info_R744aa133 就可以了。答案是 Yes。但是,如果每個(gè) function 都要你這樣寫,你不會(huì)覺得很煩嗎 ? 比方說,我們?cè)趯?driver 時(shí),很多人都會(huì)用到 printk 這個(gè) function。這是 kernel 所提供的 function。它的功能跟 printf 很像。用法也幾乎都一樣。是 debug 時(shí)很好用的東西。如果我們 module 里用了一百次 printk,那是不是我們也要打一百次的 printk_Rdd132261 呢 ? 當(dāng)然不是,聰明的人馬上會(huì)想到用 #define printk printk_Rdd132261 就好了嘛。所以啰,Linux 很體貼的幫我們做了這件事。
  如果各位的系統(tǒng)有將 set version 的選項(xiàng)打開的話,那大家可以到 /usr/src/linux/include/linux/modules 這個(gè)目錄底下。這個(gè)目錄底下有所多的 。.ver檔案。這些檔案其實(shí)就是用來做 #define 用的。我們來看看 ksyms.ver 這個(gè)檔案里,里面有一行是這樣子的 :
  #define printk _set_ver(printk)
  set_ver 是一個(gè) macro,就是用來在 printk 后面加上 version number 的。有興趣的朋友可以自行去觀看這個(gè) macro 的寫法。用了這些 ver 檔,我們就可以在 module 里直接使用 printk 這樣的名字了。而這些 ver 檔會(huì)自動(dòng)幫我們做好 #define 的動(dòng)作。可是,我們可以發(fā)現(xiàn)這個(gè)目錄有很多很多的 ver 檔。有時(shí)候,我們?cè)蹒壑牢覀円艚械?function 是在那個(gè) ver 檔里有定義呢 ? Linux 又幫我們做了一件事。/usr/src/linux/include/linux/modversions.h 這個(gè)檔案已經(jīng)將全部的 ver 檔都加進(jìn)來了。所以在我們的 module 里只要 include 這個(gè)檔,那名字的問題都解決了。但是,在此,我們奉勸各位一件事,不要將 modversions.h 這個(gè)檔在 module 里 include 進(jìn)來,如果真的要,那也要加上以下數(shù)行:
  #ifdef MODVERSIONS
  #include 《linux/modversions.h》;
  #endif
  加入這三行的原因是,避免這個(gè) module 在沒有設(shè)定 kernel version 的系統(tǒng)上,將 modversions.h 這個(gè)檔案 include 進(jìn)來。各位可以去試試看,當(dāng)你把 set version 的選項(xiàng)關(guān)掉時(shí),modversions.h 和 modules 這個(gè)目錄都會(huì)不見。如果沒有上面三行,那 compile 就不會(huì)過關(guān)。所以一般來講,modversions.h 我們會(huì)選擇在 compile 時(shí)傳給 gcc 使用。就像下面這個(gè)樣子。
  gcc -c -D__KERNEL__ -DMODULE -DMODVERSIONS main.c
  -include usr/src/linux/include/linux/modversions.h
  在這個(gè) command line 里,我們看到了 -D__KERNEL__,這是說要定義 __KERNEL__ 這個(gè) constant。很多跟 kernel 有關(guān)的 header file,都必須要定義這個(gè) constant 才能 include 的。所以建議你最好將它定義起來。另外還有一個(gè) -DMODVERSIONS。這個(gè) constant 我剛才忘了講。剛才我們說要解決 fucntion 或 variable 名字 encode 的方式就是要 include modversions.h,其實(shí)除此之外,你還必須定義 MODVERSIONS 這個(gè) constant。再來就是 MODULE 這個(gè) constant。其實(shí),只要是你要寫 module 就一定要定義這個(gè)變量。而且你還要 include module.h 這個(gè)檔案,因?yàn)?_set_ver 就是定義在這里的。
  講到這里,相信各位應(yīng)該對(duì) module 有一些認(rèn)識(shí)了,以后遇到 module unresolved 應(yīng)該不會(huì)感到困惑了,應(yīng)該也有辦法解決了。
  剛才講的都是使用別人的 function 上遇到的名字 encode 問題。但是,如果我們自己的 module 想要 export 一些東西讓別的 module 使用呢。很簡單。在 default 上,在你的 module 里所有的 global variable 和 function 都會(huì)被認(rèn)定為你要 export 出去的。所以,如果你的 module 里有 10 個(gè) global variable,經(jīng)由 ksyms,你可以發(fā)現(xiàn)這十個(gè) variable 都會(huì)被 export 出去。這當(dāng)然是個(gè)很方便的事啦,但是,你知道,有時(shí)候我們根本不想把所有的 variable 都 export 出去,萬一有個(gè) module 沒事亂改我們的 variable 怎幺辦呢 ? 所以,在很多時(shí)候,我們都只會(huì)限定幾個(gè)必要的東西 export 出去。在 2.2.1 之前的 kernel (不是很確定) 可以利用 register_symtab 來幫我們。但是,現(xiàn)在更新的版本早就出來了。所以,在此,我會(huì)介紹 kernel 2.2.1 里所提供的。kernel 2.2.1 里提供了一個(gè) macro,叫做 EXPORT_SYMBOL,這是用來幫我們選擇要 export 的 variable 或 function。比方說,我要 export 一個(gè)叫 full 的 variable,那我只要在 module 里寫:
  EXPORT_SYMBOL(full);
下載該資料的人也在下載 下載該資料的人還在閱讀
更多 >

評(píng)論

查看更多

下載排行

本周

  1. 1TC358743XBG評(píng)估板參考手冊(cè)
  2. 1.36 MB  |  330次下載  |  免費(fèi)
  3. 2開關(guān)電源基礎(chǔ)知識(shí)
  4. 5.73 MB  |  6次下載  |  免費(fèi)
  5. 3100W短波放大電路圖
  6. 0.05 MB  |  4次下載  |  3 積分
  7. 4嵌入式linux-聊天程序設(shè)計(jì)
  8. 0.60 MB  |  3次下載  |  免費(fèi)
  9. 5基于FPGA的光纖通信系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)
  10. 0.61 MB  |  2次下載  |  免費(fèi)
  11. 6基于FPGA的C8051F單片機(jī)開發(fā)板設(shè)計(jì)
  12. 0.70 MB  |  2次下載  |  免費(fèi)
  13. 751單片機(jī)窗簾控制器仿真程序
  14. 1.93 MB  |  2次下載  |  免費(fèi)
  15. 8基于51單片機(jī)的RGB調(diào)色燈程序仿真
  16. 0.86 MB  |  2次下載  |  免費(fèi)

本月

  1. 1OrCAD10.5下載OrCAD10.5中文版軟件
  2. 0.00 MB  |  234315次下載  |  免費(fèi)
  3. 2555集成電路應(yīng)用800例(新編版)
  4. 0.00 MB  |  33564次下載  |  免費(fèi)
  5. 3接口電路圖大全
  6. 未知  |  30323次下載  |  免費(fèi)
  7. 4開關(guān)電源設(shè)計(jì)實(shí)例指南
  8. 未知  |  21548次下載  |  免費(fèi)
  9. 5電氣工程師手冊(cè)免費(fèi)下載(新編第二版pdf電子書)
  10. 0.00 MB  |  15349次下載  |  免費(fèi)
  11. 6數(shù)字電路基礎(chǔ)pdf(下載)
  12. 未知  |  13750次下載  |  免費(fèi)
  13. 7電子制作實(shí)例集錦 下載
  14. 未知  |  8113次下載  |  免費(fèi)
  15. 8《LED驅(qū)動(dòng)電路設(shè)計(jì)》 溫德爾著
  16. 0.00 MB  |  6653次下載  |  免費(fèi)

總榜

  1. 1matlab軟件下載入口
  2. 未知  |  935054次下載  |  免費(fèi)
  3. 2protel99se軟件下載(可英文版轉(zhuǎn)中文版)
  4. 78.1 MB  |  537796次下載  |  免費(fèi)
  5. 3MATLAB 7.1 下載 (含軟件介紹)
  6. 未知  |  420026次下載  |  免費(fèi)
  7. 4OrCAD10.5下載OrCAD10.5中文版軟件
  8. 0.00 MB  |  234315次下載  |  免費(fèi)
  9. 5Altium DXP2002下載入口
  10. 未知  |  233046次下載  |  免費(fèi)
  11. 6電路仿真軟件multisim 10.0免費(fèi)下載
  12. 340992  |  191185次下載  |  免費(fèi)
  13. 7十天學(xué)會(huì)AVR單片機(jī)與C語言視頻教程 下載
  14. 158M  |  183278次下載  |  免費(fèi)
  15. 8proe5.0野火版下載(中文版免費(fèi)下載)
  16. 未知  |  138040次下載  |  免費(fèi)
主站蜘蛛池模板: 手机在线你懂的 | 天天干天天添 | 777色狠狠一区二区三区香蕉 | 五月天婷婷丁香中文在线观看 | 日本视频一区二区三区 | 久久久久999 | 手机在线电影你懂的 | 全免费a级毛片免费看不卡 全日本爽视频在线 | 日韩精品一卡二卡三卡四卡2021 | 干夜夜| 色综合天天综久久久噜噜噜久久〔 | 久青草国产手机视频免费观看 | 免费在线观看一区二区 | 美女被免费网站91色 | 黄色小视频日本 | 国产精品久久久福利 | 国产伦精品一区二区三区 | 亚洲午夜精品在线 | 黄色午夜网站 | www.一区二区三区.com | 欧美大黄| 亚洲 图片 小说 欧美 另类 | 欧美美女一区二区三区 | 怡红院精品视频 | a免费网站 | 国产一区二区影院 | 丁香婷婷电影 | 五月天久久婷婷 | 久久51| 99久免费精品视频在线观看2 | 色天天综合久久久久综合片 | 五月天婷婷视频在线观看 | 99成人在线| 亚洲精品播放 | 久久综合亚洲 | 激情三级视频 | 91三级在线 | videofreeones性欧美另类 | 乱h亲女小说| 黄色生活毛片 | 欧美尺寸又黑又粗又长 |