2011/12/28

gpio 隨手記

gpio_get_value()

=> __gpio_get_value()    定義在位置 kernel/drivers/gpio/gpiolib.c

 

2011/12/27

什麼是system call ?

System Call(系統呼叫)

    1. Def:

作為user program執行時與OS之間的溝通介面,當user program需要OS提供服務時,藉由呼叫system call(伴隨trap to monitor mode)通知OS,OS可依據system call ID查表,啟動service routine執行,得到結果,再傳回給user program,完成服務請求

    1. System Call種類:(P3-8~3-9)
      1. Process Control
      2. File Management
      3. Device Management
      4. Information Maintenance
      5. Communication
    2. system call的參數傳遞

有三種方法:

    1. 法一:利用registers儲存參數
      • 優:快速
      • 缺:不適用於參數多時。
        ∵register數目有限,參數不能太多
    2. 法二:將參數存在memory中的某個表格或Block,同時將此表格的起始位址存在一個register中,將此register傳給OS:
      • 優:適用於參數多時
        ∵ 可存參數較多
      • 缺:速度較慢
        ∵不限制參數的數目與長度
    3. 法三:利用system stack保存參數
      • push(保存)參數
      • OS利用POP取出參數
      • 不限制參數的數目及長度

 

Linux 驅動程式的大架構中,system call 是屬於第一層的架構;本文以一個 Linux 範例程式來展示 user application 與 Linux 驅動程式的關係。

作者/陳俊宏
www.jollen.org

System Call 與驅動程式的關係

System call 是 user application 與 Linux device driver 的溝通介面。

User application 透過呼叫 system call 來「叫起」driver 的 task,user application 要呼叫 system call 必須呼叫 GNU C 所提供的「wrapper function」,每個 system call 都會對應到 driver 內的一個 task,此 task 即是 file_operation 函數指標所指的函數。

 

Linux 驅動程式與 user application 間的溝通方式是透過 system call,實際上 user application 是以 device file 與裝置驅動程式溝通。要達成此目的,驅動程式必須建構在此「file」之上,因此 Linux 驅動程式必須透過 VFS(virtual file system)層來實作 system call。

一個簡單的範例

/dev目錄下的檔案稱為device file,是 user application 用來與硬體裝置溝通的介面。以下是一個簡單的範例:

int main(int argc, char *argv[]){    int devfd;    devfd = open("/dev/debug", O_RDONLY);    if (devfd == -1) { printf("Can't open /dev/debug\n"); return -1;    }    ioctl(devfd, IOCTL_WRITE, num);    close(devfd);    return 0;}

當我們打開/dev/debug檔案時,範例所呼叫open()函數會叫起支援/dev/debug驅動程式的對應函數;同理,我們對/dev/debug執行ioctl()函數時,也會叫起驅動程式的相對應函數。

範例中的open()與ioctl()函數皆是GLIBC裡的函數,「叫起」驅動程式函數的動作涉及user space與kernel space的切換,此動作藉由system call介面來完成。設計一個支援”/dev/debug”裝置的驅動程式則是Linux驅動程式設計師所要負責的工作。

–jollen

2011/12/20

程式碼可以用tag方式: 將vim當作source insight 來使用

Trace source at vim
幾個步驟大綱:

  • Introduce
  • Install
  • Setup
  • Tag Your Codebase
  • Text Editor
  • 進階版

[Introduce ]

•Source Insight
–Good IDE
–Good at Windows platform
–Bad Overload files
•But what if you …
–Non-Windows platform (BSD, Linux, …)
–Command line interface (CLI)
–Dislike brute force search : find / grep

[Tools ]

•vim
•ctags
•taglist

[Install ]

安裝vim:

apt-get install vim

安裝ctags:

apt-get install exuberant-ctags

然後到Taglist網站去下載zip檔

• Download taglist
–Steps:
• 下載後解壓縮該檔案
# unzip taglist_45.zip
Archive: taglist_45.zip
inflating: plugin/taglist.vim
inflating: doc/taglist.txt
• 將plugin及doc複製到家目錄的”.vim”這個目錄裏,如果不存在就建一個新的”.vim”

[setup ]

在vim裏設定功能鍵F7 – 用它來開啟/關閉taglist功能

• 在/etc/vim/vimrc裏加入下面1行

map <f7> :Tlist<CR>

[Tag Your Codebase ]
最後一個步驟,到你的原始程式目錄裏輸入
會把此目錄底下的檔案, 建立tag的資訊
所以如果很多檔案就會很久, 我通常都會縮小範圍

ctags -R -h ".h.c.cpp.java"

開啟vim xxx.c按F7
你就會看見如下圖的結果

按鍵功能:
F7 : 可以 Enable / Disable ctags
Ctrl + w + w: 可以Switch window

左視窗Left side (Tag List):
Enter就會自動跳到相對應的函式或定義

右視窗Right side:
Ctrl + ] : 可以跳到游標所指function的implement 位置
Ctrl + t : 可以返回到剛剛的位置

[進階版 ]

•apt-get install cscope
•Download
–Unzip and put these plugin files to
•~ /.vim/plugin

•Modify /etc/vim/vimrc
” Open and close all the three plugins on the same time
‚nmap <F8> :TrinityToggleAll<CR>
” Open and close the srcexpl.vim separately
‚nmap <F9> :TrinityToggleSourceExplorer<CR>
ƒ
ƒ” Open and close the taglist.vim separately
„nmap <F10> :TrinityToggleTagList<CR>
…” Open and close the NERD_tree.vim separately
†nmap <F11> :TrinityToggleNERDTree<CR>
‡set mouse=nv

[參考]:

為了apt-get修改linux route

由於我的公司網路會檔apt-get的下載與更新
讓我感到非常不方便, 甚至我不想要每次都要插拔網路線

第一種方法:
1: 拔除公司網路線
2: 連上手機當熱點的3G無線網路

  • 這種方法缺點就是要手動拔掉網路, 會造成我samba斷線, 每次都要重連

第二種方法:
1: 修改linux的route table
2: 指令:

  • 看route table
    • route -n
  • 指定網域140.x.x.x 會透過無線wlan0上網, 記住要先搞清gateway IP address
    • route add -net 140.0.0.0 netmask 255.0.0.0 gw xx.xx.xx.xx dev wlan0

2011/12/14

git format-patch 可以限定個數

git format-patch 預設會從某個commit開始
一路依照commit作出n所有patch檔案

但是有可能你只想要產生該commit的patch2,其實很簡單
後面加個-1就可以啦

git format-patch  xxxxxxxxxxxxx  -1 

如果你要該commit往後的兩個commit的patches
就改成-2

git format-patch  xxxxxxxxxxxxx  -2 

2011/12/08

printk() 採用的級別

核心通過 printk() 輸出的訊息具有日誌級別,日誌級別是通過在 printk() 輸出的字符串前加一個帶尖括號的整數來控制的,如 printk(“<6>Hello, world!\n”);。內核中共提供了八種不同的日誌級別,在 linux/kernel.h 中有相應的宏對應。

#define KERN_EMERG “<0>” /* system is unusable */
#define KERN_ALERT “<1>” /* action must be taken immediately */
#define KERN_CRIT “<2>” /* critical conditions */
#define KERN_ERR “<3>” /* error conditions */
#define KERN_WARNING “<4>” /* warning conditions */
#define KERN_NOTICE “<5>” /* normal but significant */
#define KERN_INFO “<6>” /* informational */
#define KERN_DEBUG “<7>” /* debug-level messages */

所以 printk() 可以這樣用:printk(KERN_INFO “Hello, world!\n”);。

未指定日誌級別的 printk() 採用的默認級別是 DEFAULT_MESSAGE_LOGLEVEL,這個宏在 kernel/printk.c 中被定義為整數 4,即對應KERN_WARNING。

在 /proc/sys/kernel/printk 會顯示4個數值(可由 echo 修改),分別表示當前控制台日誌級別、未明確指定日誌級別的默認消息日誌級別、最小(最高)允許設置的控制台日誌級別、引導時默認的日誌級別。當 printk() 中的消息日誌級別小於當前控制台日誌級別時,printk 的信息(要有\n符)就會在控制台上顯示。但無論當前控制台日誌級別是何值,通過 /proc/kmsg (或使用dmesg)總能查看。另外如果配置好並運行了 syslogd 或 klogd,沒有在控制台上顯示的 printk 的信息也會追加到 /var/log/messages.log 中

2011/12/05

android: get orientation data 方向/指北針的感測資料

Data may be used to calculate the orientation as outlined below:

1)
Retrieve sensor data from accelerometer and magnetic field sensor
as required by getRotationMatrix():
This actually involves a number of steps in the Activity class:

1.1)
Obtain a sensor manager.
NOTE: Context.getSystemService needs a Context, typically called
within an Activity’s context.
mSensMan = (SensorManager) getSystemService(SENSOR_SERVICE);

1.2)
Register a sensor event listener for each of the above sensor
types.
mSensMan.registerListener(this,
mSensMan.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
SensorManager.SENSOR_DELAY_UI);
mSensMan.registerListener(this,
mSensMan.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_UI);

1.3)
In the listener’s onSensorChanged method copy the data from the
SensorEvent.values.
NOTE: The data must be copied off the event.values as the system is
reusing that array in all SensorEvents, simply assigning won’t work.
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
System.arraycopy(event.values, 0, mGravs, 0, 3);
break;
case Sensor.TYPE_MAGNETIC_FIELD:
System.arraycopy(event.values, 0, mGeoMags, 0, 3);
break;
default:
return;
}
}

2)
Pass the copied sensor data as arrays to
SensorManager.getRotationMatrix() to receive the rotation matrix.
SensorManager.getRotationMatrix(mRotationM, null, mGravs, mGeoMags)

Optionally transform the returned rotation matrix through
SensorManager.remapCoordinateSystem() or multiplying by a
transformation matrix.

3)
Pass the rotation matrix to SensorManager.getOrientation() to
receive the orientation as yaw, pitch and roll expressed in radians.
SensorManager.getOrientation(mRotationM, mOrientation);

原文: http://www.mail-archive.com/android-beginners@googlegroups.com/msg23415.html


其實你可能會說:”有沒有中文的說明呀!!!”
沒錯, 有的!
http://blog.csdn.net/octobershiner/article/details/6641942
而且有寫一個小範例
有空實作一下吧

2011/12/01

pthread simple example: pthread_join



pthread_join 是等待其他的thread結束後才會return
寫的代碼中如果沒有pthread_join主線程會很快結束從而使整個進程結束,從而使創建的兩個線程沒有機會開始執行就結束了,所以沒有輸出。加入pthread_join後,主線程會一直等待直到等待的線程結束自己才結束,使創建的線程有機會執行。

pthread_create 一建立thread之後即開始執行

如果對於創建的線程如果不調用pthread_join,會造成什麼樣的後果
有可能子線程沒被執行完就退出主線程了!

能不能說清楚一下點,為什麼會這樣,如果在線程裡加上控制,應該就不會出現這個問題吧
When a joinable thread terminates, its memory resources (thread
descriptor and stack) are not deallocated until another thread performs
pthread_join on it. Therefore, pthread_join must be called once for
each joinable thread created to avoid memory leaks.
警防內存洩露

程序的主線程結束了, 這個程序的進程就over了。 進程結束時,其他線程就被清理了。也就是執行不倒了。
主要就是防止在子進程結束完之前結束主進程。

所以說,加個pthread_join,既可防止內存洩露,又可以知道子線程的退出狀態,而不是所謂的子線程無法運行下去。要知道線程還有一個狀態:DETACHED,就不需要pthread_join