深入探索C语言中的各种Sleep方法

news2024/9/23 17:19:55

在这里插入图片描述

引言

在程序设计中,有时需要让进程或线程暂停执行一段时间,这种需求可以通过使用 sleep 函数来实现。本文将详细介绍在 C 语言环境下可用的不同类型的 sleep 函数,包括它们的用途、参数以及注意事项,并提供一些示例代码。

目录

  1. 标准 sleep() 函数
    • 定义与原型
    • 参数解释
    • 返回值与错误处理
    • 示例代码
    • 底层原理
  2. 精确定时 nanosleep()
    • 定义与原型
    • 参数解析
    • 实现精确延时
    • 示例代码
    • 底层原理
  3. 非阻塞 usleep()
    • 定义与原型
    • 微秒级延迟
    • 使用场景与限制
    • 示例代码
    • 底层原理
  4. 线程专用 pthread_sleep()clock_nanosleep()
    • 线程间同步
    • 参数与用法
    • 示例代码
    • 底层原理
  5. 条件变量等待 pthread_cond_timedwait()
    • 条件变量与定时等待
    • 参数解析
    • 示例代码
    • 底层原理
  6. 总结与建议
  7. 参考资料

正文

1. 标准 sleep() 函数

定义与原型:

#include <unistd.h>
unsigned int sleep(unsigned int seconds);

参数解释:

  • seconds: 指定要挂起进程的秒数。

返回值与错误处理:

  • 成功时返回实际睡眠的秒数。
  • 失败时返回 0 并将 errno 设置为 EINTR(如果进程被信号中断)。

示例代码:

#include <stdio.h>
#include <unistd.h>

int main(void) {
    printf("Sleeping for 5 seconds...\n");
    if (sleep(5) == 0) {
        perror("Error sleeping");
    }
    printf("Woke up.\n");
    return 0;
}

底层原理:

  • sleep() 是一个系统调用,它通过发送 SIGTSTP 信号给当前进程来挂起进程。
    • 当进程调用 sleep() 函数时,它实际上是在调用内核中的一个系统调用处理程序。
    • 系统调用处理程序会检查进程是否已经准备好进入睡眠状态,并将进程的状态标记为不可中断的睡眠状态 (D)。
    • 内核会将进程添加到睡眠队列中,并开始计时。
    • 当指定的时间过去后,内核会唤醒该进程,并将进程的状态从睡眠状态改为可运行状态 ®。
    • 进程回到用户空间后,会继续执行。
    • 如果在睡眠过程中接收到一个信号(如 SIGALRM 或 SIGTERM),则进程会被立即唤醒,sleep() 函数会返回 0 并将 errno 设置为 EINTR。
    • sleep() 函数的精度相对较低,因为它只能以整秒为单位进行延时,不适合需要更高精度的应用场景。
    • 由于 sleep() 依赖于信号机制,因此在高负载情况下可能会出现延迟唤醒的情况。
    • 使用 sleep() 时需要注意避免被信号中断的问题,尤其是当需要精确控制延时时。
2. 精确定时 nanosleep()

定义与原型:

#include <time.h>
int nanosleep(const struct timespec *req, struct timespec *rem);

参数解析:

  • req: 请求的持续时间。
  • rem: 剩余的时间(如果请求的睡眠时间超过实际的睡眠时间)。

实现精确延时:
可以精确到纳秒级别。

示例代码:

#include <stdio.h>
#include <time.h>

int main(void) {
    struct timespec ts, rem;
    ts.tv_sec = 1; // 秒
    ts.tv_nsec = 500000000; // 纳秒

    printf("Sleeping for 1.5 seconds...\n");
    if (nanosleep(&ts, &rem) != 0) {
        perror("Error in nanosleep");
    } else {
        printf("Woke up.\n");
    }

    return 0;
}

底层原理:

  • nanosleep() 使用的是基于时钟的定时机制,而不是简单的信号机制。
    • 当调用 nanosleep() 时,内核会检查 req 参数中的时间值,并开始计时。
    • 内核使用一个高精度的时钟来计时,并在达到指定时间时唤醒进程。
    • 如果进程在睡眠期间被信号中断,nanosleep() 会将剩余的睡眠时间保存在 rem 结构体中。
    • nanosleep() 支持中断处理,当进程被信号中断时,剩余的睡眠时间会保存在 rem 结构体中,可以在后续调用中使用。
    • 由于 nanosleep() 可以精确到纳秒,因此它非常适合需要高精度延时的应用场景。
    • nanosleep() 函数的实现依赖于内核提供的高精度时钟源,这使得它可以提供比 sleep() 更高的精度。
    • 在现代操作系统中,nanosleep() 使用的是实时时钟,这意味着即使系统处于睡眠状态,计时也不会受到影响。
    • 使用 nanosleep() 时需要注意,尽管它可以提供较高的精度,但在高负载情况下也可能受到一定的影响。
3. 非阻塞 usleep()

定义与原型:

#include <unistd.h>
int usleep(useconds_t usec);

微秒级延迟:
适用于需要更精细控制的情况。

使用场景与限制:

  • 微秒级别的精度。
  • 注意可能存在的不精确性。

示例代码:

#include <stdio.h>
#include <unistd.h>

int main(void) {
    printf("Sleeping for 500 milliseconds...\n");
    if (usleep(500000) != 0) {
        perror("Error in usleep");
    } else {
        printf("Woke up.\n");
    }

    return 0;
}

底层原理:

  • usleep() 通常不是通过直接的系统调用来实现的,而是通过其他延时机制,如 select() 或者 poll() 来模拟实现。
    • usleep() 的实现依赖于底层操作系统的实现细节。
    • 在某些实现中,usleep() 可能会使用 select() 函数来实现延时功能。
    • select() 函数允许进程在一个或多个文件描述符上等待事件的发生,这里可以设置一个空的文件描述符列表,并设置一个延时时间。
    • 当延时时间到达后,select() 会返回,从而结束 usleep() 的调用。
    • 由于 usleep() 不是标准的系统调用,所以它的实现可能会因操作系统而异。
    • usleep() 的主要问题是它可能受到系统负载的影响,导致实际的延时时间比预期的长。
    • 在某些情况下,usleep() 可能会使用 poll() 函数来实现,这取决于操作系统的具体实现。
    • 使用 usleep() 时需要注意,虽然它可以提供微秒级别的精度,但实际延时时间可能会受到系统负载和其他因素的影响。

在这里插入图片描述

4. 线程专用 pthread_sleep()clock_nanosleep()

线程间同步:
专门用于线程的延时函数。

参数与用法:

  • clock_nanosleep() 更加灵活且具有更好的性能。

示例代码:

#include <stdio.h>
#include <pthread.h>
#include <time.h>

void* thread_func(void *arg) {
    struct timespec ts;
    ts.tv_sec = 2; // 秒
    ts.tv_nsec = 0; // 纳秒

    printf("Thread: Sleeping for 2 seconds...\n");
    clock_nanosleep(CLOCK_REALTIME, 0, &ts, NULL);
    printf("Thread: Woke up.\n");

    pthread_exit(NULL);
}

int main(void) {
    pthread_t thread;

    if (pthread_create(&thread, NULL, thread_func, NULL) != 0) {
        perror("Error creating thread");
        return 1;
    }

    if (pthread_join(thread, NULL) != 0) {
        perror("Error joining thread");
        return 1;
    }

    return 0;
}

底层原理:

  • pthread_sleep()clock_nanosleep() 都是为了支持多线程环境中的延时操作而设计的。
    • clock_nanosleep() 使用的是线程的调度器,而不是整个进程的调度器。
    • 当一个线程进入 clock_nanosleep() 后,其他线程仍然可以继续运行。
    • clock_nanosleep() 提供了更高的精度,并且不会影响到其他线程的执行。
    • 内核维护了一个高精度的时钟,当线程调用 clock_nanosleep() 时,内核会记录下线程需要睡眠的时间,并在达到这个时间时唤醒线程。
    • 由于 clock_nanosleep() 是针对单个线程的操作,因此它不会影响到其他线程的调度。
    • clock_nanosleep() 使用的时钟源通常是实时时钟,这意味着即使系统处于睡眠状态,计时也不会受到影响。
    • 使用 clock_nanosleep() 时需要注意,尽管它可以提供较高的精度,但在高负载情况下也可能受到一定的影响。
5. 条件变量等待 pthread_cond_timedwait()

条件变量与定时等待:
结合条件变量进行定时等待,常用于多线程同步。

示例代码:

#include <stdio.h>
#include <pthread.h>
#include <time.h>

int main(void) {
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
    int ready = 0;

    void *thread_func(void *arg) {
        struct timespec ts;
        ts.tv_sec = time(NULL) + 5; // 当前时间加上5秒
        ts.tv_nsec = 0;

        pthread_mutex_lock(&mutex);
        while (!ready) {
            printf("Thread: Waiting until %ld seconds...\n", ts.tv_sec);
            if (pthread_cond_timedwait(&cond, &mutex, &ts) != 0) {
                perror("Error in pthread_cond_timedwait");
                break;
            }
        }
        printf("Thread: Ready flag is set.\n");
        pthread_mutex_unlock(&mutex);
        pthread_exit(NULL);
    }

    pthread_t thread;
    if (pthread_create(&thread, NULL, thread_func, NULL) != 0) {
        perror("Error creating thread");
        return 1;
    }

    sleep(3); // 等待3秒后设置标志
    pthread_mutex_lock(&mutex);
    ready = 1;
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);

    if (pthread_join(thread, NULL) != 0) {
        perror("Error joining thread");
        return 1;
    }

    return 0;
}

底层原理:

  • pthread_cond_timedwait() 用于在条件变量上等待,直到满足某个条件或者超时为止。
    • 当线程调用 pthread_cond_timedwait() 时,它会释放互斥锁并进入等待状态。
    • 如果条件满足或者到达了指定的时间,线程就会被唤醒并重新获取互斥锁。
    • 使用条件变量可以有效地同步多个线程的执行顺序。
    • 当一个线程调用 pthread_cond_timedwait() 时,内核会检查当前时间与请求的时间,如果当前时间未达到请求的时间,线程会被加入到条件变量的等待队列中。
    • 内核会定期检查条件变量队列中的线程是否可以被唤醒。
    • 当条件满足时,调用 pthread_cond_signal()pthread_cond_broadcast() 会唤醒一个或所有等待的线程。
    • 被唤醒的线程会重新获得互斥锁并继续执行。
    • 使用 pthread_cond_timedwait() 时需要注意,尽管它可以提供精确的定时等待,但在高负载情况下也可能受到一定的影响。
6. 总结与建议
  • 选择合适的函数: 根据精度要求和使用场景选择合适的延时函数。
  • 注意中断处理: 考虑到信号中断的可能性。
  • 测试与验证: 在实际应用中进行充分的测试以确保正确性。
  • 考虑系统负载: 在高负载情况下,即使是精确的延时函数也可能出现偏差。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2093923.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HTB-Responder(文件包含和哈希破解)

前言 各位师傅大家好&#xff0c;我是qmx_07,今天给大家讲解Responder靶场 渗透过程 信息搜集 服务器开放了80,5985端口尝试访问网站5985端口是一种远程管理协议 绑定域名 我们发现访问ip&#xff0c;进行了重定向跳转&#xff0c;需要绑定一下域名 echo "10.129.160…

麦穗检测计数-目标检测数据集(包括VOC格式、YOLO格式)

麦穗检测计数-目标检测数据集&#xff08;包括VOC格式、YOLO格式&#xff09; 数据集&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1N9tGbcssxvSM1W71q2YbNA?pwd3nb3 提取码&#xff1a;3nb3 数据集信息介绍&#xff1a; 共有 3373张图像和一一对应的标注文件 标…

Python内存管理详解

Python是一种动态类型的语言&#xff0c;它提供了自动内存管理机制。这意味着开发者不需要手动管理内存的分配和释放&#xff0c;Python会自动处理这些细节。本文将深入探讨Python中的内存管理机制&#xff0c;包括对象的创建、垃圾回收以及一些最佳实践。 Python内存管理概述…

定制开发 AI 智能名片拓客微信小程序在内容营销中的应用与价值

摘要&#xff1a;本文探讨了不同类型的内容营销及其目标&#xff0c;分析了传统媒体与以社交媒体为主要发布平台的内容营销在效果衡量上的差异。引入定制开发 AI 智能名片拓客微信小程序&#xff0c;阐述其在内容营销中的作用&#xff0c;强调应以多维度视角衡量内容营销效果&a…

Python打发无聊时光:15.Python打开黑神话-八戒3D模型

一、装vtk库并下载3D模型 首先装vtk库&#xff0c;直接在终端中输入命令&#xff1a; pip install vtk 接着将下面网盘链接中的vtk模型下载下来&#xff1a; 链接: https://pan.baidu.com/s/11pEPr3URQ5oR2kkn7dBEsg?pwdfa6s 提取码: fa6s --来自百度网盘超级会员v5的分享…

zsh: command not found: ohpm - mac安装ohpm工具 - 鸿蒙开发

OHPM简介&#xff1a; OHPM CLI 是鸿蒙生态三方库的包管理工具&#xff0c;支持OpenHarmony共享包的发布、安装和依赖管理。安装开发工具DevEco Studio--自带了ohpm&#xff0c;所以无需单独下载ohpm ohpm使用指导官网地址&#xff1a; 文档中心 注意&#xff1a; ohpm命令…

初等数学几百年重大错误:N各元n的对应n+1的全体是N的真子集N+——百年病态集论的症结

黄小宁 数学图可是“离散”的点组成的点集N&#xff5b;0&#xff0c;1&#xff0c;2&#xff0c;…&#xff0c;n&#xff0c;…0&#xff5d;&#xff08;各数是点的坐标&#xff09;。设本文所说集合往往是元不少于两个的集。定义&#xff1a;若数&#xff08;点&#xff09…

微服务框架三

微服务 微服务技术栈 服务发现概念 服务发现两种方式 客户端发现 服务端服务发现 服务发现技术对比 Nacos架构图 基于dubbo nacos服务调用 Nacos核心源码解析 registery 具体实现在nacosServiceRegistery setbeat 返回clientBeatInterval

网络准入控制系统

当我们谈论网络准入控制系统时&#xff0c;我们谈论的并不是网络准入控制系统&#xff0c;而是安全&#xff0c;我们不能只囿于它表面的浮华而忘掉它的本质&#xff0c;记住&#xff0c;不管讨论什么&#xff0c;我们必须要有直达本质的能力。网络的本质就是安全。 网络准入控制…

在大语言模型中,生成文本的退出机制,受max_generate_tokens限制,并不是所有的问答都完整的跑完整个transformer模型

目录 在大语言模型中,生成文本的退出机制,受max_generate_tokens限制,并不是所有的问答都完整的跑完整个transformer模型 1. max_generate_tokens的作用 2. 退出机制与Transformer模型 3. 实际应用中的影响 4. 结论 在大语言模型中,生成文本的退出机制,受max_genera…

网站建设完成后, 做seo必须知道的专业知识之--权重

SEO的权重是指搜索引擎对网站的综合评估和信任程度&#xff0c;这直接影响到网站在搜索结果中的排名和流量。 权重越高&#xff0c;说明搜索引擎对网站的认可度越高&#xff0c;从而有助于提高网站的关键词排名和流量。虽然“百度权重”并非百度官方提出的指标&#xff0c;但这…

开学日,LabVIEW 助你踏上编程之路

九月一日&#xff0c;伴随着凉爽的秋风和崭新的课本&#xff0c;新学期正式拉开帷幕。对于许多工科学生而言&#xff0c;这不仅意味着新课程的开始&#xff0c;更是开启实验室研究和工程项目的大门。而在工程软件开发的世界里&#xff0c;LabVIEW 是一个不可忽视的存在&#xf…

微服务CI/CD实践(二)服务器先决软件安装

微服务CI/CD实践系列&#xff1a; 微服务CI/CD实践&#xff08;一&#xff09;环境准备及虚拟机创建 微服务CI/CD实践&#xff08;二&#xff09;服务器先决软件安装 微服务CI/CD实践&#xff08;三&#xff09;gitlab部署 微服务CI/CD实践&#xff08;四&#xff09;nexus3部…

每天五分钟计算机视觉:人脸识别网络FaceNet

本文重点 在前面的课程中,为了解决人脸识别的问题,我们学习了Siamese神经网络。本文我们学习另外一种人脸识别网络模型FaceNet。 论文 FaceNet: A Unified Embedding for Face Recognition and Clustering FaceNet概述 FaceNet是谷歌在CVPR 2015上提出的一种深度学习模型,…

ET6框架(九)Protobuf消息使用

文章目录 一、序列化和反序列化二、什么是Prototbuf&#xff1f;三、ET工程中的Proto&#xff1a;四、查看消息类型五、生成编译Proto2CS: 一、序列化和反序列化 序列化 &#xff1a; 将程序中的对象转化为字节序列的过程 反序列化 &#xff1a; 把字节回复为程序中的过程 在网…

可以根据手机的折叠状态改变播放音效:nova Flip 的妙趣音效

由于折叠机最基础的“可折叠”属性&#xff0c;导致折叠机的扬声器相对于人的位置来说会存在更多的变化&#xff0c;在不同的折叠状态下&#xff0c;听感方面可能就会大有不同。 nova Flip手机利用这一特性&#xff0c;首次根据折叠形态差异&#xff0c;自适应了不同形态的音效…

手把手带你实现C语言扫雷进阶(1)(接上回基础版扫雷,附上源码)

文章目录 一、扫雷进阶留下的问题二.非雷扩展周围不是雷函数三、标记雷函数四.查看排雷总时间五、扫雷进阶源码及总结 一、扫雷进阶留下的问题 我们先来看看之前讲扫雷基础的时候留下的一些问题&#xff1a; 是否可以选择游戏难度     ◦ 简单 9 * 9 棋盘&#xff0c;10个雷…

【Qt】Qt 网络 | UDP Socket

文章目录 核心API代码示例服务器客户端 要使用 Qt 网络编程&#xff0c;需要在项目中的 .pro 文件中添加 network 模块 核心API Qt 的 UDP Socket 主要的类有两个 QUdpSocket 和 QNetworkDatagram 因为是 UDP 是面向数据报的&#xff0c;QNetworkDatagram 就是对 数据报的封…

【项目管理】系统设计与开发管理规程(Word完整文件)

2 过程总体描述 2.1 过程概述 2.2 过程流程图 3 过程元素描述 3.1 产品方案 3.2 产品设计 3.3 产品实现 获取方式&#xff1a;本文末个人名片直接获取。 软件资料清单列表部分文档清单&#xff1a;工作安排任务书&#xff0c;可行性分析报告&#xff0c;立项申请审批表&#xf…

【模拟器-夜神】Mac卡在99%问题

▒ 目录 ▒ &#x1f6eb; 导读需求 1️⃣ 首次启动提示2️⃣ 手动授权允许加载驱动非苹果CPU苹果CPU &#x1f4d6; 参考资料 &#x1f6eb; 导读 需求 解决模拟器中遇到的问题 &#xff0c;汇总。 1️⃣ 首次启动提示 首次点击图标启动时会弹出提示&#xff1a; 解决方式如…