]> granicus.if.org Git - esp-idf/commitdiff
docs: Correct and extend the documentation about VFS select()
authorRoland Dobai <dobai.roland@gmail.com>
Wed, 17 Jul 2019 07:59:21 +0000 (09:59 +0200)
committerRoland Dobai <dobai.roland@gmail.com>
Thu, 15 Aug 2019 12:11:51 +0000 (14:11 +0200)
components/vfs/README.rst
components/vfs/vfs.c

index 20bc9770e7b4c11a6ff2f70a0a3ec0fe5fc82a47..c296e81a6879122491de4e501aa4ae77ed1e5060 100644 (file)
@@ -66,9 +66,29 @@ Case 2: API functions are declared with an extra context pointer (the FS driver
 Synchronous input/output multiplexing
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-If you want to use synchronous input/output multiplexing by :cpp:func:`select`
-then you need to register VFS with the functions :cpp:func:`start_select` and
-:cpp:func:`end_select` similar to the following example:
+Synchronous input/output multiplexing by :cpp:func:`select` is supported in the VFS component. The implementation
+works in the following way.
+
+1. :cpp:func:`select` is called with file descriptors which could belong to various VFS drivers.
+2. The file descriptors are divided into groups each belonging to one VFS driver.
+3. The file descriptors belonging to non-socket VFS drivers are handed over to the given VFS drivers by :cpp:func:`start_select`
+   described later on this page. This function represents the driver-specific implementation of :cpp:func:`select` for
+   the given driver. This should be a non-blocking call which means the function should immediately return after setting up
+   the environment for checking events related to the given file descriptors.
+4. The file descriptors belonging to the socket VFS driver are handed over to the socket driver by
+   :cpp:func:`socket_select` described later on this page. This is a blocking call which means that it will return only
+   if there is an event related to socket file descriptors or a non-socket driver signals :cpp:func:`socket_select`
+   to exit.
+5. Results are collected from each VFS driver and all drivers are stopped by deinitiazation
+   of the environment for checking events.
+6. The :cpp:func:`select` call ends and returns the appropriate results.
+
+Non-socket VFS drivers
+""""""""""""""""""""""
+
+If you want to use :cpp:func:`select` with a file descriptor belonging to a non-socket VFS driver
+then you need to register the driver with functions :cpp:func:`start_select` and
+:cpp:func:`end_select` similarly to the following example:
 
 .. highlight:: c
 
@@ -81,25 +101,57 @@ then you need to register VFS with the functions :cpp:func:`start_select` and
 
 :cpp:func:`start_select` is called for setting up the environment for
 detection of read/write/error conditions on file descriptors belonging to the
-given VFS. :cpp:func:`end_select` is called to stop/deinitialize/free the
-environment which was setup by :cpp:func:`start_select`. Please refer to the
+given VFS driver.
+
+:cpp:func:`end_select` is called to stop/deinitialize/free the
+environment which was setup by :cpp:func:`start_select`.
+
+Please refer to the
 reference implementation for the UART peripheral in
 :component_file:`vfs/vfs_uart.c` and most particularly to the functions
 :cpp:func:`esp_vfs_dev_uart_register`, :cpp:func:`uart_start_select`, and
-:cpp:func:`uart_end_select`.
+:cpp:func:`uart_end_select` for more information.
 
 Please check the following examples that demonstrate the use of :cpp:func:`select` with VFS file descriptors:
-- :example:`peripherals/uart_select`
-- :example:`system/select`
+    - :example:`peripherals/uart/uart_select`
+    - :example:`system/select`
+
+Socket VFS drivers
+""""""""""""""""""
+
+A socket VFS driver is using its own internal implementation of :cpp:func:`select` and non-socket VFS drivers notify
+it upon read/write/error conditions.
+
+A socket VFS driver needs to be registered with the following functions defined:
+
+.. highlight:: c
+
+::
+
+    // In definition of esp_vfs_t:
+        .socket_select = &lwip_select,
+        .get_socket_select_semaphore = &lwip_get_socket_select_semaphore,
+        .stop_socket_select = &lwip_stop_socket_select,
+        .stop_socket_select_isr = &lwip_stop_socket_select_isr,
+    // ... other members initialized
+
+:cpp:func:`socket_select` is the internal implementation of :cpp:func:`select` for the socket driver. It works only
+with file descriptors belonging to the socket VFS.
+
+:cpp:func:`get_socket_select_semaphore` returns the signalization object (semaphore) which will be used in non-socket
+drivers to stop the waiting in :cpp:func:`socket_select`.
+
+:cpp:func:`stop_socket_select` call is used to stop the waiting in :cpp:func:`socket_select` by passing the object
+returned by :cpp:func:`get_socket_select_semaphore`.
+
+:cpp:func:`stop_socket_select_isr` has the same functionality as :cpp:func:`stop_socket_select` but it can be used
+from ISR.
 
-<<<<<<< HEAD
-If :cpp:func:`select` is used for socket file descriptors only then one can
-enable the :envvar:`CONFIG_LWIP_USE_ONLY_LWIP_SELECT` option which can reduce the code
-=======
-If you use :cpp:func:`select` for socket file descriptors, you can enable the :envvar:`CONFIG_LWIP_USE_ONLY_LWIP_SELECT` option to reduce the code
->>>>>>> afc2fdf27... Review all the files in the esp-idf's api_ref/storage directory
-size and improve performance.
+Please see :component_file:`lwip/port/esp32/vfs_lwip.c` for a reference socket driver implementation using LWIP.
 
+.. note::
+    If you use :cpp:func:`select` for socket file descriptors only then you can enable the
+    :envvar:`CONFIG_LWIP_USE_ONLY_LWIP_SELECT` option to reduce the code size and improve performance.
 
 Paths
 -----
index 760d3272808a601af2fcfa6152e891f990d5587b..d681038828319f9fdd5f9614d72421ac78d0d43e 100644 (file)
@@ -858,6 +858,8 @@ static void esp_vfs_log_fd_set(const char *fds_name, const fd_set *fds)
 
 int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout)
 {
+    // NOTE: Please see the "Synchronous input/output multiplexing" section of the ESP-IDF Programming Guide
+    // (API Reference -> Storage -> Virtual Filesystem) for a general overview of the implementation of VFS select().
     int ret = 0;
     struct _reent* r = __getreent();