内核延时函数

1) msleep:实现毫秒级的延时,该延时保证至少延时所设置的延时时间,不会提前超时返回,会让出CPU

void msleep(unsigned int msecs)
{
	unsigned long timeout = msecs_to_jiffies(msecs) + 1;

	while (timeout)
		timeout = schedule_timeout_uninterruptible(timeout);
}

为什么在转换成jiffies时要+1呢?前边我们讲到,该延时要至少保证延时转换的jiffies时间,一个jiffies为10毫秒,比如我们可以查10个数表示一个jiffies,在数到5时调用了msleep,那么显然我们不能在此jiffies到时时返回,违反了至少延时设置的jiffies的原则,因此转换成jiffies+1是比较合适的,内核中也特意做了解释。

unsigned long msecs_to_jiffies(const unsigned int m)
{
	/*
	 * Negative value, means infinite timeout:
	 */
	if ((int)m < 0)
		return MAX_JIFFY_OFFSET;
。
。
。
}
/*
 * Change timeval to jiffies, trying to avoid the
 * most obvious overflows..
 *
 * And some not so obvious.
 *
 * Note that we don't want to return LONG_MAX, because
 * for various timeout reasons we often end up having
 * to wait "jiffies+1" in order to guarantee that we wait
 * at _least_ "jiffies" - so "jiffies+1" had better still
 * be positive.
 */
#define MAX_JIFFY_OFFSET ((LONG_MAX >> 1)-1)

2)msleep_interruptible:毫秒级延时,该延时函数有可能被信号打断提前超时,返回剩余的时间,会让出CPU

unsigned long msleep_interruptible(unsigned int msecs)
{
	unsigned long timeout = msecs_to_jiffies(msecs) + 1;

	while (timeout && !signal_pending(current))
		timeout = schedule_timeout_interruptible(timeout);
	return jiffies_to_msecs(timeout);
}

3)ssleep:秒级延时,通过调用msleep实现,会让出CPU

static inline void ssleep(unsigned int seconds)
{
	msleep(seconds * 1000);
}

4)usleep_range:该延时函数实现微秒级延时,特别之处在于其可以设定一个超时范围,通过看源代码可以发现此函数设置任务状态为ASK_UNINTERRUPTIBLE,即该延时至少可以保证延时min微秒而不被打断。会让出CPU

/**
 * usleep_range - Drop in replacement for udelay where wakeup is flexible
 * @min: Minimum time in usecs to sleep
 * @max: Maximum time in usecs to sleep
 */
void usleep_range(unsigned long min, unsigned long max)
{
	__set_current_state(TASK_UNINTERRUPTIBLE);
	do_usleep_range(min, max);
}

5)ndelay:纳秒级延时,不会让出CPU

static inline void ndelay(unsigned long x)
{
	udelay(DIV_ROUND_UP(x, 1000));
}

6)udelay:微秒延时,不会让出CPU

7)mdelay:毫秒级延时,不会让出CPU

关于延时函数会不会让出CPU,使用时需要注意,一般对延时要求特别精确,使用不让出CPU的延时函数;对延时要求不是特别精确的,可以使用让出CPU的延时函数,为了保证延时时系统不会进入睡眠,通常延时前要加上wakelock锁来组织睡眠。

时间: 2024-11-03 21:38:19

内核延时函数的相关文章

linux中内核延时函数

第一类延时函数原型是:(忙等) void ndelay(unsigned long nsecs); void udelay(unsigned long usecs); void mdelay(unsigned long msecs); 说明:内核函数 ndelay, udelay, 以及 mdelay 对于短延时好用, 分别延后执行指定的纳秒数, 微秒数或者毫秒数. 它们涉及到的延时常常是最多几个毫秒. 第二类延时函数原型是:(使进程进入休眠) void msleep(unsigned int

Linux 内核使用毫秒延时函数

毫秒延时函数:mdelay() 微妙延时函数:ndelay() 1 #ifndef mdelay 2 #define mdelay(n) (/ 3 (__builtin_constant_p(n) && (n)<=MAX_UDELAY_MS) ? udelay((n)*1000) : / 4 ({unsigned long __ms=(n); while (__ms--) udelay(1000);})) 5 #endif 6 7 #ifndef ndelay 8 #define n

linux设备驱动归纳总结(七):1.时间管理与内核延时【转】

本文转载自:http://blog.chinaunix.net/uid-25014876-id-100005.html linux设备驱动归纳总结(七):1.时间管理与内核延时 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 这节将介绍一些很枯燥的内核,大体是内核中时间的概念和内核延时的使用,并没有源代码. xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

SysTick 延时函数

用SYSTICK(系统滴答定时器)做延时函数 1.   4个寄存器 SysTick->CTRL,        --控制和状态寄存器 SysTick->LOAD,        --重装载寄存器 SysTick->VAL,          --当前值寄存器 SysTick->CALIB,        --校准值寄存器 下图有他们的分别描述:     下图引用地址:http://blog.csdn.net/marike1314/article/details/5673684 2.

Qt自定义sleep延时函数(巧妙的使用时间差,但这样似乎CPU满格,而不是沉睡)

Qt不像VC++的win32/MFC编程那样,提供了现成的sleep函数可供调用.Qt把sleep函数封装在QThread类中.子线程可以调用sleep函数.但是如果用户想在主线程实现延时功能,该怎么办呢?方法是自定义sleep延时函数.通过QDateTime来实现时间差. #include <QDateTime> void MainWindow::sleep(int msec)//自定义Qt延时函数,单位毫秒 { QDateTime last = QDateTime::currentDate

改进的延时函数Delay(使用MsgWaitForMultipleObjects等待消息或超时的到来)

解决上一节中延时函数占CPU使用率(达50%)的第二种方法是利用消息机制,通过API函数MsgWaitForMultipleObjects等待消息或超时的到来,从而避免使用循环检测使CPU占用率过高.完整的改进版Delay函数代码如下: [delphi] view plaincopyprint? procedure Delay(dwMilliseconds:DWORD); var endTick: DWORD; Event: THandle; begin Timer1.Enabled:=Fals

C#一些延时函数

sleep延时方法: System.Threading.Thread.Sleep(1000); //毫秒 在C#窗口程序中,如果在主线程里调用Sleep,在Sleep完成之前, 界面呈现出假死状态,不能响应任何操作! 下边实现的是非独占性延时函数,延时过时中界面仍可响应消息: public static void Delay(int milliSecond) { int start = Environment.TickCount; while (Math.Abs(Environment.Tick

单片机 延时函数

在单片机的设计中延时函数最是常见,比如流水灯的时间控制等都需对时间进行控制,因此博主贴出一个简单的延时函数供参考. /**********************************************************************/// 通过延时函数实现数码管的显示/**********************************************************************/#include<reg51.h>#define uchar

stm32中的延时函数

//粗延时函数,微秒 void delay_nus(u16 time) { u16 i=0; while(time--) { i=10;  //自己定义 while(i--) ; } } //毫秒级的延时 void delay_nms(u16 time) { u16 i=0; while(time--) { i=12000;  //自己定义 while(i--) ; } } 运用SysTick来实现准确定时: SysTick_Config(SystemCoreClock / 10)   函数的形