Monday, January 16, 2012

Git - How to use .netrc file on windows to save user and password

Reference: Git - How to use .netrc file on windows to save user and password


Is it possible to use a .netrc file on windows when I'm using Git to clone a remote repository with http and user - password?


Answer:

You must define:
  • environment variable %HOME%
  • put a _netrc file in %HOME%
If you are using Windows 7
run the cmd type this:
setx HOME %USERPROFILE%
and the %HOME% will be set to 'C:\Users\"username"'
then go to it and make a file called '_netrc'
Note: for Windows, you need a '_netrc' file, not a '.netrc'.
Its content is quite standard:
machine hostname1
login login1
password password1
machine hostname2
login login2
password password2

How to apply `git diff` patch?

Reference: How to apply `git diff` patch?
How can my client apply patch created by git diff without git installed? I have tried to use patchcommand but it always asks file name to patch.


Answer:
1. git diff --no-prefix > patchfile, patch -p0 < patchfile
2. git apply file.diff
3. git diff > patchfile, patch -p1 < patchfile

Saturday, January 14, 2012

如何選購洗衣機?


資料來源:如何選購洗衣機?

現在,即使在普通家庭,洗衣機也已是很平常的家庭電器了。隨著人們生活水平的提高,對生活品質的要求也愈來愈講究,由於普通的洗衣 機單純依靠機械力進行洗滌,有的衣物還沒有穿壞,就已經被洗壞了。因此大多數消費者對洗衣機要求已與以往有了很大不同,既要能洗的干淨,同時又不損傷衣 物。這就要求洗衣機在洗滌時,衣物不能纏繞,磨擦力不能太大;除此之外還要求洗得更快一點。如何選購適用的、能令自已滿意的洗衣機,是現在的消費者迫切需 要了解的。

選購洗衣機,首先要了解洗衣機的種類。目前世界上的洗衣機,主要有滾筒型、波輪型和攪拌型三大類。它們都是通過化 學作用、機械作用、時間和溫度來洗靜衣物的。其中攪拌型在世界市場上所佔份額極小。但是,就滾筒洗衣機和波輪洗衣機來說,兩者在衣物的洗靜度、耗電量及冼 衣所花費的時間等方面,還是有很大區別的,我們不妨對照一下:

波輪洗衣機

加熱功能不能加熱,如果冬天水溫太低,會影響洗衣粉的溶解水量及洗相對來說,用水量和消耗和洗衣粉,比滾筒洗衣機滌劑用量要多磨損度因機械力作用大,易使衣物纏繞和打結,磨損度較大

洗滌時間洗衣時間較滾筒洗衣機要短壽命大多零部件為塑料製成,時間長了會老化,易鬆動,壽命有限。

滾筒洗衣機

加熱功能可選擇加熱溫度,能激活洗衣汾中的生物?,清除頑漬,洗淨度高水量及洗洗滌時水位為波輪洗衣機的1/3,洗滌劑用量減少滌劑用量為波輪洗衣機的1/4磨損度屬拍打式洗滌,衣物不纏繞打結磨損度小,適合洗滌真絲等高檔品。

洗滌時間洗滌時間相對較長

壽命大多零部件為不銹鋼,堅固耐用使用壽命較長綜合起來看,無論從衣物的洗靜度,對衣物的磨損度、使用壽命,還是各方面能耗的情況,滾筒洗衣機都要優於波輪洗衣機,所以,選購滾筒洗衣機已成為現代家庭的一種趨勢。

目前市場上滾筒洗衣機的品牌較多,看上去似乎大同小異。其實,不同品牌的滾筒洗衣機,其品質和功能相差有時還真不小,所以選購時務必仔細比較。這裡,有10項選購要點,可供消費者在選購時作參考。

1選購滾筒洗衣機,品牌的區別是否很重要?

當然重要。

現 在市場上滾筒洗衣機的品牌很多,各品牌的最大差別就在於質量和信譽;那些具有歷史和知名度的品牌,其產品質量和信譽都經過了時間考驗,是值得信賴的品牌。 目前,由於國內滾筒洗衣機的製造技術多為國外引進,所以,購買時要詢問一下該洗衣機的技術來源、製造商的背景以及生產滾筒洗衣機的歷史。

2內外筒的品質如向辨別?

洗衣機直接與衣物接觸的部件是內筒,內筒工藝的好壞直接關係到衣物的洗淨度。內筒的沖孔邊緣要光滑,凸起的內筒外表必須是無棱角的圓弧形,這樣才不會對衣物造成磨損、鉤絲;另外,內筒沖孔數越多,過水越迅速,漂洗也就越乾淨。

由於內、外筒都直接和洗滌液接觸,並且要加熱。所以要選擇以優質不銹鋼為材質的,可以耐腐蝕,壽命也長久;有一些洗衣機的外筒用搪瓷材料,但是搪瓷易脫落,會使外筒生鏽。

3容量的大小有什麼講究?

不同的容量適應不同消費者的需要。小容量適合單身人士,大容量適合家庭。購買時要根據自已平時洗衣的習慣,選擇適合自已的型號。

一般來說,不同厚薄的滾筒洗衣機,洗衣的容量就相應有所不同。洗衣機標明的是額定容量,實際洗衣容量大約是額定容量的60%。如果所洗衣物超過最佳洗滌容量,會降低衣物的洗淨度,振動和噪音加大,縮短洗衣機的壽命。

此外,還要注意的是,洗衣乾衣機的容量一般是洗滌容量的1/3到1/2,如果洗滌容量小,乾衣容量就更小,烘乾效率降低。

4脫水速度能夠任意調節,是否更理想?

因為不同的衣物需要不同的脫水速度,甩羊毛衣物時速度要低,而甩牛仔褲時速度就要高,這樣才能做到既不損傷衣物,又保證衣物的洗淨度。

在一個範圍內,脫水速度可以任意調節,才適合所有面料衣物。從面板上看,真正可任意調整脫水轉速應該是旋鈕式的,旋動過程中有明顯停頓感的旋鈕,則做不到速度的任意選擇。

5選購洗衣乾衣機應注意什麼?

要注意烘乾容量和洗滌容量的區別。洗衣乾洗機是洗衣系統和乾衣系統的複雜結合,就技術和工藝來說,脫水速度和能耗是一個重要指標,平衡系統是關鍵,脫水速度越高,甩得越乾,烘得越快。

由於烘乾所需的能耗較大,不同品牌能耗相差甚遠,為考慮購買和使用成本,最好通過對廠家提供的數據進行認真比較後決定。

6排水系統對洗衣效果有影響嗎?

排水系統如果設計得不科學,洗衣粉及高濃度的洗滌液就會流入排水管,造成洗衣粉的大量浪費並腐蝕排水管,污水回流內筒也容易弄髒衣物。

目前市場上最先進、也是最科學的解決方法,是在排水口安裝一個球閥裝置,進水和洗滌時,球閥會堵住排水管口,防止洗衣粉和水的流失及污水回流;排水時,球閥下沉,不影響污水的排放,使漂洗乾淨徹底,並可節省40%的水和70%的洗衣粉。

7一些技術參數是否應該了解?

諸 如水、電、洗滌劑、時間消耗等技術參數,是消費者應該知道的。購買時應比較一下各品牌的傳單,上面的數字標註明確的,可信度更高,才會有保障。如果只是由 促銷員口頭說說,當然是口說無憑,則不可為據;一些沒有確切數據可比較的,諸如“節省百分之多少多少”、“提高多少多少倍”之類,不可全信。

8洗衣機有沒有靜音型的?

由於中國大多數家庭把洗衣機放在衛生間或陽台上,有的放在客廳,所以會對洗衣機的噪音十分敏感。洗衣機的噪音不僅來自於電機,而且和機器的平衡系統、轉速控制系統、超負荷洗滌相關。所以,選購時要選電機好,並且採用領先技術的滾筒洗衣機。

現在已經有採用靜音專利技術的滾筒洗衣機了,噪音在800轉/分鐘時,只有58分貝以下,比普通波輪衣機的噪音值還要低。選購時最好請銷售人員當場演示一下,比較噪音的大小,或參考一下各種品牌的噪音值。

9有沒有洗得更快一點的洗衣機?

由於滾筒洗衣機不會使衣物纏繞,所以能通過較長時間的洗滌,提高冼淨度,而不致於損傷衣物;加上洗衣過程全自動,無需監控,所以時間長一些,並不會讓人太操心。但許多消費仍然習慣於快速洗衣,這也無需擔心,因為現在已經有了新型的快洗型滾筒洗衣機了。

所 謂快洗,指的是“快洗時間+快洗節奏”。有一些所謂的“快冼”,只是提前結束洗滌程序,或把洗滌時間較短的程序改名為快洗程序,這是不能達到滿意的洗滌效 果的。專門的快洗程序,可調整洗滌的節奏,不會省略每一個必要的洗滌步驟,保證充分洗滌,而達到良好的洗滌效果,而且適合所有衣料。

10外觀及工藝好壞如何判斷?

洗衣機放在家中,體現著你的生活品,因此外觀應簡潔明快,顏色和家具相配。高質量的洗衣機壽命可達10年以上,所以最好不要選外觀太時髦的,以免很快過時。

 真正好的機器應該表裡如一,在商場選購時,可要求促銷員打開頂蓋看一下製造工藝,方法很簡單,只需下掉兩個小螺絲,看看內部的平衡塊、排線、零部件的來源及裝配,就可以幫你作出選擇。

Tuesday, January 10, 2012

如何解包/編輯/打包boot.img文件

資料來源:如何解包/編輯/打包boot.img文件

感謝本文的作者:Alansj, DarkriftX, RyeBrye, Will, Try OP9, Tonyb486, Timmmm, Lxrose還有好多不知名的作者們在wiki上的不懈努力。
來源:http://android-dls.com/wiki/index.php?title=HOWTO:_Unpack%2C_Edit%2C_and_Re-Pack_Boot_Images 

目錄
1、背景知識
2、boot和recovery映像的文件結構
3、對映像文件進行解包、編輯、打包的常規方法
3.1、另一種解包、編輯、打包的方法
4、將新的映像刷回到手機
5、解包、編輯、打包為我們帶來了什麼
6、本文講的內容與使用update.zip刷機包不是一碼事

正文
1、背景知識

Android手機的文件系統有許多存儲器組成,以下是在adb shell下面的輸出:
#cat /proc/mtd
dev:    size   erasesize  name
mtd0: 
00040000 00020000 "misc"
mtd1: 
00500000 00020000 "recovery"
mtd2: 
00280000 00020000 "boot"
mtd3: 
04380000 00020000 "system"
mtd4: 
04380000 00020000 "cache"
mtd5: 04ac0000 
00020000 "userdata"

注意,不同的手機在上述存儲設備的順序可能會各不相同!一定要檢查您的手機,確定在以下的操作中選擇正確的設備號(mtdX,這個X的序號一定要檢查清楚)。

在本嚮導中,我們主要描述對"recovery"和"boot"的存儲設備進行操作;"system"存儲設備保存了android系統目錄的所有數據(在系統啟動後會掛載到「system/」目錄);「userdata」存儲設備將保存了android數據目錄中的所有數據(在系統啟動後會掛載到「data/」目錄,裡面是會有很多應用數據以及用戶的preference之類的配置數據)。

從上面的輸出可以看出來,recovery和boot分區對應著/dev/mtd/mtd1和/dev/mtd/mtd2,在你您開始做任何修改之前一定要做兩件事情,第一件事情,一定要先對這兩個分區進行備份。
可以使用如下命令進行備份:
# cat /dev/mtd/mtd1 > /sdcard/recovery.img
# cat 
/dev/mtd/mtd2 > /sdcard/boot.img

(注意added by lxros,只有手機獲取了ROOT權限以後才能夠執行上述的備份命令)

第二件事情,你您應該把你您最喜歡的update.zip刷機包放置到你您的sd卡的根目錄上面。如此一來,即使你您在後續的操作中出了問題,也可以啟動到recovery模式進行恢復。

另外一個你您需要知道的重要文件是在android系統目錄下的/system/recovery.img,此文件是mtd1存儲設備的完全拷貝。這個文件在每次關機的時候,會自動地被寫回到mtd1存儲設備裡面。

這會意味著兩個事情:
(1)任何對/dev/mtd/mtd1中數據的直接修改都會在下一次重啟手機以後消失。
(2)如果希望對/dev/mtd/mtd1進行修改,最簡單的做法是用你您自己的recovery.img替換掉/system/recovery.img。當你您創建自己的update.zip刷機包的時候(特別是在做刷機包的適配的時候),如果你您忘記替換這個/system/recovery.img,這個recovery.img就會在關機的時候被燒寫到mtd1里面去或許會變磚。一定要注意這一點!

(譯者的話,關於這個/system/recovery.img文件,在2.1的android的平台裡面並沒有找到,或許這個機制已經out了?!或者偶本人對這段話的理解不夠深入?!希望明白的朋友不吝斧正)

2、boot和recovery映像的文件結構
boot和recovery映像並不是一個完整的文件系統,它們是一種android自定義的文件格式,該格式包括了2K的文件頭,後面緊跟著是用gzip壓縮過的內核,再後面是一個ramdisk內存盤,然後緊跟著第二階段的載入器程序(這個載入器程序是可選的,在某些映像中或許沒有這部分)。此類文件的定義可以從源代碼android-src/system/core/mkbootimg找到一個叫做bootimg.h的文件。

(譯者的話,原文是一個叫做mkbootimg.h的文件,但從Android 2.1的代碼來看,該文件名應該是改為bootimg.h了)。


/*
** +-----------------+
** | boot header     | 1 page
** +-----------------+
** | kernel          | n pages
** +-----------------+
** | ramdisk         | m pages
** +-----------------+
** | second stage    | o pages
** +-----------------+
**
** n = (kernel_size + page_size - 1) / page_size
** m = (ramdisk_size + page_size - 1) / page_size
** o = (second_size + page_size - 1) / page_size
**
** 0. all entities are page_size aligned in flash
** 1. kernel and ramdisk are required (size != 0)
** 2. second is optional (second_size == 0 -> no second)
** 3. load each element (kernel, ramdisk, second) at
**    the specified physical address (kernel_addr, etc)
** 4. prepare tags at tag_addr.  kernel_args[] is
**    appended to the kernel commandline in the tags.
** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
** 6. if second_size != 0: jump to second_addr
**    else: jump to kernel_addr
*/


ramdisk映像是一個最基礎的小型文件系統,它包括了初始化系統所需要的全部核心文件,例如:初始化init進程以及init.rc(可以用於設置很多系統的參數)等文件。如果你您希望瞭解更多關於此文件的信息可以參考以下網址:
http://git.source.android.com/?p=kernel/common.git;a=blob;f=Documentation/filesystems/ramfs-rootfs-initramfs.txt
以下是一個典型的ramdisk中包含的文件列表:
./init.trout.rc
.
/default.prop
.
/proc
.
/dev
.
/init.rc
.
/init
.
/sys
.
/init.goldfish.rc
.
/sbin
.
/sbin/adbd
.
/system
.
/data


recovery映像包含了一些額外的文件,例如一個叫做recovery的二進製程序,以及一些對該程序支持性的資源圖片文件(當你您按下home+power組合鍵的時候就會運行這個recovery程序)。
典型的文件列表如下:

./res
.
/res/images
.
/res/images/progress_bar_empty_left_round.bmp
.
/res/images/icon_firmware_install.bmp
.
/res/images/indeterminate3.bmp
.
/res/images/progress_bar_fill.bmp
.
/res/images/progress_bar_left_round.bmp
.
/res/images/icon_error.bmp
.
/res/images/indeterminate1.bmp
.
/res/images/progress_bar_empty_right_round.bmp
.
/res/images/icon_firmware_error.bmp
.
/res/images/progress_bar_right_round.bmp
.
/res/images/indeterminate4.bmp
.
/res/images/indeterminate5.bmp
.
/res/images/indeterminate6.bmp
.
/res/images/progress_bar_empty.bmp
.
/res/images/indeterminate2.bmp
.
/res/images/icon_unpacking.bmp
.
/res/images/icon_installing.bmp
.
/sbin/recovery


3、對映像文件進行解包、編輯、打包的常規方法
(注意,下面我給你您介紹的是手工命令行方式進行解包以及重新打包的方法,但是我仍然創建了兩個perl腳本,這兩個腳本可以讓你您的解包和打包工作變得輕鬆許多。
可以參考本文的附件

如果你您很擅長使用16進制編輯器的話,你您可以打開boot.img或者recovery.img,然後跳過開始的2K的頭數據,然後尋找一大堆0的數據,在這一堆0的數據後面,緊跟著1F 8B這兩個數字(1F 8B是gzip格式的文件的結束標記)。從此文件開始的地方(跳過2K的頭),一大堆0後面緊跟著到1F 8B這兩個數字為止的全部數據,就是gzip壓縮過的linux內核。從1F 8B後面緊跟著的數據一直到文件的結尾包含的全部數據,就是ramdisk內存盤的數據。你您可以把把內核和ramdisk兩個文件分別保存下來,在進行分別的修改和處理。我們可以通過un-cpio和un-gzip操作來讀取ramdisk文件中的數據,可以使用如下的命令來實現這個目的,以下操作會生成一個目錄,直接cd進去就可以看到ramdisk中的數據了:

gunzip -c ../your-ramdisk-file | cpio -i


此命令可以將ramdisk中的所有的文件解包到當前的工作目錄下面,然後就可以對它進行編輯了。

當需要重新打包ramdisk的時候,就需要re-cpio然後re-gzip這些數據和目錄,可以通過如下命令來實現:(cpio會把所有當前目錄下面的文件都打包進去,因此,在進行此步驟之前,請把不需要的文件都清除掉。)

find . | cpio --H newc | gzip > ../newramdisk.cpio.gz


最後一步就是通過mkbootimg這個工具,把kernel和ramdisk打包在一起,生成一個boot.img:

mkbootimg --cmdline 'no_console_suspend=1 console=null' --kernel your-kernel-file --ramdisk newramdisk.cpio.gz -o mynewimage.img


這裡的mkbootimg工具會在編譯android的源代碼的時候會在~/android-src/out/host/linux-x86/bin目錄下面自動生成。
下載地址:
http://git.source.android.com/?p=platform/system/core.git;a=tree;f=mkbootimg

現在,如果不想背這些複雜的命令或者擺弄那個讓人眩暈的16進制編輯器的話,可以嘗試使用我編寫的用於解包和打包的perl腳本了。希望這些腳本能夠節約各位的鍵盤。

3.1、另一種解包、編輯、打包的方法
下載split_bootimg.zip文件,在此zip文件中包含一個perl文件,split_bootimg.pl腳本,該腳本可以讀取boot.img頭(根據Android源碼中的bootimg.h讀取)將kernel和ramdisk讀取出來,此腳本也會輸出內核命令行和板子名字。http://android-dls.com/files/linux/split_bootimg.zip

(注意,不要使用從/dev/mtd/mtd2直接拷貝出來的boot.img,此映像可能在讀取過程遭到損壞。)
下面是一個從TC4-RC28更新中提取出來的boot.img進行解包操作:

% ./split_bootimg.pl boot.img Page size: 2048 (0x00000800)Kernel size: 1388548 (0x00153004)Ramdisk size: 141518 (0x000228ce)Second size: 0 (0x00000000)Board name: Command line: no_console_suspend=1
Writing boot.img-kernel ... complete.Writing boot.img-ramdisk.gz ... complete.


解包ramdisk的命令如下:
% mkdir ramdisk% cd ramdisk% gzip -dc ../boot.img-ramdisk.gz | cpio -i% cd ..


解碼完畢後,就可以修改了(例如,在default.prop設置ro.secure=0等等)

使用mkbootfs工具(mkbootfs工具是編譯完畢Android源代碼以後,就會在~/android-src/out/host/linux-x86/bin自動生成)來重新創建ramdisk,可以使用如下命令來操作:
% mkbootfs ./ramdisk | gzip > ramdisk-new.gz


使用mkbootimg來重新創建boot.img,mkbootimg也可以在~/android-src/out/host/linux-x86/bin目錄中可以找到:
% mkbootimg --cmdline 'no_console_suspend=1 console=null' --kernel boot.img-kernel --ramdisk ramdisk-new.gz -o boot-new.img

(注意:console=null的命令行選現是從TC4-RC30的boot.img引入的,用以去掉root shell)

4、將新的映像刷回到手機
可以將recovery.img拷貝到/system目錄下面,然後重新啟動手機,讓手機自動為你您刷寫到mtd裡面(工作原理在上面已經提過了)。對於boot.img可以通過將其拷貝到sd卡的根目錄,然後通過手機內的刷寫工具將此映像寫入到手機中。

例如,使用adb工具Android SDK中的一個工具)將boot.img拷貝到手機的sd卡的根目錄:
adb push ./mynewimage.img /sdcard

然後通過adb shell登錄手機(獲取過ROOT的)的shell交互模式,利用命令行進行交互:
# cat /dev/zero > /dev/mtd/mtd2   write: No space left on device [this is ok, you can ignore]# flash_image boot /sdcard/mynewimage.img

然後重啟手機。

如果手機能夠正常啟動,那麼祝賀你您,你您的修改和替換已經成功了;如果不能夠順利啟動,則需要重新啟動進入recovery模式,並且使用update.zip來恢復。

5、解包、編輯、打包為我們帶來了什麼
可以修改手機開機啟動時候的畫面,具體的操作的地址為:
http://forum.xda-developers.com/showthread.php?t=443431

6、本文講的內容與使用update.zip刷機包不是一碼事
您可以很容易地在其他論壇上看到關於如何自制update.zip刷機包的方法,也可以下載到很多在網絡上共享的自制刷機包。例如:近期的多數刷機包都來自對rc30包的修改和調整。在update.zip刷機包裡面會包括新的boot.img,recovery.img以及整個system/目錄下的若干文件的替換和更新。如果您希望自己自制boot.img以及recovery.img,建議您選取相對較新的更新和版本。(選用較老的映像的話,或許會出現兼容性問題)。

Wednesday, January 04, 2012

Linux中Workqueue機制分析

資料來源: Linux中Workqueue機制分析


Linux中Workqueue機制分析

    走入Linux的殿堂已經有一年有餘了,在這裡我想將Linux的各種實現機制分析一遍,一方面對自己來說也是溫故而知新,另一方面,促進大家的交流,最好能夠給大家一些拋磚引玉的啟迪。我是硬件出身,搞硬件已經好多年了,從是專門軟件開發也接近兩年了,在這一段時間內我越發認為軟硬件協同設計是未來發展的主流,軟硬件的界限越來越模糊,軟硬件的設計思想是相通的,實現方法是各異的,實現的結果上當然也存在較大差別,因此,很有必要做好軟硬件的協同設計。本著這樣的想法,我想將我所認識的Linux分析一遍,特別是一些我認為精華和重要的機制,另外在討論過程中,我會插入一些其他的OS實現機制,進行對比分析,我把這一類blog文章劃歸為「Linux機制分析」,希望大家支持。

什麼是workqueue

Linux中的Workqueue機制就是為了簡化內核線程的創建。通過調用workqueue的接口就能創建內核線程。並且可以根據當前系統CPU的個數創建線程的數量,使得線程處理的事務能夠並行化。
workqueue是內核中實現簡單而有效的機制,他顯然簡化了內核daemon的創建,方便了用戶的編程,

Workqueue機制的實現

Workqueue機制中定義了兩個重要的數據結構,分析如下:
1、          cpu_workqueue_struct結構。該結構將CPU和內核線程進行了綁定。在創建workqueue的過程中,Linux根據當前系統CPU的個數創建cpu_workqueue_struct。在該結構主要維護了一個任務隊列,以及內核線程需要睡眠的等待隊列,另外還維護了一個任務上下文,即task_struct
2、          work_struct結構是對任務的抽象。在該結構中需要維護具體的任務方法,需要處理的數據,以及任務處理的時間。該結構定義如下:
struct work_struct {
              unsigned long pending;
               struct list_head entry;                  /* 將任務掛載到queue的掛載點 */
               void (*func)(void *);                   /* 任務方法 */
               void *data;                                  /* 任務處理的數據*/
               void *wq_data;                           /* work的屬主 */
               strut timer_list timer;                   /* 任務延時處理定時器 */
};
      
       當用戶調用workqueue的初始化接口create_workqueue或者create_singlethread_workqueueworkqueue隊列進行初始化時,內核就開始為用戶分配一個workqueue對象,並且將其鏈到一個全局的workqueue隊列中。然後Linux根據當前CPU的情況,為workqueue對象分配與CPU個數相同的cpu_workqueue_struct對象,每個cpu_workqueue_struct對象都會存在一條任務隊列。緊接著,Linux為每個cpu_workqueue_struct對象分配一個內核thread,即內核daemon去處理每個隊列中的任務。至此,用戶調用初始化接口將workqueue初始化完畢,返回workqueue的指針。

       在初始化workqueue過程中,內核需要初始化內核線程,註冊的內核線程工作比較簡單,就是不斷的掃瞄對應cpu_workqueue_struct中的任務隊列,從中獲取一個有效任務,然後執行該任務。所以如果任務隊列為空,那麼內核daemon就在cpu_workqueue_struct中的等待隊列上睡眠,直到有人喚醒daemon去處理任務隊列。

       Workqueue初始化完畢之後,將任務運行的上下文環境構建起來了,但是具體還沒有可執行的任務,所以,需要定義具體的work_struct對象。然後將work_struct加入到任務隊列中,Linux會喚醒daemon去處理任務。

       上述描述的workqueue內核實現原理可以描述如下:





    在Workqueue機制中,提供了一個系統默認的workqueue隊列——keventd_wq,這個隊列是Linux系統在初始化的時候就創建的。用戶可以直接初始化一個work_struct對象,然後在該隊列中進行調度,使用更加方便。

Workqueue編程接口

序號
接口函數
說明
1
create_workqueue
用於創建一個workqueue隊列,為系統中的每個CPU都創建一個內核線程。輸入參數:
@nameworkqueue的名稱
2
create_singlethread_workqueue
用於創建workqueue,只創建一個內核線程。輸入參數:
@nameworkqueue名稱
3
destroy_workqueue
釋放workqueue隊列。輸入參數:
@ workqueue_struct:需要釋放的workqueue隊列指針
4
schedule_work
調度執行一個具體的任務,執行的任務將會被掛入Linux系統提供的workqueue——keventd_wq輸入參數:
@ work_struct:具體任務對象指針
5
schedule_delayed_work
延遲一定時間去執行一個具體的任務,功能與schedule_work類似,多了一個延遲時間,輸入參數:
@work_struct:具體任務對象指針
@delay:延遲時間
6
queue_work
調度執行一個指定workqueue中的任務。輸入參數:
@ workqueue_struct:指定的workqueue指針
@work_struct:具體任務對象指針
7
queue_delayed_work
延遲調度執行一個指定workqueue中的任務,功能與queue_work類似,輸入參數多了一個delay