linux内核自旋锁和中断知识讲解

一、并发与竞态三个要点

1、只要并发的执行单元同时访问共享内存是就会出现竞态


2、解决竞态的唯一途径是保证共享资源的互斥访问,即一个执行单元在访问共享资源时,其他的执行单元被禁止访问。

3、访问共享资源的代码区域被称为临界区,临界区需要被以某种互斥机制加以保护

二、自旋锁注意事项
1、自旋锁是一种忙等锁,当执行临界区是没有获得锁时,CPU一直循环执行“测试并设置”的原子操作,等待锁的获得,在等待过程中CPU不会做任何的工作,所以自旋锁一定要是用在临界区特别短的,即等待时间会很短,否则会降低系统性能
2、自旋锁会导致系统出现死锁,即已经获得自旋锁的资源重新再去获得这个自旋锁,即自旋锁的递归使用,就会发生死锁
3、在自旋锁期间不能调用可能引起进程调度的函数比如说copy_from_user,kmalloc(),msleep()等

三、中断与定时器
根据终端的来源可分为内部中断和外部中断
内部中断:例如操作系统从用户态切换到内核态需借助CPU内部的软件中断
外部中断的中断源来自CPU外部,由外设提出请求

向量中断和非向量中断:向量中断由硬件提供中断程序服务入口地址,非向量中断由软件提供中断服务程序入口地址

SGI:软件产生的中断,可用于多核之间的通信,一个CPU可以通过写GIC的寄存器给另外一个CPU产生中断,
SPI:共享的外设中断,这类外设的中断可路由到任何一个CPU

顶半部和低半部:因为中断能打断内核的调度和正常运行,会对系统性能有影响,所以中断的执行时间应该尽可能的短,但有时候又必须在中断里进行一些延时操作,所以linux将中断处理程序分为两个半部,顶半部和低半部
顶半部执行紧急的硬件操作,低半部执行延缓的耗时操作
中断的申请和释放
低半部机制
linux的低半部机制主要由taklet,工作队列,软中断和线程话irq
tasklet作为低半部处理中断程序
void xxx_do_tasklet(unsight long);
DSCLARE_TASKLET(xxx_tasklet,xxx_do_tasklet,0)
中断处理低半部
void xxx_do_tasklet(unsighned long)
{

}
中断处理顶半部
irqreturn_t xxx_interrupt(int irq,void *dev_id)
{
........
     tasklet_schedule(&xxx_tasklet);
}

int __init xxx_init(void)
{
    result = request_irq(xxx_irq,xxx_interrupt,0,"xxx",NULL);
}
void __exit xxx_exit(void){
    free_irq(xxx_irq,xxx_interrupt);
}
总结:低半部中断的处理函数tasklet一般要在顶半部经过tasklet_schedule()函数调度在适当的时候运行。执行调度函数后低半部处理函数将挂到该设备的低半部执行队列中去。

软中断只是中断低半部的一种处理机制



你可能感兴趣的:(linux内核)