2.9 初始化进程0
来源:互联网 发布:量化程序员 招聘 编辑:程序博客网 时间:2024/06/05 20:22
2.9 初始化进程0
进程0是Linux操作系统中运行的第一个进程,也是Linux操作系统父子进程创建机制的第一个父进程。下面讲解的内容对进程0能够在主机中正常运算的影响最为重要和深远,主要包含如下三方面的内容。
1)系统先初始化进程0。进程0管理结构task_struct的母本(init_task = {INIT_TASK,})已经在代码设计阶段事先设计好了,但这并不代表进程0已经可用了,还要将进程0的task_struct中的LDT、TSS与GDT相挂接,并对GDT、task[64]以及与进程调度相关的寄存器进行初始化设置。
2)Linux 0.11作为一个现代操作系统,其最重要的标志就是能够支持多进程轮流执行,这要求进程具备参与多进程轮询的能力。系统这里对时钟中断进行设置,以便在进程0运行后,为进程0以及后续由它直接、间接创建出来的进程能够参与轮转奠定基础。
3)进程0要具备处理系统调用的能力。每个进程在运算时都可能需要与内核进行交互,而交互的端口就是系统调用程序。系统通过函数set_system_gate将system_call与IDT相挂接,这样进程0就具备了处理系统调用的能力了。这个system_call就是系统调用的总入口。
进程0只有具备了以上三种能力才能保证将来在主机中正常地运行,并将这些能力遗传给后续建立的进程。
这三点的实现都是在sched_init()函数中实现的,具体代码如下:
- //代码路径:init/main.c:
- void main(void)
- {
- …
- sched_init();
- …
- }
- //代码路径:kernel/sched.c:
- …
- #define LATCH (1193180/HZ) //每个时间片的振荡次数
- …
- union task_union { // task_struct与内核栈的共用体
- struct task_struct task;
- char stack[PAGE_SIZE]; // PAGE_SIZE是4 KB
- };
- static union task_union init_task= {INIT_TASK,};//进程0的task_struct
- …
- //初始化进程槽task[NR_TASKS]的第一项为进程0,即task[0]为进程0占用
- struct task_struct * task[NR_TASKS]= {&(init_task.task), };
- …
- void sched_init(void)
- {
- int i;
- struct desc_struct * p;
- if (sizeof(struct sigaction) != 16)
- panic("Struct sigaction MUST be 16 bytes");
- set_tss_desc(gdt?+?FIRST_TSS_ENTRY,&(init_task.task.tss));//设置TSS0
- set_ldt_desc(gdt?+?FIRST_LDT_ENTRY,&(init_task.task.ldt));//设置LDT0
- p= gdt?+?2+FIRST_TSS_ENTRY; //从GDT的6项,即TSS1开始向上全部清零,并且将进程槽从
- for(i=1;i<NR_TASKS;i++) { //1往后的项清空。0项为进程0所用
- task[i]= NULL;
- p->a=p->b=0;
- p++;
- p->a=p->b=0;
- p++;
- }
- /* Clear NT, so that we won't have troubles with that later on */
- __asm__("pushfl;andl $0xffffbfff,(%esp);popfl");
- ltr(0); //重要!将TSS挂接到TR寄存器
- lldt(0); //重要!将LDT挂接到LDTR寄存器
- outb_p(0x36,0x43); /* binary, mode 3, LSB/MSB, ch 0 *///设置定时器
- outb_p(LATCH & 0xff , 0x40); /* LSB */ //每10毫秒一次时钟中断
- outb(LATCH >> 8 , 0x40); /* MSB */
- set_intr_gate(0x20,&timer_interrupt); //重要!设置时钟中断,进程调度的基础
- outb(inb_p(0x21)&~0x01,0x21); //允许时钟中断
- set_system_gate(0x80,&system_call); //重要!设置系统调用总入口
- }
- //代码路径:include\linux\sched.h:// //嵌入汇编参看trap_init的注释
- …
- #define FIRST_TSS_ENTRY 4 //参看图2-15中GDT的4项,即TSS0入口
- #define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY?+?1)//同上,5项即LDT0入口
- #define _TSS(n) ((((unsigned long) n)<<4)?+?(FIRST_TSS_ENTRY<<3))
- #define _LDT(n) ((((unsigned long) n)<<4)?+?(FIRST_LDT_ENTRY<<3))
- #define ltr(n) __asm__("ltr %%ax"::"a" (_TSS(n)))
- #define lldt(n) __asm__("lldt %%ax"::"a" (_LDT(n)))
- …
- //代码路径:include\asm\system.h:
- …
- #define set_intr_gate(n,addr) \
- _set_gate(&idt[n],14,0,addr)
- #define set_trap_gate(n,addr) \
- _set_gate(&idt[n],15,0,addr)
- #define set_system_gate(n,addr) \
- _set_gate(&idt[n],15,3,addr)
- …
- #define _set_tssldt_desc(n,addr,type) \ //嵌入汇编参看trap_init的注释
- __asm__ ("movw $104,%1\n\t" \ //将104,即1101000存入描述符的第1、2字节
- "movw %%ax,%2\n\t" \ //将tss或ldt基地址的低16位存入描述符的第
- //3、4字节
- "rorl $16,%%eax\n\t" \ //循环右移16位,即高、低字互换
- "movb %%al,%3\n\t" \ //将互换完的第1字节,即地址的第3字节存入第5字节
- "movb $" type ",%4\n\t" \ //将0x89或0x82存入第6字节
- "movb $0x00,%5\n\t" \ //将0x00存入第7字节
- "movb %%ah,%6\n\t" \ //将互换完的第2字节,即地址的第4字节存入第8字节
- "rorl $16,%%eax" \ //复原eax
- ::"a" (addr), "m" (*(n)), "m" (*(n?+?2)), "m" (*(n?+?4)), \
- "m" (*(n?+?5)), "m" (*(n?+?6)), "m" (*(n?+?7)) \
- //"m" (*(n))是gdt第n项描述符的地址开始的内存单元
- //"m" (*(n?+?2)) 是gdt第n项描述符的地址向上第3字节开始的内存单元
- //其余依此类推
- )
- //n:gdt的项值,addr:tss或ldt的地址,0x89对应tss,0x82对应ldt
- #define set_tss_desc(n,addr) _set_tssldt_desc(((char *) (n)),addr,"0x89")
- #define set_ldt_desc(n,addr) _set_tssldt_desc(((char *) (n)),addr,"0x82")
- //代码路径:include/linux/sched.h:
- …
- struct tss_struct {
- long back_link; /* 16 high bits zero */
- long esp0;
- long ss0; /* 16 high bits zero */
- long esp1;
- long ss1; /* 16 high bits zero */
- long esp2;
- long ss2; /* 16 high bits zero */
- long cr3;
- long eip;
- long eflags;
- long eax,ecx,edx,ebx;
- long esp;
- long ebp;
- long esi;
- long edi;
- long es; /* 16 high bits zero */
- long cs; /* 16 high bits zero */
- long ss; /* 16 high bits zero */
- long ds; /* 16 high bits zero */
- long fs; /* 16 high bits zero */
- long gs; /* 16 high bits zero */
- long ldt; /* 16 high bits zero */
- long trace_bitmap; /* bits: trace 0, bitmap 16-31 */
- struct i387_struct i387;
- };
- struct task_struct {
- /* these are hardcoded - don't touch */
- long state; /* -1 unrunnable, 0 runnable, >0 stopped */
- long counter;
- long priority;
- long signal;
- struct sigaction sigaction[32];
- long blocked; /* bitmap of masked signals */
- /* various fields */
- int exit_code;
- unsigned long start_code,end_code,end_data,brk,start_stack;
- long pid,father,pgrp,session,leader;
- unsigned short uid,euid,suid;
- unsigned short gid,egid,sgid;
- long alarm;
- long utime,stime,cutime,cstime,start_time;
- unsigned short used_math;
- /* file system info */
- int tty; /* -1 if no tty, so it must be signed */
- unsigned short umask;
- struct m_inode * pwd;
- struct m_inode * root;
- struct m_inode * executable;
- unsigned long close_on_exec;
- struct file * filp[NR_OPEN];
- /* ldt for this task 0 - zero 1 - cs 2 - ds&ss */
- struct desc_struct ldt[3];
- /* tss for this task */
- struct tss_struct tss;
- };
- /*进程0的task_struct
- * INIT_TASK is used to set up the first task table, touch at
- * your own risk!. Base=0, limit=0x9ffff (=640kB)
- */
- #define INIT_TASK \
- /* state etc */ { 0,15,15, \ //就绪态,15个时间片
- /* signals */ 0,{{},},0, \
- /* ec,brk... */ 0,0,0,0,0,0, \
- /* pid etc.. */ 0,-1,0,0,0, \ //进程号0
- /* uid etc */ 0,0,0,0,0,0, \
- /* alarm */ 0,0,0,0,0,0, \
- /* math */ 0, \
- /* fs info */ -1,0022,NULL,NULL,NULL,0, \
- /* filp */ {NULL,}, \
- { \
- {0,0}, \
- /* ldt */ {0x9f,0xc0fa00}, \
- {0x9f,0xc0f200}, \
- }, \
- /*tss*/ {0,PAGE_SIZE?+?(long)&init_task,0x10,0,0,0,0,(long)&pg_dir,\
- 0,0,0,0,0,0,0,0, \ //eflags的值,决定了cli这类指令只能在0特权级使用
- 0,0,0x17,0x17,0x17,0x17,0x17,0x17, \
- _LDT(0),0x80000000, \
- {} \
- }, \
- }
0 0
- 2.9 初始化进程0
- 2.9.1 初始化进程0
- 初始化0号进程
- 初始化0号进程
- 初始化0号进程
- 进程初始化
- xp初始化系统进程
- 多进程的进程表初始化
- 守护进程及初始化守护进程
- 加速交换机端口初始化进程
- linux初始化进程init分析
- 进程任务结构与初始化
- 进程任务结构与初始化
- busybox的init初始化进程
- busybox的init初始化进程
- Init进程初始化安全上下文
- unix系统之进程初始化
- ora-01033: 正在初始化或关闭 进程ID:0 oracle initialization or shutdown in progress
- Cocoa Touch框架
- Java编写网络爬虫
- 冒泡
- android clipPath切割画布
- Mybatis高级特性学习(三)
- 2.9 初始化进程0
- Linux strace命令
- 敏捷开发与敏捷测试
- Android 如何在Eclipse中查看Android API源码 及 support包源码
- 白话空间统计十九:热点分析(上)
- 二十三种设计模式之行为型模式之解释器模式
- 软件缺陷的严重性和优先级
- 模板类中重载<<和>>操作符
- Qt中foreach及QList的使用