Chinaunix首页 | 论坛 | 博客
  • 博客访问: 519766
  • 博文数量: 96
  • 博客积分: 2102
  • 博客等级: 上尉
  • 技术积分: 1695
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-11 22:12
文章分类

全部博文(96)

文章存档

2014年(2)

2012年(94)

分类: LINUX

2012-04-14 09:24:50

  在linux 内核中有一宏 : current (获取当前正在运行的进程)

linux 2.4.0

点击(此处)折叠或打开

  1. struct task_struct;

  2. static inline struct task_struct * get_current(void)

  3. {

  4. struct task_struct *current;

  5. __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL));

  6. return current;

  7. }

  8. #define current get_current()


  9. union task_union {

  10. struct task_struct task;

  11. unsigned long stack[INIT_TASK_SIZE/sizeof(long)];

  12. };
对于linux 2.6之前的内核采用的模式是:进程的PCB和进程的系统空间一块分配。对于linux2.4 来讲给进程分配系统空间和PCB用到的结构体是  union task_union .
如图:                    esp  ------------------------------ 高地址
                                    |               系统               |       
                                    |              空间                |
                                    |                                     |
                                    |                                     |
                                    | -----------------------------|
                                    |          task_struct          |
                        PCB     |------------------------------ 低地址
       
     进程的创建是在内核态的,在内核态需要用到栈和PCB ,为了方便管理将PCB和系统空间一块分配了两个连续的页面(8k),其中PCB大约为1K,进程的系统空间大约是7K。但是每次切换到内核态进程的系统栈都是空的。对于 struct task_union 分配空间都是8k的整数倍,因此在每个
struct task_union地址的后13位都是0 。因此一个进程的PCB的地址和该进程的系统的 esp 的地址除低13位都相等-------------->sp 可以移动的范围实在以PCB 为基址的条件下,以8K为跨度的偏移。
      因此可以将esp 和 0xffffffe0(地址为32位)的值进行相与,得到struct task_struct 的地址。
      因为对于系统的地址范围不缺定,因此内核使用
: (~8191UL)
   8191------>1 1111 1111 1111 B  
linux  2.6.0

点击(此处)折叠或打开

  1. struct thread_info {

  2.      struct task_struct *task;

  3.        struct exec_domain *exec_domain;

  4.          __u32 flags;

  5.      __u32 cpu;

  6.      mm_segment_t addr_limit;

  7.     __s32 preempt_count;

  8.     struct restart_block restart_block;

  9.  };



  10.   static inline struct thread_info *current_thread_info(void)

  11. {

  12.    register unsigned long sp asm ("sp");

  13.    return (struct thread_info *)(sp & ~0x1fff);

  14. }

  15. static inline struct task_struct * get_current(void)

  16. {

  17.    return current_thread_info()->task;

  18. }

  19. #define current get_current()
    从linux 2.6 开始之后内核代码有了很大的改版,因为进程的PCB中要存储的东西又增加了很多,由于进程的系统空加不能动态变化,因此是的进程的系统空间足够使用,将PCB中的一部分信息进行提取(thread_info)取代2.4内核的PCB,使得系统空间和thread_info 一块分配。
如图:                    esp  ------------------------------ 高地址
                                    |               系统               |       
                                    |              空间                |
                                    |                                     |
                                    |                                     |
                                    | -----------------------------|
                                    |          thread_info         |------------> -------------------------
                                    |------------------------------ 低地址      |        PCB               |
                                                                                            |                              |
                                                                                            --------------------------
同2.4内核一样先获得thread_info 的地址。(加粗下划线)然后根据thread_info 的结构体获得进程的pid的struct task_struct 地址。
注:0x1fff = 8191

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