linux进程的地址空间,核心栈,用户栈,内核线程

地址空间:

32位linux系统上,进程的地址空间为4G,包括1G的内核地址空间,和3G的用户地址空间。

内核栈:

进程控制块task_struct中保存了2个page大小的信息。

为什么每一个进程都是用各自的内核栈呢?

引用(http://hi.baidu.com/iruler/blog/item/0c3363f377ccc5c90a46e023.html)“

假设某个进程通过系统调用运行在内核态(使用这个全局内核堆栈),此时如果被抢占,发生一次切换,另一个进程开始运行,如果这个当前进程又通过系统调用陷入内核,那么这个进程也将使用这个全局内核堆栈,这样的话就把以前那个进程的内核空间堆栈给破坏了。
而如果进程使用独立的内核栈,就避免了这种情况的发生

内核线程:

拥有自己独立内核栈的调度单元,可以参与调度,在内核空间执行。

用户栈:

每一个线程有一个用户栈,由ss和esp指向。

===================================================

进程1                                进程2

内核代码区      kcode (0xc0001000)        
 kcode (0xc0001000)

内核栈区          kstack(0xc000F000)          kstack(0xc001F000)

内核栈区          kstack(0xc000D000)          kstack(0xc001D000)

...

内核数据区      kdata  (0xc0003000)          kdata  (0xc0003000)

---------------------------------------------------------------------------------------------

用户代码区      ucode  (0x70001000)        ucode (0x70001000)

用户栈区          ustack (0x7000F000)        ustack (0x7000F000)

用户栈区          ustack (0x7000D000)        ustack (0x7000D000)

...

用户数据区      udata   (0x70003000)        udata  (0x70003000)

===================================================

合理的解释:

内核1G空间的映射页表(256个entries*4M)只有一份,n个进程共享(都复制了一份在自己的进程页表内, 256个内核的entries+768个用户空间的entries, 总共1024个entries,假定使用4M页面,并且一开始就全都分配好)。

每个进程用户空间的这些entries各不相同,比如说,同样的0x70001000虚拟地址, 进程1指向物理内存0x2000, 而进程2指向0x1000。

每个线程对应的内核栈的虚拟地址不重叠。

thread1's kernel stack  = 0f000,

thread2's
kernel stack  = 0d000,

thread3's
kernel stack  = 1f000,

thread4's
kernel stack  = 1d000

...

思考1:

如果内核栈不是预先分配好的(分
配的意思是指"在内核空间中分出一段一段不重叠空间作为各个线程的栈", e.g. kmalloc调用),那么步入内核态的时候,
压栈,发生缺页异常,必须对内核栈占用的这个页进行换页,而换页历程的调用必然涉及参数的压栈出栈,而这个时候内核栈没有就绪,异常发生嵌套,系统出错!

思考2:

在内核里面做kmalloc是可以的,添加一个entries,关联一块物理内存,ok可以用了。

思考3:

如果希望进程共享某一个虚拟内存地址0x80001000的数据, 那么在需要共享的进程p1,p2的页表中添加1个entries(0x80001000->0x3000)。

另外内核是天然的共享对象,所以才在每一个进程中页表中设置内核空间页表的一份拷贝。

如果有个家伙特立独行,创建n个关于内核空间的页表,指向n个物理内存块,那么他就需要再在这n个物理内存中"铺设"n分内核代码和数据的副本(真是自找麻烦)。

思考4:

内核栈确实不适合共享(一个特殊的内存区域)。怎么办?像用户空间栈一样固定在某一个虚拟地址,安插页表项entries指向不同的物理内存?显然不行! 只有一个办法,在内核空间内分配n个不重叠的空间出来。

思考5:

内核步入的时候最初的“内核栈”并不是真正的内核栈,这个栈是全局的,每个cpu一个,是过渡到真正的内核栈使用的。(http://bbs.pediy.com/archive/index.php?t-87518.html)

思考6:

独立内核栈的场景, at first 我们分析一下如果共用一个内核栈会出现什么情况,假设有A、B三个进程,A调用系统调用read(1,...)读按键,此时正好又没有按键,
所以A被阻塞在内核,此时内核调度B执行,此时B也调用一个系统调用被阻塞了,而此时按键事件到来,进程A被唤醒,A继续执行。我们想想B进入内核
已经破坏了A进入内核的内核栈,那此时A能正常返回吗?所以从上面分析A、B肯定是拥有各自的内核栈。此内核栈好像是和task_struct以前分配的
一共分配了3个页面,除了task_struct占得内存外,其余的就是内核栈。而在x86上这个栈等指针保存在TSS断的SS0和Esp0中。(http://bbs.chinaunix.net/thread-1930753-1-1.html)

参考资料:

1, 内核栈的使用(http://tech.ddvip.com/2008-09/122095404362368.html)

linux进程的地址空间,核心栈,用户栈,内核线程的更多相关文章

  1. linux进程虚拟地址空间

    转载源 在多任务操作系统中,每个进程都运行在属于自己的内存沙盘中.这个沙盘就是虚拟地址空间(Virtual Address Space),在32位模式下它是一个4GB的内存地址块.在Linux系统中, ...

  2. Linux进程虚拟地址空间管理2

    2017-04-12 前篇文章对Linux进程地址空间的布局以及各个部分的功能做了简要介绍,本文主要对各个部分的具体使用做下简要分析,主要涉及三个方面:1.MMAP文件的映射过程 2.用户 内存的动态 ...

  3. LInux进程虚拟地址空间的管理

    2017-04-07 脱离物理内存的管理,今天咱们来聊聊进程虚拟内存的管理.因为进程直接分配和使用的都是虚拟内存,而物理内存则是有系统“按需”分配给进程,在进程看来,只知道虚拟内存的存在! 前言: 关 ...

  4. linux进程模型总结

    Linux进程通过一个task_struct结构体描述,在linux/sched.h中定义,通过理解该结构,可更清楚的理解linux进程模型.       包含进程所有信息的task_struct数据 ...

  5. Linux进程模型

    ----原文链接:http://www.cnblogs.com/biyeymyhjob/archive/2012/08/01/2617884.html------ Linux进程通过一个task_st ...

  6. Linux下的进程类别(内核线程、轻量级进程和用户进程)--Linux进程的管理与调度(四)

    本文中出现的,内核线程,轻量级进程,用户进程,用户线程等概念,如果不太熟悉, 可以参见 内核线程.轻量级进程.用户线程三种线程概念解惑(线程≠轻量级进程) Linux进程类别 虽然我们在区分Linux ...

  7. Linux内核线程kernel thread详解--Linux进程的管理与调度(十)

    内核线程 为什么需要内核线程 Linux内核可以看作一个服务进程(管理软硬件资源,响应用户进程的种种合理以及不合理的请求). 内核需要多个执行流并行,为了防止可能的阻塞,支持多线程是必要的. 内核线程 ...

  8. Linux进程管理 (篇外)内核线程简要介绍

    关键词:kthread.irq.ksoftirqd.kworker.workqueues 在使用ps查看线程的时候,会有不少[...]名称的线程,这些有别于其它线程,都是内核线程. 其中多数内核线程从 ...

  9. linux内核线程,进程,线程

    http://blog.csdn.net/dyllove98/article/details/8917197 Linux对于内存的管理涉及到非常多的方面,这篇文章首先从对进程虚拟地址空间的管理说起.( ...

随机推荐

  1. elr_memory_pool详解

    Preface Usually, memory allocation of OS is fast, especially the computer has just started. But over ...

  2. 有关Mysql连接问题

    问题一——Mysql number Error 2003 MySQL连接错误.错误代码10061.10061一般是Mysql服务没启动.或Mysql服务器无法连接 . 在程序栏找到Mysql\Mysq ...

  3. 两个Activity之间的交互startActivityForResult的使用

    代码如下: package com.zzw.teststartintentforrequest; import android.app.Activity; import android.content ...

  4. 不再用.NET框架

    .NET 平台很棒.真的很棒.直到它不再那么棒.我为什么不再用 .NET?简单来说,它限制了我们选择的能力(对我来说很重要),转移了我们的注意力,使得我们向内认知它的安全性,替代了帮助我们认知外面广阔 ...

  5. AndroidSDK无法下载API包的解决方法

    1:打开Android SDK Manager”,然后点击菜单栏中的“Tools”菜单选项,接下来只需选择“Options”选项即可打开设置窗体,在打开的选项中找到Others框,里面勾选第一个: F ...

  6. 存储映射IO

    mmap 将文件映射到内存, 对这块内存的修改会自动同步到相应的文件中 void *mmap(void *addr, size_t len, int prot, int flag, int fd, o ...

  7. 多实例MySQL批量添加用户和密码并授权

    OS:Cent OS 6.3 DB:5.5.14 如果一台服务器上有100个MySQL数据库实例,此时需要给不同端口的几个数据库添加用户名.密码并授权应用IP,一个个授权没问题,反正累的不是我,哇咔咔 ...

  8. Java中构造函数执行顺序的问题

    1,  先执行内部静态对象的构造函数,如果有多个按定义的先后顺序执行:而且静态类的构造函数只会被执行一次,只在其第一个对象创建时调用,即便是创建了同一个类的多个对象,例如main()函数里b1,b2创 ...

  9. oracle 外部表

    CREATE TABLE "EXT_ENTRY_WORKFLOW" ( ), ), "CREATE_DATE" DATE, ), ), ), ), ), ), ...

  10. Spring中@Transactional事务回滚实例及源码

    一.使用场景举例 在了解@Transactional怎么用之前我们必须要先知道@Transactional有什么用.下面举个栗子:比如一个部门里面有很多成员,这两者分别保存在部门表和成员表里面,在删除 ...