Re: [问题] 如何设定时间上限使程式自动输出?

楼主: Hazukashiine (私は幸せです)   2017-12-31 14:38:34
为什么用 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
作者: steve1012 (steve)   2016-01-01 01:59:00
潜艇没有很难用啊 比喻不好喔
作者: galic (嘎利)   2017-12-31 16:36:00
你到底咳了什么原Po: 请教我打造一艘船 H大: 你需要这台潜水艇 其他人: 要不要先试试这条小船 设计简单又可以马上下水原po: 其实我我需要小船 是货轮那种等级的H大: 可是潜水艇除了在水上走 还能潜水 你看潜水多棒 在水上走可能会被太阳晒到 会被月亮照到 会被海鸟喷屎 会撞到冰山
作者: CoNsTaR ((const *))   2017-12-31 17:04:00
楼上比喻怪怪的吧… 帮翻译OP:我需要一个能跨过海洋的东西H:潜水艇很好用,好处是oooxxxG:你到底嗑了什么用船就好干嘛要潜水艇
楼主: Hazukashiine (私は幸せです)   2017-12-31 17:15:00
都行都行 能过海不要翻船进水就好了嘛 QAQ
作者: Darkautism (达卡特森)   2017-12-31 18:53:00
问题是潜水艇的code就很简单,货轮比较难类比根本错误
作者: Schottky (顺风相送)   2017-12-31 23:03:00
对 SIGALRM 的几个现存问题讲得很精辟,推
作者: TWkobe (中华柯比)   2016-01-01 08:53:00
signal好用到炸好不
作者: galic (嘎利)   2016-01-01 09:25:00
我一直强调你有达到原Po的目的 要求是“指定时间好吗” 你去crontab塞的时间算得进去吗?要在C里面实作这个功能 你还要人家写script 讲一堆有的没有的 回答问题真的这么难吗 扯东扯西 你前面两点跟用SIGALRM要写的不是一样吗“如何做到指定时间停止”“你可以偶尔Ctrl+C偷看一下时间啊”这样真的是有在回答问题吗而且你说得哪一个问题 不是使用C语言或是系统提供的Library可能会面对的问题?为何还要在那恐吓Programmer? 你要Flexibility和Stability,有其他更适合的做法?重点是达到原Po的目的“Linux, C, 指定时间停止”
作者: CoNsTaR ((const *))   2016-01-02 18:21:00
哎呦 7pupu 嘻嘻 扯东扯西的不知道是谁喔
作者: LPH66 (-6.2598534e+18f)   2016-01-02 19:16:00
@galic 给你一个连结 http://tinyurl.com/q7gem8l
作者: steve1012 (steve)   2016-01-03 01:02:00
我是觉得原 po真正的目的的确是偷看进度啦
作者: Killercat (杀人猫™)   2016-01-03 06:27:00
偷看进度的话其实用另外一个thread定时把结果写进某档案(或者直接写入目前最佳解)好像比较好? XD除非结果还需要做很垄长的aggeration
作者: steve1012 (steve)   2016-01-03 12:16:00
所以我推可以log 进度最快 XD
作者: yvb   2016-01-03 12:49:00
这些争辩, 让我想到黑猫白猫论 XD

Links booklink

Contact Us: admin [ a t ] ucptt.com