DragonFly kernel List (threaded) for 2003-11
Re: Userapi, Reflection
Matthew Dillon wrote:
: I have been contemplating how the useapi portion of the project will work
:(for those not farmiliar please see
:http://www.dragonflybsd.org/Goals/userapi.cgi). What I think would be quite
:impressive would be a process that uses reflection (java and c#). Reflection
:is an api that allows for the creation of types, functions, and classes at run
:time. Please see http://java.sun.com/docs/books/tutorial/reflect/index.html
:for information how java does this.
: The idea for userapi would be to use reflection to create callable
:prototypes for systemcalls at run time. Say we have our special user level
:process that handles system calls. It is invoked by the kernel like init. It
:will have a configuration file, containing prototypes for every system call it
:knows how to handle. If linux changes a prototype for one of their system
:calls, the configuration file could be modified accordingly. On a SIGHUP the
:process would re-read the configuration file, and modify the prototypes
:accordingly. The idea is that you could modify, add, and delete system calls
:at runtime, without ever rebooting the os or modifying any code at all.
: This is just a thought I had. It is possible that it is infeasible, but I
:thought I would throw the idea out there and see what other might think of it.
Well, I guess the question is: What type of run-time entity would
use these prototypes? I can see adding and removing support for
particular system calls in libc.so dynamically, but the programs that
link into libc would have no visibility into the changes after the
fact. That is, you would still have to either restart an application
or start an application dependant on a new system call after having
loaded the configuration for the system call. This doesn't seem much
different then reinstalling libc on a live system. Applications are
still going to hardwire their understanding of a particular syscall's
I think I haven't made myself entirely clear (thats not unusual :).
The entity that would use these prototypes would be the system call
proxy itself (nothing else would use it). Forgive my ignorance on the
kernel internals, and my possible missreading/misunderstanding of the
goals envisioned for dragonfly. I will try to lay out more clearly what
I meant by the use of reflection.
My current understanding of the userapi goal:
The userapi goal provides support for emulation and system call
messaging. A processes, started and managed by the kernel, is created
at boot time. This process is a proxy to the real kernel (a proxy in
that it acts solely as a forwarding and translating entity). In
dragonfly there will be 3 real system calls, send a message to the
kernel, abort a message sent to the kernel, and wait for a message to be
returned by the kernel.
The proxy entity will act on behalf of all other processes system
calls. There will be two cases: system calls invoked by a natively
compiled process, and thus knows the proxy agent is in existent, and
system calls invoked from every other running process (freebsd binary,
linux binary, .....). In the first (native) case, a process will use
ipc, or some special messaging functionality to execute the proxy's code
within the callers context. Reflection does not help in this case. In
the second (non-native) case, A process will invoke its notion of a
system call and all will be handled by the proxy.
The non-native binary will trap to the kernel. Its notion of how
arguments should be arranged is going to occur. If it thinks its system
call arguments should be registers, they will be in registers. If it
thinks its system call arguments should be on the stack, they will be on
the stack. If a kernel receives one of these calls it shouldn't have to
do anything but forward a trap frame to the user level process acting as
a proxy. This proxy will gather up the arguments from the frame into a
system call message, and send it natively.
How reflection might be used:
Reflection could be useful in the "gather up the arguments into a
system call message" stage (a.k.a. emulation stage). Reflection would
be used here to generate the code that shims the arguments into a
message. Say linux 2.6 comes out and you would like to emulate it. Say
linux 2.6 adds a system call. Instead of modifying the code of the
proxy itself, you add the prototype to its configuration file, send
SIGHUP, poof! The new system call is now supported for emulation.
Hopefully that is somewhat clear. It may very well be the case that
the emulation will need to do a series of things besides just gather
arguments. In this case it would not make much sense to use reflection
because the proxy's configuration file would get complex, and you might
as well write the code. Also, system calls aren't added or modified all
that often, and so once again it might not be worth it to add all of
this complexity. However, if the emulation is generic enough, then it
might be worth it.