一、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. leetcode刷题2:两数相加add_two_numbers

    题目:两数相加 (难度:中等) 给定两个非空链表来表示两个非负整数.位数按照逆序方式存储,它们的每个节点只存储单个数字. 将两数相加返回一个新的链表. 你可以假设除了数字 0 之外,这两个数字都不会以 ...

  2. RHCE学习笔记 管理1 (第三~五章)

    第三章 红帽企业linux 获取帮助 (略) man .pinfo. 第四章 编辑文件 1.输出重定向到文件和程序 >file    定向文件(覆盖) >>file   定向文件(附 ...

  3. python的pexpect详解

    Pexpect 是一个用来启动子程序并对其进行自动控制的纯 Python 模块. Pexpect 可以用来和像 ssh.ftp.passwd.telnet 等命令行程序进行自动交互.继第一部分< ...

  4. JSP--常用指令

    1.JSP中的page指令: jsp中指令格式:<%@   指令名字    key=value    key=value   ......%> <%@ page language=& ...

  5. Mysql中in语句排序

    这只是Mysql语句的写法,不同数据库写法不太一样, ,,,) order by instr('1,11115,11140,11135',id); 如果不使用order by,in语句查询出来的顺序是 ...

  6. springboot - web项目

    一:使用Thymeleaf:参考http://blog.csdn.net/u012702547/article/details/53784992#t0 1.1 引入相应的包 1.2  thymelea ...

  7. DelphiXE_画图

    1.基本 DelphiXE FireMonkey 如何画图 http://www.delphitop.com/html/FireMonkey/2647.html 2. 3.

  8. 在openstack环境中安装rackspace private cloud --1 环境准备

    在一个openstack环境中安装rackspace private cloud, 环境准备: 在good-net网络中创建3个虚拟机vm Network Detail: good-net Netwo ...

  9. 《Think in Java》(七)复用类

    Java 中复用代码的方式就是复用类,复用类的方式有: 组合 继承 代理(并没有啥高深的含义,只是在使用类A前,新增了类B,让类B的每个方法去调用类A中对应的方法,也就是说类B代理了类A...不过我还 ...

  10. NodeJS入门学习

    node.js 概念:是一个由c++编写的,本质上是一个javascript的运行环境,他可以让js代码运行在服务器端. node可以解析JS代码(没有浏览器安全级的限制) 提供系统级别的API: 1 ...