2012年3月28日 星期三

Linux驅動程式--chapter 5

這章的重點是concurrency的問題,介紹的工具是semaphore、mutexes、spinlock、atomic operations、seqlock、Read-Copy-Update(RCU)
基本上快都是作業系統(OS)介紹過的東西,如果上過這個課程,對這些東西應該不陌生。雖然很想這樣結束,但是我要說,書中介紹的原則往往比教科書來的多,也來的更貼近實際狀況;另外也讓我體驗到driver有時候設計真的充滿了trade off

一般而言,我們希望使用semaphore因為會比spinlock容易(因為高階),但是spinlock會比較有效率,但是spinlock又可能引起沒效率,這種弔詭的說法有舉例

一般而言,spinlock使用的時候會取消cpu preemption的功能,希望目前的task趕緊完成工作,儘快釋放lock,很不幸很多function call會引發目前的工作釋放cpu,比方說kmalloc,而且沒有完整的列表。其次中斷也會引發目前task帶著lock且釋放出cpu,這時候可能會有很不幸的事情發生,那就是如果該中斷要求同一個spinlock,這就好玩了,他會因為拿不到,重新觸發,然後就一直浪費cpu的時間在等待task釋放cpu,但是可能又因為cpu preemption功能被關閉,本來的task進不到cpu產生了dead lock,如果不會dead lock也有可能cpu空轉上好一段時間。這也是為何說spin lock可能引起效率低落的原因。

作者給spin lock幾個建議:

  • 使用spin lock不要有cpu preemption,這點kernel會處理,不至於太擔心
  • 使用spin lock不要讓task sleep,要非常小心,因為如上所說function call & interrupt
  • 使用spin lock要儘快釋放,免得schedule的功能"失去作用",因為spin lock取走了大部分cpu時間

對於種種同步的建議是:

  • 儘量事前規劃好,省得事後debug很困難
  • 對於鎖定的資源依序取得,可以避免一些dead lock的可能性
  • 不要呼叫交互取得lock或者資源的function,這樣也很容易dead lock


atomic operation則適用於int以及bit運算,因為有時候我們希望有些簡單但是重要的count功能或者加減的功能是使用atomic operations,但是有點要認知到,就是運算的串聯次序本身並沒有被保證,也就是兩個以上task執行了各十個atomic operations,你並不能知道他們之間的次序是如何排列的。
至於詳細的API使用方式,可以參考書本

2012年3月27日 星期二

Linux驅動程式--chapter 4

這一章已經超過了單純driver,還包含到了kerenel debug的技巧,首先介紹一些在kernel hacking裡面的選項,為了debug有時候是必須打開的,接著介紹不同的技巧以及他們應用的時機
printk() : 最簡單最直接的一種,大致上分成八個level只有當設定的訊息的level小於console_loglevel的時候,訊息才會直接被送到console,作者還介紹了一個小工具程式,讓我們可以設定輸出的console。接著printk的問題就是如果在code裡面埋了一堆debugger information,要如何在編譯階段可以清理掉,作者定義了幾個macro來處理這件事情

/proc : 從2.6開始procfs被引入作為顯示系統狀態的vfs,如果老是使用printk在動作很多的時候,訊息量可以淹沒整個console畫面,反過來如果可以在適當時機將需要的資料拿出來看,這樣除錯就可以輕鬆許多,要在/proc底下註冊建立/proc檔案需要用到
struct proc_dir_entry *create_proc_read_entery(const char *name, mode_t mode, struct proc_dir_entry *base, read_proc_t *read_proc, void *data)
這一個function,可以註冊需要的路徑跟虛擬裝置,同時要提供可以讀取資料的函數(跟自己寫的module在同一檔案/空間之中),將目前module的狀態讓使用者可以用類似cat /proc/scullmem的方式取出。這種方式有個限制就是基本上是以page size,在運作,操作複雜結構的資訊並不是很容易,另外就是/proc已經開始有濫用的趨勢,/proc已經不只是讀取,還可以寫入,有點跟/dev一樣的問題。linux已經開始引入sysfs來處理這樣的問題,他要求更有架構性的資料

ioctl() : 最靈活的方式,但是程式設計師必須自行處理,在此章節作者也還不打算詳細介紹,他另外有個好處就是code獨立,不是類似printk會"汙染"到原本的code,所以忘記把它拿掉只是佔據記憶體空間:P
strace : 用來追蹤一些system call的次序,但是可讀性低於printk,有許多參數,如-o表示將輸出轉移到檔案內
strace -o /tmp/x1 ls -R > /dev/scull0

Ooops information : 當系統fault的時候(不是panic/死當),會產生類似coredump檔案的輸出,包含了CPU register等等information(P.S>我不大清楚它會產生到哪裡去@@a)

magic SysRq key : 一些特殊的組合鍵,讓使用者可以做一些事情,請參考書內內容

debugger tools : gdb、kdb、kgdb、Linux Trace Toolkit (LTT)、Dynamic Probes

裡面有提到一個有趣的User-Mode Linux,這是一個虛擬機器的機構,但是她不能讓使用者直接存取硬體

最後,其實作者的sample code的scull包含了chapter 3跟4,所以如果光看了chapter 3就去看code會感到怎麼還有很多多出來的東西

參考資料:
http://zh.wikipedia.org/wiki/Sysfs
http://blog.linux.org.tw/~asho/archives/001816.html
http://184.82.2.112/wordpress/?p=505

system log

sysklogd套件主要包含兩個訊息紀錄程式,一個是klogd(Kernel Log Daemon),另一個為 syslogd(System Log Daemon),兩個工具主要的不同在於klogd是紀錄Linux 核心訊息與Linux核心模組訊息,每當核心程式呼叫printk時,就可以由這個User-Mode的klogd程式來負責把此時的核心訊息紀錄下來,而syslogd則是負責User-Mode程式所需紀錄的系統訊息(例如紀錄在/var/log/messages的系統訊息)。
syslogd的控制可以由/etc/syslog.conf來控制,其次klogd是記錄在一個環狀的紀錄中,當紀錄太多的時候,新來的紀錄會覆蓋掉舊有的紀錄

2012年3月24日 星期六

在ubuntu上面使用mspgcc編譯MSP430的code

只是記錄一下相關的連結,還沒有時間測試
http://hackaday.com/2010/08/11/how-to-launchpad-programming-with-linux/
http://blog.wikifotos.org/2010/11/15/msp430-launchpad-in-ubuntu/
http://mylightswitch.com/2010/06/21/installing-mpsgcc4-and-mspdebug-on-kubuntu-1004/

Linux驅動程式--chapter 3

對於新手還真的有點辛苦的一章,一邊念著一邊看著原始碼,這一章節作者寫了個scull的character device的module,先利用了一些script(mknod)將這些虛擬裝置建構出來

首先替module本身與裝置連結,所以要註冊裝置的編號,在linux 2.6中使用major number跟minor number組成一個獨一無二的編號
MKDEV(scull_major, scull_minor)
跟著使用register_chrdev_region註冊數個裝置(依序,如果之前minor number是2, count是3,就會註冊2~4這幾個裝置),或者使用alloc_chrdev_region動態配置

因為作者使用記憶體取代實際可能為磁碟或者其他硬體裝得部份,所以他有些結構需要初始化,scull_devices這個變數對應每個虛擬裝置的相關資料

接著填充一些必要得功能,其中最重要的是struct file_operations這個結構,他包含了許多character device應該具備有的功能,如果沒有的話則保持NULL,如果使用者使用了不再表格內的function call,就會回傳錯誤。底下是一個範例

struct file_operations scull_fops = {
.owner =    THIS_MODULE,
.llseek =   scull_llseek,
.read =     scull_read,
.write =    scull_write,
.ioctl =    scull_ioctl,
.open =     scull_open,
.release =  scull_release,
};

該結構內並不完全都是function pointer,其中.owner就是表示這個module本身,THIS_MODULE是一個macro
另外可以看到就是read/write、llseek跟open/release這幾個常見的操作,但是為何不是close而是release,這是因為linux一般會對裝置紀錄一個count,表示有多少人或者process這在使用這個資源,只有當count為0的時候才會真真的close

接著必須對每個device作file_operations跟device的對應,使用cdev_init輸入兩個參數,分別是該裝置所需用到的資料結構(struct scull_dev)以及file_operations這個結構,作者假設有四個裝置,就分配要配置四份,但是file_operations這些操作是共用的

這裡有點好玩的是,並沒有強制規定同樣的file device必須有同樣的,甚至因為傳入的是指標,表示可以在半路抽換介面@@a,真是一個好玩的狀況!!

仔細觀察file_operations就會發見到,很多地方需要使用到struct file以及struct inode這兩個參數(由kernel傳入),inode裡面有個成員i_cdev,這裡面包含之前用cdev_init配給某個device的資料結構,需要透過struct scull_dev *dev = container_of(inode->i_cdev, struct scull_dev, cdev);這個巨集取出,這樣就可以知道process正在存取哪個device,並且使用相對應的資料空間

另外討論到記憶體的管理,如作者之前提過得,在kernel space並不能使用一般的libc函數,也就是malloc/free之類的記憶體配置不能使用,這裡必須使用kmalloc/kfree。另外值得注意的一點是如何在user space以及kernel space之間傳遞資料,這裡使用
unsigned long copy_to_user(void __user *to, const void *from, unsigned long count)
unsigned long copy_from_user(void *to, const void __user*from, unsigned long count)
在這兩個呼叫,kernel還必須要檢查適當地存取權限,還有處理使用者指向的記憶體可能是page fault的問題

所以整體來說,簡化的架構就是

  • 註冊裝置
  • 初始化相對應裝置的資料
  • 完成file_operations表格
  • 完成相對應操作的函數 
  • 最後記得要清理資料

2012年3月23日 星期五

linux kernel的相關資料

這裡只是剛好爬文到網路上一個不錯的文庫,紀錄一下
驅動程序編寫基本流程              
Linux內核的ioctl函數學習
linux內核中struct file_operations結構體介紹
幾種設備的相關開發文件:
Linux音頻編程指南
嵌入式系統中LCD驅動的實現原理

因為linux驅動程式一書在這個部份寫得比較簡略的,直接翻code在對照文中所寫,就會有豁然開朗的感覺,畢竟第一次接觸linux較完整module(相對於第二章來說,第三章的範例也完整許多),其中也稍微解釋到我以前的疑惑,kernel space與user space的資料交換


有找到一些資料,但是比較無法分類,順便歸類在這裡好了
ARM MMU工作原理剖析
WIFI環境建構

2012年3月22日 星期四

LCD之framebuffer(4)

終於在網路上看到為何framebuffer會比實際上來的大,以前有人會解釋說是為了作double-buffer,但是有時候size又不是單純的一倍大小,這樣很難自圓其說,後來發現有另外一個原因,那就是為了smooth moving,如果有打過一些以前DOS小遊戲的人(有不小心透露出自己年紀不小嗎XD),遊戲主角移動單位是一格一格的,但是移動的時候卻是平滑移動的動畫,不是跳格的方式,這時候多出來的framebuffer空間就可以作為平滑移動,只要改變指標的位置,就不用會產生跳格的感覺

另外經由Linux驅動程式一書的解釋,framebuffer屬於user space的driver,所以效能會比kernel space來的差,所以表示,如果說要使用圖形顯示,但是又想繞過xwin,或許framebuffer是個不錯的選擇,但是想要在比desktop還要差的硬體下壓榨出更多的效能,可能就得自己對driver開刀了,這恐怕是個大工程,當然很多人會想要使用DSP硬體支援,這也是時下主流平板的選擇