zoukankan      html  css  js  c++  java
  • 关于软中断和系统调用的一点分析

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

     

    软中断的定义:

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

     

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

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

     

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

     

     

    set_system_trap_gate(SYSCALL_VECTOR, &system_call);
    
    # define SYSCALL_VECTOR			0x80
    
    ENTRY(system_call)
    	RING0_INT_FRAME			# can't unwind into user space anyway
    	pushl_cfi %eax			# save orig_eax
    	SAVE_ALL
    	GET_THREAD_INFO(%ebp)
    					# system call tracing in operation / emulation
    	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
    	jnz syscall_trace_entry
    	cmpl $(nr_syscalls), %eax
    	jae syscall_badsys
    syscall_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>

     

     

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

  • 相关阅读:
    Coursera台大机器学习课程笔记8 -- Linear Regression
    近两年跟踪速度较快的算法小结(转)
    hdu 4278 Faulty Odometer
    hdu 2571 命运
    hdu 6168 Numbers
    Codeforces 888C:K-Dominant Character
    poj 3061 Subsequence
    poj 1852 Ants
    1115. Counting Nodes in a BST (30)
    1064. Complete Binary Search Tree (30)
  • 原文地址:https://www.cnblogs.com/pangblog/p/3323011.html
Copyright © 2011-2022 走看看