在讲进程之前先说一下进程的堆栈的吧:

1.进程的堆栈

内核在创建进程的时候,在创建task_struct的同一时候,会为进程创建对应的堆栈。每一个进程会有两个栈,一个用户栈。存在于用户空间,一个内核栈,存在于内核空间。当进程在用户空间执行时,cpu堆栈指针寄存器里面的内容是用户堆栈地址,使用用户栈;当进程在内核空间时,cpu堆栈指针寄存器里面的内容是内核栈空间地址,使用内核栈。

2.进程用户栈和内核栈的切换

当进程由于中断或者系统调用而陷入内核态之行时。进程所使用的堆栈也要从用户栈转到内核栈。

进程陷入内核态后,先把用户态堆栈的地址保存在内核栈之中,然后设置堆栈指针寄存器的内容为内核栈的地址,这样就完毕了用户栈向内核栈的转换;当进程从内 核态恢复到用户态之行时,在内核态之行的最后将保存在内核栈里面的用户栈的地址恢复到堆栈指针寄存器就可以。

这样就实现了内核栈和用户栈的互转。

那么,我们知道从内核转到用户态时用户栈的地址是在陷入内核的时候保存在内核栈里面的。可是在陷入内核的时候,我们是怎样知道内核栈的地址的呢?

关键在进程从用户态转到内核态的时候,进程的内核栈总是空的。这是由于。当进程在用户态执行时,使用的是用户栈,当进程陷入到内核态时,内核栈保存进程在内核态执行的相关信息。可是一旦进程返回到用户态后,内核栈中保存的信息无效,会所有恢复。因此每次进程从用户态陷入内核的时候得到的内核 栈都是空的。所以在进程陷入内核的时候。直接把内核栈的栈顶(从下往上增长的栈)地址给堆栈指针寄存器就能够了。

再来理解一下线程进程的概念:

线程:是进程中的活动对象。每一个线程都用有意个独立的程序计数器,进程栈和一组进程寄存器,内核调度的是线程,而不是进程。

进程:进程就是处于运行期的程序,可是进程并不只局限于一段可运行的程序代码,通常进程还包括其它资源,像打开的文件,挂起的信号。内核内部的数据结构,处理器状态,一个或者多个具有内存映射的内存地址空间及一个或者多个线程,也就是说进程是处于运行期的程序以及相关资源的总称。

进程提供两种虚拟机制:虚拟内存和虚拟处理器;提供给每一个进程一个独立的虚拟处理器以及独立的地址空间,给进程一种独享处理器和拥有整个系统的内存资源的假象。

内核把进程描写叙述符结构(task_struct)存放在一个双向循环链表的任务队列中;

Linux通过slab分配起分配task_struct结构。用slab分配生成的task_struct仅仅须要在栈顶(向上增长的栈)或者栈底(向下增长的栈)创建一个新的结构struct thread_info

进程描写叙述符的存放

内核通过唯一的进程标识值或者PID来标识每个进程,部分硬件体系架构能够用一个专门的寄存器来存放当前进程的task_stuct指针。用于加快訪问速度,x86架构寄存器并不多,所以智能在内核栈尾端创建thread_info结构,通过计算偏移间接地查找task_struct结构。

进程状态:

TASK_RUNNING:运行。进程是可运行的,或者是它正在运行;

TASK_INTERRUPTIBLE:可中断。进程正在睡眠或者堵塞,等待某些条件的达成。

TASK_UNINTERRUPTIBLE:不可中断,就算是接受到信号也不会被唤醒或者执行,不正确信号做不论什么响应。用的较少;

TASK_TRACED:被其它进程跟踪的进程;

TASK_STOPPED:停止,进程没有投入执行或者不能投入执行;

设置当前进程的状态可用函数:set_task_state(task,state)。

进程的创建

一般的操作系统的产生(spawn)进程的机制:新的地址空间里创建进程,读入可运行文件,最后開始运行。

Linux採用UNIX的实现方式将上述步骤分解到两个单独的函数中去运行:fork()和exit(),fork函数通过拷贝当前进程创建一个子进程,exec函数负责读取可运行文件将其加载地址空间開始运行;

写时拷贝技术:

传统的fork系统调用直接把全部资源复制给子进程。可是可能新创建的子进程运行的程序文件映像并不须要那么多资源那么拷贝就就显得非常浪费了,写时拷贝是一种推迟甚至免除拷贝的技术,仅仅有在须要写入是数据才会被拷贝,内核并不复制整个进程的地址空间。而是父子进程共享一个拷贝。

在数据须要被写入时才会复制;

下图是明显的比較:

普通操作系统创建子进程直接全拷贝数据段。堆。栈:

写时复制技术:内核仅仅为新生成的子进程创建虚拟空间结构,它们来复制于父进程的虚拟到底结构。可是不为这些段分配物理内存,它们共享父进程的物理空间,当父子进程中有更改对应段的行为发生时。再为子进程对应的段分配物理空间。

vfork():这个做法更加火爆,内核连子进程的虚拟地址空间结构也不创建了。直接共享了父进程的虚拟空间。当然了。这样的做法就顺水推舟的共享了父进程的物理空间

fork(),vfork(),_clone()--------> clone()系统调用-------------->do_fork()在kernel/fork.c中,完毕大部分的创建工作----------------->copy_process()让进程開始执行;

Copy_process():完毕创建task_struct内核栈,thread_info结构,task_struct结构,分配PID,拷贝父进程必要的资源,

线程在linux中的实现:

从内核的角度来看,是没有线程的概念的,linux把全部的线程当进程来实现的,内核并没有准备特别的调度算法或是定义特别的数据结构来表征线程。线程只被视为一个与进程共享某些资源的进程。每一个线程都有自己的task_struct,

线程的创建:

clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND , 0 );

上面的代码产生的结果和fork差点儿相同,仅仅是父子俩共享地址空间,文件系统资源,文件描写叙述符和信号处理程序。一个普通的fork例如以下:

clone( SIGHLD , 0);

Vfork的实现:

Clone(CLONE_VFORK | CLONE_VM | SIGHLD,0);

内核线程并没有独立的地址空间。它们仅仅有在内核空间中执行,从不切换到用户空间去;新任务使用kthread内核进程通过clone系统调用创建的,新创建的内核线程处于不可执行状态;假设不通过wake_up_process唤醒他不主动执行;只是创建一个内核线程并让它执行起来能够通过kthread_run来达到;相当于kthread_create()和wake_up_process()执行;

进程终结:进程析构它发生在进程调用exit系统调用时,do_exit()完毕大部分工作:删除内核定时器。释放mm_struct,离开队列,引用计数降低(为0释放)。为子进程找养父,处于僵死状态,删除进程(任务队列)。释放僵死进程资源,通知其父进程,释放task_struct内核栈,thread_info占的页。并释放task_struct所占的告诉缓存的slab;


<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>

阅读(61) | 评论(0) | 转发(0) |

linux内核——进程管理的更多相关文章

  1. Linux内核——进程管理与调度

    进程的管理与调度 进程管理 进程描写叙述符及任务结构 进程存放在叫做任务队列(tasklist)的双向循环链表中.链表中的每一项包括一个详细进程的全部信息,类型为task_struct,称为进程描写叙 ...

  2. Linux内核 ——进程管理之进程诞生(基于版本4.x)

    <奔跑吧linux内核>3.1笔记,不足之处还望大家批评指正 进程是Linux内核最基本的抽象之一,它是处于执行期的程序.它不仅局限于一段可执行代码(代码段),还包括进程需要的其他资源.在 ...

  3. Linux内核——进程管理之CFS调度器(基于版本4.x)

    <奔跑吧linux内核>3.2笔记,不足之处还望大家批评指正 建议阅读博文https://www.cnblogs.com/openix/p/3262217.html理解linux cfs调 ...

  4. Linux内核——进程管理之SMP负载均衡(基于版本4.x)

    <奔跑吧linux内核>3.3笔记,不足之处还望大家批评指正 根据实际物理属性,CPU域分类如图1所示. 图1 CPU域分类 问题一:一个4核处理器中的每个物理CPU拥有独立L1 cach ...

  5. linux内核 进程管理

    进程和线程 进程不单单包含可执行代码(代码段),好包含打开的文件,挂起的信号,处理器状态,虚拟内存地址等. 线程:从内核的角度来说,它并没有线程这个概念.Linux把所有线程都当做进程来实现.内核并没 ...

  6. Linux内核电源管理综述

    资料:http://blog.csdn.net/bingqingsuimeng/article/category/1228414http://os.chinaunix.net/a2006/0519/1 ...

  7. Linux操作系统的进程管理

    Linux操作系统的进程管理 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.进程相关概念 1>.进程概述 内核的功用: 进程管理.文件系统.网络功能.内存管理.驱动程序. ...

  8. linux 系统管理--进程管理

    目录 linux 系统管理--进程管理 一.进程基本概述 二.监控进程状态 三.进程的优先级[进阶] 四.企业案例,Linux假死是怎么回事 五.后台进程管理 六.系统平均负载[进阶] linux 系 ...

  9. .Neter玩转Linux系列之五:crontab使用详解和Linux的进程管理以及网络状态监控

    一.crontab使用详解 概述:任务调度:是指系统在某个时间执行的特定的命令或程序. 任务调度分类: (1)系统工作:有些重要的工作必须周而 复始地执行. (2)个别用户工作:个别用户可能希望执 行 ...

随机推荐

  1. 解决同伴收获&解决同伴问题补分博客

    解决同伴问题 要求: 查看同组同学的课堂笔记,尝试解决同伴的问题,格式如下: 我的同组同学是XXXX学号XXXX同学 同组同学的问题是XXXX 我理解他的意思是XXXX 他的问题我有一个小建议是XXX ...

  2. Codeforces Round #352 (Div. 2) A. Summer Camp 水题

    A. Summer Camp 题目连接: http://www.codeforces.com/contest/672/problem/A Description Every year, hundred ...

  3. 设置Nginx开机自启动

    Nginx 是一个很强大的高性能Web和反向代理服务器.虽然使用命令行可以对nginx进行各种操作,比如启动等,但是还是根据不太方便.下面介绍在linux下安装后,如何设置开机自启动. 首先,在lin ...

  4. DeveloperAppleHelp

    UIKit: 1.UIKit User Interface Catalog   视图 View控件 2.View Programming Guide for iOS 视图编程,用代码 构建界面. 3. ...

  5. ssh 远程链接时出现错误提示:WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED

    ssh 远程链接时出现错误提示 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: REMOTE HOST I ...

  6. Oracle DBA学习篇之SQL_TRACE

    SQL_TRACE ; ; set serveroutput on; alter session set sql_trace=true; select count(*) from firefox; a ...

  7. 分布式文件系统 ~MogileFS~

    一.分布式文件系统 分布式文件系统(Distributed File System)是指文件系统管理的物理存储资源不一定直接连接在本地节点上,而是通过计算机网络与节点相连,也就是集群文件系统,可以支持 ...

  8. Java_如何等待子线程执行结束

    工作中往往会遇到异步去执行某段逻辑, 然后先处理其他事情, 处理完后再把那段逻辑的处理结果进行汇总的产景, 这时候就需要使用线程了. 一个线程启动之后, 是异步的去执行需要执行的内容的, 不会影响主线 ...

  9. Android 上SuperUser获取ROOT权限原理解析

    Android 上SuperUser获取ROOT权限原理解析 一. 概述 本文介绍了android中获取root权限的方法以及原理,让大家对android 玩家中常说的“越狱”有一个更深层次的认识. ...

  10. SQLServer存储过程返回值总结

    1.  存储过程没有返回值的情况(即存储过程语句中没有return之类的语句)  用方法 int count = ExecuteNonQuery(..)执行存储过程其返回值只有两种情况  (1)假如通 ...