l4vfs and stdin/stdout handles

Martin Pohlack mp26 at os.inf.tu-dresden.de
Mon Jun 21 17:29:00 CEST 2010


On 21.06.2010 00:58, Valery V. Sedletski wrote:
> On Sun, 20 Jun 2010 14:19:29 +0200, Martin Pohlack wrote:
> 
>>> -- like in term_con_test example for term_con server, the 3, 4, 5 descriptors are returned from open().
>>
>> As there is no real fork support in l4vfs, I implemented special
>> parameters which are evaluated and eaten before main() is executed in
>> pkg/l4vfs/lib/libc_backends/io/operations.c:init_io().  These parameters
>> trigger the open to the VCs for you (--stdin, --stdout, --stderr).
>>
> 
> I checked init_io(), it seems to do the same as a fragment in term_con_test example -- it opens a terminal device
> and checks the file descriptors to be 0, 1, 2 (with unessential details). I forgot to mention that my program is an API
> server which implements an API and starts a client program using that API. I load the client program, all needed libraries
> for it. Then I start a function called trampoline() in a separate task, prepare an environment for the program in that 
> function (including file descriptors). Then I just setup registers, push params for C startup code on stack, and call an
> entry point in a client program.

I think it is not so easy to transfer these FDs into another task, as
server state is associated with many FDs (depending on the server).

> I tried to add "--stdin /dev/vc0" to API server's command line. The init_io() function opens all file descriptors successfully. 
> Then these file descriptors seem to be inherited by a client program (if I try to open /dev/vc0 in trampoline(), it returns a fd equal 
> to 3, 4, 5, so 0, 1, 2 are already used). But when I try calling read(0, ...); (I call it in the API call from the client program, so the task 
> id at the moment is from the client program) it says that 

I looked again in operations.c:init_io()

If you do not provide "--stdin x" etc. argument, dummy FDs are put into
place in the local FD table, e.g., here:

        ft_fill_entry(1, file_desc);      // fill in dummy entry

I vaguely recall doing this to prevent accidents with printf() etc. in
dietlibc which had no error checking regarding invalid FDs.  I have not
revisited this code since we switched to uclibc years ago ...

> os2serve| api_DosRead(): threadid: 11.0
> os2serve| read(): fd = '0', buf = '0x0001afd0', count = '1''
> term_con| l4vfs_common_io_read_component(): invalid read request - not owning o
> term_con: bject
> 
> and so on many times. I think it is because of the task number different from the API server one.
> (file descriptors are owned by server, not a client program).

Exactly.  This is the server state I mentioned above.

If you want to have nice support for fork etc. (which requires FD
inheritance amongst other things) you will need to extend l4vfs to
inform all relevant servers of resource transfers.  This may be
initiated from the client program, but some generic functions in servers
to support transferring resource seems in order.

This may prove to be a challenging design if you want to do it securely
though.

> Also, I tried to close all file descriptors (0, 1, 2) before opening them at the start of trampoline(). It fails:
> 
> os2serve| close(): local fd '0'
> os2serve| close(): server ret
> os2serve| close(): Error in close, unknown case!
> os2serve| close(): local fd '1'
> os2serve| close(): server ret
> os2serve| close(): Error in close, unknown case!
> os2serve| close(): local fd '2'
> os2serve| l4_exec_lx(): l4ts_create_task() returned: 0, taskid=11.0
> os2serve| close(): server ret
> os2serve| close(): Error in close, unknown case!
> 
> No idea, why the LOG tag is 'os2server' -- it executes in the separate task.
> 
> I also tried to add init_io() call at the start of trampoline() but have no idea how to pass it the command line
> with --stdin, --stdout, --stderr arguments -- when a program is started via roottask, it gets its command line from
> GRUB command line passed through bootinfo structure. But what to do if I start task via task server?

Hmm, I think the init_io() function should be called as a constructor,
you should not call it manually.

Have you checked out the loader?  I think you may not want to use the
task server directly.

http://os.inf.tu-dresden.de/l4env/doc/html/loader/interfacel4loader_1_1app.html

HTH,
Martin




More information about the l4-hackers mailing list