为什么在中断里不能sleep?
一、在中断里不能sleep的原因
“为什么在中断里不能sleep”,即“为什么在Linux里,ISR被设计成不能睡眠”。sleep会导致call scheduler以选择另一个进程来运行。内核代码里有大量的critical section(临界区)。critical section本质上是一段会访问或操作共享资源的代码,例如:
static int copy_fs(unsigned long clone_flags, struct task_struct *tsk){ struct fs_struct *fs = current->fs; if (clone_flags & CLONE_FS) { /* tsk->fs is already what we want */ spin_lock(&fs->lock); if (fs->in_exec) { spin_unlock(&fs->lock); return -EAGAIN; } fs->users++; spin_unlock(&fs->lock); return 0; } tsk->fs = copy_fs_struct(fs); if (!tsk->fs) return -ENOMEM; return 0;}
在 critical section 里,是不能 call scheduler 的。因为已经有一个进程持有锁了,如果这时切换到另一个进程,较好的情况下是等待一段无法预测的时间后前一个进程会将锁释放出来,最坏的情况是死锁。硬件中断是随时可能发生的,即便内核执行的路径正处于 critical section 中。
如果想在 ISR 里支持 sleep,也就是支持 call scheduler 的话,那么所有的 critical section 都必须得禁用中断,否则硬件中断一旦来临系统就会出现 race condition,接下来大概率是死锁。
总结:
硬件中断是超级宝贵的资源,想在中断里睡眠的话就得在大量的 critical section 中关闭中断才能避免 race condition,而关闭硬件中断将会大大地增加中断响应的延迟,降低系统的反应速度,这是操作系统的用户所无法接受的,因此内核开发者采用的设计是在中断里不允许睡眠,并且 ISR 应尽快执行并返回以便系统里的进程继续运行。
二、ISR(中断服务程序)
1、概念
所谓中断是指当CPU正在处理某件事情的时候,外部发生的某一事件(如一个电平的变化,一个脉冲沿的发生或 定时器计数溢出等)请求CPU迅速去处理,于是CPU暂时中止当前的工作,转去处理所发生的事件。中断服务处理完该事件以后,再回到原来被中止的地方继续原来的工作。
中断是一种硬件机制,用于通知CPU有个异步事件发生了。中断一旦被系统识别,CPU则保存部分(或全部)现场(context),即部分(或全部) 寄存器的值,跳转到专门的 子程序,称为 中断服务程序(ISR)。 中断服务程序做事件处理,处理完成后执行任务调度,程序回到就绪态优先级较高的任务开始运行(对于可剥夺型内核)。
2、示例
错误示例:
__interrupt double compute_area (double radius) { double area = PI * radius * radius; printf(" Area = %f", area); return area; }
正确示例:
void interrupt int60(){ puts("This is an example");}
3、注意事项
中断是嵌入式系统中重要组成部分,很多编译器开发商都让标准c支持中断,并引入关键字_interrupt。但是:
ISR不能有返回值;ISR不能传递参数;ISR应该是短而高效的,在ISR中做浮点运算是不明智的;ISR中不应该有重入和性能上的问题,因此不应该使用pintf()函数。裸奔的系统:硬件中断响应程序的运行插入时机是随机的,程序中不存在这样的调用语句:“value=interrupter( )”, 所以,即使有返回值也不知返回给谁。 同理,如果中断函数有形参,但因没有调用者,也就没有实参对形参赋值。所以,不可能有参数传递。裸奔系统中,中断程序由硬件触发执行。这意味着中断函数没有具体的调用者,所以,中断函数无法将值返回给任何对象。非裸奔系统:操作系统需要进行各种调度安排,所以接管了中断的入、出口;另外,还增加了许多软件中断。这些中断函数的运行插入时机已经不再是随机了。一个中断申请发生后,其运行时机取决于操作系统的确定安排和调用。也就是说,有了调用者,所以可以有返回值和参数传递。延伸阅读1:Linux的schedule()函数是什么
schedule() 是 linux 调度器中最重要的一个函数,就像 fork 函数一样优雅,它没有参数,没有返回值,却实现了内核中最重要的功能,当需要执行实际的调度时,直接调用 shedule(),进程就这样神奇地停止了,而另一个新的进程占据了 CPU。
猜你喜欢LIKE
相关推荐HOT
更多>>为什么在中断里不能sleep?
一、在中断里不能sleep的原因“为什么在中断里不能sleep”,即“为什么在Linux里,ISR被设计成不能睡眠”。sleep会导致call scheduler以选择另...详情>>
2023-10-14 20:44:46Jupyter Notebook为什么是现代Python的必学技术?
1、整合所有资源在软件开发过程中,频繁地切换窗口会影响开发效率。举个例子,假设你需要切换窗口去看一些文档,再切换窗口去用另一个工具画图...详情>>
2023-10-14 20:11:17Python中is和==的区别?
一、Python中is和==的区别Python 中的 is 和 == 的主要区别是== 操作符比较两个对象的值是否相等,即比较它们所包含的数据是否相同;is 操作符...详情>>
2023-10-14 18:11:35mac任务管理器快捷键是什么?
一、mac任务管理器快捷键在Mac OS X操作系统中,任务管理器被称为活动监视器(Activity Monitor),它允许用户查看和管理正在运行的进程和资源...详情>>
2023-10-14 17:46:41热门推荐
Python10行以内代码能有什么高端操作?
沸html form标签的action属性是什么?
热TCP、UDP的区别是什么,两者在什么时候使用?
热C++中引用和指针有哪些区别?
新epoll、poll、select有哪些区别?
为什么我们需要Laravel IoC容器?
为什么在中断里不能sleep?
Jupyter Notebook为什么是现代Python的必学技术?
Promise是什么?
Python有哪些优势?
项目财务管理包括什么?
Python中is和==的区别?
mac任务管理器快捷键是什么?
Java开发为什么要用IoC和AOP?