項目經驗雜記
06-17
http://blog.sina.com.cn/s/blog_6a1837e90100onsb.html2011static spinlock_tRequestResponseLock = SPIN_LOCK_UNLOCKED;spin_lock_bh(&RequestResponseLock);//spin_lock_bh 在獲取鎖之前禁止軟體中斷, 但是硬體中斷留作打開的.spin_unlock_bh(&RequestResponseLock);spin_lock(&RequestResponseLock);spin_unlock(&RequestResponseLock);//上層調用函數內包含自旋鎖時使用spin_lock_bh,而內核層底半步調用時使用spin_lock。bh指bottom_half,即底半。--------------------------------------------------------------------------------------------------create_proc_info_entry( REQUEST_RESPONSE_STATUS_NAME, 0,proc_dir, RequestResponseCacheStatus );remove_proc_entry(REQUEST_RESPONSE_STATUS_NAME,proc_dir);--------------------------------------------------------------------------------------------------init_timer(&m->timer);m->timer.function =&RequestResponseEntryExpired;m->timer.data = (unsignedlong)m;mod_timer(&m->timer,jiffies + GetRadiusResponseTimeout());del_timer(&m->timer);--------------------------------------------------------------------------------------------------struct list_head e;list_add(&m->e,&RequestResponseCache.hash_list[h].head);while(!list_empty(&RequestResponseCache.hash_list[i].head))m =list_entry(RequestResponseCache.hash_list[i].head.next, structRequestResponseEntry, e);list_for_each_entry(m,&RequestResponseCache.hash_list[h].head,e)list_del(&m->e);--------------------------------------------------------------------------------------------------insmod/lib/modules/2.6.18-8.el5/kernel/drivers/rtc/rtc-lib.koinsmodmonitor.komknod /dev/mapdrv0 c250 0rmmodmonitor--------------------------------------------------------------------------------------------------內核編程中:#include<ctype.h>存在錯誤,而#include<linux/ctype.h>正常--------------------------------------------------------------------------------------------------#ifdef __KERNEL__#include<linux/ctype.h>#else#include<ctype.h>#endif宏__KERNEL__能夠區別當前程序是在用戶層還是內核層。上述代碼包含在.h中,此頭文件可以被用戶層和內核層的程序包含。--------------------------------------------------------------------------------------------------在strnpcy之後,需在目標字元串的結尾加上" ",即strncpy(dest, src,size);dest[size] =" "--------------------------------------------------------------------------------------------------2的n次方使用(1<< n)的形式--------------------------------------------------------------------------------------------------kmalloc只能申請128K的內存,建議使用vmallocvfree()不能放在spin_lock_bh和spin_unlock_bh之間;--------------------------------------------------------------------------------------------------module_init()module_exit()函數module_init()和module_exit()是模塊編程中最基本也是必須的兩個函數。module_init()向內核註冊模塊所提供的新功能,而module_exit()註銷由模塊提供的所有功能。MODULE_LICENSE("GPL")用於聲明模塊的許可證--------------------------------------------------------------------------------------------------Linux內核模塊的編譯需要給gcc指示-D__KERNEL__-DMODULE -DLINUX參數--------------------------------------------------------------------------------------------------void *kmalloc(unsigned int len, intpriority);void kfree(void*__ptr);priority:GFP_KERNELGFP_ATOMIC--------------------------------------------------------------------------------------------------unsigned long copy_from_user(void *to,const void *from, unsigned long n);unsigned longcopy_to_user (void * to, void * from, unsigned longlen);put_userget_user--------------------------------------------------------------------------------------------------內核編程用printk替代printf內核一共有8個優先順序.如果優先順序數字比intconsole_loglevel變數小的話,消息就會列印到控制台上。如果syslogd和klogd守護進程在運行的話,則不管是否向控制台輸出,消息都會被追加進/var/log/messages文件。klogd只處理內核消息,syslogd 處理其他系統消息,比如應用程序。--------------------------------------------------------------------------------------------------include/linux/module.h中定義的宏MODULE_PARM(var,type)用於向模塊傳遞命令行參數。var為接受參數值的變數名,type為採取如下格式的字元串[min[-max]]{b,h,i,l,s}。min及max用於表示當參數為數組類型時,允許輸入的數組元素的個數範圍;b:byte;h:short;i:int;l:long;s:string。有了MODULE_PARM,在裝載內核模塊時,用戶可以向模塊傳遞一些參數,如:insmod modnamevar=value--------------------------------------------------------------------------------------------------#Makefile2.6obj-m += hellomod.o # 產生hellomod 模塊的目標文件CURRENT_PATH :=$(shell pwd) #模塊所在的當前路徑LINUX_KERNEL :=$(shell uname -r) #Linux內核源代碼的當前版本LINUX_KERNEL_PATH :=/usr/src/linux-headers-$(LINUX_KERNEL)#Linux內核源代碼的絕對路徑all:make -C$(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules #編譯模塊了clean:make -C$(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean #清理有了Makefile,執行make命令,會自動形成相關的後綴為.o和.ko文件。--------------------------------------------------------------------------------------------------模塊和內核都在內核空間運行,模塊編程在一定意義上說就是內核編程模塊是具有獨立功能的程序,它可以被單獨編譯,但不能獨立運行。模塊通常由一組函數和數據結構組成,用來實現一種文件系統、一個驅動程序或其他內核上層的功能。因為內核版本的每次變化,其中的某些函數名也會相應地發生變化,因此模塊編程與內核版本密切相關內置模塊:可載入模塊--------------------------------------------------------------------------------------------------這些變數和函數就統稱為符號。其中宏定義EXPORT_SYMBOL()本身的含義是「移出符號」。為什麼說是「移出」呢?因為這些符號本來是內核內部的符號,通過這個宏放在一個公開的地方,使得裝入到內核中的其他模塊可以引用它們。在模塊編程中,可以根據符號名從這個文件中檢索出其對應的地址,然後直接訪問該地址從而獲得內核數據。第三列「所屬模塊」指符號所在的模塊名,對於從內核這一母模塊移出的符號,這一列為空。模塊載入後,2.4內核下可通過/proc/ksyms、 2.6 內核下可通過/proc/kallsyms查看模塊輸出的內核符號--------------------------------------------------------------------------------------------------模塊依賴為了確保模塊安全地卸載,每個模塊都有一個引用計數器--------------------------------------------------------------------------------------------------1.Insmod命令:2.rmmod命令:3.lsmod命令:讀取/proc文件系統中的文件/proc/modules中的信息4.ksyms命令:讀取/proc文件系統中的文件/proc/kallsyms。--------------------------------------------------------------------------------------------------//MODULE_PARM_DESC(interface,」A networkinterface」); 2.4內核中該宏的用法molule_parm(interface,charp,0644) //2.6內核中的宏//MODULE_PARM_DESC(irq,」The IRQ of the networkinterface」);module_param(irq,int,0644);insmod myirq.kointerface=eth0 irq=9if(request_irq(irq, &myinterrupt, SA_SHIRQ,interface,&irq)) //註冊中斷,中斷值為irq,中斷函數myinterruptfree_irq(irq,&irq);具體網卡 irq的值可以查看cat /proc/interrupts可動態更改--------------------------------------------------------------------------------------------------insmod(安裝 LKM),rmmod (刪除LKM),modprobe(insmod和 rmmod的包裝器),載入當前當前模塊與其相關聯的其他模塊,單一模塊無關聯時,必須使用insmod,否則會報錯,當自寫編寫模塊時,建議不要使用。depmod(用於創建模塊依賴項),modinfo(用於為模塊宏查找值)。LKM只不過是一個特殊的可執行可鏈接格式(Executable and LinkableFormat,ELF)對象文件。在模塊的載入和卸載期間,模塊子系統維護了一組簡單的狀態變數,用於表示模塊的操作。--------------------------------------------------------------------------------------------------內核中有一個叫做 HZ的頻率變數,它表示每秒的時鐘節拍數。一般的,在某種平台上它會有一個固定值,這個固定值是人為設定的,也就是可編程的(對系統定時器編程)。設定 HZ的大小需要權衡。這個值設大了,帶來的好處是定時器間隔變小,從而使進程(任務)的調度的精確性得以提高,但帶來的缺點是導致開銷過大,讓系統變得耗電,這樣在一些經常使用電池的設備來說(比如筆記本,平板電腦)是難以接受的。在現在一般的 x86平台,2.6 內核的 linux 下,這個值會被設為 100 。也就是說,一個時鐘節拍為 1/100 = 0.01s = 10ms。一個時鐘節拍也稱為 1 個jiffy 。內核中還有一個重要的變數叫jiffies 。它記錄了系統從啟動到當前所觸發定時器的次數。jiffies 每秒鐘增加 HZ 個計數,實際上就是 N 個 jiffy。--------------------------------------------------------------------------------------------------中斷服務程序一般都是在中斷請求關閉的條件下執行的,以避免嵌套而使中斷控制複雜化。下半部運行時是允許中斷請求的,而上半部運行時是關中斷的,這是二者之間的主要區別。--------------------------------------------------------------------------------------------------小任務(Tasklet)機制Count域是小任務的引用計數器。如果它不為0,則小任務被禁止,不允許執行;只有當它為零,小任務才被激活,並且在被設置為掛起時,小任務才能夠執行。DECLARE_TASKLET(name, func, data)DECLARE_TASKLET_DISABLED(name, func, data)DECLARE_TASKLET(my_tasklet, my_tasklet_handler,dev);這行代碼其實等價於structtasklet_struct my_tasklet = { NULL, 0, ATOMIC_INIT(0),tasklet_handler, dev};static voidtasklet_handler (unsigned long data)tasklet_init(&my_tasklet,tasklet_handler, 0);tasklet_schedule(&my_tasklet);tasklet_kill(&my_tasklet);--------------------------------------------------------------------------------------------------如果推後執行的任務需要睡眠,那麼就選擇工作隊列。如果推後執行的任務不需要睡眠,那麼就選擇tasklet。另外,如果需要用一個可以重新調度的實體來執行你的下半部處理,也應該使用工作隊列。voidwork_handler(void *data); //工作隊列待執行的函數DECLARE_WORK(name, void (*func) (void *), void *data);//這樣就會靜態地創建一個名為name,待執行函數為func,參數為data的work_struct結構。INIT_WORK(struct work_struct *work, woid(*func) (void *),void *data); //這會動態地初始化一個由work指向的工作。queue =create_singlethread_workqueue(「helloworld」);if(!queue)gotoerr;destroy_workqueue(queue);schedule_work(&work);//把給定工作的待處理函數提交給預設的events工作線程schedule_delayed_work(&work, delay);//&work指向的work_struct直到delay指定的時鐘節拍用完以後才會執行。--------------------------------------------------------------------------------------------------
推薦閱讀:
推薦閱讀: