AndrewAPrice wrote:
I'm not making a POSIX compatible kernel, so my processes interact with the outside world via Services and RPCs. Services are interfaces, and any process can implement a service and register it in the kernel. So, a process that wants to read or write to disk will query the kernel for implementations of 'File Service'*, and it's possible it's not yet started (so I have a synchronous query-and-wait call), and once we have a reference to a File Service, we can call FileService->ReadFile...
For terminal input/output (where does STDOUT go? where does STDIN come from?) the program will look up Terminal Service which has read/write methods. Intercepting STDOUT/STDIN and redirecting it to the passed in Terminal Service is something I handle in my C library->system binding. My OS supports std::cout, printf, and normal C/C++ file handling this way.
Of course, my OS isn't complete, but this is the plan:
If a process just calls Terminal Service out of the blue, it'll open a new terminal window, and Terminal Service will remember PID 1234 talks to window 4. If PID 1234 launches a new process (let's call it PID 5678) PID 1234 can tell Terminal Service that PID 5678 can share window 4.
In a more complicated and flexible world, I'd support sandboxing. So, when a parent program launches a child program, it could tell the kernel to launch it with a given "sandbox". When the child looks up Terminal Service, the parent (which might be an IDE that's running terminal commands in a docked panel) could intercept the syscall query for Terminal Service and return its own implementation.
My design is going to anger people who want to stay true to the POSIX. Do what makes you happy!
Why not have the graphics service remember window 4? Then you can create terminals without tying them to windows. I'm not endorsing the Unix philosophy... I just see an opportunity for flexibility here. If tying terminals to windows is an optional thing, you can have pseudoterminals and such, all managed through the terminal service.