美文网首页
linux 进程管理

linux 进程管理

作者: MagicDong | 来源:发表于2018-04-04 11:56 被阅读0次

    进程

    1.基本描述

    • 进程是处于执行期的程序以及相关的资源总称。
    • 相关的资源:打开的文件,挂起的信号,内核内部数据,处理器的状态,一个或是多个具有内存映射的内存地址空间及一个或多个执行线程,存放全局变量的数据段等
    • 内核调度的对象是线程,资源分配的对象是进程
    • 每个线程都拥有独立的程序计数器、进程栈和一组进程寄存器。
    • 进程提供两种虚拟机制:虚拟处理器和虚拟内存,让每个进程都自己觉得好像是独占处理器,独占内存一样。
    • 内核把进程的列表存放在叫做任务队列(task list)的双向循环链表中,链表每一项都是task_struct(进程描述符)的结构,大约1.7KB。包含{打开的文件,进程的地址空间,挂起的信号,进程的状态}
    • 分配进程描述符:linux是通过slab机制分配task_struct的,可实现对象复用和缓存着色(cache coloring)
    task_struct.jpg
    • 如图,利用slab分配器动态生成task_struct,在栈底创建一个新的数据结构struct thread_info,每个任务的thread_info结构在它的内核栈的尾部分配,结构中task域中存放的是指向该任务实际task_struct的指针。
    • 内核通过一个唯一的进程标识值(process identification value)或是PID表示每个进程
    • PID的最大默认值为32768(short int),可以通过修改/proc/sys/kernel/pid_max来提高上限。
    • 如何通过current宏查找当前正在运行进程的进程描述符:1)对于寄存器充足的体系结构,有一个专门的寄存器存放当前进程的task_struct的指针。2)x86体系在内核栈的尾部创建thread_info结构,通过计算偏移间接地查找task_struct结构。

    2.状态转移

    process.jpg

    linux上进程有5种状态:

    1. 运行(正在运行或在运行队列中等待)
    2. 中断(休眠中, 受阻, 在等待某个条件的形成或接受到信号)
    3. 不可中断(收到信号不唤醒和不可运行, 进程必须等待直到有中断发生)
    4. 僵死(进程已终止, 但进程描述符存在, 直到父进程调用wait4()系统调用后释放)
    5. 停止(进程收到SIGSTOP, SIGSTP, SIGTIN, SIGTOU信号后停止运行运行)

    ps工具标识进程的5种状态码:

    1. D 不可中断 uninterruptible sleep (usually IO)
    2. R 运行 runnable (on run queue)
    3. S 中断 sleeping
    4. T 停止 traced or stopped
    5. Z 僵死 a defunct (”zombie”) process

    3.进程树(pstree)

    • 再次注意进程在任务列表中,是以循环链表连接的。
    • 进程树的树根是0号进程idle,是所有进程的祖先。
    1. 0号进程创建1号进程(创建时是内核线程),1号进程负责内核部分的初始化工作及系统配置,创建高速缓存和虚拟内存管理的内核线程
    2. 1号进程调⽤execve()运⾏磁盘上的init可执⾏程序,并演变为⽤户态1号进程,init进程
    3. init进程按照配置⽂件/etc/initab的要求,完成系统启动⼯作,创建编号为1号,2号,……的Getty进程(初始化终端)
    4. getty进程监控到终端连接信号时,通过调用execve()执行login登录程序
    5. 如果登录成功过,login程序通过execve()函数调用shell
    6. Shell进程接收getty进程的pid,取代原来的getty进程。
    • 0号进程idle
    1. idle进程只能从静态地填写thread_inf o和task_struct
    2. idle进程让CPU陷入空闲循环,空闲运行
    3. 多处理器上刚启动只有一个CPU能运行,只有CPU0上的idle进程完成初始化后才激活其它CPU,并通过copy_process()创建其他CPU的idle进程

    4.进程的创建与撤销

    • 在Linux系统中,系统通过fork()函数复制一个现有的进程创建一个新进程。接着,调用exec()函数创建新进程的地址空间,并把新程序载入其中。最终,程序通过调用exit()系统调用退出运行。进程退出后被设置为僵死状态,直到父进程检查之后调用wait(),才删除进程描述符资源。
    • frok,vfork,clone函数(重点)
      Linux中fork,vfork和clone详解(区别与联系)
    1. fork:fork创建的子进程是父进程的完整副本,==复制==父进程的全部资源,包括内存的task_struct内容。复制父进程的页表(虚拟地址相同)
    2. vfork:vfork创建的子进程与父进程==共享==所有的内存,而且由vfork创建的子进程先于父进程运行。(exit()退出),子进程在vfork()返回后直接运行在父进程的栈空间,并使用父进程的内存和数据。这意味着子进程可能破坏父进程的数据结构或栈,造成失败。
    3. clone:linux提供的创建线程的系统调用。可以传入很多参数,选择性的继承父进程的资源(clone_vm//clone_vfork),不再复制父进程的栈空间,而是自己创建一个新的。(在linux下系统堆栈空间是2页面,就是8K的内存,其中在这块内存中,低地址上放入了值,这个值就是进程控制块task_struct的值)
    4. copy-on-write:
    5. 底层do_fork函数的实现
    • 各种进程:
    1. 前台进程:它会独占命令行窗口,只有运行完了或者手动中止,才能执行其他命令。
    2. 后台进程:&

    1.继承当前 session(对话)的标准输出(stdout)和标准错误(stderr)。因此,后台任务的所有输出依然会同步地在命令行下显示。

    2.不再继承当前 session的标准输入(stdin)。你无法向这个任务输入指令了。如果它试图读取标准输入,就会暂停执行(halt)。

    1. 守护进程:特殊的后台进程,运行在后台,不受任何终端控制(syslogd、login、crond、at系统守护进程)

    1.创建子进程,终止父进程

    2.在子进程中创建新会话

    3.改变工作目录

    4.重设文件创建的掩码

    5.关闭当前文件描述符

    1. 孤儿进程:父进程先于子进程结束,子进程没了父亲,会交付给init进程,处理回收工作。
    2. 僵尸进程:子进程结束,并未被父进程调用wait函数回收,

    进程与线程

    1. 区别:
    • 进程是资源分配的基本单位,线程是调度的基本单位。
    • 实体间(进程间,线程间,进线程间)通信方式的不同:

    进程间通信:共享内存、消息队列、信号量、有名管道、匿名管道、socket、信号、文件。
    线程间通信:线程间的通信方式可沿用上述进程间的方式,且还有独特的几种方式:互斥量、自旋锁、条件变量、读写锁、线程信号、全局变量。

    • 进程有⽗⼦关系,线程只有⼀个⽗线程,其他都为⼦线程
    1. 多线程优势:
    • ==空间的花费==:它是一种非常"节俭"的多任务操作方式,在Linux系统下,启动一个新的进程必须分配给它独自的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种"昂贵"的多任务工作方式。而运行于进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间。
    • ==线程间方便的通信机制==。对不同进程来说,它们具有独自的数据空间,要进行数据的传递只能通过通信的方式进行,这种方式不仅费时,而且很不方便。线程则不然,由于****同一进程下的线程之间共享数据空间****,所以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便。
    • 使多CPU系统更加有效。操作系统会保证当线程数不大于CPU数时,不同的线程运行于不同的CPU上。

    相关文章

      网友评论

          本文标题:linux 进程管理

          本文链接:https://www.haomeiwen.com/subject/wydkhftx.html