Linux源代码注释文档格式.docx

上传人:b****5 文档编号:18595614 上传时间:2022-12-29 格式:DOCX 页数:17 大小:28.80KB
下载 相关 举报
Linux源代码注释文档格式.docx_第1页
第1页 / 共17页
Linux源代码注释文档格式.docx_第2页
第2页 / 共17页
Linux源代码注释文档格式.docx_第3页
第3页 / 共17页
Linux源代码注释文档格式.docx_第4页
第4页 / 共17页
Linux源代码注释文档格式.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

Linux源代码注释文档格式.docx

《Linux源代码注释文档格式.docx》由会员分享,可在线阅读,更多相关《Linux源代码注释文档格式.docx(17页珍藏版)》请在冰豆网上搜索。

Linux源代码注释文档格式.docx

在计算机内部所有的正在运行的进程都在等待被CPU执行,操作系统按一定的规律让所有的进程都得到CPU的执行.方法是一会儿让QQ进程执行,过了一定时间后又让MP3播放器进程得到CPU的执行,再过一定时间后让浏览器进程得到CPU的执行.相对于人的反应,CPU的执行速度太快,所以人根本感觉不到这些进程的切换过程,也不会对人的操作产生影响

现在的问题是操作系统是按照什么样的规律给个各进程分配CPU资源的.操作系统是按照个各进程的属性来分配CPU资源的.那进程的属性在什么呢?

当操作系统创建一个进程时都就为这个进程分配了一定的内存空间来存放它的属性.在Linux操作系统中,操作系统定义了一个数据结构task_struct来描述各个进程的进程属性,task_struct结构叫进程控制块(PCB),它是操作系统中重要的数据结构之一.具体定义在/include/linux/sched.h中,注意在Linux操作系统中所有的操作系统源代码都在/usr/src目录下.

task_struct结构的代码如下所示:

(这里以2.40内核为准,可能不同版本的内核代码会有一点点的不同)

(为了保持简洁,从宏关上把握,不拘泥于具体,这里只说一部分,其它的以后会讲到,这里只说功能)

____________________________________________________/include/linux/sched.h

structtask_struct{

volatilelongstate;

/*进程的状态,在代码后面有说明*/

unsignedlongflags;

/*进程标志*/

intsigpending;

mm_segment_taddr_limit;

/*线性地址空间:

0-0xBFFFFFFF为用户线性空间地址;

0-0xFFFFFFFF为内核线性空间地址*/

structexec_domain*exec_domain;

volatilelongneed_resched;

unsignedlongptrace;

intlock_depth;

longcounter;

/*进程的动态优先级,在代码后面有说明*/

longnice;

/*进程的静态优先级,在代码后面有说明*/

unsignedlongpolicy;

/*进程采用的调度策略,在代码后面有说明*/

structmm_struct*mm;

/*进程属性中指向内存管理的数据结构mm_structd的

指针,在代码后面有说明*/

inthas_cpu,processor;

unsignedlongcpus_allowed;

structlist_headrun_list;

unsignedlongsleep_time;

structtask_struct*next_task,*prev_task;

/*所以进程通过这两个指针组成

一个双向链表*/

structmm_struct*active_mm;

/*指向活动地址空间,在后面的代码有说明*/

/*taskstate*/

structlinux_binfmt*binfmt;

intexit_code,exit_signal;

intpdeath_signal;

unsignedlongpersonality;

intdid_exec:

1;

intdumpable:

pid_tpid;

/*进程标志符,,在代码后面有说明*/

pid_tpgrp;

/*进程组标号,,在代码后面有说明*/

pid_ttty_old_pgrp;

pid_tsession;

pid_ttgid;

intleader;

structtask_struct*p_opptr,*p_pptr,*p_cptr,*p_ysptr,*p_osptr;

/*这五个标志表示一个进程的在计算机中的亲属关系,

分别标志祖先进程,父进程,子进程,弟进程和兄进程,

为了在两个进程之间共享方便而设立*/

structlist_headthread_group;

structtask_struct*pidhist_next;

structtask_struct*pidhist_pprev;

/*上面两个指针是为了在计算机中快速查

一个进程而设立,具体方式以后讲*/

wait_queue_head_twait_chldexit;

structcompletion*vfork_sem;

unsignedlongrt_priority;

/*实时进程的优先级标志*/

unsignedlongit_real_value,it_prof_value,it_virt_value;

unsignedlongit_real_incr,it_prof_incr,it_virt_incr;

structtimer_listreal_timer;

structtmstimes;

structtmsgroup_times;

unsignedlongstart_time;

longper_cpu_utime[NR_CPUS],per_cpu_stime[NR_CPUS];

unsignedlongmin_flt,maj_flt,nswap,cmin_flt,cmaj_flt,cnswap;

intswappable:

uid_tuid,euid,suid,fsuid;

gid_tgid,egid,sgid,fsgid;

intngroups;

gid_tgroups[NGROUPS];

kernel_cap_tcap_effective,cap_inheritable,cap_permitted;

intkeep_capabilities:

structuser_struct*user;

structrlimitrlim[RLIM_NLIMITS];

unsignedshortused_math;

charcomm[16];

intlink_count;

structtty_struct*tty;

/*NULLifnotty*/

unsignedintlocks;

/*Howmanyfilelocksarebeingheld*/

structsem_undo*semundo;

structsem_queue*semsleeping;

structthread_structthread;

structfs_struct*fs;

/*进程属性中指向和文件管理有关的数据结构*/

structfiles_struct*files;

spinlock_tsigmask_lock;

structsignal_struct*sig;

sigset_tblocked;

structsigpendingpending;

unsignedlongsas_ss_sp;

size_tsas_ss_size;

int(*notifier)(void*priv);

void*notifier_data;

sigset_t*notifier_mask;

u32parent_exec_id;

u32self_exec_id;

spinlock_talloc_lock;

spinlock_tswitch_lock;

};

程序说明如下:

volatilelongstate定义了进程的状态,进程总共有6种状态标志,分别是:

一.TASK_RUNING.(正在运行状态或者是可运行状态)

二.TASK_INTERRUPTIBLE,(可打断睡眠状态)

三.TASK_UNINTERRUPTIBLE,(不可打断睡眠状态)

四.TASK_ZOMBLE.(僵死状态)

五.TAKS_STOPPED.(暂停状态)

六.交换状态.

这六种属性标志了此进程现在的状态,各种不同的状态决定了进程什么时候获得CPU而被执行.

正在运行状态是当前正在运行进程的状态.也就是说他的volatilelongstate被标志成TASK_RUANING.

可运行状态是那些正在等待CPU资源的进程的状态,这些进程在就绪队列run-queqe中.这些进程只要得到CPU在个资源就马上可以被运行.其也被标志也为TASK_RUANING.

可打断睡眠状态是哪些在等待队列中等待除CPU之外的其它资源的进程,只要它们所等待的资源到达就马上可以从等待队列进入就绪队列,其状态标志也

从TASK_INTERRUPTIBLE状态变成TASK_RUANING可运行状态.

不可打断睡眠状态和可睡眠状态类似,区别在于前者可以用信号唤醒,而后者不可以.

僵死状态是标志那些已经运行完毕释放了大部分资源并退出但还没有释放进程控制快task_struct的进程.

暂停状态是那些遇到突发情况或者收到暂停信号而暂时停止运行的进程的状态.

counter是进程的动态优先级,它定义了一个在就绪队列的进程当它得到CPU后可运行的时间,用静态优先级初始化,当然计算机是以时钟中断做为时间的计数器,每发送一个时钟中断,动态优先级上的时间片就减少一个时钟中断的时间,时间片减到0的时候就退出该进程而调度另一个进程获得CPU.

nice是进程的静态优先级,当一个在就绪队列中的进程获得CPU之后,它被赋予此进程可占有CPU的时间.这个时间被称为时间片.

policy是进程的调度策略标志.有三种调度标志:

SCHED_OTHER普通进程的调度策略,基于优先权的轮转法.

SCHED_FIFO实时进程的调度策略,基于先进先出的算法.

SCHED_RR实时进程的调度策略,基于优先权的轮转法.

在linux中有两种进程,一种是普通进程,一种的实时进程,实时进程的优先级总是高于普通进程,也就是说当就绪队列中即有实时进程也有普通进程时,总是先运行实时进程.不同的进程采用不同的调度策略.

rt_priority实时进程的优先级.

need_resched标志下一次有调度机会的时候是否调用此进程.如果此进程没有没有被用户关闭或者其代码全被执行完了,在下一次调度机会应该还被调用.如果被用户关闭则直接退出该进程.

mm_struct*mmmm_struct数据结构是描述内存存储信息的数据结构,进程控制块task_struct中用mm指针指想mm_struct数据结构.也就是在进程的属性中通过mm指针来管理起对应的内存区.

mm_struct*active_active内核线程用来指向调用它的普通进程的内存地址空间.当普通进程在运行时如果发生系统调用,程序就会从用户态转为内核态,内核态中执行的是内核线程,内核线程没有内存空间地址结构mm_struct,当他需要内存空间地址的时候就会调用用户态对应进程的用以空间地址结构mm_struct.内核线程就是就是通过active_mm指针来指向用户态进程的mm_struct结构.

pid_tpidpid是进程标志符,操作系统每创建一个新的进程就要为这个新进程分配一个进程控制快(PCB),那么系统内核是怎样区分这些进程的呢?

就是通过进程标志符pid,系统在为新的进程分配进程控制块的候,它不是自己去创建,而是直接从上一个进程中复制它的进程控制块,其中里面的大部分东西保留下来,只做少量的改动,然后它的进程标志符加1赋值给新的进程控制块.

进程控制块的总共有80多项,在这里就不一一介绍了,以后我们在学习过程用到什么属性就介绍什么属性,这样在宏观上把握,不至于被一个小小的进程控制块给挡住了.

接着上面的进程说明,

前面我们说了一下进程的基本概念和它的属性,接下来我们介绍一下在操作系统内部是怎样通过调度函数调度进程的.

我们在使用计算机的时候,可能同时打开了很多程序,比如同时打开IE浏览器,QQ,word文档等,那么这就意味着内核要同时管理多个用户进程.这些进程中每个进程每隔一段时间就要被CPU执行一次,所有的进程都是这样轮流执行,在Linux操作系统中一个进程占有CPU的时间为50ms(也就是5个时间滴答,关于时间滴答的概念后面介绍),这个时间对于人的反应来讲是相当快的,所以人更不感觉不到进程的调度和切换,各个进程也有轻重缓急之分,后面还会说一个goodness函数,这个函数比较简单,主要作用是综合进程属性(进程控制快)

中的各种因素和数据算出每个进程的权值,权值最大的进程就是调度程序(schedule())最应该调用的进程.

在计算机中进程以六种状态存在,这在进程的属性里已经有了介绍,其中存在于就绪队列TASK_RUNNING中处于运行状态的进程是等待计算机中唯一的资源CPU的进程,它们只要一得到CPU就马上可以被执行,那么操作系统是安什么样的规则来让这些进程合理和公平的得到CPU的呢,这就要用到计算机的调度函数schedule(),

_____________________________________________________________/kernel/sched.c

asmlinkagevoidschedule(void)

{

structschedule_data*sched_data;

structtask_struct*prev,*next,*p;

structlist_struct*tmp;

intthis_cpu,c;

if(!

current->

active_mm)BUG();

/*current指当前进程,当前进程所指的内存空间

如果为空,那么进程必定有问题,出错返回*/

need_resched_back:

prev=current;

this_cpu=prev->

processor;

if(in_interrupt())

gotoscheduling_in_interrupt;

/*上面代码的意思是:

将局部变量prev和this_cpu初始化为当前进程和当前

CPU.然后检查schedule()是否中断调用,若是则直接返回,其中goto后面的

转到的地方在本程序中有定义,比如本进程后面的scheduling_in_interrupt在本程序

的最后有定义,意思是:

打印出”Schedulingininterrupt”字符后退出*/

release_kernel_lock(prev,this_cpu);

if(softirq_active(this_cpu)&

softirq_mask(this_cpu))

gotohandle_softirq;

/*检查是否有软中断请求,软中断softirq将在后

面讲解*/

hand_softirp_back:

sched_data=&

aligned_data[this_cpu].schedule_data;

spin_lock_irp(&

runqueue_lock);

/*局部变量sched_data中保存当前进程的数据区,*/

if(prev->

policy==SCHED_RR)

gotomove_rr_last;

*当前基于优先权轮转法的调度策略实时进程,如果要调用它,先检查其count

是否0若是,则将其挂到运行队列的最后面.具体做法在后面的move_rr_last

中有定义*/

move_rr_back:

switch(prev->

state)

caseTESK_INTERRUPTIBLE:

if(sign_pending(prev))

prev->

state=TASK_RUNNING;

break;

}

default:

del_form_runqueue(prev);

caseTASK_RUNNING;

need_resched=0;

/*上面这段代码意思是:

如果进程的状态为可中断睡眠状态且唤醒它的信号正在迫近,

则将其置为可运行状态,如果状态为运行状态则忽略,如果状态除上述两种之外的其

它状态则直接删除.最后将neet_resched置为0,neet_resched置0意味着本能启

动调度函数shchedule();

*/

repeat_schedule:

next=idlt_task(this_cpu);

c=-1000;

state==TASK_RUNNING)

gotostill_running;

/*上面的代码中的c是优先级运算函数goodness的一个变量,优先级运算函数

goodness将是我们介绍的下一个函数,它的返回值是进程的权值,调度函数

判断绪队列中权值最大的进程就是最优先要被调用的进程.goodness的具体

算法看下一个函数.

上面代码的意思是:

将next设置为当前cpu的idlt_task.将当前优先级的变量

c赋值为-1000,其中-1000是goodness中最小的权值.然后判断当前进程是否

是可运行进程,若是则转到still_running处执行,still_running在本函数的后面

有解释.意思是:

将当前进程的goodness值赋予goodness优先级变量c并返回

still_running_back:

list_for_each(tmp,&

runqueue_head)

p=list_entry(tmp,structtask_struct,run_list);

if(can_schedule(p,this_cpu))

intweight=goodness(p,this_cpu,prev->

active_mm);

if(weight>

c)

c=weight,next=p;

/*上面代码的意思是:

遍历整个就绪队列,计算出每一个进程的goodness权值并且

与当前进程做比较,选择goodness权值最大的那个进程获得cpu资源.*/

c)

gotorecalculate;

如果当前goodness权值为0,则运行recalculate:

起代码在

后面有说明,意思是:

重新计算每一进程的优先权,最后转到repeat_schedule:

处执

行,repeat_schedule:

部分在前面已经有讲过,自己看有会过头去看一下吧*/

sched_data->

curr=next;

/*将当前进程信息保存到局部变量sched_data中*/

#ifdefCONFIG_SMP

next->

has_cpu=1;

processor=this_cpu;

/*意思为:

将调度数据区指针指向下一个要调度的进程并将当前进程的cpu设置为

下一个进程的当前cpu.*/

#endif

spin_unlock_irq(&

if(prev==next)

gotosame_processor;

如果当前运行的进程的goodness还是队列中所以进程中最高的,也就是

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 数学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1