linux进程的地址空间,核心栈,用户栈,内核线程
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进程的地址空间,核心栈,用户栈,内核线程的更多相关文章
- linux进程虚拟地址空间
转载源 在多任务操作系统中,每个进程都运行在属于自己的内存沙盘中.这个沙盘就是虚拟地址空间(Virtual Address Space),在32位模式下它是一个4GB的内存地址块.在Linux系统中, ...
- Linux进程虚拟地址空间管理2
2017-04-12 前篇文章对Linux进程地址空间的布局以及各个部分的功能做了简要介绍,本文主要对各个部分的具体使用做下简要分析,主要涉及三个方面:1.MMAP文件的映射过程 2.用户 内存的动态 ...
- LInux进程虚拟地址空间的管理
2017-04-07 脱离物理内存的管理,今天咱们来聊聊进程虚拟内存的管理.因为进程直接分配和使用的都是虚拟内存,而物理内存则是有系统“按需”分配给进程,在进程看来,只知道虚拟内存的存在! 前言: 关 ...
- linux进程模型总结
Linux进程通过一个task_struct结构体描述,在linux/sched.h中定义,通过理解该结构,可更清楚的理解linux进程模型. 包含进程所有信息的task_struct数据 ...
- Linux进程模型
----原文链接:http://www.cnblogs.com/biyeymyhjob/archive/2012/08/01/2617884.html------ Linux进程通过一个task_st ...
- Linux下的进程类别(内核线程、轻量级进程和用户进程)--Linux进程的管理与调度(四)
本文中出现的,内核线程,轻量级进程,用户进程,用户线程等概念,如果不太熟悉, 可以参见 内核线程.轻量级进程.用户线程三种线程概念解惑(线程≠轻量级进程) Linux进程类别 虽然我们在区分Linux ...
- Linux内核线程kernel thread详解--Linux进程的管理与调度(十)
内核线程 为什么需要内核线程 Linux内核可以看作一个服务进程(管理软硬件资源,响应用户进程的种种合理以及不合理的请求). 内核需要多个执行流并行,为了防止可能的阻塞,支持多线程是必要的. 内核线程 ...
- Linux进程管理 (篇外)内核线程简要介绍
关键词:kthread.irq.ksoftirqd.kworker.workqueues 在使用ps查看线程的时候,会有不少[...]名称的线程,这些有别于其它线程,都是内核线程. 其中多数内核线程从 ...
- linux内核线程,进程,线程
http://blog.csdn.net/dyllove98/article/details/8917197 Linux对于内存的管理涉及到非常多的方面,这篇文章首先从对进程虚拟地址空间的管理说起.( ...
随机推荐
- AngularJS(11)-API
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 关于华为C8812救砖教程
问题:华为C8812刷机后,开机显示:---------------------------------------------------------------- Image signature ...
- c# HttpWebRequest与HttpWebResponse(转)
如果你想做一些,抓取,或者是自动获取的功能,那么就跟我一起来学习一下Http请求吧.本文章会对Http请求时的Get和Post方式进行详细的说明,在请求时的参数怎么发送,怎么带Cookie,怎么设置证 ...
- unpipc.h&unpipc.c
unpipc.h #ifndef _UNPIPC_H #define _UNPIPC_H #include <stdio.h> #include <unistd.h> #inc ...
- 存储映射IO
mmap 将文件映射到内存, 对这块内存的修改会自动同步到相应的文件中 void *mmap(void *addr, size_t len, int prot, int flag, int fd, o ...
- 一个订单相关的存储过程(MySQL)
BEGIN DECLARE currentDate VARCHAR(15) ;/*当前日期,有可能包含时分秒 */ DECLARE maxNo INT DEFAULT 0 ; /* 离现在最近的满足条 ...
- 全部快捷方式图标变成LNK文件怎么办
windowsLNK文件打开方式恢复 相信有些用户曾试过错误地把LNK文件打开方式更改其文件导致系统所有快捷方式都失效vista与Windows7系统还普遍使用时候相信大家会有点惊慌失措要紧下面只要大 ...
- Oracle物理的体系结构
体系结构图的学习: 老余服装店的故事 结构图: SQL查询语句 SGA 共享池shared pool 数据缓存区Buffer cache PGA 进程 SQL更新语句 SGA: 日志缓存区 日志文件 ...
- Go在linux下的安装
在Ubuntu.Debian 或者 Linux Mint上安装Go语言 下面是在基于Debian的发行版上使用apt-get来安装Go语言和它的开发工具. $ sudo apt-get install ...
- spring中Bean的注入类型
1.属性注入 即通过setXxx()方法注入Bean的属性值或依赖对象,由于属性注入方式具有可选择性和灵活性高的优点,因此属性注入是实际应用中最常采用的注入方式. 属性注入要求Bean提供 ...