Yeah, as said above, it's just a regular function call since it's in the same ring. My drivers and kernel reside in the same ring, and I link my drivers to the kernel when they are loaded to link symbolic information (I use coff files, but a.out, elf, pe are other commonly used variants), or as stated, use a known location to generate a table (my old way I did it). Basically, set aside a block of memory to hold function pointers... so, for example... a viod SayHi(char *Say); function
.
You reserve a known address space (we'll even forget about paging right now since it's outside the scope of this discussion), lets say we want our function table to be at 0x1000, or the first 4k page boundary. Would would simply do this in the kernel:
Code: Select all
u32 *FuncTable = 0x1000;
void SayHi(char *Say)
{
kprintf("SayHi: %s\n",Say); //Print the string passed for testing
}
void SetFuncPointer(void *Func, unsigned long FunctionNumber)
{
FuncTable[FunctionNumber] = (u32)Func;
}
void InitFuncs(void)
{
SetFuncPointer(SayHi,0); //first function
}
now for your driver/application to find the function for SayHi, it knows that it is function 0... so..
Code: Select all
u32 FuncTable = (u32*)0x1000;
void *GetFuncPointer(u32 FunctionNumber)
{
return (void*)FuncTable[FunctionNumber];
}
void (*SayHi)(char *Say);
void InitKernelFuncs(void)
{
SayHi = (void(*)(char*))GetFuncPointer(0);
}
So, now your application knows that the location of the function SayHi is the first entry in the table @ 0x1000, so it can call it without any extra information once the function pointer is set at the correct place. I typed it all in this window, so maybe a casting error or similar, but it should give you the idea on what's going on.