为什么中断不能休眠

1. 中断处理的时候,不应该发生进程切换,因为在中断context中,唯一能打断当前中断handler的只有更高优先级的中断,它不会被进程打断(这点对 于softirq,tasklet也一样,因此这些bottom half也不能休眠),如果在中断context中休眠,则没有办法唤醒它,因为所有的 wake_up_xxx都是针对某个进程而言的,而在中断context中,没有进程的概念,没有一个task_struct(这点对于softirq和 tasklet一样),因此真的休眠了,比如调用了会导致block的例程,内核几乎肯定会死.


2.schedule()在切换进程时,保存当前的进程上下文(CPU寄存器的值、进程的状态以及堆栈中的内容),以便以后恢复此进程运行。中断发生后,内核会先保存当前被中断的进程上下文(在调用中断处理程序后恢复);但在中断处理程序里,CPU寄存器的值肯定已经变化了吧(最重要的程序计数器PC、堆栈SP等),如果此时因为睡眠或阻塞操作调用了schedule(),则保存的进程上下文就不是当前的进程context了.所以不可以在中断处理程序中调用schedule()。

3.中断handler会使用被中断的进程内核堆栈,但不会对它有任何影响,因为handler使用完后会完全清除它使用的那部分堆栈,恢复被中断前的原貌.


4.处于中断context时候,内核是不可抢占的,因此,如果休眠,则内核一定挂起.


如果中断是可以睡眠的,那么会引起很多问题.例 如,你在时钟中断中睡眠了,那操作系统的时钟就乱了,调度器也了失去依据;例如,你在一个IPI(处理器间中断)中,其它CPU都在死循环等你答复,你确 睡眠了,那其它处理器也不工作了;例如,你在一个DMA中断中睡眠了,上面的进程还在同步的等待I/O的完成,性能就大大降低了……还可以举出很多例子。 所以,中断是一种紧急事务,需要操作系统立即处理,不是不能做到睡眠,是它没有理由睡眠。

### 关于 `sleep` 函数不可用的原因 在多线程和异步编程环境中,`sleep` 函数通常被认为是一种低效的方式用于等待某些条件满足。其主要原因是它会阻塞当前线程的执行[^1],这意味着即使该线程处于空闲状态,也无法执行其他任务,从而浪费了宝贵的资源。 #### 解决方案 为了替代传统的 `sleep` 方法,在现代 C++ 中有更高效的解决方案: 1. **使用条件变量 (Condition Variables)** 条件变量允许线程进入休眠状态直到某个特定事件发生为止。这种方式不会无谓地消耗 CPU 资源,并且能够更好地与其他同步原语配合工作。例如: ```cpp #include <thread> #include <mutex> #include <condition_variable> std::condition_variable cv; std::mutex mtx; bool ready = false; void worker_thread() { std::unique_lock<std::mutex> lock(mtx); cv.wait(lock, []{ return ready; }); // 等待ready变为true // 继续执行... } int main() { std::thread t(worker_thread); { std::lock_guard<std::mutex> lock(mtx); ready = true; } cv.notify_one(); // 通知worker_thread继续执行 t.join(); return 0; } ``` 2. **利用 `std::future` 和 `std::async`** 这些工具可以帮助我们实现更加灵活的任务管理方式。通过它们可以轻松创建并监控后台任务的状态变化情况而无需显式调用任何形式上的延迟指令。 ```cpp #include <iostream> #include <future> #include <chrono> double calculate_something(int value) { std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作 return static_cast<double>(value)*value; } int main(){ auto fut = std::async(std::launch::async, calculate_something, 5); // 可以在此期间做别的事情... try{ if(fut.wait_for(std::chrono::milliseconds(1)) == std::future_status::timeout){ std::cout << "Still calculating..." << '\n'; }else{ std::cout << "Result is: " << fut.get() << '\n'; } }catch(const std::exception& e){ std::cerr<<e.what()<<'\n'; } return 0; } ``` 3. **采用协程技术** 协程提供了一种优雅的方式来表达长时间运行的操作序列中的暂停点。当一个协程到达这样的点时,它可以将其控制权交还给调用者或者另一个协程,之后再从中断处恢复执行。这种方法极大地提高了代码可读性和维护性的同时也减少了上下文切换开销[^4]。 ```cpp #include <coroutine> #include <iostream> struct Task { struct promise_type { Task get_return_object() { return {}; } std::suspend_never initial_suspend() noexcept { return {}; } std::suspend_never final_suspend() noexcept { return {}; } void unhandled_exception() {} void return_void() {} }; }; Task async_wait(std::chrono::milliseconds duration) { co_await std::experimental::suspend_until( std::chrono::steady_clock::now()+duration); } int main(){ async_wait(std::chrono::milliseconds(100)); } ``` 以上就是针对为何 `sleep` 不适合异步环境及其改进措施的一些见解。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值