2017年1月17日 星期二

書摘:Effective Debugging - Item 18 從你的桌面替其他不便的系統除錯

不是自己平常使用的系統當然很不習慣,例如缺少某些自己慣用的工具,這個章節提供幾個方法讓想要除錯的系統盡可能地接近自己習慣的環境。


  • 對於手機 app 或是有些 embedded devices,使用 device emulator;這樣就可以使用自己習慣的螢幕、鍵盤和編輯器。缺點是可能無法使用 symbolic debugger。
  • 搭配 device emulator,使用 shim 這種技巧的概念:使用一個中介(例如檔案 IO),來存放執行時相關的資料或是參數,實際的 code 則是跑在本機。本技巧通常只是用演算法測試,不包括 UI 測試。我自己是覺得 core.dump 就是類似的東西。書中是舉手機中某個會用到網路與 API 的應用程式先在本機上寫好並且測試好,然後包成一個 class 整合進去原本的程式碼。
  • Teamviewer 這東東應該不用再多說明了,名氣響亮。
  • Teamviewer + strace or truss command on a third-party computer.
  • KVM over IP device;使用情境:inaccessible data center. 我自己有用過這種東西(使用跟架設都有),有點厲害。例如,自己桌機的鍵盤訊號可以透過網路,在遠端的機器上就像真實的鍵盤輸入一樣(螢幕輸出則是由遠端電器訊號忠實送到你面前)。這種物理手段可以作到連 BIOS 階段都可以進去、調整。只是因為訊號傳送要一段時間,所以想要進 BIOS 有點要透過盲按 XDD 因為 BIOS 畫面往往幾秒而已,等送到你的螢幕上時早就跳掉了。


2017年1月9日 星期一

修 hot key 實例 (Ubuntu Yakkety on Dell Latitude 7370)

今天在 Launchpad 上看到有人回報筆電 Dell Latitude 7370 麥克風靜音 hotkey (Fn + F4)無效(LP:# 1654827)[1]。這個回報很有意思,顯然回報者是一位專業玩家,他的回報非常具體、提供的資訊在除錯上非常地有用,很適合做為一個小小的教學範例;因此動了念頭想介紹一下這個範例。

原因

hwdb 中原本預期的 event value 150,在 driver 中給出的值是 100150。[2]

會使用到的工具


  • acpi_listen
  • showkey
  • evtest
  • systemd-hwdb https://www.freedesktop.org/software/systemd/man/systemd-hwdb.html#

需要的背景知識



  • hwdb 經由 systemd-hwdb 這個指令會編譯成 binary (叫做 hwdb.bin),提供給  wmi 這個 module 使用。
  • hwdb https://www.freedesktop.org/software/systemd/man/hwdb.html
  • wmi https://wiki.ubuntu.com/Kernel/Reference/WMI

[1] https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/1654827
[2] https://github.com/systemd/systemd/pull/5012


2017年1月3日 星期二

Mesa 和 Linux graphic stack 簡介

前陣子提到 PRIME 技術,今天把更多相關知識補齊。

以下大多是從[1]這篇文章所做的摘要。

graphic stack 的「演化」


  • 2D: 透過 X server 來控制硬體(螢幕上畫圖等,rendering)。參考下面的「X window 架構」
  • 3D: 使用 OpenGL 實作的應用程式透過 X server 來控制硬體、rendering。這叫 indirect rendering (相對於 direct rendering 的一個詞彙)。參考下面的 「GLX 架構」
  • 3D + DRI (Direct Rendering Infrastructure): 使用 OpenGL 實作的應用程式不透過 X server 來控制硬體、rendering。

X window 架構


  • X client 控制資料運算、X server 控制硬體。(注意一台 ssh server 是透過 X client 和某處的 X server 溝通,不要混淆了一般的 server 詞彙涵義和 X server 的「server」)
  • X client 透過 X11 protocol 和 X server 溝通,實作是 Xlib。
  • X server 透過 DDX (device-dependent X) driver 和硬體溝通。


GLX 架構 / Indirecting Rendering


  • Hardware --> OpenGL --> OpenGL API --> libGL.so--> OpenGL application,但這條路在中間還有 X server 的時候會不通,因此用 GLX 來串連。
  • OpenGL application --> GLX --> X server --> GLX driver --> kernel
  • 效率會因為多一層要通過 X server 就會比較差,因此有 DRI 架構

DRI 架構

  • 上面的 in-directing rendering 效率較差,因此試試 directing rendering
  • Hardware --> kernel (DRM) --> OpenGL DRI driver --> OpenGL / libGL.so --> OpenGL application
  • DRM 可以說是 DRI 在 kernel 面向的實作,包括有給 userspace 呼叫的 API

MESA


有了上面的概念之後,就可以理解 Mesa 在 graphic stack 中扮演的角色了。Mesa 包括:
  • 包/利用 libGL
  • 基於 DRI/DRM 架構
  • Mesa 面向的 GLX;原則上還是讓 X 去控制原本 X server 已經在控制的東西,例如圖形內容;Mesa 本身只是想要同步好 X server 已經在控制的內容和透過 DRI 進出的資料與運算。





[1] https://blogs.igalia.com/itoral/2014/07/

2016年12月28日 星期三

書摘:Effective Debugging - Item 17 放大程式跑失敗的後果



Item 17: Increase the Prominence of a Failure's Effects


  • 使用版本控制來增加放大失敗效應的程式碼以便回溯,這樣才不會誤把測試程式放進 production code
  • 放大手段一:移除可能的程式碼片段。例如使用一個永遠成立的 if 條件式(ex. if(0))去執行有嫌疑的程式碼片段。
  • 放大手段二:修改程式碼,讓原本的輸出資料變得很容易觀察。例如把輸出資料故意變成原本的一千倍。
  • 放大手段三:壓力測試、並且使得失敗很快速地可以複製出來。例如使用 Apache JMeter 來執行對網站的 DDoS。故意指定超過的 thread number 來測試 concurrency。故意讓程式跑在資源缺乏的地方,例如寫入故意寫在小容量的 USB 磁碟裡。
  • 放大手段四:fuzzying。例如使用 zzuf 來亂數產生測試用的輸入資料。

書摘:Effective Debugging

最近在讀 Effective Debugging[1],發現編排方式非常適合早餐的時候閱讀 XD 作者將自身的經驗歸納成 66 個條目,每個條目長短剛好是一個早餐的閱讀份量。遣詞造句也算潛白,即使像我這種非英語母語人士也可以感受到閱讀樂趣。

當初進了 Canonical 公司[2]工作之後,基於之前大多經驗是開發 web 或是寫寫 script 跑科學計算 job,往往有完整的、成熟的 IDE 可以使用,因此有一小段時間對於除錯環境不一定well-prepared 的系統程式除錯感到不太適應。這三年摸索過去後,偶然間看到這本書,覺得很是幫自己過去三年在公司中遇到的問題做了很好的回顧和整理,當然也有啟發;因此一讀就欲罷不能 XD

接下來打算在每次閱讀之後,開始摘要 66 個條目中的內容與自己的心得。敬請期待。


Item 17 放大程式跑失敗的後果


[1] Effective Debugging: 66 Specific Ways to Debug Software and Systems (Effective Software Development Series) 1st Edition by Diomidis Spinellis,我讀的是 Amazon 上面的 Kindle 版本。
[2] https://zh.wikipedia.org/zh-tw/Canonical%E5%85%AC%E5%8F%B8

2016年12月22日 星期四

初探 PRIME 技術


最近收到通知說 12.0.5 的 mesa 打算 backport 回 Ubuntu 16.04,並且取代原本 16.04 中11.2.0 版本的 mesa,希望在正式釋出 backport 版本前提供更多測試。因此對這個技術稍微了解了一下,摘要如下。

詞彙

provider:
提供運算資源的單位,例如一張獨立顯卡。

sink output:
在這裡指有連接外部裝置 port 的 provider,但基本上不太負擔運算繪圖,只輸出。不要跟電路學中的 sink-source 混淆(電路學中是指裝置接地和電壓方式的不同)

source output:
在這裡是指負擔運算繪圖,但輸出由其他 provider.

multiplexer:
較早期不是採用動態切換時,需要關掉一個 GPU 再去啟動另外一個 GPU來達成切換,負責開關的裝置叫做 multiplexer[a],通常是一種硬體。比較新的裝置是不需要(硬體上的) multiplexer,稱為 muxless。附註資料[c][d]中的硬體透過 GCN (一種新的指令集架構)支援這種功能。


因此在處理這類問題,我們會需要知道(下文有對應指令):

  • provider 的資訊,包括他是 sink or source output
  • render 時的資訊;例如是誰在負責運算、運算結果的表現如何。

我們會需要執行下面這些動作(下文有對應指令):

  • 指定誰當 sink、誰當 source


使用情境

案例一:PRIME


一個支援 muxless 的系統有兩個顯卡,分別是主要的 integrated graphic 和第二顯卡。輸出 port 在 integrated graphic 上面。

因為 integrated graphic 是常駐的、低耗電的晶片裝置,所以平常的運算都交給他。有時如果要把運算負擔(loading)從 integrated graphic 交給第二顯卡,integrated graphic 只剩下把資料從 port 輸出,這個動作就叫做 offload。PRIME 技術就是提供 muxless 的裝置實作 offload 功能。

目前只有 AMD 的顯卡支援這技術[c][d],nvidia 還沒。

案例二:REVERSE PRIME


一個支援 muxless 的系統有兩個顯卡,分別是主要的 integrated graphic 和第二顯卡。輸出 port 在第二顯卡上面。例如 integrated graphic 是內建螢幕和 VGA 輸出,第二顯卡上則有 HDMI 和 display port 輸出,而使用者現在想用 display port 來輸出。

使用者現在想用 display port 來輸出,可是又不想用第二顯卡處理大量運算;因為第二顯卡雖然運算能力比較好,但是比較耗電。也就是說希望第二顯卡負責輸出就好,運算負擔還是 integrated graphic  在處理,只是 port 不是直接由 integrated graphic 控制。Reverse PRIME 技術可以實踐這種設定。


案例三:案例二的進階


一個支援 muxless 的系統有兩個顯卡,分別是主要的 integrated graphic 和第二顯卡。 integrated graphic 是內建螢幕輸出和 VGA 輸出,第二顯卡上則有 HDMI 和 display port 輸出。使用者想要四個 ports 都輸出,但是希望畫面流暢一點。

全部四個 ports 都由 integrated graphic 輸出的話,有可能會不流暢。因此使用者會希望運算盡量都是交給第二顯卡。


實作

案例一:PRIME

列出 provider 資訊

xrandr --listproviders

指定 provider 1 負責運算,provider 2 負責作為 sink output 輸出。(我把這個選項理解成:set provider 1 offload sink output)

xrandr --setprovideroffloadsink 1 0

在 default intel/modesetting driver 中,因為 DRI3 功能已經預設開啟,所以其實上述的設定已經是系統預設了,但手動再做一次並不會怎樣。[b]

這時候只要透過環境變數 DRI_PRIME 就可以動態地切換看是要哪個 provider 去繪圖。例如:

DRI_PRIME=1 <任何執行 render 的指令>

展示使用 provider 0 時(integrated graphic),對應的 opengl 參數 (glxinfo 這個工具可以透過安裝 mesa-utils 來取得)

DRI_PRIME=0 glxinfo

展示使用 provider 1 時(第二顯卡),對應的 opengl 參數

DRI_PRIME=1 glxinfo

在這個 merge request 中,checkbox 被加入檢查系統是否具有支援 PRIME 技術的功能;如果有支援,那麼試著在接下來的測試中使用這個技術(同時也是測試這個技術),參見原始碼。

從原始碼裡我們可以看到,要下面幾個條件被滿足才會判定系統支援 PRIME 技術,包括:

  • 系統有 amdgpu 這個套件(open source 版本的 AMD 顯卡 driver)
  • Ubuntu 系統是 Xenial
  • 有兩個以上的 GPU

案例二:REVERSE PRIME

略,參見[b]

案例三:案例二的進階

略,參見[b]



參考資料:
[a] https://wiki.archlinux.org/index.php/hybrid_graphics
[b] https://wiki.archlinux.org/index.php/PRIME
[c] https://en.wikipedia.org/wiki/Graphics_Core_Next
[d] https://en.wikipedia.org/wiki/AMD_Radeon_Rx_200_series
[e] xrandr manual

2016年4月7日 星期四

用 python 撰寫 GTK+3 架構下的視窗介面

最近想要寫一個小程式,隨手挑了一套 solution:

python - 程式語言
GTK+3 - 視窗介面程式框架
glade - 畫視窗介面的 IDE

其中 glade 可以把用 IDE 畫好的視窗 layout 直接存成 GTK 可以理解的 xml 格式檔案,藉此增加開發設計視窗外貌的速度。

選擇 GTK+3 的理由滿單純,因為我使用的系統** 上的 glib 會抱怨我所使用的 glade 必須是 3.x 版 ***


** 我是用 Ubuntu 14.04 64 bit
*** import gtk 這種語法似乎就是支援 GTK+2.x,細節可參考這個 stackoverflow 連結。



步驟一:使用 glade 畫 layout 後轉成 XML


首先啟動 glade,接著創建一個視窗(在工作 panel 中按視窗即可),注意這個視窗有個名字(預設是 window1),這個名字會被 python GTK+3 拿來取得該視窗物件,所以如果你有更改視窗名稱的話,程式中呼叫的名字也要跟著改。

畫好之後就存檔,檔案本身就會是 XML 了。

步驟二:開始寫程式


整個 python GTK+3 架構大致如下:
使用 builder 取得視窗物件、註冊 signal、設定組態等等。最後開始執行 Gtk main loop 等待事件。

範例如下:

from gi.repository import Gtk

class HellowWorldGTK(object):
    """This is a Hello World GTK application"""
    def __init__(self):
        # layout generated by glade
        layout_filename = "layout.xml"
        builder = Gtk.Builder()
        builder.add_from_file(layout_filename)
        #builder.connect_signals(self)
        self.window = builder.get_object("window1")
        if self.window:
            self.window.connect("destroy", Gtk.main_quit)
        self.window.show_all()
if __name__ == "__main__":
    hwg = HellowWorldGTK()
    Gtk.main()


其中 layout.xml 是步驟一用 glade 存成的 XML 檔案名稱,window1 也是步驟一中提到的視窗名稱。這裡比較要注意的是使用這行程式碼來讓我們可以關掉視窗的時候,同時退出 Gtk main loop。如果沒有這行,程式一但執行後就會一直跑,只能另外請作業系統殺掉它了。

self.window.connect("destroy", Gtk.main_quit)


步驟三:執行


步驟二中的範例程式碼存成 go.py,執行 go.py 即可。




更多資訊可以參考 Python GTK+3 Tutorial (剛好昨天才 release!)