进程管理(Linux内核设计与实现 整理)
2015-03-10 20:29
309 查看
一、进程线程相关概念
1.进程就是处于执行期的程序。但进程不仅仅局限于程序代码。还要包括其他资源,像打开的文件,挂起的信号,内核内部数据,处理器状态等
进程是处于执行期的程序以及相关资源的总称。
2.线程是进程中活动的对象。每个线程都拥有独立的程序计数器、进程栈和一组进程寄存器。
(查看进程和线程共享的部分???线程->fork->共享代码段,其他部分复制一份。类似的东西。要查询确认)
(全局变量在数据段,局部变量在栈,查类似的变量的存放位置????)
二、进程描述符和任务结构
1.内核把进程的列表存放在叫做任务列表的双向循环列表中。列表中的每一项都是类型为task_struct称为进程描述符。定义在 <linux/sched.h>文件中。该结构包含内核管理一个进程所需要的所有信息,能够完整的描述一个正在执行的程序。
2.linux通过slab来创建struct thread_info来创建和管理task_struct
3.进程通过pid来标识每一个进程(这个数字是有最大限制的)/proc/sys/kernel/pid_max
4.内核可以使用current指针来获取当前正在执行的进程
5.进程描述符中的state域描述进程当前的状态,可以通过set_task_state()或者set_current_state()来设置当前进程的状态
6.linux中进程存在一个明显的继承关系,所有进程都是PID为1的init进程的后代。在相应的task_struct中存在一个存放其父进程的task_struct的指针,也存在一个children的链表。分别是currect->parent指针和current->children链表
init进程的进程描述符是init_task。通过这一个关联就可以遍历整个系统中所有的进程。
三、进程创建
1.linux通过fork和exec两个步骤来进行进程的创建:
首先fork通过拷贝当前进程创建一个子进程,子进程与父进程区别仅仅在pid,ppid,某些资源和统计量
exec读取可执行文件并将其载入地址空间运行
2.写时拷贝机制
这是一种可以推迟甚至可以免除拷贝数据的技术。并不复制整个进程地址空间,而是父子进程共享,只有在需要写入的时候数据才会被复制,从而使各个进程拥有各自的拷贝。也就是说:资源的复制只有在有需要写入的时候才进行,在此之前只是以只读的方式共享。
3.fork
通过clone()系统调用实现fork,clone调用do_fork.do_fork在kernel/fork.c中
fork->clone->do_fork->copy_process
copy_process函数工作:
1.dup_task_struct为新进程创建一个内核栈,thread_info和task_struct,这些结构父子进程都是相同的。
2.检查确保创建子进程后,当前用户拥有进程数没有超过限制
3.父子进程区别开来,task_struct中的许多数据都要进行清0,其他大部分不变
4.子进程被设置为TASK_UNINTERRUPTIBLE保证不会投入运行
5.调用copy_flags更新task_struct中的flags成员
6.调用alloc_pid为新进程分配有效的PID
7.根据传给clone的标志,确定确定拷贝或共享资源
8.扫尾工作,并返回一个指向子进程的指针
回到do_fork,返回成功新创建的子进程就会唤醒并让其执行,虽然想但并非都能成功
4.vfork
四、线程
线程机制支持并发程序设计机制
在LINUX中线程被当作一个与其他进程共享某些资源的进程来进行管理,拥有自己的task_struct,所以在内核看起来他就像一个普通的进程
线程的创建和普通进程的创建类似,只不过调用clone时会传递一些参数来指明共享资源
创建线程
clone(CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND,0)
fork
clone(SIGCHLD,0)
vfork
clone(CLONE_VFORK|CLONE_VM|SIGCHLD,0)
这些标志在<linux/sched.h>中定义
五、进程的终结
exit->do_exit(kernel/exit.c中)
释放资源和设置进程状态,该进程不会再被调度
但是不会删除其进程描述符task_struct.这样可以让系统在子进程结束后还可以获取他的信息
释放资源和删除进程描述符是分开进行的,父进程获得已终结的子进程的信息后,或通知内核不需要关注相关信息后就可以删除task_struct
使用release_task释放。至此进程所有内容全部释放掉
父进程先于子进程结束,需要为父进程重新找到一个父亲,否则会造成孤儿进程,僵死在那,拜拜消耗资源,
在do_exit中会调用exit_notify()该函数会调用forget_original_parenet之后调用find_new_reaper来寻找新父亲。
实在找不到可以让init作为其父亲
1.进程就是处于执行期的程序。但进程不仅仅局限于程序代码。还要包括其他资源,像打开的文件,挂起的信号,内核内部数据,处理器状态等
进程是处于执行期的程序以及相关资源的总称。
2.线程是进程中活动的对象。每个线程都拥有独立的程序计数器、进程栈和一组进程寄存器。
(查看进程和线程共享的部分???线程->fork->共享代码段,其他部分复制一份。类似的东西。要查询确认)
(全局变量在数据段,局部变量在栈,查类似的变量的存放位置????)
二、进程描述符和任务结构
1.内核把进程的列表存放在叫做任务列表的双向循环列表中。列表中的每一项都是类型为task_struct称为进程描述符。定义在 <linux/sched.h>文件中。该结构包含内核管理一个进程所需要的所有信息,能够完整的描述一个正在执行的程序。
2.linux通过slab来创建struct thread_info来创建和管理task_struct
3.进程通过pid来标识每一个进程(这个数字是有最大限制的)/proc/sys/kernel/pid_max
4.内核可以使用current指针来获取当前正在执行的进程
5.进程描述符中的state域描述进程当前的状态,可以通过set_task_state()或者set_current_state()来设置当前进程的状态
6.linux中进程存在一个明显的继承关系,所有进程都是PID为1的init进程的后代。在相应的task_struct中存在一个存放其父进程的task_struct的指针,也存在一个children的链表。分别是currect->parent指针和current->children链表
init进程的进程描述符是init_task。通过这一个关联就可以遍历整个系统中所有的进程。
三、进程创建
1.linux通过fork和exec两个步骤来进行进程的创建:
首先fork通过拷贝当前进程创建一个子进程,子进程与父进程区别仅仅在pid,ppid,某些资源和统计量
exec读取可执行文件并将其载入地址空间运行
2.写时拷贝机制
这是一种可以推迟甚至可以免除拷贝数据的技术。并不复制整个进程地址空间,而是父子进程共享,只有在需要写入的时候数据才会被复制,从而使各个进程拥有各自的拷贝。也就是说:资源的复制只有在有需要写入的时候才进行,在此之前只是以只读的方式共享。
3.fork
通过clone()系统调用实现fork,clone调用do_fork.do_fork在kernel/fork.c中
fork->clone->do_fork->copy_process
copy_process函数工作:
1.dup_task_struct为新进程创建一个内核栈,thread_info和task_struct,这些结构父子进程都是相同的。
2.检查确保创建子进程后,当前用户拥有进程数没有超过限制
3.父子进程区别开来,task_struct中的许多数据都要进行清0,其他大部分不变
4.子进程被设置为TASK_UNINTERRUPTIBLE保证不会投入运行
5.调用copy_flags更新task_struct中的flags成员
6.调用alloc_pid为新进程分配有效的PID
7.根据传给clone的标志,确定确定拷贝或共享资源
8.扫尾工作,并返回一个指向子进程的指针
回到do_fork,返回成功新创建的子进程就会唤醒并让其执行,虽然想但并非都能成功
4.vfork
四、线程
线程机制支持并发程序设计机制
在LINUX中线程被当作一个与其他进程共享某些资源的进程来进行管理,拥有自己的task_struct,所以在内核看起来他就像一个普通的进程
线程的创建和普通进程的创建类似,只不过调用clone时会传递一些参数来指明共享资源
创建线程
clone(CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND,0)
fork
clone(SIGCHLD,0)
vfork
clone(CLONE_VFORK|CLONE_VM|SIGCHLD,0)
这些标志在<linux/sched.h>中定义
五、进程的终结
exit->do_exit(kernel/exit.c中)
释放资源和设置进程状态,该进程不会再被调度
但是不会删除其进程描述符task_struct.这样可以让系统在子进程结束后还可以获取他的信息
释放资源和删除进程描述符是分开进行的,父进程获得已终结的子进程的信息后,或通知内核不需要关注相关信息后就可以删除task_struct
使用release_task释放。至此进程所有内容全部释放掉
父进程先于子进程结束,需要为父进程重新找到一个父亲,否则会造成孤儿进程,僵死在那,拜拜消耗资源,
在do_exit中会调用exit_notify()该函数会调用forget_original_parenet之后调用find_new_reaper来寻找新父亲。
实在找不到可以让init作为其父亲
相关文章推荐
- Linux内核设计与实现——读书笔记2:进程管理
- Linux内核设计与实现-第三章 进程管理
- linux内核设计与实现笔记之第三章进程管理
- 《Linux内核的设计与实现》读书笔记(三)---进程管理
- Linux内核设计与实现之进程管理
- 【Linux内核设计与实现】进程管理
- Linux内核设计与实现(三) linux进程管理 之 进程创建-2
- linux内核设计与实现(三) linux进程管理 之 进程描述—1
- Linux内核设计与实现 学习笔记(二)进程管理
- linux内核设计与实现【第三版】摘记----第三章:进程管理
- Linux内核设计与实现笔记--chapter3 进程管理
- Linux内核设计与实现----进程管理
- linux内核设计与实现 进程管理 访问子进程的方法详解
- linux内核设计与实现(进程管理、进程调度读书笔记)
- Linux内核设计与实现----进程管理
- 【Linux内核设计与实现】进程调度
- [Linux内核设计与实现]Linux进程管理
- Linux进程(Linux内核设计与实现学习笔记)
- 《Linux内核的设计与实现》读书笔记(四)---进程调度
- 读薄「Linux 内核设计与实现」(2) - 进程管理和调度