Linunx的sleep,usleep,select,nonasleep对比与应用
Posted 北雨南萍
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linunx的sleep,usleep,select,nonasleep对比与应用相关的知识,希望对你有一定的参考价值。
前言
时钟换算:
1秒(s) = 1000 毫秒(ms) = 1,000,000 微秒(μs) = 1,000,000,000 纳秒(ns) = 1,000,000,000,000 皮秒(ps)
程序挂起主要有以下几种:
sleep, usleep, select, pselect, nanosleep;
它们的精度不同,在不同的应用场景下需要不同的函数;
一、用法
1.1 函数名: sleep
头文件:
#include <unistd.h> // 在gcc编译器中,使用的头文件因gcc版本的不同而不同
功 能: 执行挂起指定的秒数
语 法: unsigned sleep(unsigned seconds);
示例:
#include<stdio.h>
int main()
int a;
a=1;
printf("hello");
sleep(a);
printf("world");
return 0;
1.2 函数名: usleep
功 能: usleep功能把进程挂起一段时间, 单位是微秒(百万分之一秒);
头文件: #include <unistd.h>
语 法:
void usleep(int micro_seconds);
返回值: 无
内容说明:本函数可暂时使程序停止执行。参数 micro_seconds 为要暂停的微秒数(us)。
注 意:
用在Linux的测试环境下面。
参 见:usleep() 与sleep()类似,用于延迟挂起进程。进程被挂起放到reday queue。
是一般情况下,延迟时间数量级是秒的时候,尽可能使用sleep()函数。
如果延迟时间为几十毫秒(1ms = 1000us),或者更小,尽可能使用usleep()函数。这样才能最佳的利用CPU时间.
1.3 函数名:select
功能:I/O多工机制
用来等待文件描述符状态的改变。
头文件:
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
语法:
int select(int maxfdp, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval*timeout);
参数说明:
maxfdp: 最大的文件描述符加1,如果我有三个文件节点1、4、6,那第一个参数就为7(6+1)
readfds: 可读文件节点集,类型为fd_set。
通过FD_ZERO(&readfd);初始化节点集;
然后通过FD_SET(fd, &readfd);把需要监听是否可读的节点加入节点集
readfds: 可写文件节点集中,类型为fd_set。操作方法和第二个参数一样。
errorfds: 检查节点错误集。
timeout: 超时参数,类型为struct timeval,用于设置超时时间,
分别可设置秒timeout.tv_sec和微秒timeout.tv_usec。
返回值:
执行成功则返回文件描述符状态已经改变的个数,
如果返回0,则表示在描述符在状态改变前已经超过了timeout时间。
当有错误发生时,返回-1, 且错误原因保存在errno中。
定时器用法:
//test
select tv.tv_sec = 0;
tv.tv_usec = 500000;
ret = select(0, NULL, NULL, NULL, &tv);
if (-1 == ret)
fprintf(stderr, "select error. errno = %d [%s]\\n", errno, strerror(errno));
1.4 函数名:pselect
功能:I/O多工机制
头文件:
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/select.h>
语法:
int pselect(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, const struct timespec* timeout,
const sigset_t *sigmask);
说明:
pselect()和select()作用几乎一样,都是用来等待文件描述符状态的改变,
不过pselect() 还可以判断是否有信号(signal)发生。
定时器用法:
req.tv_sec = nDelay/1000000;
req.tv_nsec = (nDelay%1000000) * 1000;
ret = pselect(0, NULL, NULL, NULL, &req, NULL);
if (-1 == ret)
fprintf(stderr, "select error. errno = %d [%s]\\n", errno, strerror(errno));
1.5 函数名:nonasleep
功能:
nanosleep()函数会导致当前的线程将暂停执行,直到rqtp参数所指定的时间间隔。
或者在指定时间间隔内有信号传递到当前线程,将引起当前线程调用信号捕获函数或终止该线程。
头文件:
#include<time.h>
#include<sys/time.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/select.h>
语法:
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
描述:
nanosleep()函数会导致当前的线程将暂停执行,直到rqtp参数所指定的时间间隔。
或者在指定时间间隔内有信号传递到当前线程,将引起当前线程调用信号捕获函数或终止该线程。
暂停时间可能超过请求时间,因为参数值是sleep粒度的整数倍数或者因为其他活动的系统调度。
但是,除了被信号中断的情况下,暂停时间不会少于rqtp指定的时间,由系统时钟CLOCK_REALTIME测量。
使用nanosleep()函数对其他行为没有影响,不堵塞任何信号。
返回值:
0 :请示的时间间隔结束。
-1:信号中断或失败,并设置errno。
如果rmtp参数不为空,它所引用的timespec结构更新为包含剩余时间的间隔量(请求的时间减去实际睡眠时间)。
如果rmtp参数为NULL,不返回的剩余时间。
示例:
req.tv_sec = 0;
req.tv_nsec = 1000;
ret = nanosleep(&req, NULL);
if (-1 == ret)
fprintf (stderr, "\\t nanousleep %8u not support\\n", nDelay);
二、精确度对比
如果用于一些 C/S 数据交互等 100ms级以上精度的程序挂起,用sleep, usleep都可以。
如果是在多线程应用场景中,如用于音视频数据的同步,需要100ms以下的精度的程序挂起,则只能用select, 和 nanosleep.
这是因为,虽然sleep()和nanosleep()都是使进程睡眠一段时间后被唤醒,但是二者的实现完全不同。
Linux中并没有提供系统调用sleep(),
sleep()是在库函数中实现的,它是通过调用alarm()来设定报警时间,
调用sigsuspend()将进程挂起在信号SIGALARM上。
nanosleep()则是Linux中的系统调用,它是使用定时器来实现的,
该调用使调用进程睡眠,并往定时器队列上加入一个timer_list型定时器,time_list结构里包括唤醒时间以及唤醒后执行的函数,
通过nanosleep()加入的定时器的执行函数仅仅完成唤醒当前进程的功能。
系统通过一定的机制定时检查这些队列(比如通过系统调用陷入核心后,从核心返回用户态前,
要检查当前进程的时间片是否已经耗尽,如果是则调用schedule()函数重新调度,该函数中就会检查定时器队列,另外慢中断返回前也会做此检查),
如果定时时间已超过,则执行定时器指定的函数唤醒调用进程。
三、工程应用
这是FFmpeg的程序挂起,
int av_usleep(unsigned usec)
#if HAVE_NANOSLEEP
struct timespec ts = usec / 1000000, usec % 1000000 * 1000 ;
while (nanosleep(&ts, &ts) < 0 && errno == EINTR);
return 0;
#elif HAVE_USLEEP
return usleep(usec);
#elif HAVE_SLEEP
Sleep(usec / 1000);
return 0;
#else
return AVERROR(ENOSYS);
#endif
附:
初六 谦谦君子,用涉大川,吉。
以上是关于Linunx的sleep,usleep,select,nonasleep对比与应用的主要内容,如果未能解决你的问题,请参考以下文章
PHP 暂停函数 sleep() 与 usleep() 的区别
在 PHP 中 sleep 和 usleep 的行为是不是不同?
linux 的sleep()、usleep()、nanosleep()函数
C++之sleep/usleep/this_thread::yield/this_thread::sleep_for延时区别(一百四十)