读书人

关于软中断跟系统调用的一点分析

发布时间: 2013-09-15 19:58:13 作者: rapoo

关于软中断和系统调用的一点分析

感觉之前对于软中断一直有一些误解。

软中断的定义:

软中断是利用硬件中断的概念,用软件方式进行模拟,实现宏观上的异步执行效果。很多情况下,软中断和“信号”类似。同时,软中断又是和硬中断相对应的,“硬中断是外部设备对CPU的中断”,“软中断通常是硬件中断服务程序对内核的中断”

作为系统调用而言,对于i386则是通过软中断int80实现

对于其它的软中断,则是在硬件中断之后触发的软中断。

系统调用在Linux2.6中的实现

关于软中断跟系统调用的一点分析

关于软中断跟系统调用的一点分析

对于软中断而言,则稍微复杂些

1.注册软中断当然是通过open_softirq

例子如下:

[cpp]

view plain

copy

  1. void __init init_timers(void)
  1. {
  2. int err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE,
  3. (void *)(long)smp_processor_id());
  4. init_timer_stats();
  5. BUG_ON(err == NOTIFY_BAD);
  6. register_cpu_notifier(&timers_nb);
  7. open_softirq(TIMER_SOFTIRQ, run_timer_softirq);
  8. }
  1. void open_softirq(int nr, void (*action)(struct softirq_action *))
  1. {
  2. softirq_vec[nr].action = action;
  3. }

软中断TIMER_SOFTIRQ的中断处理函数为:run_timer_softirq

之所以成为softirq,是因为这些中断是由硬件中断来间接触发的,如何间接触发的呢:

硬件中断处理函数-->对软中断的相应位置位-->唤醒ksoftirqd线程-->执行软中断的中断处理函数

2.硬件中断如何通过置位唤醒ksoftirqd线程

timer interrupthandler->

timer_tick->

update_process_times->

run_local_timers->

hrtimer_run_queues()和raise_softirq(TIMER_SOFTIRQ)->

raise_softirq_irqoff->

__raise_softirq_irqoff{ or_softirq_pending(1UL << (nr)); }

即(local_softirq_pending() |= (x))

3.如何执行软中断的action<中断处理函数>

对于TIMER_SOFTIRQ来说,每次system clock产生中断时,即一个tick到来时,在system clock的中断处理函数中会调用run_local_timers来设置TIMER_SOFTIRQ触发条件;也就是当前CPU对应的irq_cpustat_t结构体中的__softirq_pending成员的第TIMER_SOFTIRQ个BIT被置为1。而当这个条件满足时,ksoftirqd线程(入口函数run_ksoftirqd,cpu_callback:kthread_create(run_ksoftirqd,hcpu, "ksoftirqd/%d", hotcpu);)会被唤醒,然后按照下面的流程调用TIMER_SOFTIRQ在数组softirq_vec中注册的action,即run_timer_softirq。

run_ksoftirqd--->do_softirq--->__do_softirq--->softirq_vec[TIMER_SOFTIRQ].action

[cpp]

view plain

copy

  1. static int run_ksoftirqd(void * __bind_cpu)
  1. {
  2. set_current_state(TASK_INTERRUPTIBLE);
  3. while (!kthread_should_stop()) {
  4. preempt_disable();
  5. if (!local_softirq_pending()) {
  6. preempt_enable_no_resched();
  7. schedule();
  8. preempt_disable();
  9. }
  10. __set_current_state(TASK_RUNNING);
  11. while (local_softirq_pending()) {
  12. /* Preempt disable stops cpu going offline.
  1. If already offline, we'll be on wrong CPU:
  2. don't process */
  1. if (cpu_is_offline((long)__bind_cpu))
  2. goto wait_to_die;
  3. do_softirq();
  4. preempt_enable_no_resched();
  5. cond_resched();
  6. preempt_disable();
  7. rcu_sched_qs((long)__bind_cpu);
  8. }
  9. preempt_enable();
  10. set_current_state(TASK_INTERRUPTIBLE);
  11. }
  12. __set_current_state(TASK_RUNNING);
  13. return 0;
  14. wait_to_die:
  15. preempt_enable();
  16. /* Wait for kthread_stop */
  17. set_current_state(TASK_INTERRUPTIBLE);
  18. while (!kthread_should_stop()) {
  19. schedule();
  20. set_current_state(TASK_INTERRUPTIBLE);
  21. }
  22. __set_current_state(TASK_RUNNING);
  23. return 0;
  24. }

From <http://blog.csdn.net/myarrow/article/details/7064060>

从上面两种情况的对比可以看出,系统调用的中断由于是软件触发的中断,所以称为软中断,而对于后者的软中断,虽然也是软件触发,但是并不经过中断向量表。

读书人网 >软件架构设计

热点推荐