赞
踩
- sleep函数用于让进程休眠指定的秒数,适用于需要较长时间的休眠场景;
- usleep函数用于让进程休眠指定的微秒数,适用于需要较短时间的休眠场景,不精确;
- nanosleep函数用于让进程休眠指定的纳秒数,适用于需要纳秒级的休眠场景,不精确(因为这种级别会因为系统调度和其他因素而有所不同);
- select 的精度是微妙,用于在多个文件描述符之间选择可读或可写的文件描述符,并在指定的时间内等待它们之一变为可操作,它可以用作高精度的休眠函数,虽然这并不是它的主要用途。
- std::sleep_for()可以支持任意时间段的休眠,包括微秒、毫秒、秒等,具有更加灵活的控制能力,在linux底层调用nanosleep,可以让线程休眠指定的时间量。
其次,需要权衡各个睡眠函数的优缺点。
例如,sleep函数的精度较低,适用于较长时间的休眠场景,但可能因为信号中断等原因提前结束;
usleep函数的精度较高,但也有被信号中断的风险;
nanosleep函数的精度更高,但使用稍微麻烦,使用nanosleep应注意判断返回值和错误代码,否则容易造成cpu占用率100%
select函数可以同时等待多个文件描述符,但有一定的限制,短延时推荐使用select函数,因为准确;
std::sleep_for()函数跨平台适用性好,但需要C++11支持。
最后,需要根据具体场景选择合适的睡眠函数。例如,如果需要在多个文件描述符之间选择可读或可写的文件描述符,并在指定的时间内等待它们之一变为可操作,可以使用select函数;如果需要让线程休眠指定的时间量,可以使用std::sleep_for()函数;如果需要更精确的休眠场景,可以使用nanosleep函数等。
总的来说,选择最佳的睡眠函数需要综合考虑使用场景、精度要求、可中断性等因素,并根据具体情况选择合适的睡眠函数,以提高系统的性能和稳定性。
usleep()有很大的问题
- 在一些平台下不是线程安全,如HP-UX以及Linux
- usleep()会影响信号
- 在很多平台,如HP-UX以及某些Linux下,当参数的值必须小于1 * 1000 * 1000也就是1秒,否则该函数会报错,并且立即返回。.
大部分平台的帮助文档已经明确说了,该函数是已经被舍弃的函数。
无论是WinCE还是Linux操作系统,应用线程的运行总是涉及到两个基本的参数:一个是系统分配给线程的时间片,一个是系统调度的时间间隔。Linux和WinCE下这两个参数有所不同,如下表所示:
WinCE | 嵌入式Linux | |
线程的运行时间片 | 100ms | 10ms |
系统调度间隔 | 1ms | 10ms |
- #include <unistd.h>
-
- unsigned int sleep(unsigned int seconds);
int usleep(useconds_t usec);
int nanosleep(const struct timespec *req, struct timespec *rem);
这个函数功能是暂停某个进程直到你规定的时间后恢复,参数req就是你要暂停的时间,其中req->tv_sec是以秒为单位,而tv_nsec以毫微秒为单位(10的-9次方秒)。
由于调用nanosleep是是进程进入TASK_INTERRUPTIBLE,这种状态是会相应信号而进入TASK_RUNNING状态的,这就意味着有可能会没有等到你规定的时间就因为其它信号而唤醒,此时函数返回-1,切还剩余的时间会被记录在rem中。
这个函数让进程休眠指定的纳秒数,适用于需要更精确的休眠场景。然而,实际的休眠时间可能会因为系统调度和其他因素而有所不同,所以它并不一定能保证纳秒级别的精度。
int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *reqtp, struct timespec *remtp);
- int select(int nfds, fd_set *readfds, fd_set *writefds,
- fd_set *exceptfds, struct timeval *timeout);
设置timeout的值,而将其他参数都置为NULL,当内部时间耗尽后select便会退出。
示例:
- #include "time.h"
- #include "sys/select.h"//必须调用这俩头文件
-
- struct timeval tv;//声明一个timeval类型的对象tv
- tv.tv_sec = 0;
- tv.tv_usec = 2*1000;
- select(0,NULL,NULL,NULL,&tv)
使用sleep()和usleep()的确可以达到效果,但是使用这类延时可能会导致系统产生未知问题,所以往往使用select函数,而且select的延时作用精度足够高.
几个注意事项:
1、tv_sec的初始化最好在tv_usec的前面
2、select的延时时间等于sec和usec时间之和
3、select的延时时间与设定值可能有1ms左右的误差
4、select每次运行之后,会将tv的值清零,所以如果要循环使用select,务必把tv.tv_usec的初始化放在循环中!
std::sleep_for()是C++11标准中提供的休眠函数,它可以使当前线程休眠指定的时间。函数原型如下:
- #include <chrono>
- #include <thread>
-
- namespace std {
- template<class Rep, class Period>
- void sleep_for(const chrono::duration<Rep, Period>& rel_time);
-
- void sleep_for(const chrono::nanoseconds& ns);
- void sleep_for(const chrono::microseconds& us);
- void sleep_for(const chrono::milliseconds& ms);
- void sleep_for(const chrono::seconds& s);
- void sleep_for(const chrono::minutes& m);
- void sleep_for(const chrono::hours& h);
- }
其中,第一个模板函数可以接受任意时间单位的参数,其他函数则分别接受纳秒、微秒、毫秒、秒、分、时的参数。
需要注意的是,std::sleep_for()函数会使当前线程休眠,因此应该谨慎使用,以免影响程序的正常运行。另外,由于休眠的精度受到系统调度器的影响,因此实际休眠时间可能略有偏差。
std::sleep_for()底层在 Linux 中使用的是nanosleep()函数实现的。nanosleep()函数可以使线程休眠指定的时间,精度可以达到纳秒级别。而std::sleep_for()是C++11标准中提供的休眠函数,它通过调用底层的nanosleep()函数实现线程休眠。因此,在 Linux 系统中,std::sleep_for()底层使用的就是nanosleep()函数。
下面是一个示例代码:
- #include <iostream>
- #include <chrono>
- #include <thread>
-
- using namespace std;
- using namespace std::chrono;
-
- int main() {
- auto start = high_resolution_clock::now();
-
- // 休眠1秒钟
- cout << "start sleeping..." << endl;
- std::this_thread::sleep_for(seconds(1));
- cout << "sleeping finished." << endl;
-
- auto end = high_resolution_clock::now();
- auto duration = duration_cast<milliseconds>(end - start);
- cout << "duration: " << duration.count() << "ms" << endl;
-
- return 0;
- }
阅读我的CSDN主页,解锁更多精彩内容:泡沫o0的博客主页
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。