Chinaunix首页 | 论坛 | 博客
  • 博客访问: 658002
  • 博文数量: 185
  • 博客积分: 1875
  • 博客等级: 上尉
  • 技术积分: 2107
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-23 23:21
个人简介

有时候,就是想窥视一下不知道的东东,因为好奇!

文章分类

全部博文(185)

文章存档

2024年(1)

2023年(3)

2020年(1)

2019年(1)

2018年(1)

2017年(2)

2016年(69)

2015年(53)

2014年(14)

2013年(1)

2012年(5)

2011年(25)

2010年(9)

分类: LINUX

2016-08-29 22:58:11

内核资料收集

1. 进程/轻量级进程/线程
      一般可认为,进程是程序执行时的一个实例,从内核角度看,进程是分配系统资源(cpu时间,内存等)的实体。
    进程创建时,几乎与父进程相同。他接收父进程的地址空间的一个副本,并从进程创建系统调用的下一条指令开始
    执行与父进程相同的代码。虽然父子进程共享含有程序代码的页,但他们有各自独立的数据拷贝。因此父子进程各
    自对自己的内存单元的修改时,对对方都是不可见的。
           线程可认为是一个独立执行流,可与其它执行流共享大部分的数据结构。一个进程可以拥有多个这样的执行流
    linux用轻量级进程(lightweight process)实现对多线程应用提供支持。linux通过把轻量级进程与每个线程关联,这样
     线程之间可以通过简单地共享地址空间,打开文件集等,以访问相同的的应用程序数据,同时每个线程由内核独立
     调度,以便一个睡眠的同时另一个仍然可以运行。

2.进程描述符
     进程描述符包含了一个进程的所有信息。下图示意性描述了linux的进程描述符task_struct。

2.1 标识一个进程
        每个能被独立调度的执行上下文,都必须拥有自己独立的进程描述符。即使共享大部分数据结构的轻量级进程,也有自己的
    task_struct结构。进程和进程描述符之间有严格的一一对应关系。内核对进程的大部分引用,是通过进程描述符指针进行的。
        类unix操作系统用进程标识符processID(PID)标识进程。PID被顺序编号。默认的PID上限是32767;系统管理员可以设置一
    个更小的值来减小PID上限值。内核通过pidmap-array位图管理PID。一个页框包含4096x8=32768个位,所以32位体系结构中
    的pidmap-array位图可以放在一个单独的页中。在64位系统中需要使用更多的页管理PID位图。

2.3 线程相关    
        linux引入线程组的表示。一个线程组中的所有线程,使用该线程组的领头线程相同的PID。PID存入到进程描述符的tgid字段。getpid()返回的是当前进程的tgid而不是pid的值
2.4 进程描述符的处理
         linux把内核态的进程堆栈,及紧挨进程描述符的thread_info(叫做线程描述符)紧凑的存放在一个单独为进程分配的存储区域内;
    这块存储区域的大小通常是8192字节(两个页框)。考虑效率因素,内核让这8KB空间占据连续的两个页框,并让第一个页框的地址是
    2^13的倍数。下图,线程描述符驻留于这个内存区的开始,而栈从末端向下增长。thread_info结构与task_struct结构通过task和
    thread_info字段互相关联。
        
        在80x86系统中,栈起始于末端,并朝内存区开始的方向增长。从用户态进入内核态后,进程的内核栈总是空的,即栈指针esp
    指向栈顶。数据入栈,esp递减。thread_info结构52字节长,因此内核栈能扩展到8192-52=8140字节。
            union_thread_union {
                struct thread_info thread_info;
                unsigned long stack[2048];        //对4K的栈数组下标是1024
            }
        内核使用alloc_thread_info和free_thread_info宏分配和释放存储thread_info结构和内核栈的内存区。
    
2.5 标识当前进程
        thread_info结构与内核态堆栈之间的紧密结合提供的主要好处是:内核很容易从当前内核栈指针(80x86上是esp)取得当前运行的
    进程的thread_info结构地址。如果thread_union结构长度是8K(2^13), 则esp的低13位清零就可得到thread_info结构的基地址。
    current_thread_info()函数做此工作。
        内核调用current宏获得当前CPU上运行进程的描述符指针,其本质上等价于current_thread_info()->task。进一步,进程的其它
    数据都可以得到。早先的linux内核通过引入全局静态变量current来标识正在运行进程的描述符。

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