一、sleep 和 usleep
1、不属于系统调用,是glibc 库函数实现的;
2、glibc函数库中通过调用内核的nanosleep实现的;
3、内核nanosleep通过调用 hrtimer_nanosleep 实现(/kernel/hrtime);
 
二、源码
2.1 usleep  (glibc2.11)
int usleep (useconds_t useconds)
{
struct timespec ts = { .tv_sec = (long int) (useconds / 1000000),
.tv_nsec = (long int) (useconds % 1000000) * 1000ul };
/* Note the usleep() is a cancellation point. But since we call
nanosleep() which itself is a cancellation point we do not have
to do anything here. */
return __nanosleep (&ts, NULL);
}
2.2 sleep源码
/* We are going to use the `nanosleep' syscall of the kernel.  But the
kernel does not implement the stupid SysV SIGCHLD vs. SIG_IGN
behaviour for this syscall. Therefore we have to emulate it here. */
unsigned int
__sleep (unsigned int seconds)
{
const unsigned int max
= (unsigned int) (((unsigned long int) (~((time_t) 0))) >> 1);
struct timespec ts;
sigset_t set, oset;
unsigned int result; /* This is not necessary but some buggy programs depend on this. */
if (__builtin_expect (seconds == 0, 0))
{
#ifdef CANCELLATION_P
CANCELLATION_P (THREAD_SELF);
#endif
return 0;
} ts.tv_sec = 0;
ts.tv_nsec = 0;
again:
if (sizeof (ts.tv_sec) <= sizeof (seconds))
{
/* Since SECONDS is unsigned assigning the value to .tv_sec can
overflow it. In this case we have to wait in steps. */
ts.tv_sec += MIN (seconds, max);
seconds -= (unsigned int) ts.tv_sec;
}
else
{
ts.tv_sec = (time_t) seconds;
seconds = 0;
} /* Linux will wake up the system call, nanosleep, when SIGCHLD
arrives even if SIGCHLD is ignored. We have to deal with it
in libc. We block SIGCHLD first. */
__sigemptyset (&set);
__sigaddset (&set, SIGCHLD);
if (__sigprocmask (SIG_BLOCK, &set, &oset))
return -1; /* If SIGCHLD is already blocked, we don't have to do anything. */
if (!__sigismember (&oset, SIGCHLD))
{
int saved_errno;
struct sigaction oact; __sigemptyset (&set);
__sigaddset (&set, SIGCHLD); /* We get the signal handler for SIGCHLD. */
if (__sigaction (SIGCHLD, (struct sigaction *) NULL, &oact) < 0)
{
saved_errno = errno;
/* Restore the original signal mask. */
(void) __sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL);
__set_errno (saved_errno);
return -1;
} /* Note the sleep() is a cancellation point. But since we call
nanosleep() which itself is a cancellation point we do not
have to do anything here. */
if (oact.sa_handler == SIG_IGN)
{
//__libc_cleanup_push (cl, &oset); /* We should leave SIGCHLD blocked. */
while (1)
{
result = __nanosleep (&ts, &ts); if (result != 0 || seconds == 0)
break; if (sizeof (ts.tv_sec) <= sizeof (seconds))
{
ts.tv_sec = MIN (seconds, max);
seconds -= (unsigned int) ts.tv_nsec;
}
} //__libc_cleanup_pop (0); saved_errno = errno;
/* Restore the original signal mask. */
(void) __sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL);
__set_errno (saved_errno); goto out;
} /* We should unblock SIGCHLD. Restore the original signal mask. */
(void) __sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL);
} result = __nanosleep (&ts, &ts);
if (result == 0 && seconds != 0)
goto again; out:
if (result != 0)
/* Round remaining time. */
result = seconds + (unsigned int) ts.tv_sec + (ts.tv_nsec >= 500000000L); return result;
}
2.3 内核nanosleep源码
long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,const enum hrtimer_mode mode, const clockid_t clockid)
{
struct restart_block *restart;
struct hrtimer_sleeper t;
int ret = 0;
unsigned long slack;
slack = current->timer_slack_ns;
if (rt_task(current))
slack = 0;
hrtimer_init_on_stack(&t.timer, clockid, mode);
hrtimer_set_expires_range_ns(&t.timer, timespec_to_ktime(*rqtp), slack);
if (do_nanosleep(&t, mode))
goto out;
/* Absolute timers do not update the rmtp value and restart: */
if (mode == HRTIMER_MODE_ABS) {
ret = -ERESTARTNOHAND;
goto out;
}
if (rmtp) {
ret = update_rmtp(&t.timer, rmtp);
if (ret <= 0)
goto out;
}
restart = &current_thread_info()->restart_block;
restart->fn = hrtimer_nanosleep_restart;
restart->nanosleep.clockid = t.timer.base->clockid;
restart->nanosleep.rmtp = rmtp;
restart->nanosleep.expires = hrtimer_get_expires_tv64(&t.timer);
ret = -ERESTART_RESTARTBLOCK;
out:
destroy_hrtimer_on_stack(&t.timer);
return ret;
}
SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp,
struct timespec __user *, rmtp)
{
struct timespec tu;
if (copy_from_user(&tu, rqtp, sizeof(tu)))
return -EFAULT;
if (!timespec_valid(&tu))
return -EINVAL; return hrtimer_nanosleep(&tu, rmtp, HRTIMER_MODE_REL, CLOCK_MONOTONIC);

sleep 和 usleep的实现方法的更多相关文章

  1. javaSE27天复习总结

    JAVA学习总结    2 第一天    2 1:计算机概述(了解)    2 (1)计算机    2 (2)计算机硬件    2 (3)计算机软件    2 (4)软件开发(理解)    2 (5) ...

  2. cocos2d-x 跨平台usleep方法

    #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) #define usleep(t) Sleep(t) #else #include <unistd.h ...

  3. Android(Linux)控制GPIO的方法及实时性分析

    Linux下控制GPIO的方法有N种,详细请参考<RPi GPIO Code Samples>,文中用十多种语言演示了如何控制GPIO,非常全面详尽.因此,这里不再多做赘述,仅把调试过程中 ...

  4. Linux平台延时之sleep、usleep、nanosleep、select比较

    Linux平台延时之sleep.usleep.nanosleep.select比较 标签: 嵌入式thread线程cpu多线程 2015-05-05 15:28 369人阅读 评论(0) 收藏 举报 ...

  5. Linux 高精確的時序(sleep, usleep,nanosleep) from:http://blog.sina.com.cn/s/blog_533ab41c0100htae.html

    Linux 高精確的時序(sleep, usleep,nanosleep) (2010-04-14 17:18:26) 转载▼ 标签: 杂谈 分类: linux 首先, 我会说不保证你在使用者模式 ( ...

  6. PHP截取IE浏览器并缩小原图的方法

    这篇文章主要介绍了PHP截取IE浏览器并缩小原图的方法,涉及PHP调用com组件实现图像截取的相关技巧,需要的朋友可以参考下 本文实例讲述了PHP截取IE浏览器并缩小原图的方法.分享给大家供大家参考, ...

  7. 【转载】c/c++在windows下获取时间和计算时间差的几种方法总结

    一.标准C和C++都可用 1.获取时间用time_t time( time_t * timer ),计算时间差使用double difftime( time_t timer1, time_t time ...

  8. 检测iOS的APP性能的一些方法

    首先如果遇到应用卡顿或者因为内存占用过多时一般使用Instruments里的来进行检测.但对于复杂情况可能就需要用到子线程监控主线程的方式来了,下面我对这些方法做些介绍: Time Profiler ...

  9. windows获取时间的方法

    介绍       我们在衡量一个函数运行时间,或者判断一个算法的时间效率,或者在程序中我们需要一个定时器,定时执 行一个特定的操作,比如在多媒体中,比如在游戏中等,都会用到时间函数.还比如我们通过记录 ...

随机推荐

  1. php数组函数-array_map()

    array_map()函数返回用户自定义函数作用后的数组.回调函数接受的参数 数目应该和传递给array_map()函数的数组数目一直. array_map(function,array1,array ...

  2. SQL Server获取数据库的当前连接状态

    SELECT * FROM [Master].[dbo].[SYSPROCESSES] WHERE [DBID]=(SELECT [DBID] FROM [Master].[dbo].[SYSDATA ...

  3. 在shell中使用sendmail发送邮件

    cat > sendmymail.sh #!/bin/bash/usr/sbin/sendmail -t <<EOFFrom: Mail testing <abc@gmail. ...

  4. How to use QToolBar and QToolButton in Qt

    http://developer.nokia.com/Community/Wiki/How_to_use_QToolBar_and_QToolButton_in_Qt How to use QTool ...

  5. 最全面的linux信号量解析

    信号量 一.什么是信号量 信号量的使用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程) 所拥有. 信号量的值为正的时候,说明它空闲.所测试的线程可以锁定而使用它.若为0,说明 它被占用, ...

  6. js享元模式

    享元模式(Flyweight),运用共享技术有效地支持大量细粒度的对象. 内部状态与外部状态 内部状态存储于对象内部. 内部状态可以被一些对象共享 内部状态独立于具体的场景,通常不会改变 外部状态取决 ...

  7. HTML5 Audio/Video 标签属性与事件

    chrom 只测试过部分属性,均正常,兼容性未测试: 标签属性:src:音乐的URLpreload:预加载autoplay:自动播放loop:循环播放controls:浏览器自带的控制条 1 标签属性 ...

  8. 分享知识-快乐自己:Spring_IOC(控制反转)详解

    IoC是什么: 1):Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想. 2):在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的 ...

  9. python直接赋值,浅拷贝和深拷贝

    本文参考自<Python 直接赋值.浅拷贝和深度拷贝解析> 定义 直接赋值:就是对象的引用(别名) 浅拷贝(copy):拷贝父对象,不拷贝对象内部的子对象 深拷贝(deepcopy):co ...

  10. Java企业微信开发_15_查询企业微信域名对应的所有ip

    一.前言 二.方法 1.在线网站 百度搜索"域名查IP",可查到如下网站,输入域名即可查到所有IP: 站长工具 site.ip138.com tools.ipip.net 2.li ...