进程 深入理解Linux内核(第三版)
写在前面的话,因为只看不思考真的很困,所以把一些疑惑和重要的地方记下来。
1.进程与线程的区别
进程是系统进行资源分配和调度的一个独立单位. 线程是进程的一个实体,是CPU调度和分派的基本单位。
2.父子进程
共享含有程序代码的页,但是各自拥有独立的数据拷贝,因此子进程对一个内存单元的修改对父进程是不可见的(反之亦然)。
写时复制技术允许读相同的物理页,只有两者之中的一个试图写一个物理页,内核就把这个页的内容拷贝到一个新的物理页,并把这个新的物理页分配给正在写的进程。
3.Linux下有3个特殊的进程,idle进程(PID = 0), init进程(PID = 1)和kthreadd(PID = 2)
* idle进程由系统自动创建, 运行在内核态
idle进程其pid=0,其前身是系统创建的第一个进程,也是唯一一个没有通过fork或者kernel_thread产生的进程。完成加载系统后,演变为进程调度、交换
* init进程由idle通过kernel_thread创建,在内核空间完成初始化后, 加载init程序, 并最终用户空间
由0进程创建,完成系统的初始化. 是系统中所有其它用户进程的祖先进程
Linux中的所有进程都是有init进程创建并运行的。首先Linux内核启动,然后在用户空间中启动init进程,再启动其他系统进程。在系统启动完成完成后,init将变为守护进程监视系统其他进程。
* kthreadd进程由idle通过kernel_thread创建,并始终运行在内核空间, 负责所有内核线程的调度和管理
它的任务就是管理和调度其他内核线程kernel_thread, 会循环执行一个kthread的函数,该函数的作用就是运行kthread_create_list全局链表中维护的kthread, 当我们调用kernel_thread创建的内核线程会被加入到此链表中,因此所有的内核线程都是直接或者间接的以kthreadd为父进程 。
4.孤儿进程
父进程退出,而他的一个或多个子进程还在运行,那么子进程将成为孤儿进程。孤儿进程将被init进程(pid=1)所收养,并由init进程对它们完成状态收集工作。
5.僵尸进程
一个进程使用fork()创建子进程,如果子进程退出,而父进程并没有调用wait4()或waitpid()获取子进程的状态信息,那么子进程的进程描述符将仍然保存在系统中。
6.轻量级进程
两个轻量级进程基本上可以共享一些资源,如地址空间,打开的文件等。只要其中一个修改共享资源,另一个就立即查看这种修改。当两个线程访问共享资源时就必须同步它们自己。实现多线程应用程序的一个简单的方式是,把轻量级进程与每个线程关联起来。线程之间就可以通过简单地共享同一内存地址空间、同一打开文件集等来访问相同的应用程序数据结构集,同时,每个线程都可以由内核独立调度,以便一个睡眠的同时另一个依然是可以运行的。
7.进程切换
a.切换页全局目录以安装一个新的地址空间
b.切换内核堆栈和硬件上下文,因为硬件上下文提供了内核执行新建成所需要的所有信息,包含CPU寄存器。
备注:80*86体系结构,任务状态段TSS存放硬件上下文,Linux为系统中每个不同的CPU创建一个TTS。a.当一个CPU从用户态切换到内核态时,它就从TSS中获取内核态堆栈的地址.。b.当用户态进程实体通过in或out指令访问一个I/O端口,CPU需要访问存放在TSS中的I/O许可权位图(permission bitmap)以检查该进程是否具有访问端口的权力。