内核初始化过程
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
fork调用后两个 进程有相同的数 据段内容、堆栈 段内容和代码段 内容
子进程调用 execve后,子进 程装入了另外一个 程序,两个进程的 数据段内容、堆栈 段内容和代码段内 容都不同了
创建进程1
第138-148行 所以,进程1又被 所以,进程 又被 称为init进程 称为 进程 if( !fork() ){ init(); //子进程运行函数init } for(;;) pause(); //父进程死循环
内核
高速缓冲区
主内存
main_memory_start
memory_end
程序功能
读取系统参数 初始化各个模块 创建0、1进程
初始化各个模块
mem_init(main_memory_start,memory_end); trap_init(); blk_dev_init(); chr_dev_init(); tty_init(); time_init(); sched_init(); buffer_init(buffer_memory_end); hd_init(); floppy_init(); sti();
意一个子进程结束。 意一个子进程结束。返回 值是已结束子进程的id 值是已结束子进程的
Shell的执行
交互执行
类似cmd,用键盘作为输入 exit命令终止cmd进程
批处理
类似 cmd *.bat,用文件作为输入 文件结束,则cmd进程终止
init函数
while (1) { if ((pid=fork())<0) { printf("Fork failed in init\r\n"); continue; } if (!pid) { close(0);close(1);close(2);setsid(); (void) open("/dev/tty0",O_RDWR,0); (void) dup(0);(void) dup(0); _exit(execve("/bin/sh",argv,envp)); } while (1) if (pid == wait(&i)) break; printf("\n\rchild %d died with code %04x\n\r",pid,i); sync(); } _exit(0);
第69-72行
偏移
#define CMOS_READ(addr) ({ \ outb_p(0x80|addr,0x70); \ inb_p(0x71); \ })
BCD码转换
BCD码是十进制的二进制表示 15(10)=0001 0101(bcd) 两位的BCD码转换到十进制 用BCD码的底四位+ BCD码的高四位*10
#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
时间初始化
第76行 static void time_init(void) 1、读CMOS 2、把用BCD码表示的时间转换为十进制 3、计算从1970年1月1号0点到现在为止 经过的秒数(kernel_mktime,P91)
宏_syscall1
定义在unistd.h文件中(P383第146行) #define _syscall1(type,name,atype,a) \ type name(atype a) \ {\ } 定义了一个有1个参数的函 定义了一个有 个参数的函
数,该函数的返回类型是 type,函数名称是 ,函数名称是name, , 参数类型是atype,参数名 参数类型是 , 是a
ห้องสมุดไป่ตู้
pid=fork(); if( !pid ) {
执行这里
父进程执 行的代码
} else {
执行这里
} else { }
父进程 子进程
}
在父进程中,fork 调用返回的是子 进程的进程id 在子进程中,fork 调用返回的是0
execve系统调用
在进程中装入并运行另外一个程序
pid=fork(); if( !pid ) { execve(“文件名”); } else { } pid=fork(); if( !pid ) { execve(“文件名”); } else { }
static inline _syscall0(int,fork) static inline int fork(){} static inline _syscall0(int,pause) static inline int pause(){} static inline _syscall0(int, sync) static inline int sync (){}
init函数
if( !(pid=fork()) ){ 进程2, 进程 ,用 close(0); shell执行 执行 if( open(“/etc/rc”,0_RDONLY,0) ) RC文件 文件 _exit(1); execve(“/bin/sh”,argv_rc,envp_rc); _exit(2); } wait函数被阻塞,直到任 函数被阻塞, 函数被阻塞 if( pid > 0 ) while( pid != wait(&i) );
子进程装入并 执行shell
父进程等待
永远不会被执行
Linux操作系统内核分析
湘潭大学信息工程学院
程序功能
读取系统参数 初始化各个模块 创建0、1进程
系统参数
setup通过BIOS中断调用获取了系统的各 个参数,并把这些参数保存在物理地址从 0x90000开始的内存中 参见P44的表3-3
系统参数
读取系统参数
#define EXT_MEM_K (*(unsigned short *)0x90002) #define DRIVE_INFO (*(struct drive_info *)0x90080) #define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
宏_syscall0
定义在unistd.h文件中(P383第133行) #define _syscall0(type,name) \ type name(void) \ {\ 定义了一个没有参数的函 //忽略,是一个系统调用 数,该函数的返回类型是 } type,函数名称是 ,函数名称是name
宏_syscall0展开
虚拟地址
读取系统参数
ROOT_DEV = ORIG_ROOT_DEV; drive_info = DRIVE_INFO; memory_end = (1<<20) + (EXT_MEM_K<<10);
扩展内存大小,以 K为单位
设置缓冲区和主内存起始位置
112—125,参见P16图2-9
buffer_memory_end
宏_syscall1展开
static inline _syscall1(int,setup,void *,BIOS) static inline int setup(void * BIOS){}
fork系统调用
用于创建一个进程
pid=fork(); if( !pid ) { 子进程执
行的代码 两个进程有相同 的数据段内容、 堆栈段内容和代 码段内容
程序功能
读取系统参数 初始化各个模块 创建0、1进程
创建进程0
第132行 sched_init(); 第137行 move_to_user_mode();
函数的定义
第23行 static inline _syscall0(int,fork) static inline _syscall0(int,pause) static inline _syscall1(int,setup,void *,BIOS) static inline _syscall0(int,sync)
从CMOS读时间信息
时钟信息保存在 CMOS,参见P67表 4-1 访问CMOS需要 CMOS 1、向70h端口发送要 读信息的字节偏移 2、从71端口读入信 息 偏移 0x00 0x02 0x04 0x07 0x08 0x09 内容 秒钟 分钟 小时 一月中的日期 月份 年份
从CMOS读时间信息
子进程调用 execve后,子进 程装入了另外一个 程序,两个进程的 数据段内容、堆栈 段内容和代码段内 容都不同了
创建进程1
第138-148行 所以,进程1又被 所以,进程 又被 称为init进程 称为 进程 if( !fork() ){ init(); //子进程运行函数init } for(;;) pause(); //父进程死循环
内核
高速缓冲区
主内存
main_memory_start
memory_end
程序功能
读取系统参数 初始化各个模块 创建0、1进程
初始化各个模块
mem_init(main_memory_start,memory_end); trap_init(); blk_dev_init(); chr_dev_init(); tty_init(); time_init(); sched_init(); buffer_init(buffer_memory_end); hd_init(); floppy_init(); sti();
意一个子进程结束。 意一个子进程结束。返回 值是已结束子进程的id 值是已结束子进程的
Shell的执行
交互执行
类似cmd,用键盘作为输入 exit命令终止cmd进程
批处理
类似 cmd *.bat,用文件作为输入 文件结束,则cmd进程终止
init函数
while (1) { if ((pid=fork())<0) { printf("Fork failed in init\r\n"); continue; } if (!pid) { close(0);close(1);close(2);setsid(); (void) open("/dev/tty0",O_RDWR,0); (void) dup(0);(void) dup(0); _exit(execve("/bin/sh",argv,envp)); } while (1) if (pid == wait(&i)) break; printf("\n\rchild %d died with code %04x\n\r",pid,i); sync(); } _exit(0);
第69-72行
偏移
#define CMOS_READ(addr) ({ \ outb_p(0x80|addr,0x70); \ inb_p(0x71); \ })
BCD码转换
BCD码是十进制的二进制表示 15(10)=0001 0101(bcd) 两位的BCD码转换到十进制 用BCD码的底四位+ BCD码的高四位*10
#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
时间初始化
第76行 static void time_init(void) 1、读CMOS 2、把用BCD码表示的时间转换为十进制 3、计算从1970年1月1号0点到现在为止 经过的秒数(kernel_mktime,P91)
宏_syscall1
定义在unistd.h文件中(P383第146行) #define _syscall1(type,name,atype,a) \ type name(atype a) \ {\ } 定义了一个有1个参数的函 定义了一个有 个参数的函
数,该函数的返回类型是 type,函数名称是 ,函数名称是name, , 参数类型是atype,参数名 参数类型是 , 是a
ห้องสมุดไป่ตู้
pid=fork(); if( !pid ) {
执行这里
父进程执 行的代码
} else {
执行这里
} else { }
父进程 子进程
}
在父进程中,fork 调用返回的是子 进程的进程id 在子进程中,fork 调用返回的是0
execve系统调用
在进程中装入并运行另外一个程序
pid=fork(); if( !pid ) { execve(“文件名”); } else { } pid=fork(); if( !pid ) { execve(“文件名”); } else { }
static inline _syscall0(int,fork) static inline int fork(){} static inline _syscall0(int,pause) static inline int pause(){} static inline _syscall0(int, sync) static inline int sync (){}
init函数
if( !(pid=fork()) ){ 进程2, 进程 ,用 close(0); shell执行 执行 if( open(“/etc/rc”,0_RDONLY,0) ) RC文件 文件 _exit(1); execve(“/bin/sh”,argv_rc,envp_rc); _exit(2); } wait函数被阻塞,直到任 函数被阻塞, 函数被阻塞 if( pid > 0 ) while( pid != wait(&i) );
子进程装入并 执行shell
父进程等待
永远不会被执行
Linux操作系统内核分析
湘潭大学信息工程学院
程序功能
读取系统参数 初始化各个模块 创建0、1进程
系统参数
setup通过BIOS中断调用获取了系统的各 个参数,并把这些参数保存在物理地址从 0x90000开始的内存中 参见P44的表3-3
系统参数
读取系统参数
#define EXT_MEM_K (*(unsigned short *)0x90002) #define DRIVE_INFO (*(struct drive_info *)0x90080) #define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
宏_syscall0
定义在unistd.h文件中(P383第133行) #define _syscall0(type,name) \ type name(void) \ {\ 定义了一个没有参数的函 //忽略,是一个系统调用 数,该函数的返回类型是 } type,函数名称是 ,函数名称是name
宏_syscall0展开
虚拟地址
读取系统参数
ROOT_DEV = ORIG_ROOT_DEV; drive_info = DRIVE_INFO; memory_end = (1<<20) + (EXT_MEM_K<<10);
扩展内存大小,以 K为单位
设置缓冲区和主内存起始位置
112—125,参见P16图2-9
buffer_memory_end
宏_syscall1展开
static inline _syscall1(int,setup,void *,BIOS) static inline int setup(void * BIOS){}
fork系统调用
用于创建一个进程
pid=fork(); if( !pid ) { 子进程执
行的代码 两个进程有相同 的数据段内容、 堆栈段内容和代 码段内容
程序功能
读取系统参数 初始化各个模块 创建0、1进程
创建进程0
第132行 sched_init(); 第137行 move_to_user_mode();
函数的定义
第23行 static inline _syscall0(int,fork) static inline _syscall0(int,pause) static inline _syscall1(int,setup,void *,BIOS) static inline _syscall0(int,sync)
从CMOS读时间信息
时钟信息保存在 CMOS,参见P67表 4-1 访问CMOS需要 CMOS 1、向70h端口发送要 读信息的字节偏移 2、从71端口读入信 息 偏移 0x00 0x02 0x04 0x07 0x08 0x09 内容 秒钟 分钟 小时 一月中的日期 月份 年份
从CMOS读时间信息