Linux学习记录之进程(一)
2012-07-16 19:56
239 查看
进程是Unix操作系统的最重要的抽象之一,它是处于执行期的程序,但是它不仅仅包括代码,还包括相关的文件,挂起信号等资源。线程是进程活动的对象,每个线程都有一个程序计数器,进程栈和一组进程计数器。Linux中线程是进程的一种特例。
进程提供两种虚拟机制,虚拟处理器和虚拟内存。
Linux系统中通过fork()系统调用来产生新的进程,产生的方式是复制当期的进程来产生新进程,所以调用fork()的进程称为父进程,新产生的进程被称为子进程。Linux系统中fork()是调用clone()这个系统调用。
1、进程描述符及任务结构
内核进程放在一个角task_list的双向循环链表里,每一个节点都是一个task_struct,称为进程描述符,该结构定义在<linux/sched.h>中。task_struct包含了描述一个进程的完整信息。
1.1分配进程描述符
Linux通过slab分配器来分配task_struct结构,这样能达到对象复用和缓存着色,(通过预分配和重复使用task_struct,可以避免动态分配和释放所带来的资源消耗,从而使得进程创建的速度较快)。现在不需要专门的寄存器,只需要在栈底放一个thread_info,这个struct可以方便快速计算出task_struct所在位置。
1.2进程描述符的存放
Linux为每个进程分配了一个PID,实际是个int类型,其默认最大值为32768,内核把每个进程的PID放在进程描述符中。这个值越小,转一圈的时间就越快。如果需要,可以修改/proc/sys/kernel/pid_max里的内容来修改最大值。
1.3进程的状态
1.4设置状态
内存需要经常设置进程的状态,这时候可以调用set_task_state(tast,state)函数来设置。
1.5进程上下文
在用户态执行的进程在系统调用和发送异常时会进入内核态,这时内核就成为代表程序运行的的进程上下文。
1.6进程家族树
Linux进程具备继承关系,所有的继承都是PID为1的init进程的后代。内核在系统启动的最后节点启动init进程,该进程读取初始化脚本,并执行其他的相关程序,最终完成系统启动的整个过程。每个task_struct都包含一个parent节点的指针和一个children的链表。
2进程创建
许多其他的操作系统都提供了产生集成的机制,首先在地址空间里创建进程,读入可执行文件,最后开始执行。Unix采用了与众不同的实现方式,它把上述步骤分解到两个单独的函数中去执行:fork()和exec()函数族。首先,fork()通过拷贝当期进程创建一个子进程。子进程与父进程的区别仅仅在于PID、PPD和默写资源和统计里。exec()函数负责拂去可执行文件并将其载入地址空间开始运行。
2.1写时拷贝
Linux的fork()使用写时拷贝页实现。写时拷贝可以推迟甚至免除拷贝数据。内核此时不复制整个进程的地址空间,二是让父进程和子进程共享一个拷贝。还有在需要写入的时候,数据才会被复制,从而使各个进程拥有各自的拷贝。而一般情况下,fork()之后立即调用exec(),它们就无需复制了,fork()的实际开销就是复制父进程的页表及自己吃创建唯一的基础描述符。在一般情况下,进程创建后都会马上运行一个可执行文件,这种优化可以避免拷贝大量根本就不会被使用的数据。
2..2 fork()
fork()通过clone()系统调用实现,clone()调用do_fork(),do_fork完成大部分工作,它定义在kernel/fork.c文件中。该函数调用copy_process()函数,然后让进城开始执行。copy_process()函数完成的工作:
1、调用dup_task_struct()为新进程创建一个内核栈,threa_info结构和task_struct,这些值与当期进程值形同。连进程描述符也是完全相同。
2、检测新创建的这个子进程后,当期用户所拥有的进程数目有没有超过最大值。
3、现在,进程着手是自己与父进程区别开。进程描述符内的许多成员都要被请0或设置为初始值。进程描述符的成员值不是继承而来的,而主要是统计信息。进程描述符中大多数数据都是共享的。
4、接下来,子进程的状态被设置为TASK_UNINTERRUPTEBLE以保证她不会投入运行。
5、copy_process()调用copy_flags()以更新task_struct的flags成员。表面进程是否拥有超级用户权限的PF_SUPERRIV标志被请0.表明进程还没有调用exec()函数的PF_FORKNOEXEC标志被设置。
6、调用get_pid()为新进场获取一个有效的PID。
7、根据传递给clone()的参数标志,copy_process()拷贝或共享打开的文件、文件系统信息、信号处理函数、进程地址空间和命名空间等。在一般情况下,这些资源会被给定的进程的左右进程共享;否则,这些资源对每个进程是不同的,因此被拷贝到这里。
8、让父进程和子进程评分剩余的时间片。
9、最后,copy_process()函数作搜啊为欧诺工作,并返回一个指向子进程的指针。
最后回到do_fork()函数。
进程提供两种虚拟机制,虚拟处理器和虚拟内存。
Linux系统中通过fork()系统调用来产生新的进程,产生的方式是复制当期的进程来产生新进程,所以调用fork()的进程称为父进程,新产生的进程被称为子进程。Linux系统中fork()是调用clone()这个系统调用。
1、进程描述符及任务结构
内核进程放在一个角task_list的双向循环链表里,每一个节点都是一个task_struct,称为进程描述符,该结构定义在<linux/sched.h>中。task_struct包含了描述一个进程的完整信息。
1.1分配进程描述符
Linux通过slab分配器来分配task_struct结构,这样能达到对象复用和缓存着色,(通过预分配和重复使用task_struct,可以避免动态分配和释放所带来的资源消耗,从而使得进程创建的速度较快)。现在不需要专门的寄存器,只需要在栈底放一个thread_info,这个struct可以方便快速计算出task_struct所在位置。
1.2进程描述符的存放
Linux为每个进程分配了一个PID,实际是个int类型,其默认最大值为32768,内核把每个进程的PID放在进程描述符中。这个值越小,转一圈的时间就越快。如果需要,可以修改/proc/sys/kernel/pid_max里的内容来修改最大值。
1.3进程的状态
1.4设置状态
内存需要经常设置进程的状态,这时候可以调用set_task_state(tast,state)函数来设置。
1.5进程上下文
在用户态执行的进程在系统调用和发送异常时会进入内核态,这时内核就成为代表程序运行的的进程上下文。
1.6进程家族树
Linux进程具备继承关系,所有的继承都是PID为1的init进程的后代。内核在系统启动的最后节点启动init进程,该进程读取初始化脚本,并执行其他的相关程序,最终完成系统启动的整个过程。每个task_struct都包含一个parent节点的指针和一个children的链表。
2进程创建
许多其他的操作系统都提供了产生集成的机制,首先在地址空间里创建进程,读入可执行文件,最后开始执行。Unix采用了与众不同的实现方式,它把上述步骤分解到两个单独的函数中去执行:fork()和exec()函数族。首先,fork()通过拷贝当期进程创建一个子进程。子进程与父进程的区别仅仅在于PID、PPD和默写资源和统计里。exec()函数负责拂去可执行文件并将其载入地址空间开始运行。
2.1写时拷贝
Linux的fork()使用写时拷贝页实现。写时拷贝可以推迟甚至免除拷贝数据。内核此时不复制整个进程的地址空间,二是让父进程和子进程共享一个拷贝。还有在需要写入的时候,数据才会被复制,从而使各个进程拥有各自的拷贝。而一般情况下,fork()之后立即调用exec(),它们就无需复制了,fork()的实际开销就是复制父进程的页表及自己吃创建唯一的基础描述符。在一般情况下,进程创建后都会马上运行一个可执行文件,这种优化可以避免拷贝大量根本就不会被使用的数据。
2..2 fork()
fork()通过clone()系统调用实现,clone()调用do_fork(),do_fork完成大部分工作,它定义在kernel/fork.c文件中。该函数调用copy_process()函数,然后让进城开始执行。copy_process()函数完成的工作:
1、调用dup_task_struct()为新进程创建一个内核栈,threa_info结构和task_struct,这些值与当期进程值形同。连进程描述符也是完全相同。
2、检测新创建的这个子进程后,当期用户所拥有的进程数目有没有超过最大值。
3、现在,进程着手是自己与父进程区别开。进程描述符内的许多成员都要被请0或设置为初始值。进程描述符的成员值不是继承而来的,而主要是统计信息。进程描述符中大多数数据都是共享的。
4、接下来,子进程的状态被设置为TASK_UNINTERRUPTEBLE以保证她不会投入运行。
5、copy_process()调用copy_flags()以更新task_struct的flags成员。表面进程是否拥有超级用户权限的PF_SUPERRIV标志被请0.表明进程还没有调用exec()函数的PF_FORKNOEXEC标志被设置。
6、调用get_pid()为新进场获取一个有效的PID。
7、根据传递给clone()的参数标志,copy_process()拷贝或共享打开的文件、文件系统信息、信号处理函数、进程地址空间和命名空间等。在一般情况下,这些资源会被给定的进程的左右进程共享;否则,这些资源对每个进程是不同的,因此被拷贝到这里。
8、让父进程和子进程评分剩余的时间片。
9、最后,copy_process()函数作搜啊为欧诺工作,并返回一个指向子进程的指针。
最后回到do_fork()函数。
相关文章推荐
- Linux学习记录--进程控制相关系统调用 推荐
- Linux学习记录--进程控制相关系统调用
- Linux常用进程管理工具的使用--我的学习记录
- Linux学习记录之进程(二)
- Linux学习记录--工作管理与进程管理
- Linux学习记录—进程相关
- 【Linux学习记录】Linux文件属性权限、目录管理
- Linux学习记录(8)Linux基本权限设置
- Linux学习记录——持续更新
- Linux学习之基础知识——进程管理(top、vmstat与dtstat)
- 和菜鸟一起学linux之DBUS基础学习记录
- Swoole源码学习记录(一)——进程间共享数据ShareMemory 和 MemoryPool
- UNIX/LINUX编程学习之文件锁、记录锁
- linux学习 - 守护进程
- [Linux学习]Linux下进程通讯之共享内存
- Linux进程线程学习笔记:进程间通信 之 管道
- Linux 查看进程启动详细时间及记录进程启动PID
- Linux进程通信学习笔记
- Linux基础知识学习记录:su与sudo命令的比较,ubuntu下的inittab文件
- linux 学习20170726 查看进程号及环境变量、获取字符串长度及shell版本