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

来源:互联网 发布:六场预测法 知乎 编辑:程序博客网 时间:2024/06/06 03:50

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

 

软中断的定义:

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

 

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

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

 

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

 

set_system_trap_gate(SYSCALL_VECTOR, &system_call);# define SYSCALL_VECTOR0x80ENTRY(system_call)RING0_INT_FRAME# can't unwind into user space anywaypushl_cfi %eax# save orig_eaxSAVE_ALLGET_THREAD_INFO(%ebp)# system call tracing in operation / emulationtestl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)jnz syscall_trace_entrycmpl $(nr_syscalls), %eaxjae syscall_badsyssyscall_call:call *sys_call_table(,%eax,4)movl %eax,PT_EAX(%esp)# store the return value  ENTRY(sys_call_table).long sys_restart_syscall/* 0 - old "setup()" system call, used for restarting */.long sys_exit.long ptregs_fork.long sys_read.long sys_write.long sys_open/* 5 */.long sys_close.long sys_waitpid.long sys_creat.long sys_link.long sys_unlink/* 10 */.long ptregs_execve.long sys_chdir.long sys_time.long sys_mknod.long sys_chmod/* 15 */.long sys_lchown16.long sys_ni_syscall/* old break syscall holder */.long sys_stat.long sys_lseek.long sys_getpid/* 20 */.long sys_mount.long sys_oldumount...

 

 

 

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

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.   
  5.     init_timer_stats();  
  6.   
  7.     BUG_ON(err == NOTIFY_BAD);  
  8.     register_cpu_notifier(&timers_nb);  
  9.     open_softirq(TIMER_SOFTIRQ, run_timer_softirq);  
  10. }  
  11.   
  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_SOFTIRQBIT被置为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.   
  4.     while (!kthread_should_stop()) {  
  5.         preempt_disable();  
  6.         if (!local_softirq_pending()) {  
  7.             preempt_enable_no_resched();  
  8.             schedule();  
  9.             preempt_disable();  
  10.         }  
  11.   
  12.         __set_current_state(TASK_RUNNING);  
  13.   
  14.         while (local_softirq_pending()) {  
  15.             /* 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.   
  15. wait_to_die:  
  16.     preempt_enable();  
  17.     /* Wait for kthread_stop */  
  18.     set_current_state(TASK_INTERRUPTIBLE);  
  19.     while (!kthread_should_stop()) {  
  20.         schedule();  
  21.         set_current_state(TASK_INTERRUPTIBLE);  
  22.     }  
  23.     __set_current_state(TASK_RUNNING);  
  24.     return 0;  
  25. }  

 

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

 

 

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

原创粉丝点击