intel的cpu分为四个运行级别ring0~ring3
内核创建进程,创建进程的同时创建进程控制块,创建进程自己的堆栈
一个进程有两个堆栈,用户栈和系统栈
用户堆栈的空间指向用户地址空间,内核堆栈的空间指向内核地址空间。
有个CPU堆栈指针寄存器,进程运行的状态有用户态和内核态,当进程运行在用户态时。CPU堆栈指针寄存器指向的是用户堆栈地址,使用的是用户堆栈;当进程运行在内核态时,CPU堆栈指针寄存器指向的是内核堆栈地址,使用的是内核堆栈。
堆栈切换
当系统因为系统调用(软中断)或硬件中断,CPU切换到特权工作模式,进程陷入内核态,进程使用的栈也要从用户栈转向系统栈。
从用户态到内核态要两步骤,首先是将用户堆栈地址保存到内核堆栈中,然后将CPU堆栈指针寄存器指向内核堆栈。
当由内核态转向用户态,步骤首先是将内核堆栈中得用户堆栈地址恢复到CPU堆栈指针寄存器中。
内核栈和用户栈区别
1.
栈是系统运行在内核态的时候使用的栈,用户栈是系统运行在用户态时候使用的栈。
当进程由于中断进入内核态时,系统会把一些用户态的数据信息保存到内核栈中,当返回到用户态时,取出内核栈中得信息恢复出来,返回到程序原来执行的地方。
用户栈就是进程在用户空间时创建的栈,比如一般的函数调用,将会用到用户栈。
2.
内核栈是属于 *** 作系统空间的一块固定区域,可以用于保存中断现场、保存 *** 作系统子程序间相互调用的参数、返回值等。
用户栈是属于用户进程空间的一块区域,用户保存用户进程子程序间的相互调用的参数、返回值等。
3.
每个Windows 都有4g的进程空间,系统栈使用进程空间的地段部分,用户栈是高端部分如果用户要直接访问系统栈部分,需要有特殊的方式。
为何要设置两个不同的栈?
共享原因:
内核的代码和数据是为所有的进程共享的,如果不为每一个进程设置对应的内核栈,那么就不能实现不同的进程执行不同的代码。
安全原因:
如果只有一个栈,那么用户就可以修改栈内容来突破内核安全保护。
为了区分程序的运行级别,有用户态和核心态之分,也叫目态和管态。硬件驱动、CPU和内存管理等底层 *** 作和进程管理、诊断测试相关程序运行在核心态。而部分文件系统、网络参数设置和编辑功能运行在用户态。Intel CPU提供Ring0 ~ Ring3共4种级别的运行模式。Ring0级别最高,Ring3级别最低。
内核栈、用户栈32位Linux系统上,进程的地址空间为4G,包括1G的内核地址空间-----内核栈,和3G的用户地址空间-----用户栈。
内核栈,是各个进程在刚开始建立的时候通过内存映射共享的,但是每个进程拥有独立的4G的虚拟内存空间从这一点看又是独立的,互不干扰的(只是刚开始大家都是映射的同一份内存拷贝)
用户栈就是大家所熟悉的内存四区,包括:代码区、全局数据区、堆区、栈区
用户栈中的堆区、栈区即为进程堆、进程栈
进程堆、进程栈与线程栈
1.线程栈的空间开辟在所属进程的堆区与共享内存区之间,线程与其所属的进程共享进程的用户空间,所以线程栈之间可以互访。线程栈的起始地址和大小存放在pthread_attr_t 中,栈的大小并不是用来判断栈是否越界,而是用来初始化避免栈溢出的缓冲区的大小(或者说安全间隙的大小)
2.进程初始化的时候,系统会在进程的地址空间中创建一个堆,叫进程默认堆。进程中所有的线程共用这一个堆。当然,可以增加1个或几个堆,给不同的线程共同使用或单独使用。----一个进程可以多个堆
3、创建线程的时候,系统会在进程的地址空间中分配1块内存给线程栈,通常是1MB或4MB或8MB。线程栈是独立的,但是还是可以互访,因为线程共享内存空间
4.堆的分配:从 *** 作系统角度来看,进程分配内存有两种方式,分别由两个系统调用完成:brk()和mmap(),glibc中malloc封装了
5.线程栈位置-内存分布测试代码
[cpp] view plain copy
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <malloc.h>
#include <sys/syscall.h>
void* func(void* arg)
{
long int tid = (long int)syscall(SYS_gettid)
printf("The ID of this thread is: %ld\n", tid )
static int a=10
int b=11
int* c=(int *)malloc(sizeof(int))
printf("in thread id:%u a:%p b:%p c:%p\n",tid,&a,&b,c)
printf("leave thread id:%ld\n",tid)
sleep(20)
free((void *)c)
}
void main()
{
pthread_t th1,th2
printf("pid=%u\n",(int)getpid())
func(NULL)
int ret=pthread_create(&th1,NULL,func,NULL)
if(ret!=0)
{
printf("thread1[%d]:%s\n",th1,strerror(errno))
}
ret=pthread_create(&th2,NULL,func,NULL)
if(ret!=0)
{
printf("thread2[%d]:%s\n",th2,strerror(errno))
}
pthread_join(th1,NULL)
pthread_join(th2,NULL)
}
输出:
[le@localhost threadStack]$ ./threadStack_main pid=16433
The ID of this thread is: 16433
in thread id:16433 a:0x60107c b:0x7fffc89ce7ac c:0x1b54010
leave thread id:16433
The ID of this thread is: 16461
The ID of this thread is: 16460
in thread id:16461 a:0x60107c b:0x7f6abb096efc c:0x7f6ab40008c0
leave thread id:16461
in thread id:16460 a:0x60107c b:0x7f6abb897efc c:0x7f6aac0008c0
leave thread id:16460
主线程调用func后
[le@localhost threadStack]$ sudo cat /proc/16433/maps
00400000-00401000 r-xp 00000000 fd:02 11666 /home/le/code/threadStack/threadStack_main
00600000-00601000 r--p 00000000 fd:02 11666 /home/le/code/threadStack/threadStack_main
00601000-00602000 rw-p 00001000 fd:02 11666 /home/le/code/threadStack/threadStack_main
01b54000-01b75000 rw-p 00000000 00:00 0 [heap]
7f6abb899000-7f6abba4f000 r-xp 00000000 fd:00 100678959 /usr/lib64/libc-2.17.so
7f6abba4f000-7f6abbc4f000 ---p 001b6000 fd:00 100678959 /usr/lib64/libc-2.17.so
7f6abbc4f000-7f6abbc53000 r--p 001b6000 fd:00 100678959 /usr/lib64/libc-2.17.so
7f6abbc53000-7f6abbc55000 rw-p 001ba000 fd:00 100678959 /usr/lib64/libc-2.17.so
7f6abbc55000-7f6abbc5a000 rw-p 00000000 00:00 0
7f6abbc5a000-7f6abbc70000 r-xp 00000000 fd:00 105796566 /usr/lib64/libpthread-2.17.so
7f6abbc70000-7f6abbe70000 ---p 00016000 fd:00 105796566 /usr/lib64/libpthread-2.17.so
7f6abbe70000-7f6abbe71000 r--p 00016000 fd:00 105796566 /usr/lib64/libpthread-2.17.so
7f6abbe71000-7f6abbe72000 rw-p 00017000 fd:00 105796566 /usr/lib64/libpthread-2.17.so
7f6abbe72000-7f6abbe76000 rw-p 00000000 00:00 0
7f6abbe76000-7f6abbe97000 r-xp 00000000 fd:00 105796545 /usr/lib64/ld-2.17.so
7f6abc073000-7f6abc076000 rw-p 00000000 00:00 0
7f6abc095000-7f6abc097000 rw-p 00000000 00:00 0
7f6abc097000-7f6abc098000 r--p 00021000 fd:00 105796545 /usr/lib64/ld-2.17.so
7f6abc098000-7f6abc099000 rw-p 00022000 fd:00 105796545 /usr/lib64/ld-2.17.so
7f6abc099000-7f6abc09a000 rw-p 00000000 00:00 0
7fffc89b0000-7fffc89d1000 rw-p 00000000 00:00 0 [stack]
7fffc89fe000-7fffc8a00000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
两个子线程启动后
[le@localhost threadStack]$ sudo cat /proc/16433/maps
00400000-00401000 r-xp 00000000 fd:02 11666 /home/le/code/threadStack/threadStack_main
00600000-00601000 r--p 00000000 fd:02 11666 /home/le/code/threadStack/threadStack_main
00601000-00602000 rw-p 00001000 fd:02 11666 /home/le/code/threadStack/threadStack_main
01b54000-01b75000 rw-p 00000000 00:00 0 [heap]
7f6aac000000-7f6aac021000 rw-p 00000000 00:00 0
7f6aac021000-7f6ab0000000 ---p 00000000 00:00 0
7f6ab4000000-7f6ab4021000 rw-p 00000000 00:00 0
7f6ab4021000-7f6ab8000000 ---p 00000000 00:00 0
7f6aba897000-7f6aba898000 ---p 00000000 00:00 0
7f6aba898000-7f6abb098000 rw-p 00000000 00:00 0 [stack:16461]
7f6abb098000-7f6abb099000 ---p 00000000 00:00 0
7f6abb099000-7f6abb899000 rw-p 00000000 00:00 0 [stack:16460]
7f6abb899000-7f6abba4f000 r-xp 00000000 fd:00 100678959 /usr/lib64/libc-2.17.so
7f6abba4f000-7f6abbc4f000 ---p 001b6000 fd:00 100678959 /usr/lib64/libc-2.17.so
7f6abbc4f000-7f6abbc53000 r--p 001b6000 fd:00 100678959 /usr/lib64/libc-2.17.so
7f6abbc53000-7f6abbc55000 rw-p 001ba000 fd:00 100678959 /usr/lib64/libc-2.17.so
7f6abbc55000-7f6abbc5a000 rw-p 00000000 00:00 0
7f6abbc5a000-7f6abbc70000 r-xp 00000000 fd:00 105796566 /usr/lib64/libpthread-2.17.so
7f6abbc70000-7f6abbe70000 ---p 00016000 fd:00 105796566 /usr/lib64/libpthread-2.17.so
7f6abbe70000-7f6abbe71000 r--p 00016000 fd:00 105796566 /usr/lib64/libpthread-2.17.so
7f6abbe71000-7f6abbe72000 rw-p 00017000 fd:00 105796566 /usr/lib64/libpthread-2.17.so
7f6abbe72000-7f6abbe76000 rw-p 00000000 00:00 0
7f6abbe76000-7f6abbe97000 r-xp 00000000 fd:00 105796545 /usr/lib64/ld-2.17.so
7f6abc073000-7f6abc076000 rw-p 00000000 00:00 0
7f6abc095000-7f6abc097000 rw-p 00000000 00:00 0
7f6abc097000-7f6abc098000 r--p 00021000 fd:00 105796545 /usr/lib64/ld-2.17.so
7f6abc098000-7f6abc099000 rw-p 00022000 fd:00 105796545 /usr/lib64/ld-2.17.so
7f6abc099000-7f6abc09a000 rw-p 00000000 00:00 0
7fffc89b0000-7fffc89d1000 rw-p 00000000 00:00 0 [stack]
7fffc89fe000-7fffc8a00000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)