音樂播放器之 CD 轉成 mp3《三》中

當然確定了『供電』事宜只是個『開始』,如何能減少『使用者』之『操作失敗』的『經驗』,可就是『大哉問』的了。即使祇就

【音樂播放器】需求規格一??

將音樂 CD 轉成 mp3,寫到大拇哥上!!

的考慮也是一樣。這是為什麼的呢?比方說,萬一放錯了 CD 片,一個『使用者』必須要等到做完『製造程序』才可以『換片』的嗎?與其爭議是『誰的過錯』?這難到真是『不可預見』的嗎?再者,大部分的『 USB DVD 讀寫裝置』上面都有『手動的 Eject 按鍵』,假使『作到一半』誤觸了『按鍵』,果然就『沒有辦法』能解決的嗎??『設計者』之『』和『使用人』之『』是否能夠『相通』,這正是古往今來的『器物製造』的『為何如是』之『』的吧!因而作者也就『蕭規曹隨』試圖『避免』那些也許只是『一時之誤』罷了。就裝置的『性能』與『控制』上講,當然要能『鎖定目標』隨心所欲的了!既然意圖想要『控制越多』,因而自己所需要知道的技術『細節也不少』。就像有人問《How can I disable the button of my CD/DVD drive? 》一樣,作者也曾經踏上那種『探索之路』︰

$ eject -i 1 /dev/sr0
eject: CD-Drive may NOT be ejected with device button

$ eject -i 0 /dev/sr0
eject: CD-Drive may be ejected with device button

。一般來說,『過去』 linux 系統上之『裝置驅動程式』假使沒有『提供』某種『功能』,想要自己『寫作』一個『程式』來作這麽一件事,可真的是『不容易』啊!然而在今天那個『不容易』該說是『蠻困難』,絕非是『很困難』的了。這從現今的 linux 『系統架構圖』上來看更是一目了然。

Free_and_open-source-software_display_servers_and_UI_toolkits.svg

那麼為了寫一個『應用程式』,我們需要了解多少『系統細節』的呢?廣泛的說,這是由『應用需要』所決定的事情,一般所講的廣義『應用程式界面』  API 的理念,就是為著能夠減輕不同應用程式『設計者』所需之『知學負擔』而建構的。於是進一步就有了所謂的□□『軟體開發套件』 SDK  Software Development Kit ,因此人們的『程式設計』常常就從學習○○ SDK 開始。由於我們這裡所談的事情並非是某種特定的☆☆『嵌入式系統』 Embedded system,有著很大的『自由度』,實在不好說什麼是『適切的 SDK』?因此有時不得不上窮碧落下黃泉的四下搜尋,如是對 linux 系統『運作』的『整體理解』就顯得必要的了!這好處是什麼呢?也許是在打造自己專屬的 SDK 的樂趣吧!當然像 《V怪客》 V for Vendetta 之輩或許這還是必修課的呢!即使只從『電腦病毒』的發展『歷史』來看,就可以『明白』網際網路上有『四通八達』的渠道,加上某些有心人士的『黑客資訊』。甚至一些『國際大電腦公司』都免不了中了『電腦病毒』以及遭受『駭客攻擊』。多知道一些系統底層所作的事,對於『安全性設計』而言,也是件不可或缺的『實務』的吧!!

據聞 linux kernel 自 2.6.13 提供了新的 uevent interface,而後

In April 2012, udev’s codebase was merged into the systemd source tree. In October 2012, Linus Torvalds criticized Kay Sievers’ approach of udev maintenance and bugs related to firmware loading, stating:

Yes, doing it in the kernel is “more robust”. But don’t play games, and stop the lying. It’s more robust because we have maintainers that care, and because we know that regressions are not something we can play fast and loose with. If something breaks, and we don’t know what the right fix for that breakage is, we revert the thing that broke. So yes, we’re clearly better off doing it in the kernel. Not because firmware loading cannot be done in user space. But simply because udev maintenance since Greg gave it up has gone downhill.

。從此『動態裝置熱插拔管理』 udev 納入了 systemd,由 kernel.org 來做維護管理。

起先 linux 上並沒有所謂的『熱插拔』 hotplug 裝置管理,系統上所用的所有裝置都需要建置『靜態的裝置特殊檔』 static device special file ── mknod – make block or character special files ──。聽說當年最紅火的『Red 9』發行版上有

On Red Hat 9, 18000 entries in /dev!
All entries for all possible devices
had to be created at system installation.

。這對『系統管理者』來說恐怕很難笑的出來的了。

在此我們無法詳細介紹 udev 的用法,有興趣了解的讀者可以參照《這裡》開始。此處僅針對『 USB DVD 讀寫裝置』的『熱插拔』過程有關的事物作點說明。我們可以用『 udevadm monitor 』指令來『觀察』 kernel 『 USB 熱插拔』過程的『 uevent 』,這對理解 udev 的工作方式有很大的幫助。下面列出『 USB DVD 讀寫裝置』的熱插拔過程的輸出訊息︰

$udevadm monitor
monitor will print the received events for:
UDEV – the event which udev sends out after rule processing
KERNEL – the kernel uevent

此時將 USB DVD 讀寫裝置熱插入

輸出訊息

KERNEL[306628.132803] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5 (usb)
KERNEL[306628.139360] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0 (usb)
KERNEL[306628.145393] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3 (scsi)
KERNEL[306628.145647] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/scsi_host/host3 (scsi_host)
UDEV [306628.155527] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5 (usb)
UDEV [306628.175071] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0 (usb)
UDEV [306628.178074] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3 (scsi)
UDEV [306628.182839] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/scsi_host/host3 (scsi_host)
KERNEL[306629.151250] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0 (scsi)
KERNEL[306629.151503] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0 (scsi)
UDEV [306629.153895] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0 (scsi)
UDEV [306629.178328] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0 (scsi)
KERNEL[306629.185589] add /devices/virtual/bdi/11:0 (bdi)
KERNEL[306629.187210] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/block/sr0 (block)
KERNEL[306629.187428] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/scsi_device/3:0:0:0 (scsi_device)
KERNEL[306629.188185] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/scsi_generic/sg0 (scsi_generic)
KERNEL[306629.188970] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/bsg/3:0:0:0 (bsg)
UDEV [306629.197653] add /devices/virtual/bdi/11:0 (bdi)
KERNEL[306629.199077] change /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/block/sr0 (block)
UDEV [306629.231068] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/scsi_device/3:0:0:0 (scsi_device)
UDEV [306629.244105] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/bsg/3:0:0:0 (bsg)
UDEV [306629.262723] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/scsi_generic/sg0 (scsi_generic)
UDEV [306629.903661] add /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/block/sr0 (block)
UDEV [306630.106289] change /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/block/sr0 (block)
udevadm monitor
monitor will print the received events for:
UDEV – the event which udev sends out after rule processing
KERNEL – the kernel uevent

此時將 USB DVD 讀寫裝置熱拔出

輸出訊息

KERNEL[306678.488526] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/bsg/3:0:0:0 (bsg)
UDEV [306678.493461] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/bsg/3:0:0:0 (bsg)
KERNEL[306678.496300] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/scsi_generic/sg0 (scsi_generic)
KERNEL[306678.497406] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/scsi_device/3:0:0:0 (scsi_device)
KERNEL[306678.499867] remove /devices/virtual/bdi/11:0 (bdi)
KERNEL[306678.500995] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/block/sr0 (block)
KERNEL[306678.501611] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0 (scsi)
KERNEL[306678.503098] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0 (scsi)
KERNEL[306678.508922] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/scsi_host/host3 (scsi_host)
KERNEL[306678.510244] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3 (scsi)
KERNEL[306678.510618] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0 (usb)
KERNEL[306678.512012] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5 (usb)
UDEV [306678.514032] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/scsi_device/3:0:0:0 (scsi_device)
UDEV [306678.525752] remove /devices/virtual/bdi/11:0 (bdi)
UDEV [306678.553766] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/scsi_host/host3 (scsi_host)
UDEV [306678.569584] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/scsi_generic/sg0 (scsi_generic)
UDEV [306678.578413] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0/block/sr0 (block)
UDEV [306678.591236] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0/3:0:0:0 (scsi)
UDEV [306678.593733] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3/target3:0:0 (scsi)
UDEV [306678.595992] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0/host3 (scsi)
UDEV [306678.597956] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5/1-1.2.5:1.0 (usb)
UDEV [306678.601293] remove /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.5 (usb)


難到我們真的需要知道這些事情的嗎?假使我們不知道在 raspbian 上, udev 系統自動為我們做了些什麼?比方說『一貫性』 CD 裝置名稱的設定︰

more /etc/udev/rules.d/70-persistent-cd.rules

,插拔多種品牌的『 USB DVD 讀寫裝置』後,到底『 /dev/cdrom 』是哪個裝置呢?或者現在的『 /dev/sr0 』又指的是誰丫,那我們就必須得面對這樣的『困擾』;或許根本還不要說那個檔卻是由『 /lib/udev/write_cd_rules 』自動產生的呢!更進一步的講,如果不知道『熱插拔』的『事件』之過程,我們怎麽發現『使用者』已經插上『 USB DVD 讀寫裝置』?而且放入了『音樂 CD』呢?這樣當然『很難』自動『播歌』的吧!萬一這是將來客戶所要『需求規格』之一的呢??

 

─── 待續