2009年11月22日 星期日

Linux Kernel(1)- Linux Module簡介


Linux module練習手札I紀錄如何撰寫一個簡單的module,並且編輯它,以及load和unload一個module。

write a module

#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");

static int __init init_modules(void)
{
    printk("hello world\n");
    return 0;
}

static void __exit exit_modules(void)
{
    printk("goodbye\n");
}

module_init(init_modules);
module_exit(exit_modules);
<linux/init.h>和#include <linux/module.h>是Linux 任何的module都會用到的header file,init.h主要定義module的init和cleanup,如module_init()和module_exit()。而module.h定義了module所需要的資料結構與macro。
對於__init的解釋在init.h有非常好的解釋:
The kernel can take this as hint that the function is used only during the initialization phase and free up used memory resources after.
簡單的說就是這個function在初始化後(執行完)就被free了。

而__exit的解釋是:
__exit is used to declare a function which is only required on exit: the function will be dropped if this file is not compiled as a module.

module_init()的解釋是:
The module_init() macro defines which function is to be called at module insertion time (if the file is compiled as a module), or at boot time: if the file is not compiled as a module the module_init() macro becomes equivalent to __initcall(), which through linker magic ensures that the function is called on boot.
主要是用來設定當insert該module後,應該要被執行的進入點(enrty point)。

module_exit()的解釋是:
This macro defines the function to be called at module removal time (or never, in the case of the file compiled into the kernel). It will only be called if the module usage count has reached zero. This function can also sleep, but cannot fail: everything must be cleaned up by the time it returns.
Note that this macro is optional: if it is not present, your module will not be removable (except for 'rmmod -f').

簡言之,就是當user執行rmmod時,會被執行到的function。沒有module_exit(),module就不能被rmmod。


write a Makefile to manage the module

mname := brook_modules
$(mname)-objs := main.o
obj-m := $(mname).o

KERNELDIR := /lib/modules/`uname -r`/build

all:
        $(MAKE) -C $(KERNELDIR) M=`pwd` modules

clean:
        $(MAKE) -C $(KERNELDIR) M=`pwd` clean
$(mname)-objs是告訴make這個module有哪些object files。
obj-m是告訴make這個module的name是什麼。
KERNELDIR是告訴make這個module的kernel所在的位置。
後面就接兩個target(all/clean),用於處理產生和清除module用。


load/unload a module




2009年11月20日 星期五

衝吧ubuntu


由於現在的CPU都有動態調整CPU頻率的能力,所以,一般都會在比較低的頻率上執行,在ubuntu 9.10上,預設是ondemand,所以平常都是以最低的頻率執行,有需要的時候才會逐漸調高頻率執行,有哪些參數可以下?請參考:
brook@ubuntu:~$ more /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors 
conservative ondemand userspace powersave performance 

您可以在您的/etc/init.d底下發現一個名為ondemand的檔案,將內文中的"ondemand"改為您想要執行的governor即可,我是效能愛好者,所以,我當然是"performance"嚕。如:
#! /bin/sh
### BEGIN INIT INFO
# Provides:          ondemand
# Required-Start:    $remote_fs $all
# Required-Stop:
# Default-Start:     2 3 4 5
# Default-Stop:
# Short-Description: Set the CPU Frequency Scaling governor to "ondemand"
### END INIT INFO


PATH=/sbin:/usr/sbin:/bin:/usr/bin

. /lib/init/vars.sh
. /lib/lsb/init-functions

case "$1" in
    start)
        start-stop-daemon --start --background --exec /etc/init.d/ondemand -- background
        ;;
    background)
        sleep 60 # probably enough time for desktop login

        for CPUFREQ in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
        do
                [ -f $CPUFREQ ] || continue
                echo -n performance > $CPUFREQ
        done
        ;;
    restart|reload|force-reload)
        echo "Error: argument '$1' not supported" >&2
        exit 3
        ;;
    stop)
        ;;
    *)
        echo "Usage: $0 start|stop" >&2
        exit 3
        ;;
esac



2009年11月14日 星期六

coverity初體驗


最近在玩coverity,安裝設定上看看手冊大家應該都不成問題,不過在設定green hill可能會遇到小小的問題,就是coverity用__ghs,而一般的code則使用__ghs__,所以要小改一下。
再來就是幫忙review code的看法,以及新手常犯的錯誤,拿出來一起討論一下吧:

Return Address Of Local Variable

由於local variable的address存在stack之中,當程式結束後stack就會被回收,於是存取這塊記憶體時,就會變成invalid access。
錯誤的Example
#define SIZE    10
char* test()
{
    char s[SIZE];
    strcpy(s, "hello");
    return s;
}
幸運的是,GCC通常會出現"warning: function returns address of local variable"提醒Programmer。
基本上,可以使用malloc或者由外面傳進來:
Example
char* test()
{
    char *s;
    s = (char *) malloc(sizeof(char) * SIZE);
    strcpy(s, "hello");
    return s;
}
或者
char* test(char *s, int len)
{
    strncpy(s, "hello", len);
    return s;
}
個人比較偏愛由外面傳進來,再由外面的函數負責free resource。



熱門文章