【问题标题】:How to correctly use nanosleep() to run code at specific frequency?如何正确使用 nanosleep() 以特定频率运行代码?
【发布时间】:2020-09-07 08:25:23
【问题描述】:

我正在为 6502 CPU 制作一个模拟器,我想控制它的运行频率。

没有任何延迟,我的最大平均频率约为 70-80 MHz。但是,当我尝试使用 nanosleep 来控制频率时,它只能在我达到 1 mS 延迟(1000000 nS)之前工作。 如果我尝试将延迟设置得更低,例如 0.1 毫秒,它不会改变平均执行时间。对我来说奇怪的是,如果我将延迟设置为 0.1 毫秒,实际延迟结果为 ~.008 毫秒,并且对于 1-99999 纳秒范围内的任何值都不会改变。

我尝试在调试和发布模式下编译代码

我使用 nanosleep 是不是错了?这是我第一次使用 nanosleep,我之前只使用过 sleep 和 usleep,所以我有点困惑。 有没有更好的方法来控制代码执行的频率?

【问题讨论】:

  • 请贴出包含函数调用和变量声明的代码。
  • 改用计时器。睡眠不是定期运行代码的方式
  • 如果您需要对时间进行非常精细的控制,您需要检查自上次滴答以来经过的实际时间,而不是仅仅假设 (nano)sleep 是完全准确的。一旦您的进程可能被取消计划的时间超过您的滴答持续时间(除非您还使用卡米尔回答中的实时调度程序类),您还需要处理追赶错过的滴答。
  • 我认为一次计算1024步或类似的东西然后睡觉会更聪明,否则睡觉的开销比你的实际工作要贵得多。
  • 您应该计算(虚拟)CPU 周期,并具有可变延迟(可能是循环或其他机制),使周期与经过的时间一致,以获得准确的频率。有一个计时器,定期检查虚拟 CPU 周期的数量,如果 CPU 运行太快,则增加延迟,太慢,则减少延迟。或者,计算一个确切的周期数,看看已经过去了多少实际时间。

标签: c delay


【解决方案1】:

如何正确使用 nanosleep() 以特定频率运行代码?

我说不可能使用nanosleep 以特定频率运行代码(或者,有可能达到一定的精度,但有一些偏差?)。来自man nanosleep 强调我的,但整体是相关的:

nanosleep() 函数将导致当前线程暂停执行,直到指定的时间间隔 通过 rqtp 参数已经过去或信号被传递到调用线程,其动作是调用信号捕获 函数或终止进程。 暂停时间可能比请求的长,因为参数值是向上取整的 到睡眠分辨率的整数倍或由于系统对其他活动的调度。但是,除了 在被信号中断的情况下,暂停时间应不小于由 rqtp 指定的时间,由 系统时钟 CLOCK_REALTIME。

有没有更好的方法来控制代码执行的频率?

使用计时器并尝试依靠内核来正确安排定期执行,而不是自己做。使用timer_create 在指定超时后请求中断并在超时后运行您的代码,您还可以考虑将您的进程设为实时进程。在伪代码中我想我会:

void timer_thread(union sigval s) {
    do_your_code();
}
int main() {
   timer_t t;
   timer_create(CLOCK_MONOTONIC, &(struct sigevent){
        .sigev_notify = SIGEV_THREAD,
        .sigev_notify_function = timer_thread
   }, &t);
   timer_settime(t, &(struct itimerspec){{.tv_sec = 1},{.tv_sec = 1}}, 0);
   while (1) {
      // just do nothing - code will be triggered in separate thread by timer
      pause();
   }
}

【讨论】:

    猜你喜欢
    • 2020-02-10
    • 2023-03-25
    • 1970-01-01
    • 2021-07-03
    • 2018-11-29
    • 1970-01-01
    • 2021-03-16
    • 1970-01-01
    • 2019-09-13
    相关资源
    最近更新 更多