顯示具有 Kernel 標籤的文章。 顯示所有文章
顯示具有 Kernel 標籤的文章。 顯示所有文章

2026年1月20日 星期二

修復 v4l2loopback 0.15.0 的 V4L2 緩衝區佇列問題

## 問題現象 使用 GStreamer v4l2sink 將影像送到 v4l2loopback 虛擬攝影機時出現錯誤: ``` WARN v4l2bufferpool: buffer X was not queued, this indicates a driver bug ``` 經過分析發現是 v4l2loopback 0.15.0 違反 V4L2 規格所致。 ## V4L2 緩衝區佇列規格 V4L2 規格定義的緩衝區使用流程: 1. **VIDIOC_REQBUFS** - 配置緩衝區 2. **VIDIOC_QBUF** - 將緩衝區排入驅動程式佇列 3. **VIDIOC_DQBUF** - 從驅動程式佇列取出緩衝區 核心規則:DQBUF 只能回傳先前透過 QBUF 排入的緩衝區。 正確流程:`QBUF → (處理) → DQBUF → QBUF → (處理) → DQBUF ...` v4l2loopback 0.15.0 的錯誤流程:`(預填充) → DQBUF → (自動循環) → DQBUF → (自動循環) → DQBUF ...` 錯誤點:完全不需要 QBUF,DQBUF 永遠有可用緩衝區。 ## v4l2loopback 0.15.0 的問題 ### prepare_buffer_queue() 預先填充佇列 ```c /* 原始碼 */ for (pos = 0; pos < count; ++pos) { bufd = &dev->buffers[pos]; if (list_empty(&bufd->list_head)) list_add_tail(&bufd->list_head, &dev->outbufs_list); } ``` 問題:所有緩衝區在配置後立即被加入輸出佇列,沒有經過 QBUF。 ### vidioc_dqbuf() 循環使用緩衝區 ```c /* 原始碼 */ bufd = list_first_entry_or_null(&dev->outbufs_list, ...); if (bufd) list_move_tail(&bufd->list_head, &dev->outbufs_list); ``` 問題:使用 `list_move_tail()` 將緩衝區移到佇列尾端,形成循環。 ### 違反規格的行為 1. 緩衝區未經 QBUF 就出現在輸出佇列 2. DQBUF 回傳從未排入的緩衝區 3. 緩衝區自動循環使用 實際流程:`DQBUF → DQBUF → DQBUF ...` (完全不需要 QBUF) ### GStreamer 的檢查 GStreamer v4l2bufferpool 會追蹤已排入的緩衝區。收到未排入的緩衝區時報錯: ``` WARN v4l2bufferpool: buffer X was not queued, this indicates a driver bug ``` 這是正確的行為,因為驅動程式確實違反了規格。 ## 修復方法 ### 修改 prepare_buffer_queue() 清空輸出佇列,不要預先填充: ```c /* 清空輸出佇列 */ list_for_each_entry_safe(bufd, n, &dev->outbufs_list, list_head) { list_del_init(&bufd->list_head); } /* 重設緩衝區狀態 */ for (pos = 0; pos < count; ++pos) { bufd = &dev->buffers[pos]; unset_flags(bufd->buffer.flags); dev->bufpos2index[pos % count] = bufd->buffer.index; } ``` ### 修改 vidioc_dqbuf() 移除緩衝區,不要循環使用: ```c bufd = list_first_entry_or_null(&dev->outbufs_list, ...); if (bufd) list_del_init(&bufd->list_head); /* 移除,不循環 */ ``` ### 修復後的行為 - 輸出佇列初始為空 - 緩衝區只在透過 QBUF 排入時才進入輸出佇列 - DQBUF 移除緩衝區,不循環使用 - 符合 V4L2 規格要求 ## 測試驗證 修復前: ```bash gst-launch-1.0 icamerasrc ! v4l2sink device=/dev/video0 # ERROR: buffer X was not queued, this indicates a driver bug ``` 修復後: ```bash gst-launch-1.0 icamerasrc ! v4l2sink device=/dev/video0 # 正常運作,無錯誤訊息 # Firefox/Chrome 可正常使用虛擬攝影機 ``` ## 技術細節 ### 為什麼原設計會預先填充? v4l2loopback 作為虛擬裝置,可能想簡化緩衝區管理,確保永遠有可用緩衝區。但這違反了 V4L2 規格,與嚴格遵循規格的程式(如 GStreamer)不相容。 ### list_del_init vs list_move_tail - `list_del_init()`: 明確表示「緩衝區不在佇列中」 - `list_move_tail()`: 暗示「移到另一個位置」,語義模糊 使用 `list_del_init()` 讓緩衝區狀態更清楚。 ### 多執行緒考量 正確的緩衝區狀態追蹤在多執行緒環境下很重要,可避免競爭條件。 ## 參考資料 - V4L2 Buffer: https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/buffer.html - VIDIOC_QBUF/DQBUF: https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/vidioc-qbuf.html - V4L2 Streaming I/O: https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/io.html - GStreamer v4l2bufferpool: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/blob/main/subprojects/gst-plugins-good/sys/v4l2/gstv4l2bufferpool.c ## 上游貢獻 修補程式已提交至上游:https://github.com/v4l2loopback/v4l2loopback/pull/656 ## 結論 V4L2 緩衝區管理規格的核心原則: 1. 明確的狀態轉換:QBUF → DQBUF 2. 應用程式控制:由應用程式決定何時提供緩衝區 3. 可預測行為:嚴格遵循規格 當應用程式報告 "driver bug" 時,通常確實是驅動程式的問題。

2017年6月19日 星期一

手動快速編譯 Ubuntu 16.04 當中 Linux kernel 4.4 裡面的 kernel module

以前寫過一篇「手動快速編譯 Ubuntu 14.04 當中 Linux kernel 裡面的 i915 module」這次是要針對 Ubuntu 16.04 LTS 上面的 Linux kernel 4.4 編譯,步驟都差不多只是有些不一樣的地方。

首先是 Linux kernel git tree 的來源改從 Launchpad 而來,是的! Ubuntu 使用的 Linux kernel 現在也放到 Launchpad 上面了。

$ git clone https://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux/+git/xenial

然後是編譯的設定檔的位置不一樣了,不過大致上只要找出 config.common.ubuntu config.common.amd64 config.flavour.generic 這三個檔案的位置出來就可以了。

cat ./debian.master/config/config.common.ubuntu ./debian.master/config/amd64/config.common.amd64 ./debian.master/config/amd64/config.flavour.generic > .config

然後這次我的目標是 ubuntu/i915 底下的 kernel module 其它的部份就直接參考前一份文章就可以了。

2016年7月25日 星期一

Disable Secure Boot in shim-signed

The latest Ubuntu kernel updates bring some Secure Boot enhancement for the kernel modules when the Secure Boot is enabled in BIOS settings. However there is no easy way to sign those kernel modules in DKMS packages automatically so far. If we want to use those DKMS packages, we need to disable Secure Boot in BIOS settings temporarily or we can also disable Secure Boot in shim-signed temporarily. The following steps introduced how to disable Secure Boot in shim-signed.

  1. Open a terminal by Ctrl + Alt + T, execute `sudo update-secureboot-policy` and then select ‘Yes’.
  2. Enter a temporary password between 8 to 16 digits. (For example, 12345678, we will use this password later.)
  3. Enter the same password again to confirm.
  4. Reboot the system and press any key when you see the blue screen (MOK management).
  5. Select “Change Secure Boot state”.
  6. Press the corresponding password character and press Enter. Repeat this step several times to confirm previous temporary password like ‘12345678’ in step 2&3. For exmaple, '2' for this screen.
  7. Select ‘Yes’ to disable Secure Boot in shim-signed.
  8. Press Enter key to finish the whole procedure.

We can still enable Secure Boot in shim-signed again. Just execute `sudo update-secureboot-policy --enable` and then follow the similar steps above.

2016年5月30日 星期一

編譯 Ubuntu 的 Linux kernel 來使用 USB to RS-232 輸出訊息

如果曾經有參加過台北的 Ubuntu Hardware Summit,應該都會拿到一本橘色小手冊 Ubuntu Debugging,當中有提到可以設定幾個 Linux kernel 編譯選項中

CONFIG_USB_SERIAL_CONSOLE=y
CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_PL2303=y

然後就可以在 Linux kernel 開機參數加上

console=tty console=ttyUSB0,115200n8

這樣就可以透過 USB to RS-232 傳輸線將 Linux kernel 訊息輸出到另外一台電腦上面,為什麼要這樣做有時候是因為 Linux kernel 開機時是什麼畫面也沒有,也不曉得中間到底發生了什麼事情,又或者是 Linux kernel 訊息出現的太快了,來不及看清楚完整的訊息一下子就過去了,也沒有來得及儲存到檔案系統上面就當機了,有著許許多多不同的情況可能會需要。

但是實際上要怎麼做才能夠編譯出 Ubuntu 上面所使用的 Linux kernel 呢?

首先是將 Ubuntu 所使用的 Linux kernel 的原始碼下載回來。

$ git clone git://kernel.ubuntu.com/ubuntu/ubuntu-xenial.git

然後我自己 commit 了一些修改 (主要是針對 amd64)。

$ git diff HEAD^..HEAD
diff --git a/debian.master/abi/4.4.0-22.39/amd64/generic.modules b/debian.master/abi/4.4.0-22.39/amd64/generic.modules
index e1b9392..53d7914 100644
--- a/debian.master/abi/4.4.0-22.39/amd64/generic.modules
+++ b/debian.master/abi/4.4.0-22.39/amd64/generic.modules
@@ -2873,7 +2873,6 @@ pixcir_i2c_ts
 pkcs7_test_key
 pktcdvd
 pktgen
-pl2303
 platform_lcd
 plat_nand
 plat-ram
@@ -4236,7 +4235,6 @@ usblp
 usbmon
 usbmouse
 usbnet
-usbserial
 usb-serial-simple
 usbsevseg
 usb-storage
diff --git a/debian.master/config/annotations b/debian.master/config/annotations
index 825012f..167ab6e 100644
--- a/debian.master/config/annotations
+++ b/debian.master/config/annotations
@@ -6609,7 +6609,7 @@ CONFIG_USB_STORAGE_ENE_UB6250                   policy<{'amd64': 'm', 'arm64': '
 CONFIG_USB_UAS                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
 
 # Menu: Device Drivers >> USB support >> Support for Host-side USB >> USB Serial Converter support
-CONFIG_USB_SERIAL                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL                               policy<{'amd64': 'y', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
 CONFIG_USB_SERIAL_GENERIC                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'powerpc': 'y', 'ppc64el': 'y'}>
 CONFIG_USB_SERIAL_SIMPLE                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
 CONFIG_USB_SERIAL_AIRCABLE                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
@@ -6641,7 +6641,7 @@ CONFIG_USB_SERIAL_MOS7715_PARPORT               policy<{'amd64': 'y', 'arm64': '
 CONFIG_USB_SERIAL_MOS7840                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
 CONFIG_USB_SERIAL_MXUPORT                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
 CONFIG_USB_SERIAL_NAVMAN                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
-CONFIG_USB_SERIAL_PL2303                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_PL2303                        policy<{'amd64': 'y', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
 CONFIG_USB_SERIAL_OTI6858                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
 CONFIG_USB_SERIAL_QCAUX                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
 CONFIG_USB_SERIAL_QUALCOMM                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'powerpc': 'm', 'ppc64el': 'm'}>
diff --git a/debian.master/config/config.common.ubuntu b/debian.master/config/config.common.ubuntu
index 505a3c7..7cb1284 100644
--- a/debian.master/config/config.common.ubuntu
+++ b/debian.master/config/config.common.ubuntu
@@ -8391,7 +8391,8 @@ CONFIG_USB_RIO500=m
 CONFIG_USB_RTL8150=m
 CONFIG_USB_RTL8152=m
 CONFIG_USB_S2255=m
-CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL=y
+CONFIG_USB_SERIAL_CONSOLE=y
 CONFIG_USB_SERIAL_AIRCABLE=m
 CONFIG_USB_SERIAL_ARK3116=m
 CONFIG_USB_SERIAL_BELKIN=m
@@ -8439,7 +8440,7 @@ CONFIG_USB_SERIAL_OMNINET=m
 CONFIG_USB_SERIAL_OPTICON=m
 CONFIG_USB_SERIAL_OPTION=m
 CONFIG_USB_SERIAL_OTI6858=m
-CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_PL2303=y
 CONFIG_USB_SERIAL_QCAUX=m
 CONFIG_USB_SERIAL_QT2=m
 CONFIG_USB_SERIAL_QUALCOMM=m

接著開始編譯 Linux kernel (在有八個 CPU cores 的電腦上)

$ CONCURRENCY_LEVEL=8 fakeroot debian/rules clean binary-generic

最後就會在上層目錄產生 Ubuntu 所使用的 Linux kernel 的 Debian packages 了。

$ ls -1 ../*.deb
../linux-cloud-tools-4.4.0-22-generic_4.4.0-22.40_amd64.deb
../linux-headers-4.4.0-22-generic_4.4.0-22.40_amd64.deb
../linux-image-4.4.0-22-generic_4.4.0-22.40_amd64.deb
../linux-image-extra-4.4.0-22-generic_4.4.0-22.40_amd64.deb
../linux-tools-4.4.0-22-generic_4.4.0-22.40_amd64.deb

這樣就可以將這些 Debian packages 拿去安裝使用了。

最後我放了一份在 http://people.ubuntu.com/~fourdollars/usb2rs232/ 上面,也許有人剛好也需要想要測試一下效果如何。

參考資料:https://wiki.ubuntu.com/Kernel/KernelDebuggingTricks

2015年11月9日 星期一

手動快速編譯 Ubuntu 14.04 當中 Linux kernel 裡面的 i915 module

首先要下載 Linux kernel source tree

$ git clone git://kernel.ubuntu.com/ubuntu/ubuntu-trusty.git

然後進去該目錄,並且切換到 vivid branch (這邊使用的是 Ubuntu 14.04 當中 LTS Enablement Stacks 當中的 vivid)

$ git checkout -b vivid origin/lts-backport-vivid

快速產生目標的 .config

$ cat debian.vivid/config/config.common.ubuntu debian.vivid/config/amd64/config.common.amd64 debian.vivid/config/amd64/config.flavour.generic > .config

執行一些設定腳本

$ make oldconfig && make prepare && make scripts

設定環境變數 (接下來會使用到)

$ export KDIR=$PWD

複製 Module.symvers (如果要編譯的 Linux kernel 跟系統所使用的剛好相同)

$ cp -v /lib/modules/$(uname -r)/build/Module.symvers Module.symvers

不然就需要至少編譯整個 Linux kernel 一遍才行 (-j? 可以參考 /proc/cpuinfo 的數量來決定)

$ make -j8

切換到該 module 的目錄底下,不過 Ubuntu 的 Linux kernel 目前有兩份不同的 i915 module,一份放在 drivers/gpu/drm/i915 底下,另一份放在 ubuntu/i915 底下。

$ cd drivers/gpu/drm/i915

或是

$ cd ubuntu/i915

然後開始編譯 (J=? 可以參考 /proc/cpuinfo 的數量來決定)

$ make -C $KDIR M=$PWD J=8

參考資料:Kernel/BuildYourOwnKernel - Ubuntu WikiDocumentation/kbuild/modules.txt

2014年7月15日 星期二

在 Ubuntu 上面安裝 mainline kernels

所謂的 mainline kernels 就是在 The Linux Kernel Archives 上面由 Linus Torvalds 本人釋出的版本, 而 Ubuntu 本來有一個 Ubuntu Kernel PPA 專門用來編譯這些 mainline kernels, 只是後來不曉得為何就不再使用 PPA 改用手動編譯的方式,可能是因為 Linux kernel 的釋出方式有了許多變化,除了原本的 stable 跟 mainline 還另加入了 longterm 的支援, 而 Ubuntu 的 Kernel team 本來就有準備一個 http://kernel.ubuntu.com/~kernel-ppa/mainline/ 上面備份了所有的 mainline kernels, 所以就繼續沿用這樣的名稱,但其實這上面還包括了 stable 跟 longterm 後來所有的版本。

總之 http://kernel.ubuntu.com/~kernel-ppa/mainline/ 上面放的是沒有 Ubuntu 額外加料的原始 kernel 版本,只是都編譯成了 Debian package, 所以想要使用的人可以直接下載來安裝就可以使用了,而這些 kernel 如果在安裝使用上會有什麼問題,當然也不會在 Ubuntu 的支援之中,這些 kernel 的存在只是用來測試的,藉由安裝不同的版本來找出問題是在哪兩個版本之間發生的,或是在哪兩個版本之間解決的,進而幫助開發者縮小問題發生的地方,來找出相關合適的修補檔。

但是這樣不斷地手動下載安裝,也是很麻煩的,所以我寫了一個小工具來幫忙,它就叫做 mainline-kernels.sh,下載後像下面這樣執行就可以看到使用說明:

$ ./mainline-kernels.sh --help
Usage ./mainline-kernels.sh:
    -h|--help       The manual of this script
    -f|--from NUM   Lower bound of kernel version
    -t|--to   NUM   Upper bound of kernel version
    -l|--list       List available kernel versions
    -r|--remove     Remove mainline kernels

可以先使用 ./mainline-kernels.sh --list 來找出現在有哪些 kernel 可以使用。

$ ./mainline-kernels.sh --list
2.6.15               2.6.24.7             2.6.24                       2.6.25               2.6.26               2.6.27.47-intrepid
2.6.27.58-intrepid   2.6.27.59-intrepid   2.6.27.60-intrepid           2.6.27.61-intrepid   2.6.27.62-intrepid   2.6.27
2.6.28.10            2.6.28               2.6.29.6                     2.6.29               2.6.30.10            2.6.30
...
3.15~rc3-utopic      3.15~rc4-utopic      3.15~rc5-utopic              3.15~rc6-utopic      3.15~rc7-utopic      3.15~rc8-utopic
3.15-utopic          3.15.1-utopic        3.15.2-utopic                3.15.3-utopic        3.15.4-utopic        3.15.5-utopic
3.16~rc1-utopic      3.16~rc2-utopic      3.16~rc3-utopic              3.16~rc4-utopic      3.16~rc5-utopic

然後直接安裝想要的 Linux kernel

$ ./mainline-kernels.sh 3.16~rc4-utopic 3.16~rc5-utopic

或是指定一個範圍來安裝

./mainline-kernels.sh --from 3.15~ --to 3.16

或是什麼都不指定直接執行,之後再慢慢從選單上面挑選。

./mainline-kernels.sh

最後再將安裝的 Linux kernel 移除掉。

./mainline-kernels.sh --remove

要提醒的一點是,這邊的版本號碼是遵循 Debian version 的規則,所以波浪符號有特別的意義,可以參考我以前的文章

最後分享一下 Ubuntu to Mainline kernel version mapping,結束這一回合。

2009年6月17日 星期三

FreedomHEC Taipei 2009 - Day 2

第一個議程由 CIH 介紹 Linux Kernel Module 的逆向工程
背景故事是說老闆要他 porting 一個 WLAN driver 可是沒有 datasheet 可以參考
剛好那個 WLAN driver 少了四個整數值的 header file
問題是他也不熟 ARM 的組合語言 於是他就憑藉著 GCC 的 Cross Compiler 還有中斷向量表的基本觀念
在程式碼裡面填入 asm("nop"); 指令識別透過 arm-linux-gcc -S 的指令轉譯成 ARM 的組合語言
利用這樣的技巧找出無限迴圈跟函式執行進入點 ARM 的組合語言
然後將記憶體整個 dump 出來分析 (通常網通裝置的 Linux 系統所使用的記憶體不會太大, 一般在 64M 以下)
還有透過將無限迴圈放到中斷向量表裡面一步一步抽絲剝繭地將四個重要的整數值找出來

第二個議程由 Peter Stuge 來介紹 CoreBoot (前身為 LinuxBIOS)
CoreBoot 最早叫做 LinuxBIOS 就名稱上看來就是用來啟動 Linux 的 BIOS
後來因為它也可以載入 Linux 以外的 Payload (Payload 不負責任譯為"某種會花費硬體資源的載體")
就連 GRUB 也算是一種 Payload 更多的 Payloads 在 http://www.coreboot.org/Payloads 可以看到
這東西的概念簡單說就是 GPL 授權的 BIOS 讓從事 BIOS 開發不用再從頭寫起
目前已經支援某些特定主機板的清單可以在 http://www.coreboot.org/Supported_Motherboards 上面看到
另外有趣的小東西是 BSD 授權的 Libpayload 讓你寫出自己的載體讓 CoreBoot 來載入

第三個議程由 Jon Corbet 來介紹 Kernel Community
介紹整個 Linux Kernel 開發的合作模式
就是 Linus Torvalds 本人並不會直接收別人給他的 Patch
所以別天真的以為可以把自己的 Patch 直接送給 Linus Torvalds
Linus Torvalds 只會從幾位重要的 Developer 那邊接收 Changesets
Linux Kernel 是個相當活耀開發的計畫有上千個活躍的開發者
Linus Torvalds 不可能一個人去處理所有的程式碼合併跟衝突解決
當然這所有的工作都是靠優秀的 Git 分散式版本控制系統還有優秀的同伴們協力達成的 (他們演講時沒怎麼提到 Git)
簡單說就是 Linus Torvalds 會收一小群人給的 Changesets 然後那一小群人又會從其他人那邊收 Changesets 或是 Patch
最後在 Merge Window 的時候全部再匯集在一起然後釋出 rc1
然後就是 Stabilization 所以不會再接受任何新功能
經過好幾次的 rcN release 覺得差不多了就正式 release 然後再繼續下一個 cycle
一個 cycle 大約 8~12 個星期
一個 stable 的 release 只會維護半年的安全性跟嚴重錯誤修正
另外就是有兩個特別的開發樹
一個是 linux-next 提前為下一個 mainline cycle 的 patches 整合做測試
一個是 -mm 以 linux-next 為基底收集更多雜七雜八的 patches 來做測試
最後子系統的維護者們其實才是把關者也就是所有的 patches 應該要直接送給這些維護者們去做 merge 才對
但是這些子系統的維護者們也並不是擁有絕對的權利
也就是說凡是都還是有商量的餘地

第四個議程 Greg KH 介紹 Linux Driver Project
總之 Greg KH 說把你的 Linux Driver 送交到這個計畫吧
這邊會收任何 Kernel Module 的 patches
也歡迎硬體廠商提供測試機器協助他們測試驅動程式是否正常
就算硬體都還沒有生出來也沒關係

反正早點送 patches 早點 Code Review

不用等到都做完再去送 patches
或者是你的硬體需要有人寫 Linux Driver 嗎
這邊有太多閒著沒事想要寫 Linux Driver 的人
要簽署 NDA 文件也是可以接受的
Linux Driver Project 的網址在 http://www.linuxdriverproject.org/
台灣的硬體廠商們還不快點行動嗎~ :P

第五個議題 Harald Welte 介紹 GPL Compliance
簡單講就是你有用 Linux System 做硬體嗎?
那麼你最好依照相關的規定把該放出來的 Source Code 放出來
人在做 天在看 還有我們一群擅長逆向工程的高手在看 前面 CIH 就介紹過一些方法了
不然我們找到證據就會跑去告你喔~ :O
你看我們有很多合作的模範廠商
咦~ 有些被我們告過囉~ 不過沒關係~ 後來大家都和好了~ :P
另外就是提醒程式開發者們
如果程式碼裡面有一些錯字沒關係就留在那邊
那些錯字可以方便以後我們逆向工程找證據出來

最後就是所有的講者上台接受大家問問題~
照片可以在 http://www.flickr.com/photos/acelan/3617233294/
然後就聽到大長輩田欣先生在用英文一些問題
還有這個活動籌辦人之一的 Scott Tsai 提供即時的中英雙向翻譯
Scott 自己本身也問了一些問題
在聽眾們沒有什麼問題的情況下
講者反問了聽眾們一些問題
然後又聽見田欣先生在用英文回答
還有幾位強者 Matt Hsu, Thinker, ... 也是用英文在問問題回答講者的問題

這兩天的活動於是就圓滿的結束了~
中午提供的便當還蠻好吃的~ :P
第一天中午的便當主菜有雞腿副菜有豬肉
第二天中午的便當主菜有魚副菜也有豬肉
中午吃飯的時候旁邊的窗簾被整個拉開
可以從 14 樓的窗戶看到一排山還有內湖的摩天輪
景色相當好看~ :D

以上是筆者參加過後得心得分享
因為過了一星期才憑回憶攥寫
內容不一定與當天實際情狀相符

FreedomHEC Taipei 2009 - Day 1

FreedomHEC 的全名是 Freedom Hardware Engineer Conference
中文應該是翻成『自由硬體工程師研討會』
如果沒弄錯今年是第二次舉辦 (因為第一次我沒跟到... >_<)
這次的活動總共兩天的議程
網址 http://freedomhectaipei.pbworks.com/

FreedomHEC Taipei 2009 - Day 1

第一個議程由 Jon Corbet 介紹 2.6.X 每個正式 Release 版本改進了哪些功能

只是單純地介紹歷史帶過... 不過內容好像在跟 Jon Corbet 在 LWN 上面寫的都一樣
也就是說他的投影片就是那些每次 Linux Kernel Release 時都會在 LWN 上面寫的東西是一樣的

第二個議程由 Jim Huang (jserv) & Matt Hsu 講 Qi (气) 這個簡單化的 bootloader

內容主要是在講 Qi 將 bootloader 的功能盡量地簡化把複雜的功能交給一個客製化的 Linux Kernel 來處理
也就是說 Qi 只專注在載入一個客製化的 Linux Kernel 然後再讓客製化的 Linux Kernel 透過 kexec() 來載入另一個 Linux Kernel
好處是那個客製化的 Linux Kernel 可以透過許多原本就已經支援的網路裝置
將另一個放在 TFTP 或是 NFS 上面的 Linux Kernel 載入記憶體中並且執行起來
或是載入執行在 SD / USB 等裝置上面的 Linux Kernel
在一些 Flash 儲存裝置的 Linux Driver 還沒有 Ready 前就可以做先期的開發工作

第三個議程是由 Fred Chien 介紹 Linux 快速開機的方法

像是分析啟動時的開機時間統計然後調整 /etc/init.d 裡面 script 執行的順序
或是利用一些 readahead 之類的工具事先將需要載入系統的函式庫提先載入
還有把不需要的 Linux Kernel Module 拿掉 把需要的 Linux Kernel Module build-in
改 XWindow 的滑鼠驅動程式 ... (這個筆者兩三年前在前公司也弄過, 還有改 VGA Driver)
另外就是利用休眠的功能將記憶體的資料寫到儲存裝置上
下次開機再將那些資料讀回記憶體之中
還有關閉掉一些在 BIOS 裡面不需要啟動的硬體功能減少 BIOS 啟動時間
或是將一些系統服務的啟動放在 XWindow 起來之後再去做

第四個議題是由在 VIA 服務的 Joseph Chan 介紹 VIA 是怎麼將他們公司的硬體驅動程式提交進 Linux Kernel mainline 裡面

有兩點需要注意的

第一點 Coding Style
Linux Kernel 有著慣用的 Coding Style 沒理由 Linux Kernel 的 Source Code 要去 follow 某間公司的 Coding Style
所以想要提交程式碼進去 Linux Kernel 的廠商首先就是要調整 Coding Style 去適應 Linux Kernel
而不是自己關上門來硬幹等到最後提交的時候才發現 Coding Style 要大修改

第二點 Mailing List 上面的 Review Feedback
並不是將程式碼提交出去就算是交差了事了,更重要的是要聆聽開發者的意見還有耐心等待
並不是開發者都閒閒沒事做在那邊等著別人送 Patch 給他 Review,所以要等到開發者有時間才會去看你的程式碼去給 Review Feedback
還有要注意的是收到回應後應該要馬上給對方回應儘快去修改程式碼再去做提交

而 Joseph Chan 正是將 VIA 所遭遇到的慘痛經驗分享給與會者

第五個議題是由 Greg KH 帶著大家一步一步去寫出 Linux Kernel 上面的  USB 溫度計的 Kernel Module

Greg KH 與前面的講者 Jon Corbet 剛好都是  Linux 驅動程式這本書籍的作者
所以其實 Greg KH 介紹的東西在看過這本書之後,其實很快就可以上手了
主要的重點在於 Greg KH 介紹了 USB Subsystem 的基本架構
介紹 Interface/Config 跟  IN/OUT/Endpoint{Interrupt,Bulk,Isolate} 這些觀念
然後就是一個範例一個範例地帶大家一步一步地寫出 USB 溫度計的驅動程式

2009年4月27日 星期一

如何在 Linux System 當中偵測網路線是否有接上?

其實方法很簡單,檢查 /sys/class/net/eth0/carrier 這個檔案就可以了

如果值為 1 的話代表有接上網路線

如果值為 0 的話代表沒有接上網路線

不過這也要看該網路卡的驅動程式有沒有實做這個部份