中断上下文 和 module_init

为什么在中断上下文中不能休眠?

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.2.4内核中schedule()函数本身在进来的时候判断是否处于中断上下文:
if(unlikely(in_interrupt()))
BUG();
因此,强行调用schedule()的结果就是内核BUG,但我看2.6.18的内核schedule()的实现却没有这句,改掉了.


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

 

module_init和module_exit

void init(void)

{

    init_a();

    init_b();

}

 如果再加入一个初始化函数呢,那么再init_b()后面再加一行:

init_c();

这样确实能完成我们的功能,但这样有一定的问题,就是不能独立的添加初始化函数,每次添加一个新的函数都要修改init函数,blob中的初始化函数就是完全独立的,只要用一个宏来修饰一下:

void init_a(void)

{

}

__initlist(init_a, 1);

它是通过这个宏来实现初始化函数列表的呢?

先来看__initlist的定义:

#define __init __attribute__((unused, __section__(".initlist")))

#define __initlist(fn, lvl) \
static initlist_t __init_##fn __init = { \
 magic:    INIT_MAGIC, \
 callback: fn, \
 level:   lvl }

看来就是定义了一个结构体,存了初始化函数的指针,没什么特别的。请注意:__section__(".initlist")

这个属性起什么作用呢?它告诉连接器这个变量存放在.initlist区段,如果所有的初始化函数都是用这个宏,那么每个函数会有对应的一个initlist_t结构体变量存放在.initlist区段,也就是说我们可以在.initlist区段找到所有初始化函数的指针。怎么找到.initlist区段的地址呢?

extern u32 __initlist_start;
extern u32 __initlist_end;

这两个变量起作用了,__initlist_start是.initlist区段的开始,__initlist_end是结束,通过这两个变量我们就可以访问到所有的初始化函数了。

 这两个变量在那定义的呢?

在一个连接器脚本文件里

 . = ALIGN(4);
 .initlist : {
  __initlist_start = .;
  *(.initlist)
  __initlist_end = .;
 }
这两个变量的值正好定义在.initlist区段的开始和结束地址,所以我们能通过这两个变量访问到所有的初始化函数。

与此类似,内核中也是用到这种方法,所以我们写驱动的时候比较独立,不用我们自己添加代码在一个固定的地方来调用我们自己的初始化函数和退出函数,连接器已经为我们做好了。当然module_init还有其他的特性,比如:我们的初始化函数在完成初始化后,代码占用的空间会被释放


 

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值