【Linux C/C++ 延时(延迟)函数比较】介绍Linux系统中常用的延时函数sleep、usleep、nanosleep、select和std::sleep_for()的区别和使用场景

article/2025/9/24 21:49:49

 首先,需要了解各个睡眠函数的作用和使用场景。

 

  • 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);
     //执行挂起指定的秒数
   
     返回值:
     完成seconds所指定的墙上时钟时间,返回0
     若由于进程捕捉到某个信号并从信号处理函数提早,返回时未休眠完的秒数
sleep()非系统调用,sleep()是在库函数中实现的,它是通过alarm()来设定报警时间,使用sigsuspend()将进程挂起在信号SIGALARM上。
sleep()只能精确到秒级上。sleep()会令目前的进程暂停,直到达到参数seconds 所指定的时间,或是被信号所中断.

 int usleep(useconds_t usec);

     //把进程挂起一段时间, 单位是微秒(百万分之一秒);
   
     返回值:
     完成seconds所指定的墙上时钟时间,返回0
     若由于进程捕捉到某个信号并从信号处理函数提早,返回时未休眠完的微妙数

 int nanosleep(const struct timespec *req, struct timespec *rem);

      //具有不影响任何信号的优点,它被POSIX标准化,它提供更高的定时分辨率,并且允许继续已被信号中断的睡眠更容易。
   参数:
struct timespec
              {
                      time_t  tv_sec;     //秒   
                      long    tv_nsec;     //纳妙 
              };
  req:秒或纳秒指定需要休眠的时间长度
  rem:如果某个信号中断了休眠间隔,进程没有终止,rem指向的结构体会被设置为未休眠完的时间长度,不感兴趣可设NULL。
     返回值:
     成功休眠所请求的间隔之后,返回0
     调用由信号处理程序中断或遇到错误,返回返回-1,其中errno设置为指示错误,并将剩余时间写入由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);

     //把进程挂起一段时间, 单位是微秒(百万分之一秒);
 
参数:
clock_id:指定了计算机延迟时间基于的时钟,下表所示

flags:用于控制延时是绝对的还是相对的
         当flags被设置为0的时候,睡眠时间是相对的(想要睡眠多久)
         当其数值被设置为TIMER_ABSTIME的时候,睡眠时间是绝对的,例如希望休眠到时钟到达某个特定时间。
req:秒或纳秒指定需要休眠的时间长度
rem:如果某个信号中断了休眠间隔,进程没有终止,rem指向的结构体会被设置为未休眠完的时间长度,不感兴趣可设NULL。
     返回值:
     成功休眠所请求的间隔之后,返回0
     调用由信号处理程序中断或遇到错误,返回返回-1,其中errno设置为指示错误,并将剩余时间写入由rem指向的结构中。

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的博客主页


http://chatgpt.dhexx.cn/article/3CI0vDS0.shtml

相关文章

单片机:延时函数的理解

在实现单片机功能的时候&#xff0c;经常会用到延时函数&#xff0c;那么延时函数的原理也是非常有必要了解的。一般我们写延时函数的时候&#xff0c;默认的晶振频率fosc12MHZ&#xff0c;而机器周期T12/fosc1us。 这里我们来写一个10ms的延时函数&#xff1a; void delay_10…

c/c++语言中的延时操作

大家在编程的过程中可能需要用到一些延时操作&#xff0c;比如说在使用控制台编程时&#xff0c;程序运行的时候DOS窗口会一闪而过&#xff0c;这样就会导致看不到程序在Dos界面运行的结果&#xff0c;这样有些小伙伴就纳闷了&#xff1a;怎样使得Dos窗口一直停留呢&#xff1f…

C\C++中计时、延时函数

C\C标准库中提供了两种计时函数clock()和time()。其用法如下&#xff1a; &#xff08;1&#xff09;clock()函数用法 void timeConsume() {double start,stop,durationTime;start clock();/*...代码片段*/stop clock();durationTime ((double)(stop-start))/CLK_TCK;cout…

c语言中,关于延迟函数的理解

对于延迟&#xff0c;有些c基础的人都能够做到用for或while来实现 例如&#xff1a; #include <stdio.h>int main() {int i, j, k;for (i 1; i < 1000; i){for (j 1; j < 1000; j){for (k 1; k < 1000; k){}}}printf("hello\n");return 0; }1234…

延时函数

延时函数 什么是延时函数 所谓延时函数就是在函数中设置了几个空操作的动作&#xff0c;每次操作都需要消耗一定的时间&#xff0c;动作结束了&#xff0c;就会跳出延时函数继续做其他事情了。 为什么要延时 为了使CPU某些芯片的时序而采用的一些机制&#xff0c;比如独立按…

C语言里的延时函数

C语言延时 悬赏分&#xff1a;0 - 解决时间&#xff1a;2007-2-18 14:48s级的时间延时杂写啊&#xff1f;大侠们帮哈忙啊 最佳答案 在Windows下最简单的办法是调用系统函数Sleep(time)&#xff0c;单位是ms&#xff0c;在windows.h中声明&#xff0c;注意大小写&#xff1b;不然…

连接oracle数据库报错:ORA-12505

连接oracle数据库报错:ORA-12505 今天在使用程序连接oracle数据库时本来很简单的填写url,用户名和密码&#xff0c;测试连接提示失败。和pl_sql 对比了下写的也没毛病&#xff0c;有图为证&#xff1a; 看了下数据库地址端口和用户名密码都没问题&#xff0c;打开数据日志看到…

解决oracle报错ORA-12505

连接oracle报错ORA-12505 主要原因是sid错误&#xff0c;网上有很多解决办法&#xff0c;我这里是因为url链接方式写错了&#xff0c;给我的是service-name&#xff0c;我却用jdbc:oracle:thin:host:port:SID 方式去链接&#xff0c;而正确的写法是 jdbc:oracle:thin://host:p…

连接Oracle时出现ORA-12505错误

连接Oracle时出现ORA-12505错误 问题&#xff1a;使用eclipse连接Oracle数据库时报错&#xff1a;Listener refused the connection with the following error:ORA-12505, TNS:listener does not currently know of SID given in connect descriptor 原因&#xff1a;重新配置了…

ORA-01555

报错&#xff1a; 数据泵导入时报错如下&#xff0c;快照太旧 分析原因&#xff1a; snapshot 是存储undo中 undo的作用事务恢复、事务回滚、读一致性&#xff0c;显然和读一致性作用有关 数据泵的原理&#xff1a;将数据库的信息以转储文件的形式存储到操作系统中  S…

【数据源】连接Oracle失败 Listener refused the connection with the following error: ORA-12505

连接Oracle失败 Listener refused the connection with the following error: ORA-12505 使用场景解决方案 使用场景 数据源平台配置了Oracle&#xff0c;在其它工具测试能够正常连接&#xff0c;但数据源平台在确认配置无误情况下点击测试连接提示失败&#xff0c;报错信息提…

Oracle SQL Developer连接报错(ORA-12505)

理论实践 Oracle SQL Developer连接报错(ORA-12505) 作者&#xff1a;Vashon 时间&#xff1a;20150415 之前我的Oracle数据库出现问题&#xff0c;费大波周折终于弄好了&#xff0c;今天又创建了一个DBA管理员的连接方式出现问题&#xff0c;本人现在把解决方案分享给大家&am…

使用dbeaver链接oracle报错ORA-12505, TNS:listener does not currently know of SID given in connect descripto

业务需求需要读取oracle数据库数据, 想先在dbeaver连接oracle数据库进行操作, 但是管理员一开始给的用户名与密码连接不上, 报错: 以及打开详细 Caused by: oracle.net.ns.NetException: Listener refused the connection with the following error: ORA-12505, TNS:listener …

ORA-12505错误的解决方法

在使用ORACLE数据库的时候,遇到这样一个问题:每隔一段时间,ORACLE数据库就打不开,显示错误是ORA-12505,大概就是指向监听和SID名字错误的说明。网上有很多解决办法。多数说的是将Listener-ora文件改写,将监听打开重启即可解决。在将以上措施都尝试一遍之后都没有解决,可…

【Oracle连接】java.sql.SQLException: Listener refused the connection with the following error: ORA-12505

连接数据库时&#xff0c;提示错误描述&#xff1a; java.sql.SQLException: Listener refused the connection with the following error: ORA-12505, TNS:listener does not currently know of SID given in connect descriptor 问题描述&#xff1a;情况使用帆软报表连接数…

ORA-12505:TNS:listener does not currently know of SID given in connect descriptor

Oracle安装好之后&#xff0c;默认的listener是localhost&#xff0c;现在为了在局域网内能够访问&#xff0c;其他电脑访问的时候&#xff0c;提示如下错误&#xff1a; ORA-12505&#xff1a;TNS:listener does not currently know of SID given in connect descriptor。 修…

ORA-12505:TNS: 监听程序当前无法识别连接描述符中所给出的 SID

问题描述&#xff1a; 小学期修Oracle课程&#xff0c;为了小团队的便利性&#xff0c;在腾讯云中使用Docker创建了Oracle容器进行共享&#xff0c;在这段时间使用是正常的。在一两个星期后使用nacicat连接oracle时&#xff0c;报了ORA-12505&#xff1a;TNS: 监听程序当前无法…

ORA-12505, TNS:listener does not currently know of SID given in connect descriptor解决方式

启动项目连接oracle数据报&#xff1a;ORA-12505, TNS:listener does not currently know of SID given in connect descriptor ORA-12505: TNS: 监听程序当前无法识别连接描述符中所给出的SID 报错原因&#xff1a;通过报错内容 “TNS:listener does not currently know of …

ORA-12505

oracle 数据库&#xff0c;用sqldeveloper 打开报了 ORA-12505: TNS:listener does not currently know of SID given in connect descriptor&#xff1b; 先通过sqlplus\命令行, 查看当前正在使用的数据库实例及主机名 SQL>conn/as sysdba SQL>select instance_name fr…

关于oracle连接ORA-12505错误的直观解决方法

oracle连接一直好好的&#xff0c;突然间连接的时候报错了&#xff0c;报错为ORA-12505, TNS:listener does not currently know of SID given in connect descriptor 。网上找了好长时间也没解决。现在将个人的解决方法分享出来&#xff0c;大家有什么不同意见的&#xff0c;…