【代码拾遗】linux内核中延时机制之msleep?如何利用msleep实现间歇性确认硬件状态的函数?(不可中断方式睡眠)

Linux内核msleep实现硬件状态间歇性确认

背景

msleep 函数的核心逻辑是将毫秒数转换为内核的 jiffies 单位,并通过 schedule_timeout_uninterruptible 让当前进程进入不可中断的睡眠状态。

细节

/**
 * msleep - sleep safely even with waitqueue interruptions
 * @msecs: Time in milliseconds to sleep for
 */
void msleep(unsigned int msecs)
{
   
   
	unsigned long timeout = msecs_to_jiffies(msecs) + 1;

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

可以看到将等待的毫秒换算为jiffies 然后 + 1,这里+1 是一个工程约等于。为了确保睡眠时间不会少于指定的毫秒数。msecs_to_jiffies 函数将毫秒转换为 jiffies,但由于 jiffies 是一个离散的计时单位,可能会导致精度损失。也体现了msleep精度并不是准确的毫秒。
另外可以看到msleep使用了while循环,但是会让出调度器。所以msleep会阻塞在这里。然后调度器每次调度回来msleep所在的执行单元后,会判断timeout是否已经timeout。进程会持续以不可中断的方式睡眠,直到timeout超时或者被其他机制唤醒。并且每次唤醒后会更新timeout的值。
其中schedule_timeout_uninterruptible在给定的超时时间内让当前进程进入睡眠状态,并且在睡眠期间不会被信号中断。睡眠期间,进程不会响应信号,但可以被内核的定时器机制或其他内核机制唤醒。如果超时时间到达,进程会被内核调度器唤醒。

这里所谓的不可中断为什么又能被其他机制唤醒呢?

这里涉及到Linux 内核的调度机制和信号处理机制。
“不可中断”(TASK_UNINTERRUPTIBLE)状态主体是进程。调用msleep的进程不会被信号(如 SIGINT(比如ctrl + c中断)、SIGTERM 等)唤醒。当进程处于这种状态时,它不会响应用户空间的信号中断,必须等到它自己完成睡眠或者被其他机制唤醒。
这里的中断不是只芯片的中断,不是一个概念和层次,他是一个进程能否被“叫停”。

内核驱动例子

static int wait_fw_init(struct mlx5_core_dev *dev, u32 max_wait_mili,
			u32 warn_time_mili)
{
   
   
	unsigned long warn = jiffies + msecs_to_jiffies(warn_time_mili);
	unsigned long end = jiffies + msecs_to_jiffies(max_wait_mili);</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值