Linux内核进程管理子系统有什么第六十一回 —— 进程主结构详解(57)
接前一篇文章:Linux内核进程管理子系统有什么第六十回 —— 进程主结构详解(56)
本文内容参考:
Linux内核进程管理专题报告_linux rseq-CSDN博客
《趣谈Linux操作系统 核心原理篇:第三部分 进程管理》—— 刘超
《图解Linux内核 基于6.x》 —— 姜亚华 机械工业出版社
https://www.cnblogs.com/libxing/p/16649917.html
https://blog.csdn.net/u012489236/article/details/116614606
特此致谢!
进程管理核心结构 —— task_struct
11. stack和thread_info
一目了然,包括以下两个:
#ifdef CONFIG_THREAD_INFO_IN_TASK/** For reasons of header soup (see current_thread_info()), this* must be the first element of task_struct.*/struct thread_info thread_info;
#endif
……void *stack;
这两个字段的描述如下:
(2)void *stack
由void *stack字段的描述可以知道,其代表进程的内核栈。因此,要讲清楚void *stack字段,需要先讲一下用户态函数栈和内核态函数栈。
- 内核态函数栈
上一回讲到,通过系统调用,就会从进程的内存空间(用户空间)进入(切换)到内核(空间)中了 。内核也需要有一个函数调用和传参机制。本回就来讲内核中的这一机制。
此时,void *stack这一成员就该正式登场(派上用场)了。Linux会为每个task均分配内核栈。内核栈的大小是体系结构相关的。
32位x86系统
在32位x86系统上,定义如下:
arch/x86/include/asm/page_types.h中:
/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT 12
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
arch/x86/include/asm/page_32_types.h中:
#define THREAD_SIZE_ORDER 1
#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
在32位x86系统下,一个PAGE_SIZE是4K(2^12),左移一位即乘以2,是8K,也就是内核栈的大小为8K。
64位x86系统
在64位x86系统上,定义如下:
arch/x86/include/asm/page_types.h中:
/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT 12
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
arch/x86/include/asm/page_64_types.h中:
#ifdef CONFIG_KASAN
#define KASAN_STACK_ORDER 1
#else
#define KASAN_STACK_ORDER 0
#endif#define THREAD_SIZE_ORDER (2 + KASAN_STACK_ORDER)
#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
在64位x86系统下,一个PAGE_SIZE是4K(2^12),左移(2 +KASAN_STACK_ORDER)位(通常情况下是2)即乘以4,是16K,也就是内核栈的大小为16K。同时,还要求起始地址必须是8192的整数倍。
在Linux内核代码中有这样一个十分重要的union,将thread_info和stack放在一起,共用一段内存。这个union就是union thread_union,它在include/linux/sched.h中定义,如下:
union thread_union {
#ifndef CONFIG_ARCH_TASK_STRUCT_ON_STACKstruct task_struct task;
#endif
#ifndef CONFIG_THREAD_INFO_IN_TASKstruct thread_info thread_info;
#endifunsigned long stack[THREAD_SIZE/sizeof(long)];
};
对于union thread_union的解析,请看下回。