Mar
20
线程休眠(sleep, usleep, nanosleep, pthread_delay_np)
sleep() 与 usleep()
想要延迟数秒的时间, 最佳的方法大概 是使用函式 sleep() . 想要延迟至少数十毫秒的时间 (10 ms 似乎已是最短的延迟时间了), 函式 usleep() 应该可以使用. 这些函式是让出 CPU 的使用权 给其他想要执行的行程 (processes) (``自己休息去了''), 所以没有浪费掉 CPU 的时间. 细节请参考 sleep(3) 与 usleep(3) 的说明文件.
如果让出 CPU 的使用权因而使得时间延迟了大约 50 毫秒 (这取决於处理器与机器的速度, 以及系统的负荷), 就浪费掉 CPU 太多的时间, 因为 Linux 的排程器 (scheduler) (单就 x86 架构而言) 在将控制权发还给你的行程 (process) 之前通常至少要花费 10-30 毫秒的时间. 因此, 短时间的延迟, 使用函式 usleep(3) 所得到的延迟结果通常会大於你在参数所指定的值, 大约至少有 10 ms.
需要注意的是在 windos 下面 sleep() 函数精度为毫秒级, 而在 Linux下面的 sleep() 函数精度为秒级, usleep() 已被废除, 可以使用nanosleep() 替代.
nanosleep()
在 Linux 2.0.x 一系列的核心发行版本中, 有一个新的系统呼叫 (system call), nanosleep() (请参考 nanosleep(2) 的说明文件), 他让你能够 休息或延迟一个短的时间 (数微秒或更多).
如果延迟的时间 <= 2 ms, 若(且唯若)你执行中的行程 (process) 设定了软体的即时 排程 (就是使用函式 tt/sched_setscheduler()/), 呼叫函式 nanosleep() 时不是使用一个忙碌回圈来延迟时间; 就是会像函式 usleep() 一样让出 CPU 的使用权休息去了.
这个忙碌回圈使用函式 udelay() (一个驱动程式常会用到的核心内部的函式) 来达成, 并且使用 BogoMips 值 (BogoMips 可以准确量测这类忙碌回圈的速度) 来计算回圈延迟的时间长度. 其如何动作的细节请参考 /usr/include/asm/delay.h).
pthread_delay_np()
pthread_delay_np() 类似于 sleep(), 细节请参考 pthread_delay_np(3)的说明文件. 不过需要注意的是在 Linux 下的C并没有此函数, 大概是由于在Linux下, 所有的线程本质上都是一个进程, 有clone系统调用派生, 在内核看来, 他和一个普通进程没有什么差别, 区别就在于他和派生他的进程共享同一块内存(或者是说mm_struct)吧, 某个进程的sleep不大可能阻塞其它进程.
sleep:单位为秒,1秒
usleep:单位为微秒,1/1000 秒
select:单位为微秒,1/1000 000 秒
nanosleep:单位为毫微秒,也就是纳秒,1/1000 000 000 秒
想要延迟数秒的时间, 最佳的方法大概 是使用函式 sleep() . 想要延迟至少数十毫秒的时间 (10 ms 似乎已是最短的延迟时间了), 函式 usleep() 应该可以使用. 这些函式是让出 CPU 的使用权 给其他想要执行的行程 (processes) (``自己休息去了''), 所以没有浪费掉 CPU 的时间. 细节请参考 sleep(3) 与 usleep(3) 的说明文件.
如果让出 CPU 的使用权因而使得时间延迟了大约 50 毫秒 (这取决於处理器与机器的速度, 以及系统的负荷), 就浪费掉 CPU 太多的时间, 因为 Linux 的排程器 (scheduler) (单就 x86 架构而言) 在将控制权发还给你的行程 (process) 之前通常至少要花费 10-30 毫秒的时间. 因此, 短时间的延迟, 使用函式 usleep(3) 所得到的延迟结果通常会大於你在参数所指定的值, 大约至少有 10 ms.
需要注意的是在 windos 下面 sleep() 函数精度为毫秒级, 而在 Linux下面的 sleep() 函数精度为秒级, usleep() 已被废除, 可以使用nanosleep() 替代.
nanosleep()
在 Linux 2.0.x 一系列的核心发行版本中, 有一个新的系统呼叫 (system call), nanosleep() (请参考 nanosleep(2) 的说明文件), 他让你能够 休息或延迟一个短的时间 (数微秒或更多).
如果延迟的时间 <= 2 ms, 若(且唯若)你执行中的行程 (process) 设定了软体的即时 排程 (就是使用函式 tt/sched_setscheduler()/), 呼叫函式 nanosleep() 时不是使用一个忙碌回圈来延迟时间; 就是会像函式 usleep() 一样让出 CPU 的使用权休息去了.
这个忙碌回圈使用函式 udelay() (一个驱动程式常会用到的核心内部的函式) 来达成, 并且使用 BogoMips 值 (BogoMips 可以准确量测这类忙碌回圈的速度) 来计算回圈延迟的时间长度. 其如何动作的细节请参考 /usr/include/asm/delay.h).
pthread_delay_np()
pthread_delay_np() 类似于 sleep(), 细节请参考 pthread_delay_np(3)的说明文件. 不过需要注意的是在 Linux 下的C并没有此函数, 大概是由于在Linux下, 所有的线程本质上都是一个进程, 有clone系统调用派生, 在内核看来, 他和一个普通进程没有什么差别, 区别就在于他和派生他的进程共享同一块内存(或者是说mm_struct)吧, 某个进程的sleep不大可能阻塞其它进程.
sleep:单位为秒,1秒
usleep:单位为微秒,1/1000 秒
select:单位为微秒,1/1000 000 秒
nanosleep:单位为毫微秒,也就是纳秒,1/1000 000 000 秒