⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linux源代码的注释.txt

📁 Linux源代码的注释 。对于想研究的人来说很不错
💻 TXT
📖 第 1 页 / 共 3 页
字号:
{
case TESK_INTERRUPTIBLE: 
if(sign_pending(prev))
{
prev->state = TASK_RUNNING;
break;
}
default:
del_form_runqueue(prev);
case TASK_RUNNING; 
}
prev->need_resched=0;

/* 上面这段代码意思是: 如果进程的状态为可中断睡眠状态且唤醒它的信号正在迫近, 
则将其置为可运行状态,如果状态为运行状态则忽略,如果状态除上述两种之外的其
它状态则直接删除.最后将neet_resched置为0,neet_resched置0意味着本能启
动调度函数shchedule(); */

repeat_schedule:
next = idlt_task(this_cpu);
c = -1000;
if(prev->state == TASK_RUNNING)
goto still_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, struct task_struct, run_list);
if(can_schedule(p,this_cpu))
int weight = goodness(p,this_cpu,prev->active_mm);
if(weight>c)
c=weight,next=p;
}
/* 上面代码的意思是: 遍历整个就绪队列,计算出每一个进程的goodness权值并且
与当前进程做比较,选择goodness权值最大的那个进程获得cpu资源. */

if(! c)
goto recalculate;

/* 上面代码的意思是: 如果当前goodness权值为0,则运行recalculate:,起代码在
后面有说明,意思是:重新计算每一进程的优先权,最后转到repeat_schedule:处执
行,repeat_schedule:部分在前面已经有讲过,自己看有会过头去看一下吧 */

sched_data->curr = next; /* 将当前进程信息保存到局部变量sched_data中*/

#ifdef CONFIG_SMP
next->has_cpu = 1;
next->processor = this_cpu;
/* 意思为: 将调度数据区指针指向下一个要调度的进程并将当前进程的cpu设置为
下一个进程的当前cpu. */

#endif
spin_unlock_irq(&runqueue_lock);

if(prev == next)
goto same_processor;

/* 意思为: 如果当前运行的进程的goodness还是队列中所以进程中最高的,也就是
说下一个要调度的进程还是当前进程.那么只要重新得到cpu控制权返回
need_resched_back:处执行. */ 

#ifdef CONFIG_SMP
sched_data->last_schedule = get_cycles();
#endif
kstat.context_swtch ++;

prepare_to_switch()
{
struct mm_struct *mm = next->mm;
struct mm_struct *oldmm = prev->active_mm;
if(! mm)
{ 
if(next->active_mm) BUG();
next->active = oldmm;
atomic_inc(&old_mm->mm_count);
enter_lazy_tlb(oldmm,next,this_cpu);
} 
else
{
if(next->active_mm != mm) BUG();
switch_mm(oldmm, mm, next, this_cpu);
} 
if(! prev->mm)
{
prev->active_mm = NULL;
mmdrop(oldmm);
}
}
switch_to(prev,next,prev);
__scheduel_tail(prev);

/* 上面的代码是进行进程切换 */

/* 下面的代码是前面代码中goto要转到的地方 */
same_processor:
reacquire_kernel_lock(current);
if(current -> need_resched)
goto need_resched_back;

return;

recalculate:
{
struct task_struct *p;
spin_unlock_irq(&runqueue_lock);
read_lock(&tasklist_lock);
fot_each_task(p)
p->counter = (p->counter >>1) + NICE_TO_TICKS(p_nice);
read_unlock(&tasklist_lock);
spin_lock_irq(&runqueue_lock);
} 
goto repeat_schedule;

still_running:
c = goodness(prev, this_cpu, precv->active_mm);
next=prev;
goto still_running_back;

handle_softirq:
do_softirq();
goto handle_softirq_back;

move_rr_last:
if(! prev->counter)
{
prev->counter = NICE_TO_TICKS(prev_nice);
move_last_runqueue(prev);
} 
goto move_rr_back;

scheduling_in_interrupt:
printf(“Scheduling in interrupt n”);
BUG();
return(); 
}

在上面的我们说了进程调度程序schedule(),接着说一下上面的函数中用到的进程优先级的权值的运行函数googness();
这个函数的作用很简单,就是算出就绪队列中的进程的优先级,然后调度程序调度优先级最高的进程获得当前CPU,
计算机中进程分为两种,一为普通进程,它的优先级用进程控制块中的counter表示,二
为实时进程,实时进程的优先级用rt_priority表示,它在进程控制块中有定义,当就绪队列中同时存在两种进程的时候,实时进程总是先于普通进程运行,它的实现机制是实时进程的权值以1000做为基础值,也就是说实时进程的权值是1000加上它的进程优先级,而普通进程的优先级就是它的进程优先级.
整个函数比较简单,但却是操作系统内核最为频繁调用的函数之一,也直接关系到操作系统的性能.

此函数如下:

______________________________________________________________/kernel/sched.Linux联盟收集整理 
 c

static inline int goodness(struct task_struct * p, int this_cpu, 
struct mm_struct this_mm)
int weigth;
weight=-1;
/ * 定义函数返回的权值weight并进行初始化 */

/* 下面是普通进程的处理情况 */ 
if(p->****** & SCHED_YIELD)
{
goto out;
/ * 如果要放弃本次调度,则直接返回, 转到的out处在后面有定义 */ 

if(p->policy == SCHED_OTHER)
weight = p-> counter;
if(!weight)
goto out;
/* 函数是普通进程的情况,在这种情况下,进程的权值直接为本进程的剩余时间,如果
剩余时间不存在或为0,则直接返回 */

#ifdef CONFIG_SMP
if(p->processor == this_cpu)
weight += PROC_CHANGE_PENALTY;
#endif
if(p->mm == this_mm || !p->mm)
weight +=1;
weight +=20-p->nice;
goto out; 
}

/* 下面是实时进程的处理情况 */ 
weight = 1000 + p->re_priority;
/* 实时进程的权值至少为1000,也就说它的权值是它是基数1000加上实时进程
的优先级,其中实时进程的优先级用re_priority表示,re_priority在进程的属性
中有定义, 
out:
return weight;
/* 前面的代码中有调用 */
}
______________________________________________________________/kernel/sched.c

前面我们说了关于进程的概念,属性以及调度它的函数.接下来我们讲一下进程的创建,
进程创建就是当系统接收到一个要求创建进程的信号时,系统为新进程所做的一系列工作.比如当你在使用计算机上网的时候如果打开了QQ聊天的服务程序的话.当你点击QQ图标的时候,系统就接收到了一个创建QQ进程的信号,接下来系统就要做一系列的工作来完成这个过程,这就是我们下面要讲的内容: 基础创建.
创建进程的系统调用函数(系统调用是下一个要讲的内容)有三个,它们分别是:
sys_fork(), sys_clone(), sys_vfork().由它们三个函数来完成进程的创建,这三个函数都比较简单,它们只是都同时调用了一个函数do_fork(),由于前面三个函数都比较简单,我们在后面讲,我们先讲一下do_fork()函数,这才是创建进程的主体.它被前面三个函数调用.

______________________________________________________________/kernel/fork.c

int do_fork(unsigned long clone_flags, unsigned long stack_start,
struct pt_regs, unsigned long stack_size)
{
int retval = -ENOMEN;
struct task_struct *p;
DECLARE_MUTEX_LOCKED(sem);

if(clone_flags & CLONE_PID)
if(current->pid)
return -EPERM;

/* 上面这段代码的意思是: 如果clone_flags的CLONE_PID置位,则除非是0号进程
否则将返回错误信息EPERM. clone_flags的定义将在后面介绍,0号进程就是操作
系统启动时创建的第一个进程.上面的代码中if(current->pid)要成立,除非是0号
进程.其中pid是进程标志符 */

current->vfork_sem = &sem;

p=alloc_task_struct();
if(! p)
goto fork_out;

/ * 上面代码的意思是: 申请一个新的内存控制块,其中alloc_task_struct是在/include
/asm_i386/process.h中的宏定义: 
#define alloc_task_struct() ((struct task_struct * ) _get_free_pages
(GFP_KERNEL, 1))
其中_get_free_pages是要申请两个页面,页面是内存管理的有关内容,这儿大家只要
一个页面占4个字节就可以了.两个页面就是8个字节,而大家查一下进程控制块的大
小就可以知道它只有1600KB左右,有就时说它只有1M左右,那么还剩下将近6.5M
的空间去有什么用呢?其实剩余的空间是作为内核栈空间.至于内核栈的内容以后会
讲到,但是如果申请内存空间失败则直接栈道fork_out处执行,fork_out在后面有
定义 */

*p = * current;

/ * 代码意思: 前面申请了一个存放进程控制块的内存空间,接下创建新进程的进程

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -