目录
1 为什么需要休眠
有时需要将进程暂停或休眠一段时间, 进入休眠状态之后,程序将暂停运行,直到休眠结束。
以下是一些常见的休眠场景和作用:
-
避免过载:在高负载或密集计算任务中,程序可能需要定期休眠,以避免长时间占用CPU,给系统其他部分留出处理时间。
-
定时任务:在需要执行定时任务的场景中,休眠可以用于实现简单的时间调度。
-
错误恢复:在遇到错误或异常时,程序可能会选择休眠一段时间,然后重试操作,这可以作为简单的错误恢复机制。
-
节能:在某些嵌入式系统或移动设备上,休眠可以用于节能,通过减少CPU的活动来降低功耗。
在Linux系统中,实现休眠的常用函数包括:
sleep()
:基于秒的休眠。usleep()
:基于微秒的休眠(1微秒 = 10^-6秒)。nanosleep()
:基于纳秒的休眠(1纳秒 = 10^-9秒),提供了更精细的控制。
2 sleep、usleep和nanosleep函数
2.1 sleep函数
sleep函数使调用进程休眠指定的秒数。
#include <unistd.h>
unsigned int sleep(unsigned int seconds);
seconds
:要休眠的秒数。- 返回值: 如果休眠时长为参数 seconds 所指定的秒数,则返回 0;若被信号中断则返回剩余的秒数。
2.2 usleep函数
usleep函数使调用进程休眠指定的微秒数。
#include <unistd.h>
int usleep(useconds_t usec)
- 参数:
usec
- 要休眠的微秒数。 - 返回值: 成功返回 0;失败返回-1,并设置 errno。
2.3 nanosleep函数
nanosleep函数使调用进程休眠指定的纳秒数。
#include <time.h>
int nanosleep(const struct timespec *req, struct timespec *rem);
req
- 指向timespec
结构的指针,该结构指定要休眠的时间。rem
- 指向timespec
结构的指针,用于存储未完成的剩余时间(如果函数被中断)。- 返回值: 在成功休眠达到请求的时间间隔后, nanosleep()返回 0; 如果中途被信号中断或遇到错误,则返回-1, 并将剩余时间记录在参数 rem 指向的 struct timespec 结构体变量中(参数 rem 不为 NULL 的情况下,如果为 NULL 表示不接收剩余时间),还会设置 errno 标识错误类型。
3 示例程序
示例程序使用 sleep()
、usleep()
和 nanosleep()
函数演示了当这些函数因信号中断时如何处理剩余的休眠时间。
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>
int main()
{
// 使用 sleep() 函数休眠 2 秒
printf("使用 sleep() 休眠 2 秒...\n");
unsigned int seconds = 2;
unsigned int remaining_seconds = sleep(seconds);
if (remaining_seconds == 0) {
printf("sleep() 正常结束。\n");
} else {
printf("sleep() 被中断,剩余休眠时间:%u 秒。\n", remaining_seconds);
}
// 使用 usleep() 函数休眠 1000 微秒
printf("使用 usleep() 休眠 1000 微秒...\n");
unsigned long usecs = 1000;
int result = usleep(usecs);
if (result == 0) {
printf("usleep() 正常结束。\n");
} else {
printf("usleep() 被中断,错误码:%d。\n", errno);
}
// 使用 nanosleep() 函数休眠 100 毫秒
printf("使用 nanosleep() 休眠 100 毫秒...\n");
struct timespec req, rem;
req.tv_sec = 0;
req.tv_nsec = 100000000; // 100 毫秒
while (nanosleep(&req, &rem) == -1) {
if (errno == EINTR) {
// 如果 nanosleep 被中断,更新剩余时间并重试
req = rem;
} else {
perror("nanosleep 遇到错误");
break;
}
}
printf("nanosleep() 正常结束。\n");
return 0;
}
运行结果如下: