@会网络的老鼠

涂飞平的博客空间

模拟多任务 [原]

12 年前 0

前段时间一直都在看Linux关于任务管理部分的内容,为了验证其中概念,所以做了这个小的示例程序,主要是模拟多个任务的运行和切换。
下面是源代码:

{
一个任务调度的模拟示范(模拟多线程/任务)
SundyTU 2005-06
}
program ScheduleTest;

{$APPTYPE CONSOLE}

uses
SysUtils, Windows, Messages;

type
TTaskRect = record
t_esp: integer;//当前任务的esp寄存器的备份
t_eip: integer;//当前任务的eip寄存器的备份
end;

const TaskNum = 4;
WaitCount = $7FFFFFFF;

var
task: array[0..3] of TTaskRect;
current: integer = 3;

function SetJmp(var p: TTaskRect): integer;
asm
mov dword ptr [p+0],esp
mov ecx,dword ptr [esp]
mov dword ptr [p+4],ecx
mov eax,0
end;

procedure LongJmp(var p: TTaskRect; code: integer);
asm
mov esp,dword ptr [p+0]
push ecx
mov ecx,dword ptr [p+4]
mov dword ptr [esp+4],ecx
pop ecx
mov eax,code
end;

procedure schedule();//调度的核心函数
var
prev, i: integer;
begin
prev := current;
current := current + 1;
if current = TaskNum then
begin
SetJmp(task[prev]);
current := 0;
LongJmp(task[current], 1);
end
else
begin
i := SetJmp(task[prev]);
if i 0 then exit;
if current >= 3 then
current := 0;
LongJmp(task[current], 1);
end;
end;

procedure wait();
var
index: integer;
begin
for index := WaitCount downto 0 do ;
end;

procedure Task0; //任务0
begin
writeln('Task0 is begin....');
while true do
begin
schedule();
writeln(' Task0 is Running...');
wait();
end;
end;

procedure Task1; //任务1
begin
writeln('Task1 is begin....');
while true do
begin
schedule();
writeln(' Task1 is Running...');
wait();
end;
end;

procedure Task2; //任务2
begin
writeln('Task2 is begin....');
while true do
begin
schedule();
writeln(' Task2 is Running...');
wait();
end;
end;

procedure Task_wait;
begin
while true do
begin
schedule();
writeln(' wait_for is Running...');
end;
end;

var
t_esp: integer;
begin
asm
mov t_esp,esp //取得当前栈顶地址
end;
task[0].t_esp := t_esp - 100; //这里使用一个栈的不同部分来模拟多个栈。
task[1].t_esp := t_esp - 200; //栈边界必须为4的倍数,因为栈的操作都是32位的
task[2].t_esp := t_esp - 320;
task[0].t_eip := integer(@Task0); //初始化各个任务的eip初始值(开始运行的地址)
task[1].t_eip := integer(@Task1);
task[2].t_eip := integer(@Task2);
schedule(); //开始调度
end.

由于这只是一个简单的测试,所以在setjmp函数中并没有备份当前环境下的ebp寄存器(其他的寄存器都没有保存!),所以这里的子任务都不允许使用内部变量!
运行时图片:
图片:schl.jpg
schl.jpg

编写评论