进程队列指针:
1) struc t task_struct* next_task, * prev_task
在Linux 中所有进程(以PCB 的形式)组成一个双向链表,
next_task和prev_task是链表的前后向指针。
2) struct task_struct* p_opptr, * p_pptr
struct task_struc t* p_cptr, * p_ysptr, * p_osptr
以上分别是指向该进程的原始父进程、父进程、子进程和新
老兄弟进程的指针。
3) struct task_struct* pidhash_next
struct task_struct** pidhash_pprev
用于链入进程hash表的前后指针。系统进程除了链入双
向链表外, 还被加到hash表中。
进程标识:
uid_t uid gid_t gid uid和gid分别是运行进程的用
户标识和用户组标识。
pid_t pid pid_t pgrp pid和pgrp分别是运行进程的
进程标识号和进程组标识号
时间数据成员:
long per_cpu_utime [ NR_CPUS ] per_cpu_stime
[ NR_CPUS]
per_cpu_utime 是用户态进程运行的时间, per_cpu_
stime是内核态进程运行的时间
进程创建时间unsigned long start_time
文件系统数据成员:
struct fs_struct* fs
fs保存了进程本身与VFS( 虚拟文件系统)的关系信息。
struct fs_struct
{
atom ic_t count;
rw lock_t lock;
int umask;
struct dentry* root, * pwd, * altroot;
struct vfsm ount* rootmnt, * pwdmnt, * altrootmnt;
}
其中root、rootm nt是根目录的dentry 和其mount点的vfsmount。
pwd、pwdmnt 是当前工作目录的dentry 和其mount 点的vfs..
mount。altroot、altrootmnt是保存根节点被替换之后原来根目标
的dentry和其mount点的vfsmount。
内存数据成员:
1) struct mm_struct* mm
在Linux 中, 采用按需分页的策略解决进程的内存需求。
task_struct的数据成员mm 指向关于存储管理的mm_truc t结
构。
2) struct mm_struct* active_mm
active_mm 指向活动地址空间。
3) mm_segm ent_t addr_ lim it
表示线程空间地址。
用户线程空间地址: 0..0xBFFFFFFF。
内核线程空间地址: 0..0xFFFFFFFF
4) spinlock_t alloc_ lock
用于申请空间时用的自旋锁。自旋锁的主要功能是临界区
保护。
页面管理:
1) int swappable: 1
进程占用的页面是否可换出。swappab le为1表示可换出。
2) unsigned long min_flt, maj_ flt
该进程累计minor缺页次数和major缺页次数。
3) unsigned long nswap
该进程累计换出页面数。
4) unsigned long swap_cnt
下一次循环最多可换出的页数。
以上这些便是我挑选的task_struct结构体中的一些重要的成员。
有了对进程的控制块PCB中的结构体描述表了解以后,我们还要明白一个概念,既然进程是一个程序的执行过程,那么程序又是怎么转化为进程的呢?
一般情况下Linux下C程序的生成可分为4个阶段:预编译、编译、汇编、链接。编译器gcc经过预编译、编译、汇编3个步骤将源程序文件转换为目标文件。如果程序有多个目标文件或者程序使用了库函数,编译器还要将所有的目标文件或所需要的库链接起来,最后形成可执行程序。当程序执行时,操作系统将可执行程序复制到内存中。一般程序转换为进程分一下几个步骤:
1>内核将程序读入内存,为程序分配内存空间
2>内核为该进程分配进程标识符(PID)和其他所需资源
3>内核为进程保存PID及相应的状态信息,吧进程放到运行队列中等待执行。程序转化为进程后就可以被操作系统的调度程序调度执行了。
还要明白一个概念:进程的内存映像
指内核在内存中如何存放可执行程序文件。在将程序转换为进程的过程中,操作系统将可执行程序由硬盘复制到内存中。
程序的内存映像一般布局为:从低地址到髙地址一次为:
代码段:即二进制机器代码,代码段是只读的,可被多个进程共享,如果一个进程创建了一个子进程,父子进程共享代码段,此外子进程还获得父进程数据段、堆、栈的复制。
数据段:存储已被初始化的变量,包括全局变量和已被初始化的静态变量。
未被初始化数据段:存储未被初始化的静态变量,它也被称为bss段。
堆:用于存放程序运行中动态分配的变量。
栈:用于函数调用,保存函数的返回地址、函数参数、函数内部定义的局部变量。
另外髙地址还存储了命令行参数和环境变量
可执行程序和内存映像的区别在于:可执行程序位于磁盘中而内存映像位于内存中,可执行程序没有堆栈,因为程序被加载到内存中才会分配堆栈,可执行程序虽然也有未初始化数据段但它并不被存储在位于硬盘中的可执行文件中,可执行程序是动态的、不变的,而内存映像随着程序的执行时在动态变化的,例如,数据段随着程序的执行要存储新的变量值,栈在函数调用时也是不断在变化的。