Board logo

标题: task_struct [打印本页]

作者: yuyang911220    时间: 2017-5-10 10:50     标题: task_struct

task_struct是进程描述符。操作系统通过task_struct感知进程的存在。我学习内核的入口点就是该结构体。
现在就分析分析该结构体吧。
该结构体在内核中的位置:./include/Linux/sched.h
struct task_struct {
       volatile long state;
         这个字段来描述进程的状态。这儿有个关键词volatile可是
一个熟悉的陌生人。在学C的时候一直都见过,但不知道有什么作用,现在终于有个地方用到了。这个关键词是告诉编译器不要对其优化,编译器有一个缓存优化的习惯,比如说,第一次在内存取数,编译器发现后面还要用这个变量,于是把这个变量的值就放在寄存器中。这个关键词就是要求编译器不要优化,每次都让CPU去内存取数。以确保状态的变化能及时地反映上来。
     ---------------------------------------------------------------------------------------------------  
       struct list_head tasks;
   该字段用来把系统中的PCB通过双向循环链表链接起来。可以写了几种形式的内核模块来遍历这个链表。
     ----------------------------------------------------------------------------------------------------
     struct mm_struct *mm;
   这个字段比较重要,是进程的内存描述符。我在后面会有一个内核模块来打印进程的所有虚存区的起始和末尾地址。进程的虚存区有两组组织方式,一种是链表,一种是红黑树。我后面的程序用了链表的遍历和二叉树的先序方式遍历红黑树。
     ----------------------------------------------------------------------------------------------------
    int exit_code;
    当一个进程通过exit()结束进程后,会变成一个僵尸进程,
僵尸进程几乎释放了其他所有的资源,但PCB没有释放,其中PCB中的这个字段就是记录退出的退出码。
    -----------------------------------------------------------------------------------------------------
    pid_t pid;
    pid_t tgid;
       进程的标识信息,pid表示进程ID,tgid是便是线程组的ID,其实,我们调用getpid()这个系统调用的时候返回的是tgid
这样的目的是为了兼顾POSIX标准,为了兼顾POSIX标准,linux引入了线程组的概念。当进程中没有多线程时,这两个值一样,当有多个线程时,tgid记录主线程的id,pid记录各个线程自己独有的id,这样就可以保证进程中每个线程getpid()返回出来的值一样了。
在Linux系统中,一个线程组中的所有线程使用和该线程组的领头线程(该组中的第一个轻量级进程)相同的PID,并被存放在tgid成员中。只有线程组 的领头线程的pid成员才会被设置为与tgid相同的值。注意,getpid()系统调用返回的是当前进程的tgid值而不是pid值。   
------------------------------------------------------------------------------------------------------
         struct list_head thread_group;
         这个字段我实验过,就是在用户态写一个多线程的程序,然后通过该字段遍历线程组中所有线程的PCB,这个字段将一个进程(也就是一个线程组)中的所有线程的PCB通过链表链接起来。
用户态的的线程组中有三个线程,结果如下:
[  803.985895] pid = 2151,tgid = 2151,name = a.out
[  803.985904] pid = 2152,tgid = 2151,name = a.out
[  803.985909] pid = 2153,tgid = 2151,name = a.out
由此可以看出getpid返回出的是tgid而不是pid。
     --------------------------------------------------------------------------------------------------
         char comm[TASK_COMM_LEN];
           这个字段很简单,就是一个字符数组记录这个进程的名字。
     --------------------------------------------------------------------------------------------------




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0