Chinaunix首页 | 论坛 | 博客
  • 博客访问: 177464
  • 博文数量: 30
  • 博客积分: 2010
  • 博客等级: 大尉
  • 技术积分: 440
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-23 19:45
文章分类

全部博文(30)

文章存档

2016年(2)

2010年(3)

2009年(8)

2008年(17)

我的朋友

分类: LINUX

2008-10-21 20:49:41

进程是一个抽象的概念,在内核中用task_struct结构体来描述它,内核定义如下:
struct task_struct {
        volatile long state;    /* -1 unrunnable, 0 runnable, >0 stopped */
                                    /*进程状态*/

        unsigned int flags;     /* per process flags, defined below */
        unsigned int ptrace;  /*表示进程是否被跟踪*/

......................................

        int prio, static_prio, normal_prio;//进程优先级
        struct list_head run_list;  //运行队列,如果进程是运行状态将链入此队列
......................................

        unsigned int policy;  //进程的调度策略

        unsigned int time_slice;  //进程的时间片

......................................
        struct list_head tasks;  //所有进程均被链接到这个链表中
 
        struct mm_struct *mm, *active_mm; //指向内存区描述符的指针

/* task state */
//下面是进程的状态,比如退出状态,进程pid等
        struct linux_binfmt *binfmt;
        int exit_state;
        int exit_code, exit_signal;
        int pdeath_signal;  /*  The signal sent when the parent dies  */

        unsigned int personality;
        unsigned did_exec:1;
        pid_t pid;
        pid_t tgid;

...............................
        /*
         * pointers to (original) parent process, youngest child, younger sibling,
         * older sibling, respectively.  (p->father can be replaced with
         * p->parent->pid)
         */
          //real_parent指向创建了它的进程,如果他的父进程不存在了,就指向init的描述符
        struct task_struct *real_parent; /* real parent process (when being debugged) */
                       //parent指向当前的父进程
        struct task_struct *parent;     /* parent process */
                      //children是子进程的链表, sibling是兄弟进程的链表
        struct list_head children;      /* list of my children */
        struct list_head sibling;       /* linkage in my parent's children list */
                        //group_leader线程组的描述符
        struct task_struct *group_leader;       /* threadgroup leader */


        struct list_head thread_group;

          unsigned int rt_priority; //实时进程特有的,用于实时进程间的选择
     
   /* filesystem information */
        struct fs_struct *fs;//文件系统指针,描述了此进程所在的位置
/* open file information */
        struct files_struct *files; //文件表结构,描述了进程所打开的所有文件

};
进程描述符task_struct中的字段多而且复杂,在这里只是列出了部分字段,简单的解释了部分字段。想知道更详细的可以看这里http://blog.chinaunix.net/u/6071/showart.php?id=193614
知道了进程在内核中是怎样描述的以后,那么我们接下来看看如果内核创建了一个进程,那么这个task_struct怎在内核存在的。看下面的图:

 
内核在创建每个进程时都为其创建了这样一个结构,此结构定义如下:
1443 union thread_union {                                                                                                                                   
1444         struct thread_info thread_info;
1445         unsigned long stack[THREAD_SIZE/sizeof(long)];
1446 };
这是一个联合结构,其中定义了一个栈stack其大小为两个页大小,也就是8KB。另外一个结构如下定义:
 struct thread_info {
...............
       struct task_struct      *task;          /* main task structure */
   
...................
 30 };
在这个结构中包含了task_struct结构的指针。
也许你会纳闷内核为了创建一个进程结构,竟然这样费劲。这里自有他的道理。
首先来看看这个栈,为何创建这个栈了?进程运行有两种方式,一种是用户态,另一种是内核态。当由于某种原因如中断等,进程从用户态下转到内核态时就得保存用户态下的一些东西,比如用户数据段,代码段,用户栈等等,这样内核就不必专门开出一片内存区域来存放这些东西了,每个进程自身带一个栈就好了。栈的大小可以变化,早些的内核版本是一共共享一个页面,也就是4KB大小的内存区。
进程描述符保存在8KB内存区的起始,而栈从末端向下增长,
esp寄存器是CPU栈指针,用来存放栈顶单元。内核使用alloc_thread_info()和free_thread_info()宏来分配大小为两个页面大小的thread_info结构和内核栈的内存区。

将内核态堆栈与thread_info结构紧密结合在一起的另一一个重要好处就是可以提高效率,如何提高?通过指针esp,内核将很容易找到当前在CPU上运行的进程的thread_info结构的地址了。如果thread_info结构长度是8KB(2的13次方),那么内核只需屏蔽掉esp的低13位地址就可以获得thread_info的地址了。如果其长度是4KB,则屏蔽12位。这些操作由current_thread_info()函数完成,其主要指令是与操作。
表示当前进程的current宏就是利用这个函数,实现如下:
 #define current (current_thread_info()->task)

 
阅读(1938) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~