当前位置:首页 » 操作系统 » linux内核栈

linux内核栈

发布时间: 2023-05-25 16:21:16

linux为什么需要内核栈,系统调用时直接使用用户栈不行吗

在空气中喷出

❷ Linux内核中用户空间栈和内核栈的区别

您好,很高兴为您解答。

1.进程的堆栈

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

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

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

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

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

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

3.内核栈的实现

内核栈在kernel-2.4和kernel-2.6里面的实现方式是不一样的。

在kernel-2.4内核里面,内核栈的实现是:

Uniontask_union{
Structtask_structtask;
Unsignedlongstack[INIT_STACK_SIZE/sizeof(long)];
};

其中,INIT_STACK_SIZE的大小只能是8K。

内核为每个进程分配task_struct结构体的时候,实际上分配两个连续的物理页面,底部用作task_struct结构体,结构上面的用作堆栈。使用current()宏能够访问当前正在运行的进程描述符。

注意:这个时候task_struct结构是在内核栈里面的,内核栈的实际能用大小大概有7K。

内核栈在kernel-2.6里面的实现是(kernel-2.6.32):

Unionthread_union{
Structthread_infothread_info;
Unsignedlongstack[THREAD_SIZE/sizeof(long)];
};

其中THREAD_SIZE的大小可以是4K,也可以是8K,thread_info占52bytes。

当内核栈为8K时,Thread_info在这块内存的起始地址,内核栈从堆栈末端向下增长。所以此时,kernel-2.6中的current宏是需要更改的。要通过thread_info结构体中的task_struct域来获得于thread_info相关联的task。更详细的参考相应的current宏的实现。

structthread_info{
structtask_struct*task;
structexec_domain*exec_domain;
__u32flags;
__u32status;
__u32cpu;
…..
};

注意:此时的task_struct结构体已经不在内核栈空间里面了。


如若满意,请点击右侧【采纳答案】,如若还有问题,请点击【追问】

希望我的回答对您有所帮助,望采纳!

~ O(∩_∩)O~

❸ 请问linux内核的netfilter与内核的网络协议栈(我们网络编程经常用到的sock_packet)有什么区别何联系

看看相关书籍,查一下用户手册就行了。

❹ linux内核中内核局部变量过大不会导致栈溢出吗

不会首先全局变量是不占堆栈空间的
全局全量编译的时侯是放在.data段的
只有没有static修饰的局部变含空量在程序运行的时侯临时分配在栈上,new,或malloc等定义的变量分配在堆上
如果想让栈溢出也很容易,栈也有其极谈猛瞎限的,只要定义一个无限递归函数,让它没完没了的递归就行了,一会就崩了知改。
建议学一下编译原理

❺ 进程内核栈,用户栈及 Linux 进程栈和线程栈的区别

内核栈、用户栈

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
#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]

❻ linux进程为什么有用户栈和内核栈,

linux下的cpu有两个状态:内核态和用户态,内核态的cpu的权限高于用户态下的cpu。
linux下的内存分为用户态内存和内核态内存,一般4个G内存,3个G的分给用户态,1个G分给内核态。
linux进程有时需要调用内核资源时,如读写文件,io读写等,这时候是通过系统调用实现对内核资源的访问的,在访问内核资源前是用户栈,经过系统调用进入到内核态时,cpu的状态也由用户态变为内核态,访问的内存就是内核态下管理的内存了-内核栈,对内核里的资源访问完返回,内存又回到了用户栈,cpu也回到用户态。

❼ linux 线程默认栈多大

linux的线程栈大小可以使用ulimit -s查看,对于ubuntu 2.6的内核线程栈的默认大小为8M

热点内容
scratch少儿编程课程 发布:2025-04-16 17:11:44 浏览:642
荣耀x10从哪里设置密码 发布:2025-04-16 17:11:43 浏览:368
java从入门到精通视频 发布:2025-04-16 17:11:43 浏览:89
php微信接口教程 发布:2025-04-16 17:07:30 浏览:311
android实现阴影 发布:2025-04-16 16:50:08 浏览:794
粉笔直播课缓存 发布:2025-04-16 16:31:21 浏览:347
机顶盒都有什么配置 发布:2025-04-16 16:24:37 浏览:213
编写手游反编译都需要学习什么 发布:2025-04-16 16:19:36 浏览:818
proteus编译文件位置 发布:2025-04-16 16:18:44 浏览:369
土压缩的本质 发布:2025-04-16 16:13:21 浏览:595