1 = Components = 2 3 Access to files is provided by a number of programs acting as components. For 4 convenience, the component-level operations are wrapped up in a 5 [[ClientLibrary|client library]] that aims to provide simpler, more familiar 6 mechanisms for opening, reading, writing, and closing files, together with 7 various other operations. 8 9 <<TableOfContents(2,3)>> 10 11 Components are accessed via interfaces defined using the interface description 12 language supported by the ``idl4re`` tool. Interface operations in this 13 document are described using excerpts from the appropriate interface 14 descriptions. 15 16 == Overview == 17 18 An overview of the component interactions involved in opening a file is 19 provided by the diagram below. 20 21 ######## A graph showing the interactions between components 22 23 {{{#!graphviz 24 #format svg 25 #transform notugly 26 digraph components { 27 node [fontsize="12.0",fontname="sans-serif",shape=box]; 28 edge [fontsize="12.0",fontname="sans-serif"]; 29 rankdir=LR; 30 31 subgraph { 32 node [label="Client",style=solid,color="#000000",fontcolor="#000000"]; 33 rank=min; 34 35 Client1; Client2; Client3; Client4; Client5; Client6; Client7; 36 } 37 38 subgraph { 39 rank=same; 40 Memory [label="filename",shape=note]; 41 } 42 43 subgraph { 44 rank=same; 45 Filesystem; 46 47 subgraph { 48 node [label="Opener\n(user)"]; 49 Opener1; Opener2; 50 } 51 52 subgraph { 53 node [label="OpenerContext"]; 54 OpenerContext1; OpenerContext2; OpenerContext3; 55 } 56 57 MappedFile; 58 } 59 60 Client1 -> Client2 -> Client3 -> Client4 -> Client5 -> Client6 -> Client7 [arrowhead=none,style=dotted]; 61 Opener1 -> Opener2 [arrowhead=none,style=dotted]; 62 OpenerContext1 -> OpenerContext2 -> OpenerContext3 [arrowhead=none,style=dotted]; 63 64 Client1 -> Filesystem [label="open_for_user(user)"]; 65 Filesystem -> Opener1; 66 Opener1 -> Client2; 67 68 Client3 -> Opener2 [label="context()"]; 69 Opener2 -> OpenerContext1; 70 OpenerContext1 -> Client4; 71 72 Client5 -> Memory -> OpenerContext2; 73 74 Client6 -> OpenerContext3 [label="open(flags, ...)"]; 75 OpenerContext3 -> MappedFile; 76 MappedFile -> Client7; 77 } 78 }}} 79 80 ######## 81 82 In pseudocode, the operations as conducted by the client program are as 83 follows: 84 85 {{{ 86 opener = filesystem.open_for_user(user) 87 context = opener.context() 88 context.write("filename") # this being a memory access operation 89 file = context.open(flags, ...) 90 }}} 91 92 == Filesystems == 93 94 Filesystems implement the `Filesystem` interface which provides the 95 `open_for_user` operation: 96 97 {{{ 98 open_for_user(in user_t user, out cap opener) 99 }}} 100 101 The operation yields a file opener appropriate for the given [[Users|user]] 102 credentials. 103 104 == File Openers == 105 106 File openers implement the `Opener` interface which provides the `context` 107 operation: 108 109 {{{ 110 context(out cap context) 111 }}} 112 113 Each client program, task or thread obtains its own context because it will 114 need its own dedicated channel for communication with the filesystem. 115 116 == Opener Contexts == 117 118 An opener context acts as a dataspace, meaning that it can be attached to a 119 task using a region manager and provide a buffer via a region of mapped memory 120 that the task can write to. In the case of a context, the task will write a 121 filesystem path indicating the file to be opened. 122 123 Each context allows a client program to request access to individual files via 124 operations provided by the `OpenerContext` interface, of which the most 125 pertinent is the `open` operation: 126 127 {{{ 128 open(in flags_t flags, out offset_t size, out cap file, 129 out object_flags_t object_flags) 130 }}} 131 132 Using the path information written to the context's memory region, the `open` 133 operation will obtain a reference to a file-like object whose characteristics 134 are described by the accompanying `object_flags`, these helping the client to 135 distinguish between files that support arbitrary memory mapping operations and 136 pipes that mandate sequential region-by-region access. 137 138 Alongside regular files, directories may also be opened. Reading from them 139 yields a listing of directory entries. 140 141 == Files == 142 143 Files themselves act as dataspaces, meaning that they can be attached to a 144 task using a region manager and provide their content via a region of mapped 145 memory. Files implement the `MappedFile` interface. 146 147 Control over the region of the file provided via mapped memory occurs 148 using the `mmap` operation: 149 150 {{{ 151 mmap(in offset_t position, in offset_t length, 152 out offset_t start_pos, out offset_t end_pos, 153 out offset_t size) 154 }}} 155 156 Files also implement the more general `File` interface that provides the 157 `resize` operation: 158 159 {{{ 160 resize(inout offset_t size) 161 }}} 162 163 This allows the portion of the memory region dedicated to the file's contents 164 to be extended. 165 166 == Directories == 167 168 Directories are also meant to be accessed like files, meaning that it should 169 be possible to attach them to a task using a region manager and access the 170 provided content, this being a listing of directory entries, via the mapped 171 region. 172 173 However, unlike files which may support arbitrary mapping of their contents, 174 the provided content may be supplied by a pipe endpoint, thereby not 175 supporting precisely the same navigation mechanisms as those supported by 176 files. 177 178 '''Note''' that directories may well be redefined to support multiple 179 operations, one of which supporting the file-like access described above. 180 181 == Pipe Openers == 182 183 Distinct from filesystems but potentially used by them, pipe openers provide a 184 means of obtaining pipes, which are channels that support unidirectional 185 communication via shared memory. 186 187 Pipe openers implement the `PipeOpener` interface and support the following 188 operation: 189 190 {{{ 191 pipe(in offset_t size, out cap reader, out cap writer) 192 }}} 193 194 The size is indicated to request pipe regions long enough for the needs of the 195 communicating parties, with both reader and writer endpoint capabilities being 196 returned. Such capabilities may be propagated to the eventual parties, these 197 typically being separate tasks. 198 199 == Pipes == 200 201 Although not generally obtained from filesystems, pipes may be involved in 202 providing content from some filesystem objects such as directories. However, 203 they are also obtained directly from an appropriate pipe server providing pipe 204 opening facilities. 205 206 Pipes expose single regions of shared memory to their endpoints, with the 207 writing endpoint populating one region while the reading endpoint accesses the 208 other. The reading endpoint may advance to the region being written, and this 209 will free up a new region for the writer when it has filled its region. When 210 the writer itself advances, it permits the reader to consume all data in the 211 fully populated region. Naturally, the reader may not advance ahead of the 212 writer. 213 214 Pipes implement the `Pipe` interface and a number of operations to support 215 this interaction mechanism. 216 217 The details of an endpoint's current region can be queried using the following 218 operation: 219 220 {{{ 221 current_region(out offset_t populated_size, out offset_t size) 222 }}} 223 224 This provides details of the populated size (or amount of written data) in a 225 region along with the size of the region. 226 227 Navigation to the next available region of the pipe is performed using the 228 following operation: 229 230 {{{ 231 next_region(inout offset_t populated_size, out offset_t size) 232 }}} 233 234 Here, the populated size may be specified by the writer so that the reader may 235 query the current region's properties using the appropriate operation. 236 237 The status of the pipe can be queried using the `closed` operation: 238 239 {{{ 240 closed(out int closed) 241 }}} 242 243 This indicates through a boolean-equivalent parameter whether one or both 244 endpoints have been closed.