2017年8月25日 星期五

pthread cancel

pthread_cancel() 送取消請求給 thread,thread 依據其取消狀態 (cancellation state) 及取消 type 因應。

thread 的取消狀態有啟用 (預設) 和停用,可由 pthread_setcancelstate() 設定。停用時收到取消請求暫不處理 (queued),直到啟用。收到取消請求且啟用時,type 決定取消何時進行。

thread 的取消 type 有 deferred (預設) 及 asynchronous,可由 pthread_setcanceltype() 設定。Asynchronous 表示可在任何時間點取消,但系統不保證立即進行。Deferred 表示直到 thread 呼叫到含有取消點 (cancellation point) 的函數才進行取消動作。

取消動作依序包括:
  1. pop 每個 Cancellation clean-up handlers 並執行。(見 pthread_cleanup_push())
  2. 呼叫 thread-specific data destructors (見 pthread_key_create())
  3. thread 結束 (見 pthread_exit())
pthread_cancel() 回傳值 0 表示成功送出請求。用 pthread_join() 得到 thread 的 exit status 是 PTHREAD_CANCELED 才能知道取消動作完成。

Linux 用 signal 實作 thread 取消,在 NPTL 是第一個 real-time signal (也就是 signal 32)。

pthread_cancel() MT-safe

async-cancel-safe 函數:能夠在啟用 asynchronous 取消的應用安全使用的函數,包括 pthread_cancel()、pthread_setcancelstate()、pthread_setcanceltype()。

必須含有取消點的函數:包括 sleeps() 等,列表見 man pthreads
  • pthread_testcanel():測試是否取消
可能含有取消點的函數:列表見 man pthreads

應用:有些 thread 設計是無窮的迴圈,其它 thread 呼叫 pthread_cancel() 作為結束。

參考來源
  1. man pthread_canel
  2. man pthreads

2016年9月25日 星期日

AM335x Ethernet

AM335x 內建有 3 埠 Ethernet Switch,連接兩個 GMII 埠及 SoC Host,驅動程式使用 cpsw (CONFIG_CPSW,device tree 是 ti,cpsw)。

網路界面可使用單一 eth0,或者 eth0 加上 eth1。後者是 dual_emac 模式,可透過 device tree 設定。dual_emac 會有兩份 net_device 及 priv,有各自的 MAC address,但有許多東西是相同或共用的。

接收封包 (使用 NAPI)
  • 原本就有 sk_buff,open 時就準備好給驅動程式 DMA 使用。
  • 如果是 dual_emac 模式,會去看來自哪個 GMII port,取得精確的 net_device 及 priv
  • 取新 sk_buff 給之後封包 DMA 用。如果取不到,拋棄此封包,原本的 sk_buff 給之後封包 DMA 用。
  • 設 time stamp、protocol,netif_receive_skb() 及統計
註:
  • AM335x 不是 ARCH_DAVINCI,但用 DaVinci 的 MDIO 及 CPDMA。ti 有下列網路界面
    • CPSW (ARCH_DAVINCI or SOC_AM33XX): +DaVinci MDIO +DaVinci CPDMA +CPSW Phy sel
      • CPTS (CPSW): +PTP_1588_CLOCK
    • DaVinci EMAC (ARCH_DAVINCI or ARCH_OMAP3): +DaVinci MDIO +DaVinci CPDMA
    • TLAN (PCI or EISA)
    • CPMAC (AR7)
  • kernel source code 在 git://git.ti.com/ti-linux-kernel/ti-linux-kernel.git
參考來源
  1. http://processors.wiki.ti.com/index.php/Linux_Core_CPSW_User%27s_Guide

2016年9月12日 星期一

GPS

衛星導航 (satellite navigation 或 satnav) 系統
Global Navigation Satellite System (GNSS) 涵蓋全球的導航衛星系統

全球定位系統 (Global Positioning System,GPS) 原為美軍用來定位及導航,後來擴大給民間使用。因為 GPS 是最普遍的衛星定位系統,而變成通稱,還有其它系統,支援越多系統也就可以看到越多衛星。

衛星定位原理

GPS 衛星不斷往地面傳送衛星位置及時間等資訊,GPS 接收器收到後依據位置變化及訊號接收的時間差推算出跟衛星的距離。當只有一顆衛星時,只知道接收器位置是在一個球面。當有兩顆衛星時,接收器位置縮小為兩個球面相交的地方,也就是一個圓。當有三顆衛星時再縮小為兩點,其中只有一點是在地球表面,可決定出位置。實際上需要第四或更多的衛星來增進準確度,特別是高度。高樓、峽谷、密林、高壓電塔等也會干擾 GPS 信號,能看到越多的衛星也就越能增進可靠度。

衛星定位系統
  • GPS (美):21 顆運作衛星及 3 顆備份衛星在互成 30 度的 6 個軌道,在任何時間任何地點皆可同時觀測到 4 至 7 顆衛星,精確度 5M。
  • GLONASS (GLObal NAvigation Satellite System,俄):跟 GPS 類似,但每顆衛星信號頻率不同 (可防止整個系統同時被敵方干擾)、使用前蘇聯的地心座標系、莫斯科標準時間
  • BDS (中國北斗系統,發展中,計畫 2020 完成)
  • Galilen (歐,完成時間未定):24 顆運行衛星及 6 顆備份衛星組成,精確度 1M (public) 1cm (加密)
  • QZSS (Quasi-Zenith Satellite System,日本準天頂):3 顆只覆蓋東亞的輔助 GPS 衛星,增進信號的可用性、準確度和可靠度。
單靠衛星就可以完成定位,但加上其它輔助可加快定位時間、增加定位精準度。
  • A-GPS (Assisted GPS)
    • 透過網路 (線上或離線) 取得衛星位置 => 大幅減少首次定位時間
    • 由基地台計算位置 => 減低行動裝置所需計算能力
    • Wi-Fi ESSID 或基地台 Cell ID 透過網路查詢大約位置 => 加速定位時間
  • 全球衛星導航增強系統 (GNSS Augmentation System) 或 WADGPS (Wide Area Differential GPS):在地面增設固定位置的地面站,提供更精確的定位資料,讓計算出來的位置更精準。
  • 慣性導航:藉由陀螺儀、加速計、電子羅盤、氣壓計、計步器、單車轉速等資訊推算,尤其在收不到衛星或其它無線訊號時。
應用
  • 定位 (經緯度及海拔)
  • 移動軌跡:位置移動的連續定位結果。可即時或事後對應到地圖上使用。或者按照之前的儲存的路徑去行進,不需要地圖。
  • 測速:移動軌跡上每個定位點加上時間可算出速度
  • 導航:定位搭配地圖資料行進
參考來源
  1. 手機GPS登山推廣計畫
  2. 關於衛星導航系統的兩三事
  3. OpenStreetMap wiki:Accuracy of GPS data
  4. http://tech.shaolin.tw/posts/2013/07/13/wi-fi-positioning-system-spoofing-1/

2016年8月28日 星期日

git describe

用最近的 tag 及其間隔的送交數目來描述一個送交,格式是 <tag>-<間隔的送交數目>-g<短 HASH 碼>,後面可以選擇加是否 dirty。<短 HASH 碼> 前面的 g 代表 git,用來區別 SCM。
指令格式
git describe [--all] [--tags] [--contains] [--abbrev=<n>] [<commit-ish>...]
git describe [--all] [--tags] [--contains] [--abbrev=<n>] --dirty[=<mark>]

尋找最近的 tag,首先先看送交本身有沒有 tag,沒有則往上游找。annotated tag 比 lightweight tag 優先,新的比舊的優先。往上游找 tag 的過程中,可能會因合併的送交而有好幾個候選的 tag,最後以間隔的送交數目少的出線。

預設只找 annotated tag
--tags:也找 lightweight tag
--all:也找 refs/ 下的任何 ref,可能是已知的分支、遠端追蹤的分支、或 lightweight tag。
--contains:也找 lightweight tag,但找下游的 tag
--first-parent:只往第一上游找
--match <pattern>:只找符合 <pattern> 的 tag。(似乎 wildcard <pattern> 有些清況比對會有問題)
--exact-match:只看送交本身的 tag
--candidates=<n>:設定候選 tag 的數目,預設只考慮 10 個,設大於 10 執行會慢一些,但較精準,用 --debug 可看每個候選 tag 的結果。設為 0 相當於 --exact-match。
--debug:在 stderr 顯示對每個 tag 尋找的結果

--abbrev=<n>:設定短 HASH 碼的碼數,預設是 9。設為 0 則不加 HASH 碼。

--dirty[=<mark>]:只能用在 HEAD,增加描述 dirty 的清況,預設加 -dirty,可提供 dirty 時要加的描述,例如 M。較舊版本的 git 無此選項,可用 git status | grep 'Change.*:' 判斷。

--long:送交本身有 tag 時預設不顯示間隔的送交數目及短 HASH 碼,加 --long 參數總是顯示這些部份。
--always:當找不到任何 tag 時,顯示短 HASH 碼

參考來源:git help describe

git tag

git 的標籤 (tag) 有 annotated tag 及 lightweight tag 兩種,以有沒有註釋區別。後者沒有註釋、只是代表某個送交不好記憶的 HASH 碼,比較偏向私人或暫時使用。前者有註釋,比較偏向釋出版本用,除了註釋外,還包含日期、貼標籤者的資訊 (名子及 e-mail),可以選擇加上 GnuPG 簽名。

新增 tag

指令格式:git tag [-a | -s | -u <keyid>] [-f] [-m <msg> | -F <file>] <tagname> [<commit> | <object>]

沒加特別的參數則是新增名為 <tagname> 的 lightweight tag 到目前送交,可用 <commit> 或 <object> 指定 tag 是要加到哪個送交。

加參數 -a、-s、或 -u <keyid> 的話都是用來新增 annotated tag,這三者不同在於 -a 沒有簽名,-s 是用目前使用者的簽名,-u <keyid> 是用 <keyid> 的簽名。annotated tag 需要加訊息,會跳出編輯器輸入,或用 -m <msg> 透過指令行加訊息,或用 -F <file> 自檔案取得訊息。由於 annotated tag 才能加訊息,沒有 -a、-s、或 -u <keyid>,但有 -m <msg> 或 -F <file> 也是新增 annotated tag,隱含 -a 新增沒簽名的 annotated tag。

-f 或 --force 是強制取代已存在相同名子的 tag
--cleanup

列表

指令格式:git tag 或 git tag [-n[<num>]] -l [--contains <commit>] [--points-at <object>] [--column[=<options>] | --no-column] [--create-reflog] [--sort=<key>] [--format=<format>] [--[no-]merged [<commit>]] [<pattern>...]

(沒有 <tagname> 或含有參數 -l 或 --list)

-n[<num>]:加顯示 tag 的訊息,預設只顯示一行,可指定顯示幾行。
--contains <commit>:只顯示包含特定送交的 tag
--points-at <object>:只顯示特定送交的 tag
--column[=<options>]:column 顯示
--no-column
--create-reflog
--sort=<key>:排序
--format=<format>:顯示格式
--[no-]merged [<commit>]:只列特定送交可到達與否 (待深入了解)
<pattern>:只顯示樣式比對符合的

刪除

(含有參數-d 或 --delete)

簽名校驗

(含有參數 -v 或 --verify)

tag 修改

以修改 annotated tag 為例:
git tag <tagname> <tagname> -a -f
自動跳出編輯器修改之前的註釋
git show <tagname>
可看到除了原本的註釋,另外有多一筆註釋。如果要覆蓋原本的註釋則用
git tag <tagname> <tagname>^{} -a -f
送交修改的 tag
git push <tagname> -f

在別的 git clone 執行 git pull 並不會更新註釋內容,除非知道哪個 tag 有修改,移除它,再 pull
git tag -d <tagname>
git pull

參考及延伸閱讀

2016年7月24日 星期日

scanf()

輸入格式轉換,存到記憶體

#include <stdio.h>

int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *str, const char *format, ...);

#include <stdarg.h>

int vscanf(const char *format, va_list ap);
int vsscanf(const char *str, const char *format, va_list ap);
int vfscanf(FILE *stream, const char *format, va_list ap);

format 是一個字串,描述如何處理輸入字元。如果沒有輸入、或比對失敗,就停止,回傳轉換成功的次數。format 內容可以是:
  • 空白字元集,包括 space、tab、newline 等,比對 0 個以上的空白字元集。
  • % 開頭的轉換規範。
  • 其它一般字元
每個轉換規範以 '%' 或 %n$ 開始,後者指定用第幾個變數存。接著:
  • (optional) '*':依照轉換定義讀取,但不儲存,不計成功轉換次數。
  • (optional) 'm':用在字串轉換 (%s, %c, %[),自動配置足夠的記憶體放字串,之後需要 free()。
  • (optional) 十位數字說明最大 field width,不含字串結尾 0。
  • (optional) 改變存成的資料型態
    • h:存成 short int 或 unsigned short int
    • hh:存成 signed char 或 unsigned char
    • j:存成 intmax_t 或 uintmax_t
    • l:整數存成 long 或 unsigned long,浮點存成 double
    • ll:跟 L 一樣,用在 %c 或 %s 表示寬字元。
    • L:整數存成 long long,浮點存成 long double
    • t:存成 ptrdiff_t
    • z:存成 size_t
  • 轉換定義
    • %:比對 %
    • d:比對十進位整數,可以是有號,結果存到 int
    • i:比對對整數,可以是有號,可以是 0x 或 0X 開始的十六進位數字、0 開頭的八進位數字、不然則是十進位。結果存到 int。
    • o:比對無號八進位整數,結果存到 unsigned int。
    • u:比對無號十進位整數,結果存到 unsigned int。
    • x, X:比對無號十六進位整數,結果存到 unsigned int。
    • f, e, g, E, a:有號浮點數字,結果存到 float。
    • s:不含 white-space 的字串,存到字串。
    • c:數個字元,存到 char 陣列。
    • [字元集]:比對字元集存到字串。字元集不能是空的,不省略開頭的 white space。排除這些字元集的話,字元集以 ^ 開始。如果字元集要包含 ],可放在第一個字元。兩字元間可夾 - 表示範圍。例如 [^]0-9-] 表示任何字元不含 ]、0 到 9、-。
    • p:比對指標值存到 void 指標。
    • n:計數字元數目存到 int。可能不計成功的轉換次數。

問題:可以忽略開頭字元嗎?

參考:printf

2016年7月23日 星期六

SIP REGISTER

SIP 註冊 [RFC3261 §10]

SIP 用戶在網域 (domain) 中有個帳號「user@domain」,稱為 address-of-record,但連結到用戶實際所在的位址 (binding) 是可以變動的,可透過 SIP REGISTER 請求向 registrar 登記目前的位址。

registrar 專指接受並回覆 SIP REGISTER 請求的 UAS,在其管理的網域維護 binding 對應表,讓其它用戶要建立通話時可透過 proxy server 或 redirect server 查詢。

                                              bob
                                            +----+
                                            | UA |
                                            |    |
                                            +----+
                                               |
                                               |3)INVITE
                                               |   carol@chicago.com
      chicago.com        +--------+            V
      +---------+ 2)Store|Location|4)Query +-----+
      |Registrar|=======>| Service|<=======|Proxy|sip.chicago.com
      +---------+        +--------+=======>+-----+
            A                      5)Resp      |
            |                                  |
            |                                  |
  1)REGISTER|                                  |
            |                                  |
         +----+                                |
         | UA |<-------------------------------+
cube2214a|    |                            6)INVITE
         +----+                    carol@cube2214a.chicago.com
          carol

SIP REGISTER 可進行的動作包括建立 (create)、新增 (add)、更新效期 (refresh)、詢問 (query)、移除 (delete)、及修改 (modify)。每個用戶可有多個位址,可能是多個 UAC 註冊的不同位址,或者是不同情況使用的位址。每個位址都有效期限,到期前需要更新效期才能持續使用。效期設為 0 將位址移除,之後可再新增來達到修改的目的。

REGISTER 請求
  • Request-URI (必要):domain,例如 "sip:chicago.com",不能有 "userinfo" 及 "@"。
  • To (必要):要建立、詢問、或修改的 address-of-record,包含有 user name。
  • From (必要):負責註冊者的 address-of-record,通常跟 To: 一致,或者由第三方註冊。
  • Call-ID 及 CSeq (必要):對特定 registrar,UAC 每次開機後應該使用相同的 Call-ID,搭配 CSeq 每次請求加一,依此 registrar 可以偵測出沒按照順序到達的 REGISTER 請求。(反之,如果 Call-ID 不同便無法偵測順序是否正確)
  • Contact (may): 要登記連結的位址 (address bindings),可有多個,可以是 sip:、tel:、mailto: 等。可加 q 參數作為偏好使用。沒此項欄位時用來詢問。
  • Contact 各自的 expires 參數、或 Expires (may):到期秒數,註冊時可建議,但最終由 registar 決定。大於 232-1 (4294967295 秒或 136 年) 可視為 232-1,Malformed 值應該視為 3600。0 表示移除,此時 Contact 可用 * 移除所有位址連結。
  • Route (may)
  • Record-Route (有可能會有,但忽略):因為不會建立 dialog,所以沒效用。
  • Contact 的 action 參數:來自 RFC 2543,deprecated,不該使用。
動作ContactExpire
建立特定位址建議值
新增特定位址建議值
更新效期特定位址建議值
詢問不需要
移除特定位址,或 * 表全部。0
修改特定位址建議值

registrar response:

  • 2xx 的 Contact 會列出所有的 binding。註冊成功的 UA 找出自己那一項,根據其 expires 參數或 Expires 欄位值計算並更新有效期限。
  • Date: 用來設定時間。
  • 423 (Interval Too Brief) 的 Min-Expires:可使用等於或大於 Min-Expires 的 expires 值重新嘗試註冊。
  • 501 Not Implemented:不支援單純詢問。
  • 不能產生 6xx,不能有 Record-Route。

registrar 位址除了使用設定外,也可以用 domain 位址 DNS 取得,或 well-known "all SIP servers" 的 multicast 位址 "sip.mcast.net" (IPv4 是 224.0.1.75,IPv6 ?)。但使用 multicast 只是讓 registrar 知道位置,不會有回應 (為什麼?)。

參考

  • From TS 24.229:Unless either the user or the application within the UE has determined that a continued registration is not required the UE shall reregister an already registered public user identity either 600 seconds before the expiration time if the previous registration was for greater than 1200 seconds, or when half of the time has expired if the previous registration was for 1200 seconds or less, or when the UE intends to update its capabilities according to RFC 3840 [62] or when the UE needs to modify the ICSI values that the UE intends to use in a g.3gpp.icsi-ref media feature tag or IARI values that the UE intends to use in the g.3gpp.iari-ref media feature tag.
  • M. Schooler, "A multicast user directory service for synchronous rendezvous," Master's Thesis CS-TR-96-18, Department of Computer Science, California Institute of Technology, Pasadena, California, Aug. 1996.

SIP header Via

所有 SIP 訊息 都要有 Via,縮寫 v。一開始的 UAC 和後續途經的每個 proxy 都會疊加一個 Via 放傳送的位址,依序作為回應的路徑。 格式 sent-protocol sent-by [ ;branch= branch ][ ; 參數 ...] s...