用户态 0-3G 内核态 0-4G 虚拟地址(MMU)
系统调用的意义:
用户态进程与硬件设备进行交互提供了一组接口:
a .把用户从底层的硬件编程中解放出来
b.极大的提高了系统的安全性
c.使用户程序具有可移植性
进程的概念:
进程:有独立的内核堆栈(如8k),一个task_struct,专用的用户空间,并利用这些资源运行一个或者多个程序。 如果没有用户空间,则是 内核线程(thread); 如果共享用户空间,则称为 用户线程。 进程和线程是进程调度的基本单位。
内核把所有处于TASK_RUNNING状态的进程组织成一个可运行双向循环队列。 调度函数通过扫描整个可运行队列,取得最值得执行的进程投入执行。避免扫描所有进程,提高调度效率。 问题:可运行进程(n)越多,每次调度的开销越大。这是2.4的O(n)调度算法的缺点。
内核挂起正在CPU上执行的进程,并恢复以前挂起的某个进程的执行,叫做进程切换,任务切换,上下文切换。
什么是进程上下文:
包含了进程执行需要的所有信息 用户地址空间 包括程序代码,数据,用户堆栈等 控制信息 进程描述符,内核堆栈等 硬件上下文
什么是硬件上下文?
进程恢复执行前必须装入寄存器的一组数据,包括: 通用寄存器 系统寄存器 所有的进程共享CPU的寄存器。因此,内核在恢复一个进程执行之前,必须确保每个寄存器装入了挂起进程时的值。这样才能正确的恢复一个进程的执行。
什么是线程0?
在系统初始化阶段由start_kernel()函数从无到有手工创建的一个内核线程 包括:进程描述符、内核态堆栈、mm、fs、files、signals等 线程0最后的初始化工作是创建init内核线程,此后运行cpu_idle,线程0成为idle线程。
什么是1号进程
当调度程序选择到init线程时,init线程开始执行init()函数。 init()函数最后调用execve()系统调用装入可执行程序init。从此,init内核线程变成一个普通的进程。 init进程从不终止,因为它创建和监控操作系统外层的所有进程的活动
系统初始化得三个阶段:
第一阶段:CPU本身的初始化,例如虚拟地址模式的开启;
head.S 完成的主要工作: 使能cache 建立内核初始化需要的页面映射 使能MMU 建立初始异常向量表 初始化BSS段 跳到start_kernel执行下一步初始化
第二阶段:系统基础设施的初始化,例如内存管理和进程管理的建立和初始化;
初始化系统的核心数据结构,主要包括: setup_arch():执行与体系结构相关的设置 trap_init():设置各种异常入口地址 init_IRQ():初始化IRQ中断处理机制 sched_init():初始化每个处理器的可运行进程队列,设置 系统初始化线程即0号线程。 softirq_init():对软中断子系统进行初始化 console_init():初始化控制台、显示器 init_modules():初始化kernel_module fork_init():定义系统最大进程数 最后进入rest_init()函数并调用kernel_thread()创建init内核线程,进行系统配置。 init内核线程占用进程描述表的第一项,由它来创建其他进程完成系统初始化。
第三阶段:根设备的安装和外部设备的初始化,载入init进程。
init内核线程首先调用do_basic_setup()来初始化外部设备及加载驱动程序。如: PCI总线初始化、网络初始化、文件系统初始化、加载文件系统。 初始化结束,打开/dev/console 设备重新定向控制台。 用系统调用execve执行用户态程序/sbin/init。 至此,linux的内核初始化工作完成。