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