linux 2.6源代码情景分析笔记之进程2
能被独立调度的每个执行上下文都必须拥有自己的进程描述符。进程和进程描述符之间有严格的对应关系,使用32位进程描述符地址标识,进程描述符指针指向这些地址,内核对进程的大部分引用是通过进程描述符指针进行的。
可以使用pid(进程标识符)来标记进程,存放在字段pid中,PID被顺序编号,新创建的进程PID通常是前一个进程的PID加一。
#define PID_MAX_DEFAULT 0x8000
一个线程租中的所有线程使用和该线程组的领头线程(thread group leader)相同的PID,也就是该组中第一个轻量级进程的PID,被存入进程描述符的tgid字段中。getpid()系统调用返回当前进程的tgid值而不是pid的值,因此一个多线程应用的所有线程共享相同的PID。绝大多数进程都属于一个线程组,包含单一的成员;线程组领头线程其tgid的值与pid的相同,因而getpid()系统调用对这类进程所其的作用和一般进程是一样的。
对每个进程来说,linux把两个不同的数据结构紧凑地存放在一个单独为进程分配的存储区域内:一个内核态的进程堆栈,另一个是紧挨进程描述符的小数据结构thread_info,叫做线程描述符,这块存储区域的大小通常为8192个字节(两个页框)。内核让这8k空间占据连续的两个页框并让第一个页框的起始地址是2^13的倍数。当几乎没有可用的动态内存空间时,就会很难找到这样的两个连续页框,因为空闲空间可能存在大量碎片。内核态的进程访问处于内核数据段的栈,这个栈不同于用户态的进程所用的栈。因为内核控制路径使用很少的栈,因此只需要几千个字节的内核态堆栈。使用task和thread_info字段使thread_info结构与task_struct结构互相关联。
esp寄存器是cpu栈指针,用来存放栈顶单元的地址。栈起始于末端,并朝这个内存区开始的方向增长。从用户态刚切换到内核态之后,进程的内核栈总是空的,因此,esp寄存器指向这个栈的顶端。一旦数据写入堆栈,esp的数值就递减。(thread_info结构是52个字节长)
union thread_union {
struct thread_info thread_info;
unsigned long stack[THREAD_SIZE/sizeof(long)];
};
使用以上联合结构表示一个进程的线程描述符和内核栈。
struct thread_info {
struct task_struct *task; /* main task struct
相关文档:
引导 Linux® 系统的过程包括很多阶段。不管您是引导一个标准的 x86 桌面系统,还是引导一台嵌入式的
PowerPC® 机器,很多流程都惊人地相似。本文将探索 Linux
的引导过程,从最初的引导到启动第一个用户空间应用程序。在本文介绍的过程中,您将学习到各种与引导有关的主题,例如引导加载程序、内核解压、初始
RA ......
我们在Linux下安装系统软件的时候,经常遇到一些系统环境变量配置的问题。什么是环境变量?如何定制环境变量?我将在下面做一些介绍。
一、什么是环境变量?
Linux是一个多用户的操作系统。多用户意味着每个用户登录系统后,都有自己专用的运行环境。而这个环境是由一组变量所定义,这组变量被称为环境变量。用户可以对自 ......
内核使用的基本数据类型主要有: int : 标准的C语言整数类型 u32 : 32位整数类型 pid_t : 特定内核对象pid的类型 在不同CPU体系结构上,C语言的数据类型所占用的空间是不一样的。在x86系列结构下,数据类型占用的字节数如下表所示: arch char short int long ptr ......
linux/arch/i386/boot/compressed/head.S
在setup()结束后,此函数就被移动到物理地址0x00100000处或者0x00001000处,这取决于内核映像是被高装载到ram中还是低装载到ram中。
解读函数:
startup_32:
cld
cli
&n ......