进程调度之thread_info和thread_struct
对于thread_struct内核还需要存储每个进程的PCB信息, linux内核是支持不同体系的的, 但是不同的体系结构可能进程需要存储的信息不尽相同, 这就需要我们实现一种通用的方式, 我们将体系结构相关的部分和无关的部门进行分离对于PPC来说,结构体如下struct thread_struct {unsigned longksp;/* Kernel stack poin...
对于thread_struct
- 内核还需要存储每个进程的PCB信息, linux内核是支持不同体系的的, 但是不同的体系结构可能进程需要存储的信息不尽相同, 这就需要我们实现一种通用的方式, 我们将体系结构相关的部分和无关的部门进行分离
对于PPC来说,结构体如下
struct thread_struct {
unsigned long ksp; /* Kernel stack pointer */
#ifdef CONFIG_PPC64
unsigned long ksp_vsid;
#endif
struct pt_regs *regs; /* Pointer to saved register state */
mm_segment_t fs; /* for get_fs() validation */
#ifdef CONFIG_PPC32
void *pgdir; /* root of page-table tree */
#endif
#if defined(CONFIG_4xx) || defined (CONFIG_BOOKE)
unsigned long dbcr0; /* debug control register values */
unsigned long dbcr1;
#endif
double fpr[32]; /* Complete floating point set */
struct { /* fpr ... fpscr must be contiguous */
unsigned int pad;
unsigned int val; /* Floating point status */
} fpscr;
int fpexc_mode; /* floating-point exception mode */
unsigned int align_ctl; /* alignment handling control */
#ifdef CONFIG_PPC64
unsigned long start_tb; /* Start purr when proc switched in */
unsigned long accum_tb; /* Total accumilated purr for process */
#endif
unsigned long dabr; /* Data address breakpoint register */
#ifdef CONFIG_ALTIVEC
/* Complete AltiVec register set */
vector128 vr[32] __attribute((aligned(16)));
/* AltiVec status */
vector128 vscr __attribute((aligned(16)));
unsigned long vrsave;
int used_vr; /* set if process has used altivec */
#endif /* CONFIG_ALTIVEC */
#ifdef CONFIG_SPE
unsigned long evr[32]; /* upper 32-bits of SPE regs */
u64 acc; /* Accumulator */
unsigned long spefscr; /* SPE & eFP status */
int used_spe; /* set if process has used spe */
#endif /* CONFIG_SPE */
};
而核心是如下数据结构是PPC的寄存器信息。
struct pt_regs {
unsigned long gpr[32];
unsigned long nip;
unsigned long msr;
unsigned long orig_gpr3; /* Used for restarting system calls */
unsigned long ctr;
unsigned long link;
unsigned long xer;
unsigned long ccr;
#ifdef __powerpc64__
unsigned long softe; /* Soft enabled/disabled */
#else
unsigned long mq; /* 601 only (not used at present) */
/* Used on APUS to hold IPL value. */
#endif
unsigned long trap; /* Reason for being here */
/* N.B. for critical exceptions on 4xx, the dar and dsisr
fields are overloaded to hold srr0 and srr1. */
unsigned long dar; /* Fault registers */
unsigned long dsisr; /* on 4xx/Book-E used for ESR */
unsigned long result; /* Result of a system call */
};
对于X86来说,定义则依赖于X86的CPU实现
struct thread_struct {
/* cached TLS descriptors. */
struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
unsigned long esp0;
unsigned long sysenter_cs;
unsigned long eip;
unsigned long esp;
unsigned long fs;
unsigned long gs;
/* Hardware debugging registers */
unsigned long debugreg[8]; /* %%db0-7 debug registers */
/* fault info */
unsigned long cr2, trap_no, error_code;
/* floating point info */
union i387_union i387;
/* virtual 86 mode info */
struct vm86_struct __user * vm86_info;
unsigned long screen_bitmap;
unsigned long v86flags, v86mask, saved_esp0;
unsigned int saved_fs, saved_gs;
/* IO permissions */
unsigned long *io_bitmap_ptr;
unsigned long iopl;
/* max allowed port in the bitmap, in bytes: */
unsigned long io_bitmap_max;
};
该结构体处于进程数据结构里面:
struct task_struct
thread_struct thread;
对于thread_info
- 内核栈跟thread_info共用结构体
用一种通用的方式来描述进程, 这就是struct task_struct, 而thread_info就保存了特定体系结构的汇编代码段需要访问的那部分进程的数据,我们在thread_info中嵌入指向task_struct的指针, 则我们可以很方便的通过thread_info来查找task_struct
struct thread_info {
struct task_struct *task; /* main task structure */
struct exec_domain *exec_domain; /* execution domain */
unsigned long flags; /* low level flags */
unsigned long status; /* thread-synchronous flags */
__u32 cpu; /* current CPU */
int preempt_count; /* 0 => preemptable, <0 => BUG */
mm_segment_t addr_limit; /* thread address space:
0-0xBFFFFFFF for user-thead
0-0xFFFFFFFF for kernel-thread
*/
void *sysenter_return;
struct restart_block restart_block;
unsigned long previous_esp; /* ESP of the previous stack in case
of nested (IRQ) stacks
*/
__u8 supervisor_stack[0];
};
union thread_union {
struct thread_info thread_info;
unsigned long stack[THREAD_SIZE/sizeof(long)];
};
该结构体在task_struct的位置如下:
看一下这个函数就明白了
static struct task_struct *dup_task_struct(struct task_struct *orig)
{
struct task_struct *tsk;
struct thread_info *ti;//声明
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;
}
*tsk = *orig;
tsk->stack = ti;//与task_struct关联
setup_thread_stack(tsk, orig);
#ifdef CONFIG_CC_STACKPROTECTOR
tsk->stack_canary = get_random_int();
#endif
/* One for us, one for whoever does the "release_task()" (usually parent) */
atomic_set(&tsk->usage,2);
atomic_set(&tsk->fs_excl, 0);
#ifdef CONFIG_BLK_DEV_IO_TRACE
tsk->btrace_seq = 0;
#endif
tsk->splice_pipe = NULL;
return tsk;
}
Linux进程内核栈与thread_info结构详解--Linux进程的管理与调度(九)
http://blog.csdn.net/gatieme/article/details/51577479
Linux下0号进程的前世(init_task进程)今生(idle进程)----Linux进程的管理与调度(五)
https://blog.csdn.net/gatieme/article/details/51484562
Linux内核分析(八):Linux进程调度的时机和进程切换
https://blog.csdn.net/u013291303/article/details/70199645
Linux内核分析(六):进程的描述和进程的创建
https://blog.csdn.net/u013291303/article/details/68954599
进程内核栈、用户栈
https://blog.csdn.net/bailyzheng/article/details/8015618
更多推荐
所有评论(0)