System API abstraction question

Discussions on more advanced topics such as monolithic vs micro-kernels, transactional memory models, and paging vs segmentation should go here. Use this forum to expand and improve the wiki!
Post Reply
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

System API abstraction question

Post by neon »

Hello everyone,

This is a design question. The system API can be called upon in my system by using a software interrupt and passing a function identifier in eax. I was thinking of abstracting this behind a dynamic library API for user mode software.

For example, instead of a program having to set up registers and call the system interrupt directly, it can just use the C API library and do something like sysopen() which will set everything up.

The method seems to be very clean but I want to get some feedback on the idea. The problem that I see is that most of the routines will just be one liners like this:

Code: Select all

//NtSystemRequest puts the parameters in the registers and calls the system software interrupt that will call the correct kernel mode function

int
NtBrk (DWORD EndDataSegment) {

	return NtSystemRequest (SYSTEM_CALL_BRK, EndDataSegment, 0, 0);
}
//100 some other routines might be like this... o_o
What do you think of the idea? Any comments? Should I go for it?
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
User avatar
thepowersgang
Member
Member
Posts: 734
Joined: Tue Dec 25, 2007 6:03 am
Libera.chat IRC: thePowersGang
Location: Perth, Western Australia
Contact:

Re: System API abstraction question

Post by thepowersgang »

... this is what usually happens.

Most OSs will have a library called libthisos.so (or something like that, I have libacess.so) that abstracts the systemcalls out from mov eax, CALL; int 0xXX to a C function, usually by using inline assembler.

Int the example you provided, NtSystemRequest would probably be either a macro, or an assembly function that calls the system call in a clean way.
Kernel Development, It's the brain surgery of programming.
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: System API abstraction question

Post by neon »

thepowersgang wrote:... this is what usually happens.
Oh. I knew Windows did it (Didnt know Linux also), it just seems .. long-winded. ie, having 100-200 some one liner routines.

Thanks for your suggestion :)
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
bitshifter
Member
Member
Posts: 50
Joined: Sun Sep 20, 2009 4:03 pm

Re: System API abstraction question

Post by bitshifter »

Alernatively you could have a call-table.
Which user app can use int to fill local table.
DexOS use this method.
There is a trade-off between size and speed.
You want it to be small or fast?
Grunt
Member
Member
Posts: 37
Joined: Fri Nov 06, 2009 1:05 am

Re: System API abstraction question

Post by Grunt »

bitshifter wrote:Alernatively you could have a call-table.
This is not about how you implement system calls, but wrapping them.

I would use #defines, but that's just personal preference.
User avatar
qw
Member
Member
Posts: 792
Joined: Mon Jan 26, 2009 2:48 am

Re: System API abstraction question

Post by qw »

You could implement several layers and use the layer that meets your needs best in a certain situation.

For example, you could use INT, SYSCALL, or SYSENTER in raw assembly if speed is your main concern. Then you could use NtSystemRequest() as a wrapper in C for OS-specific code. On top of that a POSIX-style function like open() that calls NtSystemRequest(SYSTEM_CALL_OPEN, ...) and on top of that the ISO C function fopen() that calls open().

This way the design is the cleanest, I think.

Roel

EDIT: NtSystemRequest() could choose to use INT, SYSCALL, or SYSENTER at run time.
User avatar
Love4Boobies
Member
Member
Posts: 2111
Joined: Fri Mar 07, 2008 5:36 pm
Location: Bucharest, Romania

Re: System API abstraction question

Post by Love4Boobies »

Probably has the most overhead too.
"Computers in the future may weigh no more than 1.5 tons.", Popular Mechanics (1949)
[ Project UDI ]
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: System API abstraction question

Post by neon »

Hello,
Love4Boobies wrote:Probably has the most overhead too.
That is what I am worried about. Grunt's method would certainly solve that issue but at the cost of user mode software having to be compiled with the system API #defines.

With my current method, Im going to be ending up with a library filled with 100-200 some one-liner routines calling NtSystemRequest. I suppose it wont be that bad if NtSystemRequest is inline though.

I appreciate the suggestions :D
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
FlashBurn
Member
Member
Posts: 313
Joined: Fri Oct 20, 2006 10:14 am

Re: System API abstraction question

Post by FlashBurn »

The library has also one advantage over the defines which every user code would use. If you change something with you System API, the programs wills till work, because all you need to do is change this library. But this also works just if you needn´t one more parameter.
User avatar
inx
Member
Member
Posts: 142
Joined: Wed Mar 05, 2008 12:52 am

Re: System API abstraction question

Post by inx »

Personally, I use a jump table because one of my goals in my system is to, at least mostly, keep binary compatibility between revisions on the same architecture. I have different jump tables for SYSCALL/SYSRET, SYSENTER/SYSEXIT, and INT calls, and just choose which to use at boot and map it into the top of each process's address space. My syscall.h is just a bunch of function pointers that point to the right offsets in the jump table.
Post Reply