是对从进程创建fork(),到调度执行schedule(),退出exit(),再到资源回收的wait(),整个进程生命周期的管理。
调度算法,是基于优先级的调度,计算密集型的进程处于低优先级,用户交互的进程处于高优先级,以提高Linux系统对用户操作的响应速度。
在调度器里,有一整套算法来根据进程的运行数据计算调度优先级。鼠标键盘操作比较多的进程,肯定要给予高优先级,这是交互进程。
页表,同时也是内存管理的一部分,它关联着进程虚拟空间到物理内存的映射,和进程的每个内存页的权限管理。
例如代码段只可读、可执行,数据段只可读、可写,就可以在进程的页表里把相关的页设置为对应的权限。
页表的基地址指针,intel平台是放在cr3寄存器的,叫页目录基地址寄存器,属于控制寄存器之一,在用户态不可操作。
具体的物理地址不需要记录,数组的索引index乘以页的大小page_size就是物理地址,4096一个页的线位:index 12。
这样,只有操作同一个页的CPU才需要互相等待,而不是所有操作物理内存数组的CPU都要互相等待,降低了等待时间。
内核页表,在32位机上是把内存映射到3G-4G之间的高地址空间。64位机不清楚映射到哪个地址段了。
为了省事,在21天学写操作系统时也可以直接映射到0-1G,这样计算起来简单,直接与物理地址一一对应。
32位机的页表是分两级的,第一级是页目录,大小为4096字节,每个元素4字节,管理1024个页表。
对于一个32位的虚拟地址addr(无符号整数),它的高10位对应页目录的索引,中间10位对应(这个目录下的)页表的索引,低12位对应页内的偏移量。
Linux内核分配内存页的函数是get_free_pages(),可以一次分配1个或多个页。
不够一个页的小数据结构的分配,则是kmalloc(),与用户态的malloc()用法功能一样。
页表设置好之后,虚拟地址到物理地址的转换是MMU自动完成的,操作系统只需要在页错误时处理页表:例如父子进程共享的内存页需要写数据,但这个页只有读权限,这时需要复制一个新的内存页,并且打开对应的页表元素的写权限。
最顶层为虚拟文件系统VFS,用于统一各种文件系统的接口,类似C++的虚基类,定义了open、close、read、write、fcntl、mmap等一堆文件操作的函数指针。
网络子系统socket也是个API有点别扭的文件系统,打开不用open()函数而是socket()函数,但除了打开的API不一样,还多了send、recv、setsockopt等几个函数之外,也与通常的文件差不多。
tmpfs就是内存文件系统,在Linux的/tmp目录。共享内存如果不使用shm_open()函数,直接建个挂载tmpfs文件系统的目录,然后把这个目录下的某个文件mmap到进程也是一样的,一样是内存数据,而不需要读写硬盘。
proc文件系统在/proc目录,用于内核与用户的交互,显示一些关键的系统信息,例如是否允许IP转发,即ip_forward。
也就是通常说的TCP/IP协议栈,是Linux里面相当庞大的一部分,不只是TCP、IP、UDP,而是包含网卡驱动、数据链路层、DNS、ICMP等的一个庞大系统。

