Re: [問題] 如何設定時間上限使程式自動輸出?
看板C_and_CPP (C/C++)作者Hazukashiine (みなさん、こんにちは)時間8年前 (2017/12/31 14:38)推噓8(9推 1噓 27→)留言37則, 10人參與討論串2/3 (看更多)
為什麼用 SIGINT 可能比 SIGALRM 好的幾個原因
1. Flexibility
SIGINT 不需要將時間間隔寫進程式
可以透過系統的殼層腳本觸發
隨情況調整觸發的頻率跟是否要觸發
這有助於程式的彈性和降低重新編譯的次數
甚至可能之後
想要對寫好的程式進行 profile
去計算 cache miss rate 等等
就可以免去 SIGALRM 開銷帶來的副作用
因此 SIGINT 可以說是方便很多
在很多時候會有意想不到的好處
2. Stability
A. Timer Inheritance 計時器繼承
fork() / exec()-s:
POSIX 標準規定使用 alarm() 觸發計時器時
在往後調用 fork() 的時候會清除
在往後調用 exec() 系列函數的時候
保留剩餘的時間到下一個行程映像持續計算
Alarms created by alarm are preserved across execve
and are not inherited by children created via fork.
然而標準對 signal disposition 卻有不同的邏輯
在 fork() 的時候被繼承
在 exec() 的時候卻會被重設成預設的 handler
A child created via fork inherits a copy of its
parent's signal dispositions. During an execve,
the dispositions of handled signals are reset to
the default; the dispositions of ignored signals
are left unchanged.
不一致的設計潛在隱患
可能導致非常難以除錯或是異常的行為
B. Timer Anomaly 計時器異常
除此之外
Linux 對 setitimer() 的異常行為有以下的描述:
The generation and delivery of a signal are distinct,
and only one instance of each of the signals listed
above may be pending for a process. Under very heavy
loading, an ITIMER_REAL timer may expire before the
signal from a previous expiration has been delivered.
The second signal in such an event will be lost.
ITIMER_REAL 觸發的是 SIGALRM
如果要避免上述的問題
可以採用 ITIMER_VIRTUAL 計時器
而它相對應的信號是 SIGVTALRM
但是它的時間不再是 wall time (real time)
而是 execution time
C. Unspecified Interactions 未定義行為
sleep(), usleep(), ualarm(), setitimer():
根據 POSIX 的標準
所有的計時器都是 per-process basis
而且不會 stack 起來
所以設定新的計時器會覆蓋舊有的計時器
因此每次檢查 alarm 的返回值至關重要
不然可能導致不再有 SIGALRM 被觸發
3. Conclusions
計時器的設定有很多瑣碎的細節
甚至可能有上述我沒想到的更隱晦的
都可能在一個不經意的情況
讓程式運作的不如預期
除非真的很需要計時器這種對時間很要求的情況
才有使用的必要
如果只是想要看看目前執行的進度
定期寫記錄到硬碟或 SIGINT 不失為一個好方法
※ 引述《BreathWay (息尉)》之銘言:
: 標題: [問題] 如何設定時間上限使程式自動輸出?
: 時間: Sat Dec 30 11:04:55 2017
:
: 問題(Question):
: 我寫了一個以暴力演算法求最佳解的程式,
: 主要是透過不斷更新所找到的更好的解來達成。
: 但是我希望能設定一個時間上限,
: 如果程式還沒跑完就直接輸出目前找到的最好的解。
: 請問有辦法在 C 裡面實作這個功能嗎?
:
: 推 Hazukashiine: POSIX Thread 或是 Signal Handler 12/30 14:32
: → Hazukashiine: 像是可以 SIGINT 時印出 ex. ping 12/30 14:34
: → Hazukashiine: 事實上你可以搭配 Linux 的 cron (job scheduler) 12/30 22:35
: → Hazukashiine: 來達成定時發送 SIGINT 的任務 不一定要人親自去按 12/30 22:35
: → galic: Ctrl+C只是其中一種Signal(SIGINT)好嗎 然後推文為何一直叫 12/30 23:01
: → galic: 人家用SIGINT 明明就有timer用的signal 12/30 23:01
: → galic: 你也只有polling counter或是透過timer兩種作法 12/30 23:03
: → galic: 但照po後來的回覆 這種需求就是要走timer阿 12/30 23:06
: → galic: 那就看一看timer的文件 https://tinyurl.com/lo9e3w3 12/30 23:08
: → galic: https://tinyurl.com/d5fw2rh 12/30 23:09
: → Hazukashiine: 用 SIGINT 是因為方便 彈性比較高 可以搭配腳本使用 12/30 23:40
: → Hazukashiine: 如果程式正在前景跑 但是手癢想在 timer expired 12/30 23:40
: → Hazukashiine: 前看偷看 按一下 ctrl + c 就可以了 如果想要靜靜放 12/30 23:40
: → Hazukashiine: 後景跑 就指令後面加 & 如果直接用樓上的方法寫死在 12/30 23:40
: → Hazukashiine: 程式裡編譯好的話 就沒有這種好處了 更何況樓主可能 12/30 23:40
: → Hazukashiine: 只是想偶爾偷看一下進度而已 我覺得用 SIGINT 合適 12/30 23:40
: → galic: 不用幫別人腦補 12/30 23:49
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 122.116.185.23
※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1514702318.A.C18.html
→
12/31 16:36,
8年前
, 1F
12/31 16:36, 1F
→
12/31 16:39,
8年前
, 2F
12/31 16:39, 2F
→
12/31 16:39,
8年前
, 3F
12/31 16:39, 3F
→
12/31 16:39,
8年前
, 4F
12/31 16:39, 4F
→
12/31 16:41,
8年前
, 5F
12/31 16:41, 5F
→
12/31 16:41,
8年前
, 6F
12/31 16:41, 6F
→
12/31 16:41,
8年前
, 7F
12/31 16:41, 7F
可是有一艘潛艇便宜好打造又安全 就直接打造一艘潛艇 >///<
1. signal(SIGINT, handler);
2. static void handler(int sig) { /* progress */ }
3. add "one line" with crontab for running periodically
※ 編輯: Hazukashiine (122.116.185.23), 12/31/2017 17:12:35
推
12/31 17:04,
8年前
, 8F
12/31 17:04, 8F
→
12/31 17:04,
8年前
, 9F
12/31 17:04, 9F
→
12/31 17:04,
8年前
, 10F
12/31 17:04, 10F
→
12/31 17:04,
8年前
, 11F
12/31 17:04, 11F
→
12/31 17:15,
8年前
, 12F
12/31 17:15, 12F
推
12/31 18:53,
8年前
, 13F
12/31 18:53, 13F
→
12/31 18:53,
8年前
, 14F
12/31 18:53, 14F
推
12/31 23:03,
8年前
, 15F
12/31 23:03, 15F
推
01/01 01:59,
9年前
, 16F
01/01 01:59, 16F
推
01/01 08:53,
9年前
, 17F
01/01 08:53, 17F
噓
01/01 09:25,
9年前
, 18F
01/01 09:25, 18F
→
01/01 09:25,
9年前
, 19F
01/01 09:25, 19F
→
01/01 09:29,
9年前
, 20F
01/01 09:29, 20F
→
01/01 09:29,
9年前
, 21F
01/01 09:29, 21F
→
01/01 09:29,
9年前
, 22F
01/01 09:29, 22F
→
01/01 09:30,
9年前
, 23F
01/01 09:30, 23F
→
01/01 09:30,
9年前
, 24F
01/01 09:30, 24F
→
01/01 09:34,
9年前
, 25F
01/01 09:34, 25F
→
01/01 09:34,
9年前
, 26F
01/01 09:34, 26F
→
01/01 09:34,
9年前
, 27F
01/01 09:34, 27F
→
01/01 09:34,
9年前
, 28F
01/01 09:34, 28F
→
01/01 09:36,
9年前
, 29F
01/01 09:36, 29F
推
01/02 18:21,
9年前
, 30F
01/02 18:21, 30F
推
01/02 19:16,
9年前
, 31F
01/02 19:16, 31F
推
01/03 01:02,
9年前
, 32F
01/03 01:02, 32F
→
01/03 06:27,
9年前
, 33F
01/03 06:27, 33F
→
01/03 06:28,
9年前
, 34F
01/03 06:28, 34F
→
01/03 06:29,
9年前
, 35F
01/03 06:29, 35F
→
01/03 12:16,
9年前
, 36F
01/03 12:16, 36F
推
01/03 12:49,
9年前
, 37F
01/03 12:49, 37F
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 2 之 3 篇):
C_and_CPP 近期熱門文章
PTT數位生活區 即時熱門文章