# HG changeset patch # User Paul Boddie # Date 1630103326 -7200 # Node ID 78a45e9e4a55144016c5358a4d14a66d4c8c3bfb # Parent 0c0b89f3831244cf3dbc25873a8d222277286fe4# Parent c3411a9a7102103bf23ede7808b854f1e4dea0da Merged concurrent changes. diff -r 0c0b89f38312 -r 78a45e9e4a55 docs/tools/depgraph --- a/docs/tools/depgraph Sat Aug 28 00:26:18 2021 +0200 +++ b/docs/tools/depgraph Sat Aug 28 00:28:46 2021 +0200 @@ -24,7 +24,7 @@ filter_libraries() { - grep -v '\|\|\|' + grep -v '\|\|\|\|\|\|' } # Select basenames in search result filenames. @@ -86,7 +86,7 @@ | colour_sources \ | select_basenames \ | sed 's/\.cc//' \ -| sed 's/$/;/' \ +| sed 's/^/ /;s/$/;/' \ >> "$DOTFILE" # Generate header file relationships. diff -r 0c0b89f38312 -r 78a45e9e4a55 docs/wiki/ClientLibrary --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/wiki/ClientLibrary Sat Aug 28 00:28:46 2021 +0200 @@ -0,0 +1,146 @@ += Client Library = + +The filesystem client library offers abstractions and a number of layers of +functionality to support interaction with [[Components|components]] and the +provision of higher-level mechanisms and abstractions for file access. + +<> + +== File Data Structures == + +Since files are accessed using file references, the `file_t` data structure is +used to wrap such references and other relevant state. Thus, such structures +can be broadly regarded as similar to the traditional `FILE` data structure. + +The fields of the `file_t` data structure are as follows: + +|| '''Field''' || '''Description''' || +|| `memory` || The memory address of the exposed file region || +|| `start_pos` || The start position of the region in the file || +|| `end_pos` || The end position of the region in the file || +|| `data_end` || The amount or extent of populated data in the region || +|| `data_current` || The offset used to track client position in the region || +|| `size` || The total size of the file || +|| `object_flags` || Flags indicating support for certain file features || +|| `can_block` || Notification flags for blocking access to the file || +|| `notifications`|| Notification flags set for the file || + +== Client Programming Interface == + +The client programming interface provides functions somewhat resembling the +traditional C library and low-level Unix interfaces for file access, and these +functions are intended to support such traditional interfaces. + +=== Files === + +Files are opened and closed using the following functions: + +{{{ +file_t *client_open(const char *name, flags_t flags); +}}} + +Each file endpoint may be closed using `client_close`. + +=== Pipes === + +Pipes are opened using a special function: + +{{{ +long client_pipe(file_t **reader, file_t **writer, flags_t flags); +}}} + +Each pipe endpoint may be closed using `client_close`. + +=== Closing Files and Pipes === + +Closing files and pipes involves a common operation: + +{{{ +void client_close(file_t *file); +}}} + +When client programs terminate, the freeing of their object capabilities +should cause the closure of files and pipes, but programs may choose to close +such resources explicitly. + +=== Reading and Writing === + +Reading and writing files and pipes involves functions resembling the +traditional low-level `read` and `write` functions: + +{{{ +offset_t client_read(file_t *file, void *buf, offset_t count); +offset_t client_write(file_t *file, const void *buf, offset_t count); +}}} + +=== Navigation in Files === + +Support for navigation in files is provided using functions resembling the +traditional higher-level `fseek` and `ftell` functions: + +{{{ +offset_t client_seek(file_t *file, offset_t offset, int whence); +long client_tell(file_t *file); +}}} + +=== Accessing Exposed Memory Regions === + +Although the client library (and the provision of files) employs mapped +memory, a function can be used to explicitly reference memory for file access: + +{{{ +void *client_mmap(file_t *file, offset_t position, offset_t length); +}}} + +Pipes support a different mechanism for navigation involving the following +functions: + +{{{ +long client_current_region(file_t *file); +long client_next_region(file_t *file); +}}} + +Such navigation functions for files and pipes do not need to be used where the +higher-level reading, writing and seeking functions are in use. + +=== Flushing and Synchronisation === + +For synchronisation purposes, either with the filesystem itself or with other +users of the filesystem, a function resembling the traditional `fflush` +function is provided: + +{{{ +long client_flush(file_t *file); +}}} + +This updates the file data structure with new details of the file size, also +updating any altered details of the extent of the data in the currently +accessed region of the file. + +=== Notifications === + +Since files and pipes may be accessed by multiple clients, necessarily for any +sensible use of the latter, notifications can be configured to communicate a +change in state to other users of these resources when they are accessed. + +Notification types are specified using values encoding a number of flags, and +the following flags are available for this purpose: + +|| '''Flag''' || '''Notification Type''' || +|| `NOTIFY_CONTENT_AVAILABLE` || Content available to read || +|| `NOTIFY_PEER_CLOSED` || Other party has closed their endpoint || +|| `NOTIFY_SPACE_AVAILABLE` || Space available for writing || + +=== Blocking Operations === + +Reading and writing operations can be configured to block if data cannot be +read or written respectively. The following function is provided for this +purpose: + +{{{ +long client_set_blocking(file_t *file, notify_flags_t flags); +}}} + +For pipes, blocking behaviour is the default and must be disabled explicitly, +either by opening using the `O_NONBLOCK` flag or by calling +`client_set_blocking` with no flags set. diff -r 0c0b89f38312 -r 78a45e9e4a55 docs/wiki/Components --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/wiki/Components Sat Aug 28 00:28:46 2021 +0200 @@ -0,0 +1,227 @@ += Components = + +Access to files is provided by a number of programs acting as components. For +convenience, the component-level operations are wrapped up in a +[[ClientLibrary|client library]] that aims to provide simpler, more familiar +mechanisms for opening, reading, writing, and closing files, together with +various other operations. + +<> + +Components are accessed via interfaces defined using the interface description +language supported by the ``idl4re`` tool. Interface operations in this +document are described using excerpts from the appropriate interface +descriptions. + +######## A graph showing the interactions between components + +{{{#!graphviz +#format svg +#transform notugly +digraph components { + node [fontsize="12.0",fontname="sans-serif",shape=box]; + edge [fontsize="12.0",fontname="sans-serif"]; + rankdir=LR; + + subgraph { + node [label="Client",style=solid,color="#000000",fontcolor="#000000"]; + rank=min; + + Client1; Client3; Client5; + + subgraph { + node [label="Client",color="#999999",fontcolor="#999999"]; + Client2; Client4; Client6; + } + } + + subgraph { + rank=same; + Filesystem; + + subgraph { + node [label="Opener\n(user)"]; + Opener1; Opener2; + } + + subgraph { + node [label="OpenerContext"]; + OpenerContext1; OpenerContext2; + } + + MappedFile; + } + + Client1 -> Client2 -> Client3 -> Client4 -> Client5 -> Client6 [arrowhead=none,style=invisible]; + Opener1 -> Opener2 [arrowhead=none,style=invisible]; + OpenerContext1 -> OpenerContext2 [arrowhead=none,style=invisible]; + + Client1 -> Filesystem [label="open_for_user(user)"]; + Filesystem -> Opener1; + Opener1 -> Client2 [style=dashed]; + + Client3 -> Opener2 [label="context()"]; + Opener2 -> OpenerContext1; + OpenerContext1 -> Client4 [style=dashed]; + + Client5 -> OpenerContext2 [label="open(flags, ...)"]; + OpenerContext2 -> MappedFile; + MappedFile -> Client6 [style=dashed]; +} +}}} + +######## + +== Filesystems == + +Filesystems implement the `Filesystem` interface which provides the +`open_for_user` operation: + +{{{ +open_for_user(in user_t user, out cap opener) +}}} + +The operation yields a file opener appropriate for the given [[Users|user]] +credentials. + +== File Openers == + +File openers implement the `Opener` interface which provides the `context` +operation: + +{{{ +context(out cap context) +}}} + +Each client program, task or thread obtains its own context because it will +need its own dedicated channel for communication with the filesystem. + +== Opener Contexts == + +An opener context acts as a dataspace, meaning that it can be attached to a +task using a region manager and provide a buffer via a region of mapped memory +that the task can write to. In the case of a context, the task will write a +filesystem path indicating the file to be opened. + +Each context allows a client program to request access to individual files via +operations provided by the `OpenerContext` interface, of which the most +pertinent is the `open` operation: + +{{{ +open(in flags_t flags, out offset_t size, out cap file, + out object_flags_t object_flags) +}}} + +Using the path information written to the context's memory region, the `open` +operation will obtain a reference to a file-like object whose characteristics +are described by the accompanying `object_flags`, these helping the client to +distinguish between files that support arbitrary memory mapping operations and +pipes that mandate sequential region-by-region access. + +Alongside regular files, directories may also be opened. Reading from them +yields a listing of directory entries. + +== Files == + +Files themselves act as dataspaces, meaning that they can be attached to a +task using a region manager and provide their content via a region of mapped +memory. Files implement the `MappedFile` interface. + +Control over the region of the file provided via mapped memory occurs +using the `mmap` operation: + +{{{ +mmap(in offset_t position, in offset_t length, + out offset_t start_pos, out offset_t end_pos, + out offset_t size) +}}} + +Files also implement the more general `File` interface that provides the +`resize` operation: + +{{{ +resize(inout offset_t size) +}}} + +This allows the portion of the memory region dedicated to the file's contents +to be extended. + +== Directories == + +Directories are also meant to be accessed like files, meaning that it should +be possible to attach them to a task using a region manager and access the +provided content, this being a listing of directory entries, via the mapped +region. + +However, unlike files which may support arbitrary mapping of their contents, +the provided content may be supplied by a pipe endpoint, thereby not +supporting precisely the same navigation mechanisms as those supported by +files. + +'''Note''' that directories may well be redefined to support multiple +operations, one of which supporting the file-like access described above. + +== Pipe Openers == + +Distinct from filesystems but potentially used by them, pipe openers provide a +means of obtaining pipes, which are channels that support unidirectional +communication via shared memory. + +Pipe openers implement the `PipeOpener` interface and support the following +operation: + +{{{ +pipe(in offset_t size, out cap reader, out cap writer) +}}} + +The size is indicated to request pipe regions long enough for the needs of the +communicating parties, with both reader and writer endpoint capabilities being +returned. Such capabilities may be propagated to the eventual parties, these +typically being separate tasks. + +== Pipes == + +Although not generally obtained from filesystems, pipes may be involved in +providing content from some filesystem objects such as directories. However, +they are also obtained directly from an appropriate pipe server providing pipe +opening facilities. + +Pipes expose single regions of shared memory to their endpoints, with the +writing endpoint populating one region while the reading endpoint accesses the +other. The reading endpoint may advance to the region being written, and this +will free up a new region for the writer when it has filled its region. When +the writer itself advances, it permits the reader to consume all data in the +fully populated region. Naturally, the reader may not advance ahead of the +writer. + +Pipes implement the `Pipe` interface and a number of operations to support +this interaction mechanism. + +The details of an endpoint's current region can be queried using the following +operation: + +{{{ +current_region(out offset_t populated_size, out offset_t size) +}}} + +This provides details of the populated size (or amount of written data) in a +region along with the size of the region. + +Navigation to the next available region of the pipe is performed using the +following operation: + +{{{ +next_region(inout offset_t populated_size, out offset_t size) +}}} + +Here, the populated size may be specified by the writer so that the reader may +query the current region's properties using the appropriate operation. + +The status of the pipe can be queried using the `closed` operation: + +{{{ +closed(out int closed) +}}} + +This indicates through a boolean-equivalent parameter whether one or both +endpoints have been closed. diff -r 0c0b89f38312 -r 78a45e9e4a55 docs/wiki/Files --- a/docs/wiki/Files Sat Aug 28 00:26:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,237 +0,0 @@ -= Files = - -Access to files is provided by a number of programs acting as components. For -convenience, the component-level operations are wrapped up in a client library -that aims to provide simpler, more familiar mechanisms for opening, reading, -writing, and closing files, together with various other operations. - -<> - -== Components == - -At the lowest level in L4Re, files are accessed via a suite of components. -These components are principally of interest to library developers since they -only provide a limited level of abstraction. - -=== Filesystems === - -Filesystems implement the `Filesystem` interface which provides the -`open_for_user` operation: - -{{{ -open_for_user(in user_t user, out cap opener) -}}} - -The operation yields a file opener appropriate for the given user credentials. - -=== File Openers === - -File openers implement the `Opener` interface which provides the `context` -operation: - -{{{ -context(out cap context) -}}} - -Each client program, task or thread obtains its own context because it will -need its own dedicated channel for communication with the filesystem. - -=== Contexts === - -A context acts as a dataspace, meaning that it can be attached to a task using -a region manager and provide a buffer via a region of mapped memory that the -task can write to. In the case of a context, the task will write a filesystem -path indicating the file to be opened. - -Each context allows a client program to request access to individual files via -operations provided by the `OpenerContext` interface, of which the most -pertinent is the `open` operation: - -{{{ -open(in flags_t flags, out offset_t size, out cap file, - out object_flags_t object_flags) -}}} - -Using the path information written to the context's memory region, the `open` -operation will obtain a reference to a file-like object whose characteristics -are described by the accompanying `object_flags`, these helping the client to -distinguish between files that support arbitrary memory mapping operations and -pipes that mandate sequential region-by-region access. - -Alongside regular files, directories may also be opened. Reading from them -yields a listing of directory entries. - -=== Files === - -Files themselves act as dataspaces, meaning that they can be attached to a -task using a region manager and provide their content via a region of mapped -memory. Files implement the `MappedFile` interface. - -Control over the region of the file provided via mapped memory occurs -using the `mmap` operation: - -{{{ -mmap(in offset_t position, in offset_t length, - out offset_t start_pos, out offset_t end_pos, - out offset_t size) -}}} - -Files also implement the more general `File` interface that provides the -`resize` operation: - -{{{ -resize(inout offset_t size) -}}} - -This allows the portion of the memory region dedicated to the file's contents -to be extended. - -=== Directories === - -Directories are also meant to be accessed like files, meaning that it should -be possible to attach them to a task using a region manager and access the -provided content, this being a listing of directory entries, via the mapped -region. - -However, unlike files which may support arbitrary mapping of their contents, -the provided content may be supplied by a pipe endpoint, thereby not -supporting precisely the same navigation mechanisms as those supported by -files. - -=== Pipe Openers === - -Distinct from filesystems but potentially used by them, pipe openers provide a -means of obtaining pipes, which are channels that support unidirectional -communication via shared memory. - -Pipe openers implement the `PipeOpener` interface and support the following -operation: - -{{{ -pipe(in offset_t size, out cap reader, out cap writer) -}}} - -The size is indicated to request pipe regions long enough for the needs of the -communicating parties, with both reader and writer endpoint capabilities being -returned. Such capabilities may be propagated to the eventual parties, these -typically being separate tasks. - -=== Pipes === - -Although not generally obtained from filesystems, pipes may be involved in -providing content from some filesystem objects such as directories. However, -they are also obtained directly from an appropriate pipe server providing pipe -opening facilities. - -Pipes expose single regions of shared memory to their endpoints, with the -writing endpoint populating one region while the reading endpoint accesses the -other. The reading endpoint may advance to the region being written, and this -will free up a new region for the writer when it has filled its region. When -the writer itself advances, it permits the reader to consume all data in the -fully populated region. Naturally, the reader may not advance ahead of the -writer. - -Pipes implement the `Pipe` interface and a number of operations to support -this interaction mechanism. - -The details of an endpoint's current region can be queried using the following -operation: - -{{{ -current_region(out offset_t populated_size, out offset_t size) -}}} - -This provides details of the populated size (or amount of written data) in a -region along with the size of the region. - -Navigation to the next available region of the pipe is performed using the -following operation: - -{{{ -next_region(inout offset_t populated_size, out offset_t size) -}}} - -Here, the populated size may be specified by the writer so that the reader may -query the current region's properties using the appropriate operation. - -The status of the pipe can be queried using the `closed` operation: - -{{{ -closed(out int closed) -}}} - -This indicates through a boolean-equivalent parameter whether one or both -endpoints have been closed. - -== Libraries == - -The filesystem client library offers abstractions and a number of layers of -functionality to support interaction with components and the provision of -higher-level mechanisms and abstractions for file access. - -=== Client Library === - -The client library provides functions somewhat resembling the traditional C -library and low-level Unix interfaces for file access, and these functions are -intended to support such traditional interfaces. - -Since files are accessed using file references, the `file_t` data structure is -used to wrap such references and other relevant state. Thus, such structures -can be broadly regarded as similar to the traditional `FILE` data structure. - -Files are opened and closed using the following functions: - -{{{ -file_t *client_open(const char *name, flags_t flags); -void client_close(file_t *file); -}}} - -Pipes are opened using a special function: - -{{{ -long client_pipe(file_t **reader, file_t **writer, flags_t flags); -}}} - -Each pipe endpoint may be closed using `client_close`. - -Reading and writing files and pipes involves functions resembling the -traditional low-level `read` and `write` functions: - -{{{ -offset_t client_read(file_t *file, void *buf, offset_t count); -offset_t client_write(file_t *file, const void *buf, offset_t count); -}}} - -Support for navigation in files is provided using functions resembling the -traditional higher-level `fseek` and `ftell` functions: - -{{{ -offset_t client_seek(file_t *file, offset_t offset, int whence); -long client_tell(file_t *file); -}}} - -Although the client library (and the provision of files) employs mapped -memory, a function can be used to explicitly reference memory for file access: - -{{{ -void *client_mmap(file_t *file, offset_t position, offset_t length); -}}} - -Pipes support a different mechanism for navigation involving the following -functions: - -{{{ -long client_current_region(file_t *file); -long client_next_region(file_t *file); -}}} - -Such navigation functions for files and pipes do not need to be used where the -higher-level reading, writing and seeking functions are in use. - -For synchronisation purposes, either with the filesystem itself or with other -users of the filesystem, a function resembling the traditional `fflush` -function is provided: - -{{{ -long client_flush(file_t *file); -}}} diff -r 0c0b89f38312 -r 78a45e9e4a55 docs/wiki/Filesystems --- a/docs/wiki/Filesystems Sat Aug 28 00:26:18 2021 +0200 +++ b/docs/wiki/Filesystems Sat Aug 28 00:28:46 2021 +0200 @@ -5,4 +5,6 @@ == Topics == - * [[Files]] + * [[Components]] + * [[ClientLibrary|Client Library]] + * [[Users]]