2019年5月31日 星期五

行動電源

行動電源的電源輸出入大多使用 USB,但也可能使用其它界面,可用來手機充電、驅動 LED 燈條、驅動風扇、筆電供電、救車等。

輸入:最好是 USB-C 的,逐步淘汰 micro USB。 輸出:最好有 USB-A 和 USB-C 雙輸出,過渡到 USB-C。
  • USB-A
  • USB-C (支援筆電電壓)
  • 救車 (需要瞬間大電流)

行動電源容量有兩種,一種是電芯(電)容量,另一種是輸出的額定(電)容量。輸出時,不同電壓耗損不同,對應的額定容量也不同。電容量單位可能是「mAh」或「Wh」。mAh 要乘以電壓除以 1000 是 Wh,電芯電壓一般是 3.6V,輸出電壓有 5V 等。另外行動電源充電時也會有耗損,所以充電電容量 > 電芯電容量 > 額定電容量。

電容量輸入或輸出的速度是功率,單位是 W,或以電壓和電流分別表示 (5V / 1A、5V / 2A、9V / 2A、12.1V / 1.5A 等)。一般輸出功率越高能源轉換耗損越高,轉換效率越低。

產品
  • ASUS ZenPower (32Wh, 5V)
  • ASUS ZenPower Pro PD (48.96 Wh, 輸出 5/9/15/20V max. 45W)
  • ASUS ZenPower Max:等效 3.6V x 26800mAh = 96.48 Wh [港都狼仔評測]
  • QUANHAN全漢創意PD20000: 等效 3.6V x 20000mAh = 72Wh, 65W
  • V-Mount鋰電池:單顆PAGlink電池的電力為96瓦-小時、14.8V、6.5Ah
  • Lenovo USB-C 筆記型電腦行動電源 14000 mAh = 48Wh:USB-C x1 45W, USB-A x2 各 10W, 292g
  • mophie powerstation USB-C 3XL 電池:26,000 mAh,45W USB-C,額外的 USB-A 輸出。Priority+ 直通式充電功能先對裝置充電,後會對本身充電。
  • mophie powerstation USB-C XXL 通用電池:19,500mAh,30W USB-C,額外的 2.4A USB-A 輸出。透過電腦充電時,可將 USB 埠切換成電源輸入。Priority+ 直通式充電功能先對裝置充電,後會對本身充電。
  • Anker PowerCore+ 10000 Pro 行動充電器:同時對 PowerCore 電池及 iPhone 充電。PowerCore+ app 韌體更新。
  • Zendure|27000mAh SuperTank 四孔極速行動電源:邊充邊放
  • ZENDURE SuperTank Pro 26800mAh/96.48Wh 行動電源簡測:支援邊充邊放。4 組 USB-C 埠,最大 100W PD 輸入/輸出。OLED 螢幕顯示資訊。可更新韌體。18650 電池。
  • Zendure SuperMini 10000mAhx3.63V=36.4Wh 180g 21700 電池 $1680 $1380

2019年5月25日 星期六

prefetch

在 Linux Kernel,為了減少 cache miss 來增進效能,可將預期會用到的資料用 prefetch() 事先讀取,但有些只是想像效能會較好,沒有實證反而可能有反效果。

例如 <linux/list.h> 的 list_for_each() macro:
    #define list_for_each(pos, head) \
 for (pos = (head)->next; prefetch(pos->next), pos != (head); \
            pos = pos->next)
經過實證反而效能較差 (短 list、null prefetch),硬體自己做的不會較差。

其它:
  • reordering structures that commonly accessed together fields are found in the same cache line
  • linked-list => cache-unfriendly
  • singly-linked hlist hash table list 
  • likely()
參考:
The problem with prefetch

2019年4月5日 星期五

Base64

Base64 編碼用 64 個可列印字元來表示二進位資料。二進位資料每 6-bit 為一個單元,對應到 26 = 64 可列印字元中的其中一個。每 3-byte = 24-bit 用 4 個可列印字元表示。

64 個可列印字元前 62 個依序是 A-Z、a-z、0-9,剩下兩個字元大多使用 + 和 /,但有其它變種。另外,資料長度不是 3 的倍數時,可以加以填充,多 1 需要填 ==,多 2 需要填 =,讓結果長度都是 4 的倍數。

傳送或儲存二進位資料時,有些情況有些字元有特別用途,所以需要 Base64,限縮只用可列印字元來表示,包括 MIME 的電子郵件等。

用在 URL:+ 和 / 會轉為 %XX 格式,所以改用 - 和 _。

用在正規表示式:+ 和 / 有特殊含意,所以改用 ! 和 -。

其它使用不同 64 字元集的編碼方法則不稱為 Base64,如 uuencode、BinHex。

https://en.wikipedia.org/wiki/Base64

2019年3月30日 星期六

hotplug2

hotplug2 是輕巧版的 udev,在 OpenWrt 已經由 procd 取代。

程式 /sbin/hotplug2 會常駐,連結到 netlink socket 讀取 uevent,變數拿來跟每個規則比對,符合的就執行對應的指令。

規則比對有 "==" 及 "!=" 檢查字串是否相等、"~~" 及 "!~" 執行正規表示式比對、"is set" 及 "is unset" 檢查有無此變數。每個規則可以有多項比對用「,」隔開,接著是以 { } 包起來的指令。指令也可以有多個,可執行的指令有:
  • print <text>:印訊息
  • print-event [rule label]:印出整個 event。If the rule label is provided, it is printed along with the rule.
  • setenv <key> <value>:設定環境變數
  • remove <file>:移除檔案
  • chown <owner> <file>:改變檔案的擁有者
  • chgrp <group> <file>:改變檔案的群組
  • chmod <mode> <file>:改變檔案的存取模式
  • run <command>:使用 system() 執行 shell 指令
  • exec <command> [arg1 [arg2 [... [argn]]]]:直接執行指令
  • mknod <filepath> <mode>:建立 device node (使用 MAJOR, MINOR 及 SUBSYSTEM 變數)
  • load-firmware <firmware directory>:載入存在 <firmware directory> 的韌體,需要 FIRMWARE 變數
  • serialize [socket:]:
  • next-event:跳到下個 event,也就是不比對接下來的規則。
  • branch-event [success]:如果上個指令執行失敗 (或成功),跳到下個 event。
  • branch-rule [success]:如果上個指令執行失敗 (或成功),跳出此規則,繼續比對接下來的規則。
最後三個是流程控制。

OpenWrt preinit 時,規則是 /etc/hotplug2-init.rules,如果是按鍵 (SUBSYSTEM == button) 就「kill -USR1 1」。

在 init 的 boot 時,規則會改設為 /etc/hotplug2-init.rules,會再包含 /etc/hotplug2-platform.rules 及 /etc/hotplug2-common.rules。這些規則有一部分會去執行 /sbin/hotplug-call,第一個參數是 SUBSYSTEM 變數值或 firmware,會去執行 /etc/hotplug.d/$1/ 下所有的程式

preinit 時, 如果沒有 devfs,則執行
/sbin/hotplug2 --set-worker /lib/hotplug2/worker_fork.so --set-rules-file /etc/hotplug2-init.rules --no-persistent --set-coldplug-cmd /sbin/udevtrigger
/sbin/hotplug2 --set-worker /lib/hotplug2/worker_fork.so --set-rules-file /etc/hotplug2-init.rules --persistent &
在 init 的 boot
/sbin/hotplug2 --override --persistent --set-rules-file /etc/hotplug2.rules --set-coldplug-cmd /sbin/udevtrigger --max-children 1 >/dev/null 2>&1 &
疑問:
  • hotplug 跟 hotplug2 的關係?
參考來源:
  1. https://wiki.openwrt.org/doc/techref/hotplug
  2. hotplug2 原始碼
  3. OpenWrt 原始碼
延伸閱讀:
  • devtmpfs
  • devfs
  • udev
  • mdev (busybox 的簡化版 udev)
  • hotplug ()

2019年3月24日 星期日

OpenWrt procd

OpenWrt 使用 procd 取代傳統 Linux 使用的 init 及 udev。

procd 原始碼除了套件 procd 外,還包括套件 procd-ujail、procd-seccomp、procd-nand、procd-nand-firstboot。procd 套件包括二進位程式 init、procd、askfirst、udevtrigger,shell 指令檔 reload_config 和 procd.sh,以及 hotplug json 檔 hotplug-preinit.json 和 hotplug.json。


在 OpenWrt 開機,Linux 最後會執行腳本 /etc/preinit註1 開始 userspace 的動作,但現在一開始就先插隊執行 /sbin/init,然後才執行原本的 /etc/preinit,最後交棒給 procd 繼續執行,變成:/sbin/init → /etc/preinit → /sbin/procd。

註: 在 OpenWrt 開機,Linux 最後會執行腳本 /etc/preinit (`try_to_run_init_process("/etc/preinit")`@init/main.c → do_execve()@fs/exec.c), 執行時會檢查檔案開頭決定何種執行檔,腳本需要以 #! 開頭 (load_script()@fs/binfmt_script.c),/etc/preinit 使用的直譯器是 busybox sh

init

一開始 PREINIT 沒設,執行 init 取代自己
[ -z "$PREINIT" ] && exec /sbin/init
  1. `ulog_open(ULOG_KMSG, LOG_DAEMON, "init")`: 設定 log 方式
  2. SIGTERM、SIGUSR1、SIGUSR2 的處置是 sa_shutdown
  3. `early()`:掛載檔案系統及設定環境變數
  4. `cmdline()`:讀取 Linux 指令行參數 init_debug 設定 debug 等級。
  5. `watchdog_init(1)`:初始化 watchdog,使用 /dev/watchdog
  6. fork() 執行 `/sbin/kmodloader /etc/modules-boot.d/` 載入一些 kernel 模組,並等候結束
  7. fork() 執行 `/sbin/procd -h /etc/hotplug-preinit.json` 處理事件
    • 載入韌體:使用 /sbin/hotplug-call
    • failsafe 按鍵:執行 /etc/rc.button/failsafe 產生 /tmp/failsafe_button
  8. fork() 執行 `PREINIT=1 /bin/sh /etc/preinit`,執行 /etc/preinit 原本該跑的腳本,結束時執行
    1. 如果 hotplug-preinit.json 還在跑,殺了他。
    2. 如果檔案 /tmp/sysupgrade 存在,就一直睡吧不往下執行了 (等候 reboot 嗎?) 
    3. 清掉環境變數 INITRAMFS、PREINIT
    4. 設環境變數 WDTFD 交出 watchdog file descriptor
    5. 交接除錯等級
    6. 改為繼續執行 /sbin/procd

procd

procd 其實可看成是兩個程式,有加 -h 參數是當作 hotplug daemon (hotplug_run()),否則
  1. 繼承除錯等級或重設,並設定 log 方式
  2. `setsid()`:建立新 session 並成為 process goup leader,且成為 process group 唯一的成員,使用 process ID 作為 session ID 及 process group ID,回傳 session ID。no controlling terminal。如果已經是 process group leader,則回傳 -1 且 errno 為 EPERM。
  3. `procd_signal()`:signal 的處置
    • SIGTERM、SIGINT、SIGUSR1、SIGUSR2:sa_shutdown
    • SIGSEGV、SIGBUS:sa_crash
    • SIGHUP、SIGKILL、SIGSTOP:sa_dummy
  4. 如果不是第 1 個 process,一秒後連結到 ubus,否則進入以下 state
  5. STATE_EARLY
    1. 設定 watchdog timeout
    2. hotplug(/etc/hotplug.json) 事件處理
    3. fork() 執行 `udevtrigger`,結束 ... 進入下個 state
  6. STATE_UBUS
    1. 重開 /dev/console stdin/stdout/stderr
    2. ubus timeout:ubus 連上後最後進入下個 state
    3. service_start_early()
  7. STATE_INIT
    1. LOG("- init -\n");
    2. `procd_inittab()`:讀取 inittab 建立 actions 列表 (id:run-level:action:process)
      • process 切出 argv
      • 除了 sysinit 及 shutdown 外,可以有多個
    3. `procd_inittab_run("respawn")`:
    4. `procd_inittab_run("askconsole")`
    5. `procd_inittab_run("askfirst")`
    6. `procd_inittab_run("sysinit")`:依序執行 /etc/rc.d/ 下 S 開始的腳本中的 boot() 部份
    7. `ulog_open(ULOG_SYSLOG, LOG_DAEMON, "procd")`:切換到 syslog
  8. STATE_RUNNING:沒做什麼事,只是 log 完成 init
  9. STATE_SHUTDOWN:shutdown 時進入,依序執行 /etc/rc.d/ 下 K 開始的腳本中的 shutdown() 部份
  10. STATE_HALT
sysinit 跟 shutdown 都是執行 /etc/rc.d/ 下的腳本,這些腳本通常是依所要執行的順序連結到 /etc/init.d/ 下的腳本,在 inittab 可能的內容如下:
::sysinit:/etc/init.d/rcS S boot
::shutdown:/etc/init.d/rcS K shutdown
在 procd 會用 glob() 取出所有 /etc/rc.d/S* 的檔案,全部加到 libubox runqueue 去執行。

askfirst

用在 inittab

udevtrigger

...

procd.sh

共用腳本函數,當 init 腳本使用 procd 方式時 (USE_PROCD=1) 使用。

OpenWrt 的 init 腳本通常透過 /etc/rc.common 執行,在開機時是執行 shell function  boot(),而 boot() 預設是執行 start()。在傳統方式,由 init 腳本提供 start() 功能,但當使用 procd 方式時則改提供 start_service()。
oldprocd
start()start_service() 至少要提供 json command 的部份
stop()已採用 procd_kill 停止程式,stop_service()
reload()如有 reload_service() 則執行,不然執行 start()
running()
trace()
使用 procd 方式的特別之處
  • 所有引數會打包成 json 格式,透過 ubus 送給 procd
    • command
    • respawn
    • ...
  • service_triggers() 可用 procd_add_reload_trigger() 登記哪些設定檔改變後執行 reload_config 需要重新執行。可用 procd_add_network_trigger() 登記網路改變作為重啟的 trigger

範例:package/network/services/dnsmasq

詳情見 OpenWrt package/base-files/files/etc/rc.common。
rc.common 會載入 /lib/functions.sh (一些共同的函數,包括 config_ 開頭的函數)、/lib/config/uci.sh (uci_ 開頭存取 uci 的函數)、及 /lib/functions/service.sh (使用 busybox start-stop-daemon 提供 service_ 開頭的函數)。

reload_config

configd 完成前的臨時替代方案,
檢查設定有改變則呼叫 `ubus call service event { "type": "config.change", "data": { "package": "設定檔名" }}`

開機時會產生設定檔的 MD5 checksum 存在記憶體,更改設定後執行 reload_config 會自動重啟相關的程式。

hotplug-preinit.json 及 hotplug.json。

...

延伸閱讀


/sbin/procd (不設 INITRAMFS,不設 PREINIT)
│ hotplug(/etc/hotplug.json)
├→ udevtrigger
│ubus_connect()...service_init, /etc/inittab
│? /sbin/ubus
├respawn→
├askconsole→
├askfirst→/sbin/askfirst
sysinit⇄用 runqueue 一次跑一個 /etc/rc.d/S* boot,pipe STDOUT/STDERR

hotplug_run() 每次事件發生時
exec→
load-firmware→

libubox uloop
libubox blob, blobmsg
json_script_init
ubus
service
ustream

延伸閱讀:http://data.pavlix.net/installfest/2014/openwrt-software.pdf

2019年3月17日 星期日

行動電話世代

行動電話的世代

1G:類比語音。

2G:數位語音。

  • GSM 系統採用電路交換的語音通道來打電話和傳送簡訊。2G 架構包括基地台子系統 (Base Station Subsystem, BSS) 和 網路子系統(Network SubSystem, NSS)。BSS 由基地台接收站 (Base Transceiver Station, BTS) 以及基地台控制器 (Base Station Controller, BSC) 所組成,負責無線傳輸的排程以及 MAC 的控制訊息。NSS 主要元件為無線交換機中心 (Mobile Switching Center, MSC),負責接入公共交換電話網路(PSTN)。
  • GPRS 系統提供封包交換功能來上網,但仍使用語音通道傳送資料封包,所以速度很慢。2.5G 架構在 GSM 架構加上 GPRS 核心網路,主要由 SGSN (Serving GPRS Support Node) 和 GGSN(Gateway GPRS Support Node) 所組成,負責 IP 網路資料傳遞。BSC 會依據收到的資料決定要傳送到 NSS 或是 GPRS 核心網路。
3G:行動上網。UMTS (Universal Mobile Telecommunications System, 通用行動通訊系統) 由 3GPP 基於 GSM 發展,使用新的 W-CDMA 無線介面等構成的通用無線接入網 (GRAN) 連入不同的骨幹網路 (電路交換或封包交換),如網際網路、ISDN、GSM 或者 UMTS網路,可以用更快的速度上網。
  • 2006 出現智慧型手機

4G:完全 IP 封包化,行動寬頻上網。

  • 4G (2008)
  • 4G LTE (2010)
  • LTE Advanced:引進 CA、MIMO,1Gbps
  • LTE Advanced Pro: >3Gbps, < 2ms 延遲。引進 Full Dimension Massive MIMO、低速低功耗網路。

4G LTE 的傳輸是使用 IP 分封交換 (Packet Switching),不同於 2G / 3G 所使用的電路交換 (Circuit Switched) 傳輸方式。
語音通話服務可以透過 CSFB、SGLTE 或 VoLTE 等方法來達到 。

* CSFB (Circuit Switched Fallback):上網用 4G,語音切回 3G
* SGLTE (Simultaneous GSM and LTE):同時使用 4G 及 GSM (較耗電)
* SVLTE (Simultaneous Voice and LTE):同時使用 4G 及 CDMA (較耗電)
* SRVCC (Single Radio Voice Call Continuity):3GPP 標準,話音通話在 VoLTE 跟 2G/3G 之間切換時能維持通話連續性,在 LTE 覆蓋率不佳的環境可確保通話不中斷。

### VoLTE [[教學]何謂VoLTE?認識新一代高品質語音通話服務]

5G:三大面向:大容量 (達 20Gbps),低延遲 (<1ms),大量低價 IoT 連結。M2M
  • 應用:更高畫質的影片、更快的檔案傳輸、可靠的即時控制應用...
  • Band Steering (頻段引導):引導使用較好的頻段
  • Client Steering (裝置引導):引導使用較好的 AP
  • Seamless Roaming (無縫漫遊):毫秒切換 AP
世代系統名稱調變方式多工方式通道頻寬資料傳輸率頻譜效率
2GGSMGMSKFDMA/TDMA200KHz9.6K/14.4K0.05/0.07
2.5GGPRSGMSKFDMA/TDMA200KHz9.6K/115K0.05/0.58
2.75GEDGE8PSKFDMA/TDMA200KHz384K/384K1.92/1.92
3GW-CDMAQPSKFDMA/CDMA5MHz64K/2M0.01/0.40
3.5GHSDPA16QAMFDMA/CDMA5MHz384K/14.4M0.08/2.88
3.75GHSUPAQPSKFDMA/CDMA5MHz5.76M/14.4M1.15/2.88
4GLTE64QAMFDMA/OFMA20MHz50M/100M2.5/5
4GLTE-A64QAMFDMA/OFMA100MHz500M/1G5/10
4.5GLTE-A Pro256QAM?/???/3G (32CA)?/?
「頻譜效率」(Spectrum efficiency) 是單位頻寬 (Hz) 有多少資料傳輸率 (bps)。

調變技術 (Modulation)

2G 以後是採用數位調變,用不同波形 (symbol) 的類比電磁波 (包括用振幅大小、頻率高低、相位不同等) 來代表 0 與 1 的數位訊號。數位調變的優點包括可以偵錯與除錯、壓縮與解壓縮、加密與解密、更好的抗雜訊能力等。

多工技術 (Multiplex)

將電磁波給不同的使用者使用,常見的包括下列 4 種:
  • 分時多工接取 (TDMA):依照「時間先後」區分。
  • 分頻多工接取 (FDMA):依照「頻率範圍不同」區分。
  • 分碼多工接取 (CDMA):用不同的碼加密資料後傳送,只有有特定碼的接收端以不同的密碼來分辨要接收的訊號。
  • 正交分頻多工 (OFDM):使用彼此頻率「正交」的 FDMA。LTE / LTE-A、無線區域網路 (IEEE802.11a/g/n)、數位電視 (DTV)、數位音訊廣播 (DAB) 都有使用。
通常同時使用兩種以上的多工技術來增加資料傳輸率,滿足每個人都要使用的需求。

參考來源

http://technews.tw/2015/10/12/3g、4g、5g-meaning-part-two

2019年2月16日 星期六

SIP INFO

SIP Method INFO 是在 Dialog 內交換訊息。

傳統 SIP INFO 定義在 RFC 2976,運用在一些標準或私訂的應用 (legacy INFO usage):
  • RFC 3372 在 SIP 信體放 ISDN User Part (ISUP) 訊息,ITU-T 和 3GPP 也有類似規範。
  • ECMA-355 在 SIP 信體放 QSIG。
  • 作為 Media Server Control Markup Language (MSCML) (RFC 5022) 的傳送機制,使用 Require 信頭欄位的一個 option-tag 來確保接收端了解 INFO 內容。
  • 作為 Media Server Markup Language (MSML) (RFC 5707) 的傳送機制。
  • 請求快速影片更新,目前基於 RTCP 的標準機制定義在 RFC 5168。
  • 傳送 DTMF 音,所有機制都是私訂未標準化。

傳統 INFO 無法表示支援哪些應用和傳送的資訊是哪種,通常需要靜態設定,而有相容互通問題。

RFC 6086 導入 Info Package 機制,新增兩個信頭欄位 -- Recv-Info 和 Info-Package。Recv-Info 告訴對方可接受哪些 Info Package。Info-Package 信頭欄位用在 INFO 請求來表示使用哪一個 Info Package。沒有 Info-Package 的 INFO 請求則使用傳統 SIP INFO。另有 Info Package 規範定義如何應用,名稱可以註冊到 IANA。

Info Package 機制

Info-Package 信頭欄位參數

INFO 請求信體可放應用的資訊,可以是單一 MIME 類型或 multipart [RFC5621 "Message Body Handling in the SIP"]。Info Package 的 INFO 請求的信體由 Content-Disposition 信頭欄位值的 Info-Package 標示。Info Package 的 INFO 回應不能有信體。

沒定義傳送順序機制,可依賴 CSeq 信頭欄位偵測順序是否正確。如果特定應用需要額外傳送順序機制,在關聯的 Info Package 定義。

SIP header Via

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