system library how-to

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
com1
Member
Member
Posts: 105
Joined: Sat Apr 28, 2007 11:57 am
Location: TN

system library how-to

Post by com1 »

hey,


i would like to know how to write a system library, how to enable fork() and POSIX functions in the library, etc.
oh microsoft, microsoft, what souls you have dismayed
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post by AJ »

Hi,

First off, you will need kernel support functions.

Take fork() (which I believe copies the current task space but I've never programmed on linux). You will need some kind of function in your system call library which forks the current process. The actual user-space library then just calls this function. For example, in user-space:

Code: Select all

void fork()
{
    syscall(0x01);
}

syscall:
   pop eax
   int 0x30
ret
These functions are obviously not in the same source file. This assumes your kernel provides system services on int 0x30, for whatever reason.

Now, your kernel needs to handle int 0x30 with some kind of function lookup table. As you have called it with eax = 0x01, it will jump to handled function 1:

Code: Select all

int fn0x01()
{
    clonecurrentprocess();
    return(successvalue);
}
That's about the size of it for all system services you plan on providing. For an idea about what services OS's generally provide, have a look here, where you can see what services DOS and Windows provide and here for linux system calls.

HTH
Adam
com1
Member
Member
Posts: 105
Joined: Sat Apr 28, 2007 11:57 am
Location: TN

i actually...

Post by com1 »

I actually created an interrupt handler for fork() the system defines fork() pid_t as an interrupt at 0x80 then I wrote the interrupt handler for it when i use fork(), so the system library associates it with 0x80
oh microsoft, microsoft, what souls you have dismayed
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post by AJ »

Good - hope it all works. Just a couple of (small) points.

1. As you are likely to want several system calls, it is fairly usual to use EAX as a function selector. This means that INT 0x80 with EAX 0x02 may be fork, whereas INT 0x80 with EAX 0x01 may be exit process (as in Linux).

2. I have no idea of the ultimate goal of your OS, but if you ever plan on emulating Linux system calls, Linux uses int 0x80, so you may want to steer clean of that number. If you ever plan on other people writing code for your OS, it may be confusing for people porting Linux code that your int 0x80 function 0x10 is "Load Driver", whereas the Linux version is "unlink" (for the sake of argument).

Cheers,
Adam
TomTom
Posts: 23
Joined: Tue May 01, 2007 2:03 am
Location: USA

Post by TomTom »

or write yourself a tool/script that generates those call stubs automatically from a list of functions with the number of parameters. That script could then also automatically generate the system call table for the kernel. Using headers and a static library (or just compile it into the binary) would then enable you to simply do a fork(), or any other system call without having to think about system call numbers.

The downside is that all libraries/applications that use that static library need to be in sync with the kernel. That means that you'd have to re-compile all those components every time you modify your system call list. To minimize that, you can add another layer between applications and the kernel. That means that you have a native library that all other libraries and programs link against dynamically, so that only the native library does system calls directly. This way applications and libraries are still working even if you change or add/remove system calls. This is how windows does it, btw.
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Post by jnc100 »

AJ wrote:1. As you are likely to want several system calls, it is fairly usual to use EAX as a function selector. This means that INT 0x80 with EAX 0x02 may be fork, whereas INT 0x80 with EAX 0x01 may be exit process (as in Linux).
Yes, try and keep all your syscalls using the same interrupt, then you can change to using sysenter/sysexit without too many problems. To make it even easier to switch at will, define a SYSCALL macro in you libc and use that instead, e.g.

Code: Select all

#define SYSCALL(func, arg, ret) __asm volatile ( "int $0x80" : "=a" (ret) : "a" (func), "b" (arg) );
then you can quickly switch to using sysenter by conditionally compiling

Code: Select all

#define SYSCALL(func, arg, ret) __asm volatile ( "sysenter" : "=a" (ret) : "a" (func), "b" (arg) );
or syscall etc. You obviously need to pair it with the correct return (iret, sysexit, sysret) in the kernel. Alternatively you can use function pointers and select the correct one at startup if you don't want to recompile for each architecture.

I suggest you list your function numbers as defines in a header file that is included both into your kernel and libc, so that you can easily keep them in sync.

Regards,
John.
com1
Member
Member
Posts: 105
Joined: Sat Apr 28, 2007 11:57 am
Location: TN

thanks

Post by com1 »

thanks for all the help :D i used 0x80 because i knew that Linux used it for syscalls too.
oh microsoft, microsoft, what souls you have dismayed
com1
Member
Member
Posts: 105
Joined: Sat Apr 28, 2007 11:57 am
Location: TN

what

Post by com1 »

do i need to add anything to my IDT if i create a new interrupt? a new isr?
i have currently 31 ISR for the Intel exception messages and such, but do i need to reconfigure a new ISR for my fork() and system calls ints?
oh microsoft, microsoft, what souls you have dismayed
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post by AJ »

Yes - in addition to setting up the 16 IRQ's and 32 exceptions, you will need entries for any system service ints you want. These can be set up in the same way as the other IDT's you already have.

Adam
Post Reply