Page 1 of 1

Creating process

Posted: Sun Nov 16, 2008 10:43 pm
by leledumbo
How to create a process? I've never seen any explanation on the Wiki for this. I already have a memory manager (both physical and virtual) but no file system yet (of course I already have a console, keyboard driver, ISRs, IRQs, and any other pre-requirements). Is that enough?

Re: Creating process

Posted: Sun Nov 16, 2008 11:06 pm
by Brendan
Hi,
leledumbo wrote:How to create a process? I've never seen any explanation on the Wiki for this. I already have a memory manager (both physical and virtual) but no file system yet (of course I already have a console, keyboard driver, ISRs, IRQs, and any other pre-requirements). Is that enough?
The general idea is to allocate a new virtual address space, create a structure or something describing the process (including which virtual address space and which EIP), and then tell the scheduler that the new process can be given CPU time. Then, when the scheduler gives the process some CPU time it'd start running some kernel code that gets the process ready (e.g. loads an executable file from disk, or sets up the anything else that's needed by the process). Then the kernel would "return" to the CPL=3 code (e.g. push CPL=3 values for EFLAGS, CS:EIP and SS:ESP on the stack and do an IRET).

There's lots of details missing in my quick description though, like whether the scheduler runs processes or threads, and if the virtual address space is cloned (e.g. "fork()" with copy on write) or entirely new, and which things the new process inherits from the parent process (file handles, stdin, stdout, file permissions, environment, root directory, working directory, signal handling, CPU affinity, scheduling priority, etc).


Cheers,

Brendan

Re: Creating process

Posted: Sun Nov 16, 2008 11:54 pm
by leledumbo
allocate a new virtual address space
OK, the virtual memory manager can do that.
create a structure or something describing the process (including which virtual address space and which EIP)
Well, that's not hard. I just need to know what info should be kept. Except for getting the EIP, I don't know how to do it. Something like:

Code: Select all

mov eax,eip
fails with eip being undefined.
tell the scheduler that the new process can be given CPU time
I guess this is where I really got lost. What is this scheduler? Is it a device or some other code?

Re: Creating process

Posted: Sun Nov 16, 2008 11:58 pm
by piranha
The scheduler is the code that decides which task to run next, and then maybe load the task.
For me, the scheduler saves the state of the old task, decide which task to run next, and then load the new task and jump to it.

Check this out: http://jamesmolloy.co.uk/tutorial_html/ ... sking.html

-JL

Re: Creating process

Posted: Mon Nov 17, 2008 12:15 am
by leledumbo
I'll (re)read that (I already have the copy actually #-o ).
Wow! So my OS is actually a combination of 3 tutorials: brendan, jamesmolloy, and brokenthorn. With a modification here and there plus my own craziness, of course 8) .

Re: Creating process

Posted: Mon Nov 17, 2008 4:34 am
by ru2aqare
leledumbo wrote:Except for getting the EIP, I don't know how to do it. Something like:

Code: Select all

mov eax,eip
fails with eip being undefined.
Use

Code: Select all

    db 0E8h, 00h, 00h ; call near $+3
    pop eax ; load address of this instruction into eax
or something similar. The eip/rip register is not accessible to the programmer, and can only be modified by control transfer instructions (near and far calls and near and far jumps).
leledumbo wrote: I guess this is where I really got lost. What is this scheduler? Is it a device or some other code?
It's an algorithm you have to implement. On each timer interrupt, it selects the next thread to run. There are many variations to it, starting from simple round-robin to complex ones like the one used by the NT kernel. Besides this, you have to make it run very fast - those algorithms are the best that have a running time independent of the count of active threads (in other words, they have O(1) execution time).

Re: Creating process

Posted: Mon Nov 17, 2008 11:19 pm
by leledumbo
Thanks. But your code gives me:
Image

Code: Select all

procedure DumpRegs;
var
  reg: LongWord;
begin
  asm
    mov reg,eax
  end;
  WriteStrLn('EAX = '#9+HexStr(reg,8));
  asm
    mov reg,ebx
  end;
  WriteStrLn('EBX = '#9+HexStr(reg,8));
  asm
    mov reg,ecx
  end;
  WriteStrLn('ECX = '#9+HexStr(reg,8));
  asm
    mov reg,edx
  end;
  WriteStrLn('EDX = '#9+HexStr(reg,8));
  asm
    mov reg,esi
  end;
  WriteStrLn('ESI = '#9+HexStr(reg,8));
  asm
    mov reg,edi
  end;
  WriteStrLn('EDI = '#9+HexStr(reg,8));
  asm
    mov reg,esp
  end;
  WriteStrLn('ESP = '#9+HexStr(reg,8));
  asm
    mov reg,ebp
  end;
  WriteStrLn('EBP = '#9+HexStr(reg,8));
  asm
    db  0E8h, 00h, 00h
    pop eax
    mov reg,eax
  end;
  WriteStrLn('EIP = '#9+HexStr(reg,8));
  asm
    mov reg,cs
  end;
  WriteStrLn('CS  = '#9+HexStr(reg,8));
  asm
    mov reg,ds
  end;
  WriteStrLn('DS  = '#9+HexStr(reg,8));
  asm
    mov reg,es
  end;
  WriteStrLn('ES  = '#9+HexStr(reg,8));
  asm
    mov reg,fs
  end;
  WriteStrLn('FS  = '#9+HexStr(reg,8));
  asm
    mov reg,gs
  end;
  WriteStrLn('GS  = '#9+HexStr(reg,8));
  asm
    mov reg,ss
  end;
  WriteStrLn('SS  = '#9+HexStr(reg,8));
end;
... starting from simple round-robin ...
What? Round robin is simple? Perhaps it's just my foolishness that I think of it as complicated (I got it in OS class). I just want to use FCFS, I don't care how bad, I just want to see that I can make it.

Re: Creating process

Posted: Tue Nov 18, 2008 4:07 am
by ru2aqare
leledumbo wrote:

Code: Select all

procedure DumpRegs;
...
Does your Pascal compiler preserve all registers across procedure calls? If not, your DumpRegs procedure is flawed - it will print incorrect values for some registers. A procedure like this would work regardless of your compiler preserving registers or not:

Code: Select all

Procedure DumpRegs2;
Var
  Reg : Array[16] of LongWord;
  SReg : Array[6] of Word;
  Eip : LongWord;
  EFlags : LongWord;
Begin
  Asm
    ; save registers while they are not modified by another procedure call. note that depending
    ; on your compiler settings, ebp may already be trashed (stack frame)
    mov dword ptr Reg[4*0],eax
    mov dword ptr Reg[4*1],ecx
    mov dword ptr Reg[4*2],edx
    mov dword ptr Reg[4*3],ebx
    mov dword ptr Reg[4*4],esp ; esp is already incorrect since it was decreased by the amount of stack space the local variables require
    mov eax, 16*4 + 6*2 + 4 + 4
    add dword ptr Reg[4*4], eax ; correct esp
    mov dword ptr Reg[4*5],ebp
    mov dword ptr Reg[4*6],esi
    mov dword ptr Reg[4*7],edi
    ; save segment registers
    mov word ptr SReg[2*0], ds
    mov word ptr SReg[2*1], es
    mov word ptr SReg[2*2], cs
    mov word ptr SReg[2*3], ss
    mov word ptr SReg[2*4], fs
    mov word ptr SReg[2*5], gs
    ; save eflags
    pushfd
    pop dword ptr EFlags
    ; now get eip.
    call $+3
    pop dword ptr Eip
  End;
  WriteLn('EAX = '#9 + HexStr(Reg[0],8));
  WriteLn('ECX = '#9 + HexStr(Reg[1],8));
  WriteLn('EDX = '#9 + HexStr(Reg[2],8));
  WriteLn('EBX = '#9 + HexStr(Reg[3],8));
  // etc.
End;
Note that the way you intend to get the instruction pointer is still incorrect - it will load the address of the instruction following the 'call $+3' instruction - which is probably not what you want.

Code: Select all

    mov eax, [esp+4 + size_of_local_variables] ; if no stack frames
    mov eax, [ebp+4] ; if stack frames are generated
would get the address where the DumpRegs procedure was called from - which may be inside your exception handler, and will still not supply you with the address where the actual exception occurred. To get that address, you have to save the return address inside your exception handler stub written in assembly.
What? Round robin is simple? Perhaps it's just my foolishness that I think of it as complicated (I got it in OS class). I just want to use FCFS, I don't care how bad, I just want to see that I can make it.
Actually, Round Robin is a preemptive version of First Come First Serve, if I remember my classes correctly; and as such, FCFS is suited for cooperative multitasking, where all applications voluntarily give up their time slice sooner or later. RR does not require cooperation from applications.

Edit: clarified difference between RR and FCFS.

Re: Creating process

Posted: Tue Nov 18, 2008 8:56 pm
by leledumbo
Ah... I didn't notice that. I use Free Pascal so the default calling convention would be Register. Since each WriteStrLn expects one argument, the value of EAX will be altered on each call. I should've known that. Everything works fine now, thanks.

P.S.: That's the way Oberon declare arrays, not Pascal :wink:

Re: Creating process

Posted: Wed Nov 19, 2008 4:25 am
by ru2aqare
leledumbo wrote:Everything works fine now, thanks.

P.S.: That's the way Oberon declare arrays, not Pascal :wink:
Okay, good to hear that. And it seems I have seriously forgotten how to Pascal. I have been using C for the last eight years or so.

Re: Creating process

Posted: Sun Dec 14, 2008 5:52 am
by djsilence
HI.

You know I've got the same problem with Jame's tutorial (e.g. pagefault on trying to create process). I was not able to find the solution, so I left that problem. Maybe someone know the solution?

Thanks!