參數
- -d:Verbose
- -n:不常駐
- -q:(quit) 時間設完後結束
- -N:高優先權執行
- -w:不設定時間,只是詢問 peers,隱含 -n
- -l:作為 NTP server
- -S PROG:在特定時候執行 PROG,包括時間調整 (stepping time, step)、stratum 等級改變 (stratum)、每 11 分鐘 (period)、及失去同步 (unsync) 時,並透過環境變數 stratum、freq_drift_ppm、poll_interval、及 offset 提供同步狀態。stratum 最大 16,表示沒取到時間。
- -p PEER:從 PEER 取得時間,可有多個
- ntp_init():初始化及讀取設定
- stratum = MAXSTRAT
- poll_exp = BURSTPOLL
- 如果有 peer add_peers(),否則
- 主迴圈
- 預設下次動作時間為
- 如果亦作為 server,將自己加到 poll 列表
- 檢查每個 peer
- 動作時間到了
- socket 未建立,嘗試送詢問封包
- resolve peer:失敗 => 下次動作時間 5 秒後
- socket()、bind()、sendto():失敗 =>下次動作時間 5 秒後
- 下次動作時間 15 秒 (回覆的 timeout) 後
- socket 已建立:表示 timeout 了,關閉 socket,下次動作時間加快兩級
- 紀錄所有 peer 中,最近的詢問時間為下次動作時間
- 活動中的 socket 加到 poll 列表
- poll(),如有 peer socket,嘗試 timeout 1 秒,否則依照最近動作時間 + 1 秒作為 timeout。
- 沒 poll() 到:上次執行 script 超過 11 分鐘則執行 script
- 有 poll() 到:recv_and_process_client_pkt() 或 recv_and_process_peer_pkt()
- 檢查 unsync
- 結束動作
- 接收封包:如果接收錯誤,用 retry_interval() 設定下次動作時間為隨機 5 或 6 秒後
- 封包有誤:忽略
- 關閉 socket
- 還未同步:poll_interval(0) 設定下次詢問時間
- 取得 T1, T2, T3, T4
- T1:client 發出請求的時間
- T2:server 收到請求的時間
- T3:server 回覆的時間
- T4:client 收到回覆的時間
- 計算往返的延遲 (delay) = (T4 - T1) - (T3 - T2)
- 在 server 跟 client 的 clock 跑的速度不同且網路非常快時,算出來有可能是負的,為了避免違反 Principle of Least Astonishment (最小驚訝原則),delay 最小設為系統精度 0.002 秒
- 往返的延遲如果比上次大四倍以上,則不採用:poll_interval(0) 設定下次動作時間
- 有八組 datapoint,內容包括 T4、offset = ((T2 - T1) + (T3 - T4)) / 2、及 dispersion = LOG2D(msg.m_precision_exp) + 精度。如果首次 reachable,八組 offset 都設成一樣。
- filter_datapoints()
- filter_offset 用最近的 offset 算 filter_dispersion
- 算 filter_jitter:(平均 offset - 各自 offset) 平方相加後平均,然後開更號 (均方根?),最小為「精度」
- select_and_cluster() 回傳最佳 server
- 有回傳最佳 server 時執行 update_local_clock(),除了設定時間外,亦決定詢問週期要調大還是調小
- 調整詢問週期
- 設定下次詢問時間:一般是依據誤差 32 秒 ~ 1.1 小時間變動,誤差小週期就變大。如果 offset 變動過大,調整下次動作時間不要大於 32 秒
沒有留言:
張貼留言