Chinaunix首页 | 论坛 | 博客
  • 博客访问: 9608
  • 博文数量: 5
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 50
  • 用 户 组: 普通用户
  • 注册时间: 2015-03-08 18:47
文章分类
文章存档

2015年(5)

我的朋友
最近访客

分类: LINUX

2015-04-05 21:28:35

内核代码理解起来还是太困难了,需要对体系结构有很强的了解才行,这周作业就简单写一下吧。

系统调用经过了如下的流程
1) 初始化
首先,在内核初始化时,前几周已经讲到了通过start_kernel进行全局的初始化工作。
start_kernel中会调用trap_init来进行中断相关的初始化工作。

点击(此处)折叠或打开

  1.     setup_log_buf(0);
  2.     pidhash_init();
  3.     vfs_caches_init_early();
  4.     sort_main_extable();
  5.     trap_init();
  6.     mm_init();
trap_init源码如下所示,

点击(此处)折叠或打开

  1. void __init trap_init(void)
  2. {
  3.     int i;

  4. #ifdef CONFIG_EISA
  5.     void __iomem *p = early_ioremap(0x0FFFD9, 4);

  6.     if (readl(p) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24))
  7.         EISA_bus = 1;
  8.     early_iounmap(p, 4);
  9. #endif

  10.     set_intr_gate(X86_TRAP_DE, &divide_error);
  11.     set_intr_gate_ist(X86_TRAP_NMI, &nmi, NMI_STACK);
  12.     /* int4 can be called from all */
  13.     set_system_intr_gate(X86_TRAP_OF, &overflow);
  14.     set_intr_gate(X86_TRAP_BR, &bounds);
  15.     set_intr_gate(X86_TRAP_UD, &invalid_op);
  16.     set_intr_gate(X86_TRAP_NM, &device_not_available);
  17. #ifdef CONFIG_X86_32
  18.     set_task_gate(X86_TRAP_DF, GDT_ENTRY_DOUBLEFAULT_TSS);
  19. #else
  20.     set_intr_gate_ist(X86_TRAP_DF, &double_fault, DOUBLEFAULT_STACK);
  21. #endif
  22.     set_intr_gate(X86_TRAP_OLD_MF, &coprocessor_segment_overrun);
  23.     set_intr_gate(X86_TRAP_TS, &invalid_TSS);
  24.     set_intr_gate(X86_TRAP_NP, &segment_not_present);
  25.     set_intr_gate_ist(X86_TRAP_SS, &stack_segment, STACKFAULT_STACK);
  26.     set_intr_gate(X86_TRAP_GP, &general_protection);
  27.     set_intr_gate(X86_TRAP_SPURIOUS, &spurious_interrupt_bug);
  28.     set_intr_gate(X86_TRAP_MF, &coprocessor_error);
  29.     set_intr_gate(X86_TRAP_AC, &alignment_check);
  30. #ifdef CONFIG_X86_MCE
  31.     set_intr_gate_ist(X86_TRAP_MC, &machine_check, MCE_STACK);
  32. #endif
  33.     set_intr_gate(X86_TRAP_XF, &simd_coprocessor_error);

  34.     /* Reserve all the builtin and the syscall vector: */
  35.     for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++)
  36.         set_bit(i, used_vectors);

  37. #ifdef CONFIG_IA32_EMULATION
  38.     set_system_intr_gate(IA32_SYSCALL_VECTOR, ia32_syscall);
  39.     set_bit(IA32_SYSCALL_VECTOR, used_vectors);
  40. #endif

  41. #ifdef CONFIG_X86_32
  42.     set_system_trap_gate(SYSCALL_VECTOR, &system_call);
  43.     set_bit(SYSCALL_VECTOR, used_vectors);
  44. #endif

  45.     /*
  46.      * Should be a barrier for any external CPU state:
  47.      */
  48.     cpu_init();

  49.     x86_init.irqs.trap_init();
  50. }
可以看到,trap_init中主要对中断门进行了初始化工作。 对于X86结构来说,中断向量表中1-32与0x80分配给内部中断,内部中断又分为“异常” “陷阱” (?),具体分配情况如代码所示,

点击(此处)折叠或打开

  1. /* Interrupts/Exceptions */
  2. enum {
  3.     X86_TRAP_DE = 0,    /* 0, Divide-by-zero */
  4.     X86_TRAP_DB,        /* 1, Debug */
  5.     X86_TRAP_NMI,        /* 2, Non-maskable Interrupt */
  6.     X86_TRAP_BP,        /* 3, Breakpoint */
  7.     X86_TRAP_OF,        /* 4, Overflow */
  8.     X86_TRAP_BR,        /* 5, Bound Range Exceeded */
  9.     X86_TRAP_UD,        /* 6, Invalid Opcode */
  10.     X86_TRAP_NM,        /* 7, Device Not Available */
  11.     X86_TRAP_DF,        /* 8, Double Fault */
  12.     X86_TRAP_OLD_MF,    /* 9, Coprocessor Segment Overrun */
  13.     X86_TRAP_TS,        /* 10, Invalid TSS */
  14.     X86_TRAP_NP,        /* 11, Segment Not Present */
  15.     X86_TRAP_SS,        /* 12, Stack Segment Fault */
  16.     X86_TRAP_GP,        /* 13, General Protection Fault */
  17.     X86_TRAP_PF,        /* 14, Page Fault */
  18.     X86_TRAP_SPURIOUS,    /* 15, Spurious Interrupt */
  19.     X86_TRAP_MF,        /* 16, x87 Floating-Point Exception */
  20.     X86_TRAP_AC,        /* 17, Alignment Check */
  21.     X86_TRAP_MC,        /* 18, Machine Check */
  22.     X86_TRAP_XF,        /* 19, SIMD Floating-Point Exception */
  23.     X86_TRAP_IRET = 32,    /* 32, IRET Exception */
  24. };
举一例来说, set_intr_gate(X86_TRAP_PF, &page_fault);
就是将page_fault这个函数,注册给缺页异常。 当系统内产生缺页异常时,则调用page_fault。
当然,在Trap_init中,我们关注的是  set_system_trap_gate(SYSCALL_VECTOR, &system_call);
对比一下,setset_intr_gate与set_system_trap_gate的实现,发现他们最终都是操作了IDT(Interrupt Descriptor Table--中断描述表),来完成的中断服务程序函数与中断号的绑定。

set_intr_gate
set_intr_gate_ist                              
set_system_intr_gate  ---> _set_gate ---> pack_gate / write_idt_entry

点击(此处)折叠或打开

  1. static inline void pack_gate(gate_desc *gate, unsigned char type,
  2.                  unsigned long base, unsigned dpl, unsigned flags,
  3.                  unsigned short seg)
  4. {
  5.     gate->a = (seg << 16) | (base & 0xffff);
  6.     gate->b = (base & 0xffff0000) | (((0x80 | type | (dpl << 5)) & 0xff) << 8);
  7. }

  8. static inline void native_write_idt_entry(gate_desc *idt, int entry, const gate_desc *gate)
  9. {
  10.     memcpy(&idt[entry], gate, sizeof(*gate));
  11. }
关于IDT的结构,如下

点击(此处)折叠或打开

  1. /* 8 byte segment descriptor */
  2. struct desc_struct {
  3.     union {
  4.         struct {
  5.             unsigned int a;
  6.             unsigned int b;
  7.         };
  8.         struct {
  9.             u16 limit0;
  10.             u16 base0;
  11.             unsigned base1: 8, type: 4, s: 1, dpl: 2, p: 1;
  12.             unsigned limit: 4, avl: 1, l: 1, d: 1, g: 1, base2: 8;
  13.         };
  14.     };
  15. }
base就是中断服务程序isr的地址。

(逐项分析一下idt的内容,比较一下异同)

顺便提一句,另外还有听着相似的gdt,ldt两个概念,分别是
GDT:Global Descriptor Table   --全局描述表
LDT:Local Descriptor Table    --局部描述表
后续,在评论中会补充一下这两个表的含义

=====
分析 system_call

未完成






阅读(615) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~