位置: 编程技术 - 正文

进程的内核栈是什么?浅谈Linux的进程内核栈(进程 内核栈)

编辑:rootadmin

推荐整理分享进程的内核栈是什么?浅谈Linux的进程内核栈(进程 内核栈),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:每个进程都有自己的内核栈,每个进程都有自己的内核栈,进程 内核栈,进程的内核栈是共用的吗,进程的内核栈是什么意思,进程的内核栈是共用的吗,进程的内核栈是共用的吗,进程的内核栈是什么意思,内容如对您有帮助,希望把文章链接给更多的朋友!

在重游《LDD3》的时候,又发现了一个当年被我忽略的一句话:

“内核具有非常小的栈,它可能只和一个字节大小的页那样小”

针对这句话,我简单地学习了一下进程的“内核栈”

什么是进程的“内核栈”?

在每一个进程的生命周期中,必然会通过到系统调用陷入内核。在执行系统调用陷入内核之后,这些内核代码所使用的栈并不是原先用户空间中的栈,而是一个内核空间的栈,这个称作进程的“内核栈”。

比如,有一个简单的字符驱动实现了open方法。在这个驱动挂载后,应用程序对那个驱动所对应的设备节点执行open操作,这个应用程序的open其实就通过glib库调用了Linux的open系统调用,执行系统调用陷入内核后,处理器转换为了特权模式(具体的转换机制因构架而异,对于ARM来说普通模式和用户模式的的栈针(SP)是不同的寄存器),此时使用的栈指针就是内核栈指针,他指向内核为每个进程分配的内核栈空间。

内核栈的作用

我个人的理解是:在陷入内核后,系统调用中也是存在函数调用和自动变量,这些都需要栈支持。用户空间的栈显然不安全,需要内核栈的支持。此外,内核栈同时用于保存一些系统调用前的应用层信息(如用户空间栈指针、系统调用参数)。

内核栈与进程结构体的关联

每个进程在创建的时候都会得到一个内核栈空间,内核栈和进程的对应关系是通过2个结构体中的指针成员来完成的:

(1)struct task_struct

在学习Linux进程管理肯定要学的结构体,在内核中代表了一个进程,其中记录的进程的所有状态信息,定义在Sched.h (includelinux)。

其中有一个成员:void *stack;就是指向下面的内核栈结构体的“栈底”。

在系统运行的时候,宏current获得的就是当前进程的struct task_struct结构体。

(2)内核栈结构体union thread_union

union thread_union {

struct thread_info thread_info;

unsigned long stack[THREAD_SIZE/sizeof(long)];

};

其中struct thread_info是记录部分进程信息的结构体,其中包括了进程上下文信息:

/*

* low level task data that entry.S needs immediate access to.

* __switch_to() assumes cpu_context follows immediately after cpu_domain.

*/

struct thread_info {

unsigned long flags; /* low level flags */

int preempt_count; /* 0 => preemptable, <0 => bug */

mm_segment_t addr_limit; /* address limit */

struct task_struct *task; /* main task structure */

struct exec_domain *exec_domain; /* execution domain */

__u cpu; /* cpu */

__u cpu_domain; /* cpu domain */

struct cpu_context_save cpu_context; /* cpu context */

__u syscall; /* syscall number */

__u8 used_cp[]; /* thread used copro */

unsigned long tp_value;

struct crunch_state crunchstate;

union fp_state fpstate __attribute__((aligned(8)));

union vfp_state vfpstate;

#ifdef CONFIG_ARM_THUMBEE

unsigned long thumbee_state; /* ThumbEE Handler Base register */

#endif

struct restart_block restart_block;

};

关键是其中的task成员,指向的是所创建的进程的struct task_struct结构体

而其中的stack成员就是内核栈。从这里可以看出内核栈空间和 thread_info是共用一块空间的。如果内核栈溢出, thread_info就会被摧毁,系统崩溃了~~~

进程的内核栈是什么?浅谈Linux的进程内核栈(进程 内核栈)

内核栈---struct thread_info----struct task_struct三者的关系入下图:

内核栈的产生

在进程被创建的时候,fork族的系统调用中会分别为内核栈和struct task_struct分配空间,调用过程是:

fork族的系统调用--->do_fork--->copy_process--->dup_task_struct

在dup_task_struct函数中:

static struct task_struct *dup_task_struct(struct task_struct *orig)

{

struct task_struct *tsk;

struct thread_info *ti;

unsigned long *stackend;

int err;

prepare_to_copy(orig);

tsk = alloc_task_struct();

if (!tsk)

return NULL;

ti = alloc_thread_info(tsk);

if (!ti) {

free_task_struct(tsk);

return NULL;

}

err = arch_dup_task_struct(tsk, orig);

if (err)

goto out;

tsk->stack = ti;

err = prop_local_init_single(&tsk->dirties);

if (err)

goto out;

setup_thread_stack(tsk, orig);

......

其中alloc_task_struct使用内核的slab分配器去为所要创建的进程分配struct task_struct的空间

而alloc_thread_info使用内核的伙伴系统去为所要创建的进程分配内核栈(union thread_union )空间

注意:

后面的tsk->stack = ti;语句,这就是关联了struct task_struct和内核栈

而在setup_thread_stack(tsk, orig);中,关联了内核栈和struct task_struct:

static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org)

{

*task_thread_info(p) = *task_thread_info(org);

task_thread_info(p)->task = p;

}

内核栈的大小

由于是每一个进程都分配一个内核栈空间,所以不可能分配很大。这个大小是构架相关的,一般以页为单位。其实也就是上面我们看到的THREAD_SIZE,这个值一般为4K或者8K。对于ARM构架,这个定义在Thread_info.h (archarmincludeasm),

#define THREAD_SIZE_ORDER 1

#define THREAD_SIZE

#define THREAD_START_SP (THREAD_SIZE - 8)

所以ARM的内核栈是8KB

在(内核)驱动编程时需要注意的问题:

由于栈空间的限制,在编写的驱动(特别是被系统调用使用的底层函数)中要注意避免对栈空间消耗较大的代码,比如递归算法、局部自动变量定义的大小等等

Linux多队列网卡的硬件的实现详解 多队列网卡是一种技术,最初是用来解决网络IOQoS(qualityofservice)问题的,后来随着网络IO的带宽的不断提升,单核CPU不能完全处满足网卡的需求,通过

lxde桌面美化怎么样?选择LXDE作为Linux桌面的八大理由 去年年底,升级到Fedora带来的新版本KDEPlasma,想必让很多人都不习惯吧,这也直接导致我很难完成预定的工作计划。我决定尝试其他Linux桌面环境有两

linux管道及重定向详解 在linux系统中,大多数命令很简单,很少出现复杂功能的命令,每个命令往往实现一个或者几个功能十分简单的功能,我们可以通过将多个简单的命令组

标签: 进程 内核栈

本文链接地址:https://www.jiuchutong.com/biancheng/361978.html 转载请保留说明!

上一篇:Linux 系统内核的调试详解(linux系统内核的功能)

下一篇:Linux多队列网卡的硬件的实现详解(linux 多网卡配置)

  • 应纳税所得额高了好还是低了好
  • 小规模纳税人没有税控盘怎么报税
  • 什么是财务报表审计
  • 服务费发票的税率是多少
  • 退回代征手续费怎么做会计分录
  • 个人劳务票必须本人开吗
  • 运输部门计入什么会计科目
  • 电子记账凭证需要划线吗
  • 制造费用结转成什么
  • 车船税每年都要交吗标准多少
  • 购买金蝶软件多少钱
  • 普票丢失了能作废重开吗
  • 2019年印花税税率多少
  • 税控盘专票认证登录密码正确还是登录不上去
  • 增值税专用发票抵扣税额是什么意思
  • 应收票据贴现的含义
  • 装饰设计事务所平面图
  • 固定资产造成的损失可以税前扣除吗
  • 小微企业如何申请土地建厂房
  • 缴纳土地增值税
  • 会务费税率是多少 2021
  • 税局税种认定
  • 水利建设基金按什么基数计算
  • 残保金补报
  • 增值税普通发票和普通发票的区别怎么交税
  • 工会经费申报网址是什么
  • 买卖不破租赁什么情况必须搬走
  • 信用卡核销是什么意思
  • 应付职工薪酬调到其他应付款
  • 关于linux说法错误的是
  • linux禁用root用户
  • 生产成本包括什么科目内容
  • win7电脑怎么样
  • 财务里计提是什么意思
  • xampp如何运行php项目
  • phpadmin官网
  • php面向对象的三大特征
  • php 字符串函数
  • 新准则规定
  • php rewind
  • 采购国产设备退税公告
  • 企业收到分红款,要怎么处理才合理
  • php使用oci8扩展连接oracle
  • vue数据加载完成显示页面过渡动画
  • 金融企业往来支出是一级科目吗
  • 二季度报表是累计数吗
  • 融资租赁有免租金吗
  • mysql使用ssl连接
  • 企业负担的社保费会计分录
  • 一税两费减免政策
  • 自己动手把桌子改窄
  • mysql数据类型和java对应
  • 物业公司一般纳税人简易征收
  • 自产产品对外捐赠为什么不确认收入
  • 成本结账是什么意思
  • 期初建账库存现金如何填写
  • 合伙企业与公司相比,有什么优势呢?
  • 党委费用支出需要什么票据
  • 企业转让固定资产企业所得税
  • 合并两公司的帐务处理
  • 苹果今日报价
  • WIN7系统如何设置自动关机
  • centos为什么没有桌面
  • win10 提示你的设备遇到问题 需要重新启动
  • 深入解析windows第7版
  • vs2012配置opencv4.8
  • nodejs爬虫框架crawler
  • android开发工程师案例教程源码
  • selenium csdn
  • 炉石 xhope
  • linux脚本自启
  • vue实现下载功能
  • javascript绘制图形
  • jQueryUI Datepicker组件设置日期高亮
  • [Phonegap+Sencha Touch] 移动开发50 Android修改新建虚拟机存放的位置
  • Android优化蓝牙
  • 简述javascript原型和原型链有什么特点?
  • 两个fragment之间传值
  • 员工离职了个人所得税年度汇算应申报未申报怎么处理
  • 南昌契税政策
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设