星期日, 10月 24, 2021

busybox top

第一行是記憶體使用狀態,讀取 /proc/meminfo 顯示 ...。

第二行是整體 CPU 使用率,讀取 /proc/stat 而來

第三行是系統負載,讀取 /proc/loadavg。

剩下部份是依資源使用多寡排行的 process 列表,主要資料是掃描每一個 /proc/<PID>/stat 整理而來。

原始碼 procps/top.c

  • 透過 libbb 函數 procps_scan(flags) 逐次讀取 /proc 下的 <PID> 目錄得知 pid,依據 flags 取得相關資訊。procps_scan() 用在 ps、top、pgrep、kill、和 find_pid_by_name()。
    • getpidcon()
    • /proc/<PID>/ 目錄的 Effective uid/gid,
    • /proc/<PID>/stat 得到 ppid、vsz (in KB)、ticks (stime+utime)、state 字串、comm 字串等。
  • 預設啟用 FEATURE_TOP_CPU_USAGE_PERCENTAGE 功能,顯示每個 process 的 CPU 使用比率,會執行 do_stats() 在 get_jiffy_counts() 讀取 /proc/stat
    • /proc/stat 第一行開頭是 cpu,是全部 cpu 的統計,後面有 8 個數字表示累積使用的 jiffy,分別是 usr、nic、sys、idle、iowait、irq、softirq、和 steal。這 8 個數字加起來是 total,busy 是 total 減去 idle 和 iowait。接下來是各個 cpu 的統計,有同樣格式。
    • 由於是統計是累積的 jiffy,需要保留上個週期讀取的結果,相減計算才是這個週期的比例。
  • /proc/meminfo (比較 free)
  • FEATURE_TOP_CPU_USAGE_PERCENTAGE 時能啟用 FEATURE_TOP_CPU_GLOBAL_PERCENTS_功能,顯示 CPU  用在 usr、sys、nic、idle、io、irq 和 sirq 比率 %,算法是 (這次的值 - 上次的值)/(這次的 total - 上次的 total)。
  • /proc/loadavg (比較 uptime)
參數
  • -d <秒數>:顯示週期,預設 5 秒。
  • -n <次數>:顯示次數,預設無限。
  • -b:batch mode,接續全部顯示,沒有 run-time 指令而無法離開。預設只顯示一整頁,有 run-time 指令。
  • -m:[FEATURE_TOPMEM] (busybox 特有選項)

run-time 指令

  • q:離開
  • n:pid 排序
  • m:記憶體排序優先
  • h
  • p:pcpuc 排序優先
  • t:time 排序優先
  • s:[FEATURE_TOPMEM]
  • r:[FEATURE_TOPMEM] 反向?
  • c 或 1:照 CPU 用量?

ENABLE_FEATURE_FAST_TOP:大約增加 100 bytes,但讓 top 快 20%。如果有上萬 processes 可能就很重要。

參考

  • top
  • /proc/loadavg:前面三個欄位分別是 1、5、15 分鐘平均 job 數目在 run queue (state R) 或等候 disk I/O (state D)。第四的欄位是所有 thread 中多少 runnable。第五個欄位是最後建立的 PID。
  • Linux Load Averages: Solving the Mystery

星期一, 10月 11, 2021

DTMF

標準話機 12 按鍵 0~9,* (star), # (octalthorpe, pound, hash)。

A, B, C, D

最少按 50 ms,inter-digit interval 50 ms,每碼平均 0.1 sec。

星期日, 10月 03, 2021

Linux on M1 Macs

採用 M1, M1 PRO, M1 MAX 處理器。

2021/6 Linux 5.13 提供基本支援,未支援圖形加速,且還有很多需解決的問題。

2022/3/22 Asahi Linux alpha release

虛擬器

Corellium 連接埠

Parallels

UTM:提供虛擬化和模擬功能。ARM VM: Arch Linux/Debian/Ubuntu, x86-64: Win XP/10/11, macOS 9

星期六, 10月 02, 2021

Socket Options

設定 socket 選項 (options) 功能。

int getsockopt(int fd,
    int level, int optname, void *optval, int *optlen);
int setsockopt(int fd,
    int level, int optname, const void *optval, int optlen);

成功回傳 0、失敗回傳 -1。

  • level:處理選項的 layer,例如 SOL_SOCKET、IPPROTO_IP。
  • optname:是要設定或取得的選項,透過值 optval 和長度 optlen。取得時,optlen 給 optval 長度,並回傳取得的 optval 長度。

有些選項是唯讀的,只能 getsockopt()。有些選項是唯寫的,只能 setsockopt()。

TLPI §61.11,accept() 會繼承 listen() socket 的選項。dup() 和 fork() 也會

SOL_SOCKET SO_TYPE 唯讀 取得 socket 類型 int SOCK_STREAM、SOCK_DGRAM

multicasting 用在 family AF_INET (?AF_INET6)、type 是 SOCK_DGRAM 或 SOCK_RAW 的 socket。常用在 SOCK_DGRAM,如果用在 routing daemon 可能需要 SOCK_RAW。level 是 IPPROTO_IP,有關的選項包括:


                        setsockopt()            getsockopt()
IP_MULTICAST_LOOP           yes                     yes
IP_MULTICAST_TTL            yes                     yes
IP_MULTICAST_IF             yes                     yes
IP_ADD_MEMBERSHIP           yes                      no
IP_DROP_MEMBERSHIP          yes                      no

參考

  1. https://www.tldp.org/HOWTO/Multicast-HOWTO-6.html
  2. TLPI §61.9  

Stevens et al., 2004

tcp(7), udp(7), ip(7). scoket(7), unix(7) manual pages

socket

socket 是一款 IPC,會使跨主機,大部分作業系統攏有實作。(閣有什麼 IPC?見 TLPI §43,fifo、message queue,...)

socket 的系統呼叫。大部分 Linux 平台是透過單一系統呼叫 socket() 來實現。

  • fd = socket(family, type, protocol):建立一個通訊端點後回傳 file descriptor,給後續 syscall 參照使用。
    • family 或稱 domain,有 AF_UNIX、AF_INET、AF_INET6、AF_PACKET (收送 L2 封包) 等。
    • type
    • protocol
  • bind(fd, addr, addrlen):指定自己的位址,位址格式和長度由 family 決定。位址通用格式是 struct sockaddr,內含 family 欄位,cast 成不同格式。位址指定過後才能接收封包,Server 通常需要指定 well-known 位址。Client 有指定可事先決定從哪個位址發,否則送封包時由系統自動指定。
  • listen():讓 stream socket 可在背景等候其它 socket 來的連線。
  • accept():等候的 stream socket 接受連線得到新的 socket 及對方位址。預設會 block。concurrent server 通常會 fork() 另一個 process 處理新連線,舊 process 繼續 accept() 下個新連線。
  • connect():指定對方的位址。在 connection-oriented client 會決定自己的位址後跟對方建立連線。在 connectionless client 只是事先指定對方位址作為傳送以及可接收的對象,後續可使用 read()、write()、recv()、send(),也可以接收傳送位址錯誤的訊息。
  • close()
  • shutdown()

socket I/O 可用傳統的 read() 和 write() 系統呼叫,或用 socket 專用的系統呼叫,例如 send()、recv()、sendto()、和 recvfrom()。如果 I/O 操作不能馬上完成,這些系統呼叫預設會 block,透過 fcntl() F_SETFL 操作 (TLPI §5.3) 設為 Nonblocking (O_NONBLOCK)。

註:

  • AF 代表「address family」,PF 代表「protocol family」。原本一個 PF 打算支援多個 AF,但實際上都只有一個,所以 PF_xxx 常數可一對一同義對應的 AF_xx 常數。詳情可見 [Stevens et al., 2004] 的 §4.2。

參考

TLPI §56~61

56 SOCKETS: INTRODUCTION
56.1 Overview
56.2 Creating a Socket: socket()
56.3 Binding a Socket to an Address: bind()
56.4 Generic Socket Address Structures: struct sockaddr
56.5 Stream Sockets
56.5.1 Listening for Incoming Connections: listen()
56.5.2 Accepting a Connection: accept()
56.5.3 Connecting to a Peer Socket: connect()
56.5.4 I/O on Stream Sockets
56.5.5 Connection Termination: close()
56.6 Datagram Sockets
56.6.1 Exchanging Datagrams: recvfrom() and sendto()
56.6.2 Using connect() with Datagram Sockets
56.7 Summary

57 SOCKETS: UNIX DOMAIN
57.1 UNIX Domain Socket Addresses: struct sockaddr_un
57.2 Stream Sockets in the UNIX Domain
57.3 Datagram Sockets in the UNIX Domain
57.4 UNIX Domain Socket Permissions
57.5 Creating a Connected Socket Pair: socketpair()
57.6 The Linux Abstract Socket Namespace
57.7 Summary
57.8 Exercises

58 SOCKETS: FUNDAMENTALS OF TCP/IP NETWORKS
58.1 Internets
58.2 Networking Protocols and Layers
58.3 The Data-Link Layer
58.4 The Network Layer: IP
58.5 IP Addresses
58.6 The Transport Layer
58.6.1 Port Numbers
58.6.2 User Datagram Protocol (UDP)
58.6.3 Transmission Control Protocol (TCP)
58.7 Requests for Comments (RFCs)
58.8 Summary

59 SOCKETS: INTERNET DOMAINS
59.1 Internet Domain Sockets
59.2 Network Byte Order
59.3 Data Representation
59.4 Internet Socket Addresses
59.5 Overview of Host and Service Conversion Functions
59.6 IPv6 and IPv4 Address Conversion: inet_pton() and inet_ntop()
59.7 Client-Server Example (Datagram Sockets)
59.8 Domain Name System (DNS)
59.9 The /etc/services File
59.10 Protocol-Independent Host and Service Conversion
59.10.1 The getaddrinfo() Function
59.10.2 Freeing addrinfo Lists: freeaddrinfo()
59.10.3 Diagnosing Errors: gai_strerror()
59.10.4 The getnameinfo() Function
59.11 Client-Server Example (Stream Sockets)
59.12 An Internet Domain Sockets Library
59.13 Obsolete APIs for Host, Service, and Address Conversion
59.13.1 The inet_aton() and inet_ntoa() Functions
59.13.2 The gethostbyname() and gethostbyaddr() Functions
59.13.3 The getservbyname() and getservbyport() Functions
59.14 UNIX Versus Internet Domain Sockets
59.15 Further Information
59.16 Summary
59.17 Exercises

60 SOCKETS: SERVER DESIGN
60.1 Iterative and Concurrent Servers
60.2 An Iterative UDP echo Server
60.3 A Concurrent TCP echo Server
60.4 Other Concurrent Server Designs
60.5 The inetd (Internet Superserver) Daemon
60.6 Summary
60.7 Exercises

61 SOCKETS: ADVANCED TOPICS
61.1 Partial Reads and Writes on Stream Sockets
61.2 The shutdown() system call
61.3 Socket-Specific I/O System Calls: recv() and send()
61.4 The sendfile() System Call
61.5 Retrieving Socket Addresses: getsockname() and getpeername()
61.6 A Closer Look at TCP
61.6.1 Format of a TCP Segment
61.6.2 TCP Sequence Numbers and Acknowledgements
61.6.3 TCP State Machine and State Transition Diagram
61.6.4 TCP Connection Establishment
61.6.5 TCP Connection Termination
61.6.6 Calling shutdown() on a TCP Socket
61.6.7 The TIME_WAIT State
61.7 Monitoring Sockets: netstat
61.8 Using tcpdump to Monitor TCP Traffic
61.9 Socket Options: setsockopt() and getsockopt()
61.10 The SO_REUSEADDR Socket Option
61.11 Inheritance of File Flags and Socket Options across accept()
61.12 TCP Versus UDP
61.13 Advanced Features
61.13.1 Out-of-Band Data
61.13.2 The sendmsg() and recvmsg() System Calls
61.13.3 Passing File Descriptors
61.13.4 Receiving Sender Credentials
61.13.5 Sequenced-Packet Sockets
61.13.6 SCTP and DCCP Transport-Layer Protocols
61.14 Summary
61.15 Exercises