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:
parent
930af43437
commit
870828c8af
3
docs/code/.gitignore
vendored
Normal file
3
docs/code/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
*/*
|
||||
!*.c
|
||||
!*.h
|
||||
82
docs/code/Makefile
Normal file
82
docs/code/Makefile
Normal 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
|
||||
12
docs/code/default-loop/main.c
Normal file
12
docs/code/default-loop/main.c
Normal 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;
|
||||
}
|
||||
@ -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.
|
||||
|
||||
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
|
||||
|
||||
@ -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
|
||||
loop.
|
||||
|
||||
.. rubric:: default-loop/main.c
|
||||
.. literalinclude:: ../../code/default-loop/main.c
|
||||
:language: c
|
||||
:linenos:
|
||||
|
||||
.. note::
|
||||
|
||||
node.js uses the default loop as its main loop. If you are writing bindings
|
||||
@ -119,9 +124,9 @@ loop.
|
||||
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
|
||||
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
|
||||
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
|
||||
handle is used for.
|
||||
handle is used for.
|
||||
|
||||
.. rubric:: libuv watchers
|
||||
.. code-block:: c
|
||||
@ -169,6 +174,16 @@ handle is used for.
|
||||
typedef struct uv_udp_send_s uv_udp_send_t;
|
||||
typedef struct uv_fs_s uv_fs_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
|
||||
|
||||
@ -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
|
||||
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*.
|
||||
|
||||
@ -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
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 26-40
|
||||
:lines: 26-39
|
||||
:emphasize-lines: 2,8,12
|
||||
|
||||
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
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 16-24
|
||||
:lines: 17-24
|
||||
:emphasize-lines: 6
|
||||
|
||||
.. 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_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_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_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);
|
||||
@ -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_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_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_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);
|
||||
@ -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_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_statfs(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb);
|
||||
|
||||
|
||||
.. _buffers-and-streams:
|
||||
@ -190,7 +193,7 @@ and freed by the application.
|
||||
|
||||
.. 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
|
||||
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
|
||||
:language: c
|
||||
:linenos:
|
||||
:lines: 61-80
|
||||
:lines: 62-80
|
||||
:emphasize-lines: 4,5,15
|
||||
|
||||
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] ...
|
||||
|
||||
.. 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()``:
|
||||
|
||||
.. rubric:: onchange/main.c - The setup
|
||||
@ -300,8 +310,8 @@ argument, ``flags``, can be:
|
||||
.. 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 {
|
||||
UV_FS_EVENT_WATCH_ENTRY = 1,
|
||||
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
|
||||
file which was changed. Only non-``null`` on Linux and Windows. May be ``null``
|
||||
even on those platforms.
|
||||
#. ``int flags`` - one of ``UV_RENAME`` or ``UV_CHANGE``, or a bitwise OR of
|
||||
both.
|
||||
#. ``int status`` - Currently 0.
|
||||
#. ``int events`` - one of ``UV_RENAME`` or ``UV_CHANGE``, or a bitwise OR of
|
||||
both.
|
||||
#. ``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
|
||||
``system()``.
|
||||
|
||||
@ -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
|
||||
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
|
||||
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
|
||||
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
|
||||
----
|
||||
|
||||
All the code from this book is included as part of the source of the book on
|
||||
Github. `Clone`_/`Download`_ the book, then build libuv::
|
||||
All the example code and the source of the book is included as part of
|
||||
the libuv_ project on Github.
|
||||
Clone or Download libuv_, then build it::
|
||||
|
||||
cd libuv
|
||||
./autogen.sh
|
||||
sh autogen.sh
|
||||
./configure
|
||||
make
|
||||
|
||||
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
|
||||
.. _Download: https://github.com/nikhilm/uvbook/downloads
|
||||
.. _v1.3.0: https://github.com/libuv/libuv/tags
|
||||
.. _v1.42.0: https://github.com/libuv/libuv/releases/tag/v1.42.0
|
||||
.. _V8: https://v8.dev
|
||||
.. _libev: http://software.schmorp.de/pkg/libev.html
|
||||
.. _libuv: https://github.com/libuv/libuv
|
||||
|
||||
Loading…
Reference in New Issue
Block a user