doc/guide: update content and sample code (#3408)

- Add `Makefile` for example codes. (cherry-pick from old uvbook repo)
- Add a new example "Default loop" to "Basics of libuv"/"Default loop"
- Document review and update: `Introduction`, `Basics of libuv`, `Filesystem`
    + Update the referenced libuv code snippet
    + Link update: http->https
    **Content Updates**:
    - `filesystem.rst`#L291-L297: Add note for `uv_fs_event_start`
    - `filesystem.rst`#L334: Add description of the callback function parameter `status`

The following examples have been tested manually in WSL2 (Ubuntu 20.04) with libuv 1.42.0:
- helloworld
- default-loop
- idle-basic
- uvcat
- uvtee
- onchange (test on macOS)

Co-authored-by: Nikhil Marathe <nsm.nikhil@gmail.com>
This commit is contained in:
woclass 2022-02-01 05:52:42 +08:00 committed by GitHub
parent 930af43437
commit 870828c8af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 144 additions and 24 deletions

3
docs/code/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*/*
!*.c
!*.h

82
docs/code/Makefile Normal file
View File

@ -0,0 +1,82 @@
examples=\
helloworld\
default-loop\
idle-basic\
uvcat\
uvtee\
onchange\
thread-create\
queue-work\
progress\
tcp-echo-server\
dns\
udp-dhcp\
idle-compute\
ref-timer\
spawn\
detach\
proc-streams\
cgi\
pipe-echo-server\
multi-echo-server\
tty\
tty-gravity\
interfaces\
locks \
signal \
uvstop \
queue-cancel
UV_PATH=$(shell pwd)/../..
UV_LIB=$(UV_PATH)/.libs/libuv.a
CFLAGS=-g -Wall -I$(UV_PATH)/include
LIBS=
uname_S=$(shell uname -s)
ifeq (Darwin, $(uname_S))
CFLAGS+=-framework CoreServices
SHARED_LIB_FLAGS=-bundle -undefined dynamic_lookup -o plugin/libhello.dylib
endif
ifeq (Linux, $(uname_S))
LIBS=-lrt -ldl -lm -pthread -lcurl
SHARED_LIB_FLAGS=-shared -Wl,-soname,libhello.so -o plugin/libhello.so
PLUGIN_EXE_FLAGS=-Wl,-export-dynamic
endif
all: $(examples) plugin/plugin proc-streams/test cgi/tick multi-echo-server/worker uvwget/uvwget
$(examples): % : %/main.c
gcc $(CFLAGS) -o $@/$@ $< $(UV_LIB) $(LIBS)
plugin: plugin/plugin
plugin/plugin: plugin/*.c
gcc $(CFLAGS) $(PLUGIN_EXE_FLAGS) -o plugin/plugin plugin/main.c $(UV_LIB) $(LIBS)
gcc -g -Wall -c -fPIC -o plugin/hello.o plugin/hello.c
gcc $(SHARED_LIB_FLAGS) plugin/hello.o
proc-streams/test: proc-streams/test.c
gcc -g -Wall -o proc-streams/test proc-streams/test.c
cgi/tick: cgi/tick.c
gcc -g -Wall -o cgi/tick cgi/tick.c
multi-echo-server/worker: multi-echo-server/worker.c
gcc $(CFLAGS) -o multi-echo-server/worker multi-echo-server/worker.c $(UV_LIB) $(LIBS)
uvwget: uvwget/uvwget
uvwget/uvwget: uvwget/main.c
gcc $(CFLAGS) `curl-config --cflags --libs` -o uvwget/uvwget uvwget/main.c $(UV_LIB) $(LIBS)
clean:
for dir in $(examples); do cd $$dir; rm -f $$dir; rm -rf $$dir.dSYM; cd ..; done
rm -rf plugin/*.o plugin/libhello.*
rm -rf plugin/plugin plugin/plugin.dSYM
rm -rf proc-streams/test proc-streams/test.dSYM
rm -rf cgi/tick cgi/tick.dSYM
rm -rf multi-echo-server/worker multi-echo-server/worker.dSYM
rm -rf uvwget/uvwget uvwget/uvwget.dSYM
.PHONY: clean all $(examples) plugin uvwget

View File

@ -0,0 +1,12 @@
#include <stdio.h>
#include <uv.h>
int main() {
uv_loop_t *loop = uv_default_loop();
printf("Default loop.\n");
uv_run(loop, UV_RUN_DEFAULT);
uv_loop_close(loop);
return 0;
}

View File

@ -71,7 +71,7 @@ architecture of libuv and its background. If you have no prior experience with
either libuv or libev, it is a quick, useful watch. either libuv or libev, it is a quick, useful watch.
libuv's event loop is explained in more detail in the `documentation libuv's event loop is explained in more detail in the `documentation
<http://docs.libuv.org/en/v1.x/design.html#the-i-o-loop>`_. <https://docs.libuv.org/en/v1.x/design.html#the-i-o-loop>`_.
.. raw:: html .. raw:: html
@ -109,6 +109,11 @@ A default loop is provided by libuv and can be accessed using
``uv_default_loop()``. You should use this loop if you only want a single ``uv_default_loop()``. You should use this loop if you only want a single
loop. loop.
.. rubric:: default-loop/main.c
.. literalinclude:: ../../code/default-loop/main.c
:language: c
:linenos:
.. note:: .. note::
node.js uses the default loop as its main loop. If you are writing bindings node.js uses the default loop as its main loop. If you are writing bindings
@ -119,9 +124,9 @@ loop.
Error handling Error handling
-------------- --------------
Initialization functions or synchronous functions which may fail return a negative number on error. Async functions that may fail will pass a status parameter to their callbacks. The error messages are defined as ``UV_E*`` `constants`_. Initialization functions or synchronous functions which may fail return a negative number on error. Async functions that may fail will pass a status parameter to their callbacks. The error messages are defined as ``UV_E*`` `constants`_.
.. _constants: http://docs.libuv.org/en/v1.x/errors.html#error-constants .. _constants: https://docs.libuv.org/en/v1.x/errors.html#error-constants
You can use the ``uv_strerror(int)`` and ``uv_err_name(int)`` functions You can use the ``uv_strerror(int)`` and ``uv_err_name(int)`` functions
to get a ``const char *`` describing the error or the error name respectively. to get a ``const char *`` describing the error or the error name respectively.
@ -134,7 +139,7 @@ Handles and Requests
libuv works by the user expressing interest in particular events. This is libuv works by the user expressing interest in particular events. This is
usually done by creating a **handle** to an I/O device, timer or process. usually done by creating a **handle** to an I/O device, timer or process.
Handles are opaque structs named as ``uv_TYPE_t`` where type signifies what the Handles are opaque structs named as ``uv_TYPE_t`` where type signifies what the
handle is used for. handle is used for.
.. rubric:: libuv watchers .. rubric:: libuv watchers
.. code-block:: c .. code-block:: c
@ -169,6 +174,16 @@ handle is used for.
typedef struct uv_udp_send_s uv_udp_send_t; typedef struct uv_udp_send_s uv_udp_send_t;
typedef struct uv_fs_s uv_fs_t; typedef struct uv_fs_s uv_fs_t;
typedef struct uv_work_s uv_work_t; typedef struct uv_work_s uv_work_t;
typedef struct uv_random_s uv_random_t;
/* None of the above. */
typedef struct uv_env_item_s uv_env_item_t;
typedef struct uv_cpu_info_s uv_cpu_info_t;
typedef struct uv_interface_address_s uv_interface_address_t;
typedef struct uv_dirent_s uv_dirent_t;
typedef struct uv_passwd_s uv_passwd_t;
typedef struct uv_utsname_s uv_utsname_t;
typedef struct uv_statfs_s uv_statfs_t;
Handles represent long-lived objects. Async operations on such handles are Handles represent long-lived objects. Async operations on such handles are

View File

@ -13,7 +13,7 @@ Simple filesystem read/write is achieved using the ``uv_fs_*`` functions and the
watchers registered with the event loop when application interaction is watchers registered with the event loop when application interaction is
required. required.
.. _thread pool: http://docs.libuv.org/en/v1.x/threadpool.html#thread-pool-work-scheduling .. _thread pool: https://docs.libuv.org/en/v1.x/threadpool.html#thread-pool-work-scheduling
All filesystem functions have two forms - *synchronous* and *asynchronous*. All filesystem functions have two forms - *synchronous* and *asynchronous*.
@ -66,7 +66,7 @@ The ``result`` field of a ``uv_fs_t`` is the file descriptor in case of the
.. literalinclude:: ../../code/uvcat/main.c .. literalinclude:: ../../code/uvcat/main.c
:language: c :language: c
:linenos: :linenos:
:lines: 26-40 :lines: 26-39
:emphasize-lines: 2,8,12 :emphasize-lines: 2,8,12
In the case of a read call, you should pass an *initialized* buffer which will In the case of a read call, you should pass an *initialized* buffer which will
@ -91,7 +91,7 @@ callbacks.
.. literalinclude:: ../../code/uvcat/main.c .. literalinclude:: ../../code/uvcat/main.c
:language: c :language: c
:linenos: :linenos:
:lines: 16-24 :lines: 17-24
:emphasize-lines: 6 :emphasize-lines: 6
.. warning:: .. warning::
@ -132,6 +132,7 @@ same patterns as the read/write/open calls, returning the result in the
int uv_fs_copyfile(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb); int uv_fs_copyfile(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb);
int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb); int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb);
int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb); int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb);
int uv_fs_mkstemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb);
int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb); int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb);
int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent); int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent);
@ -149,6 +150,7 @@ same patterns as the read/write/open calls, returning the result in the
int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb); int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb);
int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb); int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb);
int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, double mtime, uv_fs_cb cb); int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, double mtime, uv_fs_cb cb);
int uv_fs_lutime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb);
int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb); int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb);
int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb); int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb);
@ -158,6 +160,7 @@ same patterns as the read/write/open calls, returning the result in the
int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb); int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb);
int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb); int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb);
int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb); int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb);
int uv_fs_statfs(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
.. _buffers-and-streams: .. _buffers-and-streams:
@ -190,7 +193,7 @@ and freed by the application.
.. ERROR:: .. ERROR::
THIS PROGRAM DOES NOT ALWAYS WORK, NEED SOMETHING BETTER** **THIS PROGRAM DOES NOT ALWAYS WORK, NEED SOMETHING BETTER**
To demonstrate streams we will need to use ``uv_pipe_t``. This allows streaming To demonstrate streams we will need to use ``uv_pipe_t``. This allows streaming
local files [#]_. Here is a simple tee utility using libuv. Doing all operations local files [#]_. Here is a simple tee utility using libuv. Doing all operations
@ -209,7 +212,7 @@ opened as bidirectional by default.
.. literalinclude:: ../../code/uvtee/main.c .. literalinclude:: ../../code/uvtee/main.c
:language: c :language: c
:linenos: :linenos:
:lines: 61-80 :lines: 62-80
:emphasize-lines: 4,5,15 :emphasize-lines: 4,5,15
The third argument of ``uv_pipe_init()`` should be set to 1 for IPC using named The third argument of ``uv_pipe_init()`` should be set to 1 for IPC using named
@ -285,6 +288,13 @@ a command whenever any of the watched files change::
./onchange <command> <file1> [file2] ... ./onchange <command> <file1> [file2] ...
.. note::
Currently this example only works on OSX and Windows.
Refer to the `notes of uv_fs_event_start`_ function.
.. _notes of uv_fs_event_start: https://docs.libuv.org/en/v1.x/fs_event.html#c.uv_fs_event_start
The file change notification is started using ``uv_fs_event_init()``: The file change notification is started using ``uv_fs_event_init()``:
.. rubric:: onchange/main.c - The setup .. rubric:: onchange/main.c - The setup
@ -300,8 +310,8 @@ argument, ``flags``, can be:
.. code-block:: c .. code-block:: c
/* /*
* Flags to be passed to uv_fs_event_start(). * Flags to be passed to uv_fs_event_start().
*/ */
enum uv_fs_event_flags { enum uv_fs_event_flags {
UV_FS_EVENT_WATCH_ENTRY = 1, UV_FS_EVENT_WATCH_ENTRY = 1,
UV_FS_EVENT_STAT = 2, UV_FS_EVENT_STAT = 2,
@ -319,9 +329,9 @@ The callback will receive the following arguments:
#. ``const char *filename`` - If a directory is being monitored, this is the #. ``const char *filename`` - If a directory is being monitored, this is the
file which was changed. Only non-``null`` on Linux and Windows. May be ``null`` file which was changed. Only non-``null`` on Linux and Windows. May be ``null``
even on those platforms. even on those platforms.
#. ``int flags`` - one of ``UV_RENAME`` or ``UV_CHANGE``, or a bitwise OR of #. ``int events`` - one of ``UV_RENAME`` or ``UV_CHANGE``, or a bitwise OR of
both. both.
#. ``int status`` - Currently 0. #. ``int status`` - If ``status < 0``, there is an :ref:`libuv error<libuv-error-handling>`.
In our example we simply print the arguments and run the command using In our example we simply print the arguments and run the command using
``system()``. ``system()``.

View File

@ -8,7 +8,7 @@ It is meant to cover the main areas of libuv, but is not a comprehensive
reference discussing every function and data structure. The `official libuv reference discussing every function and data structure. The `official libuv
documentation`_ may be consulted for full details. documentation`_ may be consulted for full details.
.. _official libuv documentation: http://docs.libuv.org/en/v1.x/ .. _official libuv documentation: https://docs.libuv.org/en/v1.x/
This book is still a work in progress, so sections may be incomplete, but This book is still a work in progress, so sections may be incomplete, but
I hope you will enjoy it as it grows. I hope you will enjoy it as it grows.
@ -47,25 +47,23 @@ Since then libuv has continued to mature and become a high quality standalone
library for system programming. Users outside of node.js include Mozilla's library for system programming. Users outside of node.js include Mozilla's
Rust_ programming language, and a variety_ of language bindings. Rust_ programming language, and a variety_ of language bindings.
This book and the code is based on libuv version `v1.3.0`_. This book and the code is based on libuv version `v1.42.0`_.
Code Code
---- ----
All the code from this book is included as part of the source of the book on All the example code and the source of the book is included as part of
Github. `Clone`_/`Download`_ the book, then build libuv:: the libuv_ project on Github.
Clone or Download libuv_, then build it::
cd libuv sh autogen.sh
./autogen.sh
./configure ./configure
make make
There is no need to ``make install``. To build the examples run ``make`` in the There is no need to ``make install``. To build the examples run ``make`` in the
``code/`` directory. ``docs/code/`` directory.
.. _Clone: https://github.com/nikhilm/uvbook .. _v1.42.0: https://github.com/libuv/libuv/releases/tag/v1.42.0
.. _Download: https://github.com/nikhilm/uvbook/downloads
.. _v1.3.0: https://github.com/libuv/libuv/tags
.. _V8: https://v8.dev .. _V8: https://v8.dev
.. _libev: http://software.schmorp.de/pkg/libev.html .. _libev: http://software.schmorp.de/pkg/libev.html
.. _libuv: https://github.com/libuv/libuv .. _libuv: https://github.com/libuv/libuv