用户态/内核态、用户栈/内核栈

一、用户态和内核态

内核态和用户态是操作系统的两种运行级别,用于区分不同程序的不同权利。

内核态就是拥有资源多的状态,或者说访问资源多的状态,也称为特权态。相对来说,用户态就是非特权态,访问的而资源将受到限制。如果一个程序运行在特权态,该程序就可以访问计算机的任何资源,它的资源访问权限不受限制。如果一个程序运行在用户态,其资源需求将受到各种限制。如:要访问操作系统的内核数据结构,如进程表,则需要在特选态下才能办到。如果要访问用户程序里的数据,在用户态即可。

二、用户栈和内核栈

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

当进程因为中断或者系统调用陷入到内核态时,进程所使用的堆栈也要从用户栈转到内核栈。进程陷入到内核态后,先把用户态堆栈的地址保存在内核栈之中,然后设置堆栈指针寄存器的内容为内核栈的地址,这样就完成了用户栈向内核栈的转换;当进程从内核态恢复到用户态之后时,在内核态之后的最后将保存在内核栈里面的用户栈的地址恢复到堆栈指针寄存器即可。这样就实现了用户栈和内核栈的互转。

那么,知道从内核转到用户态时,用户栈的地址是在陷入内核的时候保存在内核栈里面的,但是在陷入内核的时候,如何知道内核栈的地址?关键在进程从用户态转到内核态的时候,进程的内核栈总是空的。这是因为当进程在用户态运行时,使用的用户栈,当进程陷入到内核态时,内核保存进程在内核态运行的相关信息,但是一旦进程返回到用户态后,内核栈中保存的信息无效,会全部恢复,因此每次进程从用户态陷入内核的时候得到的内核栈都是空的。所以在进程陷入内核的时候,直接把内核栈的栈顶地址给堆栈指针寄存器就可以了。

简而言之,一个程序至少有一个进程,一个进程至少有一个线程. 线程的划分尺度小于进程,使得多线程程序的并发性高。 
另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。 
同一个进程的多个子线程在进程的共享内存中分配独立的栈空间 
栈:是个线程独有的,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化,每个线程的栈互相独立,因此,栈是thread safe的。每个C++对象的数据成员也存在在栈中,每个函数都有自己的栈,栈被用来在函数之间传递参数。操作系统在切换线程的时候会自动的切换栈,就是切换SS/ESP寄存器。栈空间不需要在高级语言里面显式的分配和释放。 
在Linux系统上每一个线程,实际上都有独立的2个栈空间,用户栈空间和内核栈空间。(注意是每个线程) 
进程和线程在Linux上的唯一区别就是同一个进程的不同线程共享进程的地址空间,仅此而已。

原文地址:https://www.cnblogs.com/kukudi/p/11422320.html

时间: 2024-10-18 08:51:55

用户态/内核态、用户栈/内核栈的相关文章

用户态内核态

Q:怎么从用户态切换到内核态 A:用户程序调用系统调用的时候,用户程序先将系统调用号放入eax,执行int0x80指令触发中断,中断发生时,cpu切入内核态,从 用户栈 切换到 内核栈 ,在 内核栈 中依次压入用户态的寄存器,也就是保护现场,根据中断号在中断向量表中查找对应的中断处理程序,并调用它. 中断 中断:操作系统是通过中断来从用户态切换到内核态 中断分两种: 硬件中断:电源掉电,键盘被按下 软件中断:i386下是 int 指令 linux上系统调用的中断号是0x80,而windows上是

DSP 之原子与高性能设计(一) 用户态/内核态 原子原语

type __sync_fetch_and_add (type *ptr, type value, ...)type __sync_fetch_and_sub (type *ptr, type value, ...)type __sync_fetch_and_or (type *ptr, type value, ...)type __sync_fetch_and_and (type *ptr, type value, ...)type __sync_fetch_and_xor (type *pt

用户态-内核态

前戏 我们知道计算机主要分为三部分,硬件,操作系统和应用程序,然后硬件的头脑cpu才是控制内核态和用户态的大佬 操作系统 操作系统是直接和硬件打交道的,操作系统在内核态下运行,从而可以访问整个硬件 应用程序 应用程序直接和用户交互,但是应用程序不能直接操作硬件,应用程序在用户态下运行,但是有时候应用程序也需要操作硬件,这个时候,就涉及到用户态和内核态的切换 内核态-用户态概念 内核态(所有指令都给操作系统使用) 当cpu在内核态运行时,cpu可以执行指令集中所有的指令,很明显,所有的指令中包含了

linux 用户态 内核态

http://blog.chinaunix.net/uid-1829236-id-3182279.html 究竟什么是用户态,什么是内核态,这两个基本概念以前一直理解得不是很清楚,根本原因个人觉得是在于因为大部分时候我们在写程序时关注的重点和着眼的角度放在了实现的功能和代码的逻辑性上,先看一个例子: 1)例子 C代码 1.     void testfork(){   2.     if(0 = = fork()){   3.     printf(“create new process suc

进程:linux用户态-内核态

用户态:Ring3运行于用户态的代码则要受到处理器的诸多检查,它们只能访问映射其地址空间的页表项中规定的在用户态下可访问页面的虚拟地址,且只能对任务状态段(TSS)中I/O许可位图(I/O Permission Bitmap)中规定的可访问端口进行直接访问. 内核态:Ring0在处理器的存储保护中,核心态,或者特权态(与之相对应的是用户态),是操作系统内核所运行的模式.运行在该模式的代码,可以无限制地对系统存储.外部设备进行访问. 一.用户态和内核态 现在我们从特权级的调度来理解用户态和内核态就

从socket can中断到netlink用户态内核态通信

1. Linux中的进程间的通信机制源自于Unix平台上的进程通信机制.Unix的两大分支AT&T Unix和BSD Unix在进程通信实现机制上的各有所不同,前者形成了运行在单个计算机上的System V IPC,后者则实现了基于socket的进程间通信机制.同时linux也遵循IEEE制定的posix IPC标准,在三者的基础上实现以下几种主要的IPC机制:管道(Pipe)和命名管道(Name Pipe),信号(Signal),消息队列(Message queue),共享内存(Shared

关于内核态用户态和信号的思考(其中中断上下段没有看懂)

终于搞懂用户态内核态以及中断.信号的上下文切换关系了,处于内核态的时候用户态的上下文保存在内核栈中,此时如果发生中断或者切换,是不会区分进程处于用户态还是内核态的,直接切之,软中断导致的是内核态和用户态的转化,也即是用户上下文到内核上下文的转化,而中断导致的是用户态或者内核态上下文到中断上下文的转化,进程切换导致的是用户态/内核态上下文到用户态/内核态上下文的转化.关键是每个进程都对应一个用户栈和内核栈. 扩展阅读: http://19880512.blog.51cto.com/936364/2

关于内核态和用户态切换开销的测试

最近开发用到fuse文件系统,这个文件系统的功能实现是在用户态下进行的,然而它的文件系统操作接口必须在内核态注册,所以需要研究一下内核态到用户态的开销到底如何.下面这个例子是在stackoverflow上看到的,基本能反映开销的差异了:在linux测试这个测试程序,getuid是一个系统调用,返回当前用户的id 1 #include <unistd.h> 2 3 #define MAX 100000000 4 int main() { 5 int ii; 6 for (ii=0; ii<

用户态与内核态之间的切换

时间:2014.06.08 地点:基地 说明:本文由网上资料整理而成 -------------------------------------------------------------------------------------- 一.用户态与内核态 程序在运行时会消耗操作系统的物理资源,比如在创建新进程时涉及物理内存的分配,从父进程拷贝相关信息,拷贝设置页目录.页表等.这些都涉及很底层的操作,不可随便让程序去做,而是由更高级的程序完成,以达到对资源的集中管理,减少冲突.在Linux