linux创建新进程的内核实现,对Linux的进程内核栈的认识

(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 */

__u32            cpu;        /* cpu */

__u32            cpu_domain;    /* cpu domain */

struct cpu_context_save    cpu_context;    /* cpu context */

__u32            syscall;    /* syscall number */

__u8            used_cp[16];    /* 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就会被摧毁,系统崩溃了~~~

内核栈---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 (arch\arm\include\asm),

#define THREAD_SIZE_ORDER    1

#define THREAD_SIZE     8192

#define THREAD_START_SP     (THREAD_SIZE - 8)

所以ARM的内核栈是8KB

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

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

更多关于内核栈的资料请参考:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值