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

Linux内核中用户空间栈和内核栈的区别,第1张

您好,很高兴为您解答。

1.进程的堆栈

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

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

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

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

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

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

3.内核栈的实现

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

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

 Union task_union {

                  Struct task_struct task

                  Unsigned long stack[INIT_STACK_SIZE/sizeof(long)]

 }

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

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

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

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

Union thread_union {

                  Struct thread_info thread_info;

                  Unsigned long stack[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宏的实现。

 struct thread_info {

                  struct task_struct *task;

                  struct exec_domain *exec_domain;

                  __u32 flags;

        __u32 status

                  __u32 cpu

                  …  ..

 }

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

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

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

                                                                                                                            ~ O(∩_∩)O~

中标麒麟Neokylin Linux *** 作系统介绍(来自官网):

中标麒麟高级服务器 *** 作系统软件是中标软件有限公司在多年Linux研制经验基础上,适应虚拟化、云计算、大数据时代对业务性能、扩展性、安全需要,依照CMMI5标准研发,针对关键业务及数据负载而构建的功能丰富、安全、高可靠、易管理、高性能的自主服务器 *** 作系统;广泛应用于物理和虚拟化环境,公共云平台、私有云环境和混合云环境。

安装体验:

通过虚拟机进行安装

启动安装界面:

语言选项:

初始化安装配置界面

软件环境安装选项

用户设置:

新建用户:

安装完成进行重启

重启后的用户协议:

完成安装

登陆界面,没有授权可以试用60天

中标麒麟Neokylin Linux用户桌面

中标麒麟Neokylin Linux系统工具界面:

注册产品获取支持

版本信息:

采用3.10.0linux内核

[root@localhost ~]# uname -aLinux localhost.localdomain3.10.0-693.el7.x86_64#1 SMP Thu Sep 14 15:11:35 CST 2017 x86_64 x86_64 x86_64 GNU/Linux[root@localhost ~]#

居然还有redhat-release 信息

[root@localhost ~]# cat /etc/redhat-releaseRed Hat Enterprise Linux Server release7.4(Maipo)

系统版本信息

[root@localhost ~]# cat /proc/versionLinux version3.10.0-693.el7.x86_64 (mockbuild@svr151.cs2c.com.cn) (gcc version4.8.520150623(NeoKylin4.8.5-16) (GCC) )#1 SMP Thu Sep 14 15:11:35 CST 2017[root@localhost ~]#

可以直接yum进行软件安装

官方yum源信息:

[root@localhost ~]# cat /etc/yumyum/ yum.conf yum.repos.d/[root@localhost ~]# cat /etc/yum.repos.d/ns7-adv.repo[ns7-adv-os]name=NeoKylin Linux Advanced Server 7 - Osbaseurl=http://update.cs2c.com.cn:8080/NS/V7/V7Update4/os/adv/lic/base/$basearch/gpgcheck=0gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-neokylin-releaseenabled=1​​[ns7-adv-updates]name=NeoKylin Linux Advanced Server 7 - Updatesbaseurl=http://update.cs2c.com.cn:8080/NS/V7/V7Update4/os/adv/lic/updates/$basearch/gpgcheck=0gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-neokylin-releaseenabled=1​​[ns7-adv-addons]name=NeoKylin Linux Advanced Server 7 - Addonsbaseurl=http://update.cs2c.com.cn:8080/NS/V7/V7Update4/os/adv/lic/addons/$basearch/gpgcheck=0gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-neokylin-releaseenabled=0

通过安装可以看出中标麒麟高级服务器 *** 作系统(Neokylin Linux Advanced Server)是基于红帽的Linux发行版本进行修改的,对应熟悉红帽 *** 作系统的用户来说可以快速上手。

除对了x86架构CPU的支持外,还支持龙芯、申威、海光、ARM64和Power等CPU。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7515461.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-06
下一篇 2023-04-06

发表评论

登录后才能评论

评论列表(0条)

保存