出看linux内核,问题请教

love514425 2008-09-30 10:23:46

// 为新进程取得不重复的进程号last_pid,并返回在任务数组中的任务号(数组index)。
int
find_empty_process (void)
{
int i;

repeat:
if ((++last_pid) < 0)
last_pid = 1;
for (i = 0; i < NR_TASKS; i++)
if (task[i] && task[i]->pid == last_pid)
goto repeat;
for (i = 1; i < NR_TASKS; i++) // 任务0 排除在外。
if (!task[i])
return i;
return -EAGAIN;
}
]
last_pid 在上面定义为0,也就是0号进程(祖先进程)岂不会永远的去执行goto语句,那下面的for循环就不会执行了?
...全文
144 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
elauman 2008-10-04
  • 打赏
  • 举报
回复
逻辑关系正确:
task[i] = NULL;//空闲

task[i] != NULL;//非空闲
xlanchen 2008-10-02
  • 打赏
  • 举报
回复
无语!!

楼主,仔细想想

if 什么时候条件为真?

if(!task[i]),理解为,若task[i]没有被占用

if(task[i]),理解为,若task[i]被占用
love514425 2008-10-01
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 xlanchen 的回复:]
呵呵,这个指针,被用了,就是非空闲的,此时指针值非NULL,(注意,NULL一般被定义为0)
没有被用,就是空闲的,也就是这个指针的值为NULL,即0

它是否被使用,是随着进程的创建和撤销发生变化的
你看的这个函数本身不会使用它,因此不会改变它的状态,而仅仅是判断它的状态

!task[i],仅仅是一种判断的方法而已

做个比喻,就好像,服务员给一个杯子加水,而顾客会从杯子中喝水,加水或者喝水,都会导致杯子的状…
[/Quote]
首先非常感谢你的回复!
但你说的不恰恰矛盾么?
被用了,就是非空闲的,此时指针值非NULL
那么找一个空闲的指针一个是
if(task[i])才对.
而不是 if(!task[i]) 啊
xlanchen 2008-10-01
  • 打赏
  • 举报
回复
呵呵,这个指针,被用了,就是非空闲的,此时指针值非NULL,(注意,NULL一般被定义为0)
没有被用,就是空闲的,也就是这个指针的值为NULL,即0

它是否被使用,是随着进程的创建和撤销发生变化的
你看的这个函数本身不会使用它,因此不会改变它的状态,而仅仅是判断它的状态

!task[i],仅仅是一种判断的方法而已

做个比喻,就好像,服务员给一个杯子加水,而顾客会从杯子中喝水,加水或者喝水,都会导致杯子的状态发生变化
此时,大堂经理过来看看杯子的状态,是空还是非空,但他既不加水也不喝水,不会导致杯子的状态发生变化

这个函数就像一个大堂经理一样,仅仅用来检查指针是否被占用,呵呵,

不知道说清楚没有呢
xlanchen 2008-10-01
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 love514425 的回复:]

if (!task[i])        //用来找到第一个空闲的指针
return i;
return -EAGAIN;  //失败的情况,即没有空闲的task指针
}

这个if(!task[i])是什么意思,不为空??? 还是?
[/Quote]

在Linux0.11中,最多允许同时有64个进程存在,参见如下定义:

struct task_struct * task[NR_TASKS] = {&(init_task.task), };

其中,
#define NR_TASKS 64

task指针数组用来记录当前系统中有哪些进程。当一个新进程被创建的时候,
就要从这个数组中找到一个空闲的指针,来指向这个新进程

随着进程的创建和撤销,这个指针数组中的指针会不断发生变化,有的空闲,有的非空闲

因此需要通过遍历的方法,在这个指针数据中寻找空闲指针

关于“if(!task[i])”这纯粹是C语言,
if中条件的值为0,则false,否则true
task[i]为NULL时,!task[i]就非0,则true,也就是这个task指针是空闲的,返回索引号i
否则false,寻找下一个task指针
love514425 2008-10-01
  • 打赏
  • 举报
回复
关于“if(!task[i])”这纯粹是C语言,
if中条件的值为0,则false,否则true
task[i]为NULL时,!task[i]就非0,则true,也就是这个task指针是空闲的,返回索引号i
否则false,寻找下一个task指针
=====================================
还有一个问题, 为什么在 !task[i] 下才是空闲的呢?
帅得不敢出门 2008-10-01
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 love514425 的回复:]
嗯,感谢LS的.
大致明白了.

if (!task[i]) //用来找到第一个空闲的指针
return i;
return -EAGAIN; //失败的情况,即没有空闲的task指针
}

这个if(!task[i])是什么意思,不为空??? 还是?
[/Quote]
空闲
love514425 2008-10-01
  • 打赏
  • 举报
回复
非常感谢LS的!
love514425 2008-10-01
  • 打赏
  • 举报
回复
嗯,感谢LS的.
大致明白了.

if (!task[i]) //用来找到第一个空闲的指针
return i;
return -EAGAIN; //失败的情况,即没有空闲的task指针
}

这个if(!task[i])是什么意思,不为空??? 还是?
xlanchen 2008-09-30
  • 打赏
  • 举报
回复
这段代码在系统调用fork()中用到。fork()对应的内部例程为sys_fork,在system_call.s中定义,如下:

_sys_fork:
call _find_empty_process
testl %eax,%eax
js 1f
push %gs
pushl %esi
pushl %edi
pushl %ebp
pushl %eax
call _copy_process
addl $20,%esp
1: ret

其中,find_empty_process用来找到一个空闲的pid和一个空闲的task[i],定义如下:

int find_empty_process(void)
{
int i;

repeat:
if ((++last_pid)<0) last_pid=1; //若pid已经越界,则从1开始循环寻找
for(i=0 ; i<NR_TASKS ; i++)
if (task[i] && task[i]->pid == last_pid) goto repeat; // 用来判断,pid是否被使用了,若被使用了则要寻找下一个
for(i=1 ; i<NR_TASKS ; i++)
if (!task[i]) //用来找到第一个空闲的指针
return i;
return -EAGAIN; //失败的情况,即没有空闲的task指针
}

其中,last_pid用来找到从当前last_pid开始,在所有有效task中都没有用过的空闲的pid号
而,i用来定位task数组中,第一个空闲的task指针

其中,pid为0的,一定是0号进程,所以在寻找可用pid的时候不必考虑0
而task数组中,第一个也一定是用作0号进程的,所以在寻找第一个可用的空闲task指针的时候也不必考虑i=0的情况。
love514425 2008-09-30
  • 打赏
  • 举报
回复
是的.
linux早期的版本!
brookmill 2008-09-30
  • 打赏
  • 举报
回复
这是内核的代码么?
感觉逻辑有点怪怪的
love514425 2008-09-30
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 brookmill 的回复:]

if ((++last_pid) < 0)
// ++last_pid
[/Quote]
但我这的内核代码并没有 ++last_pid
0.11版本
brookmill 2008-09-30
  • 打赏
  • 举报
回复

if ((++last_pid) < 0)
// ++last_pid
Linux内核一直是学习的难点:将近3000万行代码,5万多个源文件,代码庞大繁杂、代码很难看懂。《Linux内核编程》将突破以往传统的学习方式,采取更有效和科学的学习方法,多角度地对内核进行多层次分析,不局限于形式,不拘泥细节,目的只有一个:更轻松、更高效地去理解内核、学习内核。为了更好地让学员掌握内核编程技能,更好地理解内核,本课程将采用并不局限于以下学习方法进行课程的录制:降维分析,化简为繁,将复杂的系统简单化用软件工程的方法分析内核:软件分层、模块化分解、框架迭代多角度立体分析Linux内核,目的只有一个:更好地理解内核利用Linux内核中的面向对象编程思想去分析复杂的子系统、子系统交互利用多任务编程的思想去分析Linux内核本套课程预计分为20个左右的小模块,每个模块一个专题,每个专题会陆续发布。拟录制的模块包括但不限于:模块机制、内核裁剪与配置、内核编译与启动、系统调用、中断、文件系统、调度、内存管理、内核同步、设备模型、字符驱动、块驱动、定时器、input、platform设备驱动、device tree、proc、sysfs、I/O...  本课程是《Linux内核编程》的入门篇,主要给大家介绍一下Linux内核开发、Linux驱动开发的就业行情、行业生态、需要掌握哪些技能、Linux内核的学习方法、如何搭建Linux内核的学习开发环境。 

4,441

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 内核源代码研究区
社区管理员
  • 内核源代码研究区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧