paul@142 | 1 | = Files = |
paul@142 | 2 | |
paul@142 | 3 | Access to files is provided by a number of programs acting as components. For |
paul@142 | 4 | convenience, the component-level operations are wrapped up in a client library |
paul@142 | 5 | that aims to provide simpler, more familiar mechanisms for opening, reading, |
paul@142 | 6 | writing, and closing files, together with various other operations. |
paul@142 | 7 | |
paul@142 | 8 | <<TableOfContents(2,3)>> |
paul@142 | 9 | |
paul@142 | 10 | == Components == |
paul@142 | 11 | |
paul@142 | 12 | At the lowest level in L4Re, files are accessed via a suite of components. |
paul@142 | 13 | |
paul@142 | 14 | === Filesystems === |
paul@142 | 15 | |
paul@142 | 16 | Filesystems implement the `Opener` interface which provides the `context` |
paul@142 | 17 | operation: |
paul@142 | 18 | |
paul@142 | 19 | {{{ |
paul@142 | 20 | context(out cap context) |
paul@142 | 21 | }}} |
paul@142 | 22 | |
paul@142 | 23 | Each client program, task or thread obtains its own context because it will |
paul@142 | 24 | need its own dedicated channel for communication with the filesystem. |
paul@142 | 25 | |
paul@142 | 26 | === Contexts === |
paul@142 | 27 | |
paul@142 | 28 | A context acts as a dataspace, meaning that it can be attached to a task using |
paul@142 | 29 | a region manager and provide a buffer via a region of mapped memory that the |
paul@142 | 30 | task can write to. In the case of a context, the task will write a filesystem |
paul@142 | 31 | path indicating the file to be opened. |
paul@142 | 32 | |
paul@142 | 33 | Each context allows a client program to request access to individual files via |
paul@142 | 34 | operations provided by the `OpenerContext` interface, of which the most |
paul@142 | 35 | pertinent is the `open` operation: |
paul@142 | 36 | |
paul@142 | 37 | {{{ |
paul@142 | 38 | open(in flags_t flags, out offset_t size, out cap file) |
paul@142 | 39 | }}} |
paul@142 | 40 | |
paul@142 | 41 | Using the path information written to the context's memory region, the `open` |
paul@142 | 42 | operation will obtain a reference to a file. |
paul@142 | 43 | |
paul@142 | 44 | === Files === |
paul@142 | 45 | |
paul@142 | 46 | Files themselves act as dataspaces, meaning that they can be attached to a |
paul@142 | 47 | task using a region manager and provide their content via a region of mapped |
paul@142 | 48 | memory. Files implement the `MappedFile` interface. |
paul@142 | 49 | |
paul@142 | 50 | Control over the region of the file provided via mapped memory occurs |
paul@142 | 51 | using the `mmap` operation: |
paul@142 | 52 | |
paul@142 | 53 | {{{ |
paul@142 | 54 | mmap(in offset_t position, in offset_t length, |
paul@142 | 55 | out offset_t start_pos, out offset_t end_pos, |
paul@142 | 56 | out offset_t size) |
paul@142 | 57 | }}} |
paul@142 | 58 | |
paul@142 | 59 | Files also implement the more general `File` interface that provides the |
paul@142 | 60 | `resize` operation: |
paul@142 | 61 | |
paul@142 | 62 | {{{ |
paul@142 | 63 | resize(inout offset_t size) |
paul@142 | 64 | }}} |
paul@142 | 65 | |
paul@142 | 66 | This allows the portion of the memory region dedicated to the file's contents |
paul@142 | 67 | to be extended. |
paul@142 | 68 | |
paul@142 | 69 | == Libraries == |
paul@142 | 70 | |
paul@142 | 71 | The filesystem client library offers abstractions and a number of layers of |
paul@142 | 72 | functionality to support interaction with components and the provision of |
paul@142 | 73 | higher-level mechanisms and abstractions for file access. |
paul@142 | 74 | |
paul@142 | 75 | === Client Library === |
paul@142 | 76 | |
paul@142 | 77 | The client library provides functions somewhat resembling the traditional C |
paul@142 | 78 | library and low-level Unix interfaces for file access, and these functions are |
paul@142 | 79 | intended to support such traditional interfaces. |
paul@142 | 80 | |
paul@142 | 81 | Since files are accessed using file references, the `file_t` data structure is |
paul@142 | 82 | used to wrap such references and other relevant state. Thus, such structures |
paul@142 | 83 | can be broadly regarded as similar to the traditional `FILE` data structure. |
paul@142 | 84 | |
paul@142 | 85 | Files are opened and closed using the following functions: |
paul@142 | 86 | |
paul@142 | 87 | {{{ |
paul@142 | 88 | file_t *client_open(const char *name, flags_t flags); |
paul@142 | 89 | void client_close(file_t *file); |
paul@142 | 90 | }}} |
paul@142 | 91 | |
paul@142 | 92 | Reading and writing files involves functions resembling the traditional |
paul@142 | 93 | low-level `read` and `write` functions: |
paul@142 | 94 | |
paul@142 | 95 | {{{ |
paul@142 | 96 | offset_t client_read(file_t *file, void *buf, offset_t count); |
paul@142 | 97 | offset_t client_write(file_t *file, const void *buf, offset_t count); |
paul@142 | 98 | }}} |
paul@142 | 99 | |
paul@142 | 100 | Support for navigation in files is provided using functions resembling the |
paul@142 | 101 | traditional higher-level `fseek` and `ftell` functions: |
paul@142 | 102 | |
paul@142 | 103 | {{{ |
paul@142 | 104 | offset_t client_seek(file_t *file, offset_t offset, int whence); |
paul@142 | 105 | long client_tell(file_t *file); |
paul@142 | 106 | }}} |
paul@142 | 107 | |
paul@142 | 108 | Although the client library (and the provision of files) employs mapped |
paul@142 | 109 | memory, a function can be used to explicitly reference memory for file access: |
paul@142 | 110 | |
paul@142 | 111 | {{{ |
paul@142 | 112 | void *client_mmap(file_t *file, offset_t position, offset_t length); |
paul@142 | 113 | }}} |
paul@142 | 114 | |
paul@142 | 115 | For synchronisation purposes, either with the filesystem itself or with other |
paul@142 | 116 | users of the filesystem, a function resembling the traditional `fflush` |
paul@142 | 117 | function is provided: |
paul@142 | 118 | |
paul@142 | 119 | {{{ |
paul@142 | 120 | long client_flush(file_t *file); |
paul@142 | 121 | }}} |