LIBUV(1) libuv API documentation LIBUV(1) (NAME) libuv - / (OVERVIEW) libuv / . Node.js Luvit Julia uvloop . : (Pull Requests) ! (FEATURES) o epoll kqueue IOCP event ports. o TCP UDP o (DNS) o o o TTY ANSI o (IPC) () o (Child processes) o (thread pool) o o (High resolution clock) o (DOCUMENTATION) (Design overview) libuv Node.js . / . (polling) / : <<>> (handles) <<>> (streams) / . libuv : [image] (Handles and requests) libuv : (handles) (requests). . : o (prepare handle) . o TCP . . : : getaddrinfo . : 1. uv_foo_init() uv_close() <#c.uv_close> . . 2. . uv_tcp_t <#c.uv_tcp_t> uv_write_t <#c.uv_write_t> . 3. uv_close_cb <#c.uv_close_cb> . 4. init + start/stop . : uv_tcp_t <#c.uv_tcp_t> uv_process_t <#c.uv_process_t> uv_spawn() <#c .uv_spawn> . 5. uv_cancel() <# c.uv_cancel> . 6. uv_fs_t <#c.uv_fs_t> uv_getaddrinfo_t <#c.uv_getaddrinfo_t>. uv_fs_t <#c .uv_fs_t> uv_fs_req_cleanup() <#c.uv_fs_req_cleanup> uv_getaddrinfo_t <#c.uv_getaddrinfo_t> uv_freeaddrinfo() <#c.uv_freeaddrinfo> . 7. . / (The I/O loop) / ( ) libuv . / (thread) . . libuv ( API ) (thread-safe ). / : / () (non- blocking) (poll) : epoll kqueue OSX BSD event ports SunOS IOCP . / (poller) ( ) / . : [image] 1. (<<>> now) . 2. UV_RUN_DEFAULT . now . 3. (alive) . (ref'd) . 4. (Pending) . / (polling) / . . / . 5. (idle handles) . . 6. (prepare handles) . / . 7. (Poll timeout) . / . : o UV_RUN_NOWAIT 0 . o ( uv_stop() <#c.uv_stop> ) 0 . o 0 . o (idle) 0 . o 0 . o . 8. / . / . / (file descriptor) . 9. (check handles) . / . . 10. . uv_close() <#c.uv_close> . 11. (<<>> now) . 12. . <<>> . . 13. . UV_RUN_NOWAIT UV_RUN_ONCE uv_run() <#c.uv_run> . UV_RUN_DEFAULT . : libuv (thread pool) / / ( ) . : (polling) libuv . / (File I/O) / / libuv / (thread pool) . / : . libuv . : o o DNS ( getaddrinfo getnameinfo) o uv_queue_work() <#c .uv_queue_work> : <#threadpool> . (API documentation) (Error handling) libuv . API . . : : errno ( -errno) libuv . (Error constants) UV_E2BIG UV_EACCES UV_EADDRINUSE UV_EADDRNOTAVAIL UV_EAFNOSUPPORT UV_EAGAIN UV_EAI_ADDRFAMILY UV_EAI_AGAIN UV_EAI_BADFLAGS ai_flags UV_EAI_BADHINTS hints UV_EAI_CANCELED UV_EAI_FAIL UV_EAI_FAMILY ai_family UV_EAI_MEMORY UV_EAI_NODATA UV_EAI_NONAME UV_EAI_OVERFLOW UV_EAI_PROTOCOL UV_EAI_SERVICE UV_EAI_SOCKTYPE UV_EALREADY UV_EBADF UV_EBUSY UV_ECANCELED UV_ECHARSET UV_ECONNABORTED UV_ECONNREFUSED UV_ECONNRESET UV_EDESTADDRREQ UV_EEXIST UV_EFAULT UV_EFBIG UV_EHOSTUNREACH UV_EINTR UV_EINVAL UV_EIO / UV_EISCONN UV_EISDIR UV_ELOOP UV_EMFILE UV_EMSGSIZE UV_ENAMETOOLONG UV_ENETDOWN UV_ENETUNREACH UV_ENFILE UV_ENOBUFS UV_ENODEV UV_ENOENT UV_ENOMEM UV_ENONET UV_ENOPROTOOPT UV_ENOSPC UV_ENOSYS UV_ENOTCONN UV_ENOTDIR UV_ENOTEMPTY UV_ENOTSOCK UV_ENOTSUP UV_EOVERFLOW UV_EPERM UV_EPIPE UV_EPROTO UV_EPROTONOSUPPORT UV_EPROTOTYPE UV_ERANGE UV_EROFS UV_ESHUTDOWN UV_ESPIPE UV_ESRCH UV_ETIMEDOUT UV_ETXTBSY UV_EXDEV UV_UNKNOWN UV_EOF UV_ENXIO UV_EMLINK UV_ENOTTY ioctl UV_EFTYPE UV_EILSEQ UV_ESOCKTNOSUPPORT UV_EUNATCH (API) UV_ERRNO_MAP(iter_macro) iter_macro . iter_macro : UV_ . const char *uv_strerror(int err) . . char *uv_strerror_r(int err, char *buf, size_t buflen) . buf buflen . 1.22.0 . const char *uv_err_name(int err) . . char *uv_err_name_r(int err, char *buf, size_t buflen) . buf buflen . 1.22.0 . int uv_translate_sys_error(int sys_errno) libuv : POSIX ( errno ) Win32 ( GetLastError() WSAGetLastError() ). sys_errno libuv . 1.10.0 : . (Version-checking macros and functions) 1.0.0 libuv . . libuv . (Macros) UV_VERSION_MAJOR libuv. UV_VERSION_MINOR libuv. UV_VERSION_PATCH libuv. UV_VERSION_IS_RELEASE 1 libuv 0 . UV_VERSION_SUFFIX libuv. (Release Candidates) "rc" . UV_VERSION_HEX libuv . . libuv 1.2.3 0x010203 . 1.7.0 . (Functions) unsigned int uv_version(void) UV_VERSION_HEX . const char *uv_version_string(void) libuv . . uv_loop_t --- (Event loop) (Event loop) libuv . (polling) / (I/O) (callbacks) . (Data types) type uv_loop_t . enum uv_loop_option . : uv_loop_configure(). typedef enum { UV_LOOP_BLOCK_SIGNAL = 0, UV_METRICS_IDLE_TIME, UV_LOOP_USE_IO_URING_SQPOLL } uv_loop_option; enum uv_run_mode uv_run(). typedef enum { UV_RUN_DEFAULT = 0, UV_RUN_ONCE, UV_RUN_NOWAIT } uv_run_mode; typedef void (*uv_walk_cb)(uv_handle_t <#c.uv_handle_t> *handle, void *arg) uv_walk(). (Public members) void *uv_loop_t <#c.uv_loop_t>.data . libuv . (API) int uv_loop_init(uv_loop_t <#c.uv_loop_t> *loop) uv_loop_t . int uv_loop_configure(uv_loop_t <#c.uv_loop_t> *loop, uv_loop_option <# c.uv_loop_option> option, ...) 1.0.2. . uv_run() . 0 UV_E* . UV_ENOSYS . : o UV_LOOP_BLOCK_SIGNAL: (polling) . uv_loop_configure() . SIGPROF (sampling profiler) . UV_EINVAL . o UV_METRICS_IDLE_TIME: (event provider) . uv_metrics_idle_time() <#c.uv_metrics_idle_time> . o UV_LOOP_USE_IO_URING_SQPOLL: SQPOLL io_uring . 1.39.0: UV_METRICS_IDLE_TIME . 1.49.0: UV_LOOP_USE_IO_URING_SQPOLL . int uv_loop_close(uv_loop_t <#c.uv_loop_t> *loop) . UV_EBUSY . . uv_loop_t <#c.uv_loop_t> *uv_default_loop(void) . NULL . uv_loop_init() . ( ) uv_loop_close() . : (thread-safe ). int uv_run(uv_loop_t <#c.uv_loop_t> *loop, uv_run_mode <#c.uv_run_mode> mode) . : o UV_RUN_DEFAULT: . uv_stop() . . o UV_RUN_ONCE: / (poll) . (block) . ( ) ( ) . o UV_RUN_NOWAIT: / . ( ) . uv_run() (reentrant) . . int uv_loop_alive(const uv_loop_t <#c.uv_loop_t> *loop) . void uv_stop(uv_loop_t <#c.uv_loop_t> *loop) uv_run() . (iteration) . / / . size_t uv_loop_size(void) uv_loop_t . FFI . int uv_backend_fd(const uv_loop_t <#c.uv_loop_t> *loop) (file descriptor) . kqueue epoll event ports . uv_run(loop, UV_RUN_NOWAIT) (thread) test/test-embed.c . : fd kqueue (pollset) kqueue . fd . int uv_backend_timeout(const uv_loop_t <#c.uv_loop_t> *loop) (poll timeout) . -1 . uint64_t uv_now(const uv_loop_t <#c.uv_loop_t> *loop) . (cache) uv_update_time() . (monotonically) . . : uv_hrtime() <#c.uv_hrtime> . void uv_update_time(uv_loop_t <#c.uv_loop_t> *loop) <<>> (now) . Libuv (cache) . <<>> . void uv_walk(uv_loop_t <#c.uv_loop_t> *loop, uv_walk_cb <#c.uv_walk_cb> walk_cb, void *arg) : walk_cb arg . int uv_loop_fork(uv_loop_t <#c.uv_loop_t> *loop) 1.12.0. fork(2) . (watchers) . ( ). uv_run() API . . . fork . UV_ENOSYS . : . . API ABI . : Mac OS X (FS event) FSEvent . FS event kqueue . : AIX SunOS (forking) . . : uv_backend_fd() . . void *uv_loop_get_data(const uv_loop_t <#c.uv_loop_t> *loop) loop->data . 1.19.0. void uv_loop_set_data(uv_loop_t <#c.uv_loop_t> *loop, void *data) loop->data data . 1.19.0. uv_handle_t --- (Base handle) uv_handle_t libuv . libuv uv_handle_t (cast) . API . Libuv (non-movable) . . (stack) . (Data types) type uv_handle_t libuv. enum uv_handle_type libuv. typedef enum { UV_UNKNOWN_HANDLE = 0, UV_ASYNC, UV_CHECK, UV_FS_EVENT, UV_FS_POLL, UV_HANDLE, UV_IDLE, UV_NAMED_PIPE, UV_POLL, UV_PREPARE, UV_PROCESS, UV_STREAM, UV_TCP, UV_TIMER, UV_TTY, UV_UDP, UV_SIGNAL, UV_FILE, UV_HANDLE_TYPE_MAX } uv_handle_type; type uv_any_handle (Union) . typedef void (*uv_alloc_cb)(uv_handle_t <#c.uv_handle_t> *handle, size_t suggested_size, uv_buf_t <#c.uv_buf_t> *buf) uv_read_start() <#c .uv_read_start> uv_udp_recv_start() <#c.uv_udp_recv_start>. uv_buf_t <#c.uv_buf_t> . NULL (base) 0 UV_ENOBUFS uv_udp_recv_cb <#c .uv_udp_recv_cb> uv_read_cb <#c.uv_read_cb> . uv_udp_recv_cb <#c .uv_udp_recv_cb> uv_read_cb <#c.uv_read_cb> . ( 65536) . . freelist (allocation pools) slab . : static void my_alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { buf->base = malloc(suggested_size); buf->len = suggested_size; } typedef void (*uv_close_cb)(uv_handle_t <#c.uv_handle_t> *handle) uv_close(). (Public members) uv_loop_t <#c.uv_loop_t> *uv_handle_t <#c.uv_handle_t>.loop uv_loop_t <#c.uv_loop_t> . . uv_handle_type <#c.uv_handle_type> uv_handle_t <#c.uv_handle_t>.type uv_handle_type . . void *uv_handle_t <#c.uv_handle_t>.data . libuv . (API) UV_HANDLE_TYPE_MAP(iter_macro) iter_macro . iter_macro : uv_handle_type UV_ uv_ _t. int uv_is_active(const uv_handle_t <#c.uv_handle_t> *handle) . <<>> : o uv_async_t uv_close(). o uv_pipe_t uv_tcp_t uv_udp_t - / - / . o uv_check_t uv_idle_t uv_timer_t uv_check_start() uv_idle_start() . : uv_foo_t uv_foo_start() . uv_foo_stop() . int uv_is_closing(const uv_handle_t <#c.uv_handle_t> *handle) . : (close callback) . void uv_close(uv_handle_t <#c.uv_handle_t> *handle, uv_close_cb <#c .uv_close_cb> close_cb) . close_cb . . close_cb . close_cb . . uv_connect_t uv_write_t status=UV_ECANCELED . close_cb NULL . void uv_ref(uv_handle_t <#c.uv_handle_t> *handle) . (idempotent) . : (Reference counting). void uv_unref(uv_handle_t <#c.uv_handle_t> *handle) . . : (Reference counting). int uv_has_ref(const uv_handle_t <#c.uv_handle_t> *handle) . : (Reference counting). size_t uv_handle_size(uv_handle_type <#c.uv_handle_type> type) . FFI . (Miscellaneous API functions) API uv_handle_t . int uv_send_buffer_size(uv_handle_t <#c.uv_handle_t> *handle, int *value) . *value == 0 *value . *value > 0 *value . . TCP UDP TCP UDP . : . int uv_recv_buffer_size(uv_handle_t <#c.uv_handle_t> *handle, int *value) . *value == 0 *value . *value > 0 *value . . TCP UDP TCP UDP . : . int uv_fileno(const uv_handle_t <#c.uv_handle_t> *handle, uv_os_fd_t <# c.uv_os_fd_t> *fd) . : TCP TTY UDP poll. UV_EINVAL . UV_EBADF . : . libuv . uv_loop_t <#c.uv_loop_t> *uv_handle_get_loop(const uv_handle_t <#c .uv_handle_t> *handle) handle->loop . 1.19.0. void *uv_handle_get_data(const uv_handle_t <#c.uv_handle_t> *handle) handle->data . 1.19.0. void uv_handle_set_data(uv_handle_t <#c.uv_handle_t> *handle, void *data) handle->data data . 1.19.0. uv_handle_type <#c.uv_handle_type> uv_handle_get_type(const uv_handle_t <#c.uv_handle_t> *handle) handle->type . 1.19.0. const char *uv_handle_type_name(uv_handle_type <#c.uv_handle_type> type) "pipe" ( uv_pipe_t <#c.uv_pipe_t>) UV_NAMED_PIPE. NULL . 1.19.0. (Reference counting) libuv ( ) . uv_unref() uv_timer_start() <#c .uv_timer_start>. (idempotent) . uv_is_active() . uv_req_t --- (Base request) uv_req_t libuv . libuv uv_req_t (cast) . API . (Data types) type uv_req_t libuv. type uv_any_req (Union) . enum uv_req_type libuv. typedef enum { UV_UNKNOWN_REQ = 0, UV_REQ, UV_CONNECT, UV_WRITE, UV_SHUTDOWN, UV_UDP_SEND, UV_FS, UV_WORK, UV_GETADDRINFO, UV_GETNAMEINFO, UV_REQ_TYPE_MAX, } uv_req_type; (Public members) void *uv_req_t <#c.uv_req_t>.data . libuv . uv_req_type <#c.uv_req_type> uv_req_t <#c.uv_req_t>.type uv_req_type . . (API) UV_REQ_TYPE_MAP(iter_macro) iter_macro . iter_macro : uv_req_type UV_ uv_ _t. int uv_cancel(uv_req_t <#c.uv_req_t> *req) . . 0 < 0 . uv_fs_t <#c.uv_fs_t> uv_getaddrinfo_t <#c.uv_getaddrinfo_t> uv_getnameinfo_t <#c .uv_getnameinfo_t> uv_random_t <#c.uv_random_t> uv_work_t <#c.uv_work_t> . . . : o req->result uv_fs_t <#c.uv_fs_t> UV_ECANCELED . o uv_work_t <#c.uv_work_t> uv_getaddrinfo_t <#c.uv_getaddrinfo_t> uv_getnameinfo_t <#c .uv_getnameinfo_t> uv_random_t <#c.uv_random_t> status == UV_ECANCELED . size_t uv_req_size(uv_req_type <#c.uv_req_type> type) . FFI . void *uv_req_get_data(const uv_req_t <#c.uv_req_t> *req) req->data . 1.19.0. void uv_req_set_data(uv_req_t <#c.uv_req_t> *req, void *data) req->data data . 1.19.0. uv_req_type <#c.uv_req_type> uv_req_get_type(const uv_req_t <#c .uv_req_t> *req) req->type . 1.19.0. const char *uv_req_type_name(uv_req_type <#c.uv_req_type> type) "connect" ( uv_connect_t <#c.uv_connect_t>) UV_CONNECT. NULL . 1.19.0. uv_timer_t --- (Timer handle) . (single-shot) . <<>> (rearm) . Libuv <<>> / . : uv_update_time() <#c.uv_update_time>. : 50 17 33 . 33 . (Data types) type uv_timer_t . typedef void (*uv_timer_cb)(uv_timer_t <#c.uv_timer_t> *handle) uv_timer_start(). (Public members) (N/A) : uv_handle_t <#c.uv_handle_t> . (API) int uv_timer_init(uv_loop_t <#c.uv_loop_t> *loop, uv_timer_t <#c .uv_timer_t> *handle) . int uv_timer_start(uv_timer_t <#c.uv_timer_t> *handle, uv_timer_cb <#c .uv_timer_cb> cb, uint64_t timeout, uint64_t repeat) . timeout repeat . timeout . repeat timeout repeat . : <<>> . uv_update_time() <#c.uv_update_time> . . int uv_timer_stop(uv_timer_t <#c.uv_timer_t> *handle) . int uv_timer_again(uv_timer_t <#c.uv_timer_t> *handle) repeat (timeout) . UV_EINVAL . void uv_timer_set_repeat(uv_timer_t <#c.uv_timer_t> *handle, uint64_t repeat) . (time-slice overrun) . : . . . uint64_t uv_timer_get_repeat(const uv_timer_t <#c.uv_timer_t> *handle) . uint64_t uv_timer_get_due_in(const uv_timer_t <#c.uv_timer_t> *handle) 0 . uv_now() <#c.uv_now> . 1.40.0. : API uv_handle_t <#c.uv_handle_t> . uv_prepare_t --- (Prepare handle) (Prepare) (poll) / . (Data types) type uv_prepare_t (Prepare). typedef void (*uv_prepare_cb)(uv_prepare_t <#c.uv_prepare_t> *handle) uv_prepare_start(). (Public members) (N/A) : uv_handle_t <#c.uv_handle_t> . (API) int uv_prepare_init(uv_loop_t <#c.uv_loop_t> *loop, uv_prepare_t <#c .uv_prepare_t> *prepare) . . 0 int uv_prepare_start(uv_prepare_t <#c.uv_prepare_t> *prepare, uv_prepare_cb <#c.uv_prepare_cb> cb) . cb NULL . 0 UV_EINVAL cb == NULL . int uv_prepare_stop(uv_prepare_t <#c.uv_prepare_t> *prepare) . . 0 : API uv_handle_t <#c.uv_handle_t> . uv_check_t --- (Check handle) (Check) / . (Data types) type uv_check_t (Check). typedef void (*uv_check_cb)(uv_check_t <#c.uv_check_t> *handle) uv_check_start(). (Public members) (N/A) : uv_handle_t <#c.uv_handle_t> . (API) int uv_check_init(uv_loop_t <#c.uv_loop_t> *loop, uv_check_t <#c .uv_check_t> *check) . . 0 int uv_check_start(uv_check_t <#c.uv_check_t> *check, uv_check_cb <#c .uv_check_cb> cb) . cb NULL . 0 UV_EINVAL cb == NULL . int uv_check_stop(uv_check_t <#c.uv_check_t> *check) . . 0 : API uv_handle_t <#c.uv_handle_t> . uv_idle_t --- (Idle handle) (Idle) uv_prepare_t <#c .uv_prepare_t> . : / (zero timeout poll) . : <<>> (idle) . (Data types) type uv_idle_t (Idle). typedef void (*uv_idle_cb)(uv_idle_t <#c.uv_idle_t> *handle) uv_idle_start(). (Public members) (N/A) : uv_handle_t <#c.uv_handle_t> . (API) int uv_idle_init(uv_loop_t <#c.uv_loop_t> *loop, uv_idle_t <#c .uv_idle_t> *idle) . . 0 int uv_idle_start(uv_idle_t <#c.uv_idle_t> *idle, uv_idle_cb <#c .uv_idle_cb> cb) . cb NULL . 0 UV_EINVAL cb == NULL . int uv_idle_stop(uv_idle_t <#c.uv_idle_t> *idle) . . 0 : API uv_handle_t <#c.uv_handle_t> . uv_async_t --- (Async handle) (Async) <<>> (wakeup) . (Data types) type uv_async_t (Async). typedef void (*uv_async_cb)(uv_async_t <#c.uv_async_t> *handle) uv_async_init(). (Public members) (N/A) : uv_handle_t <#c.uv_handle_t> . (API) int uv_async_init(uv_loop_t <#c.uv_loop_t> *loop, uv_async_t <#c .uv_async_t> *async, uv_async_cb <#c.uv_async_cb> async_cb) . NULL . 0 < 0 . : . int uv_async_send(uv_async_t <#c.uv_async_t> *async) . 0 < 0 . : . . : uv_async_send() (async-signal-safe) . (signal handler) . : libuv uv_async_send() (coalesce) . : uv_async_send() 5 . uv_async_send() . : API uv_handle_t <#c.uv_handle_t> . uv_poll_t --- (Poll handle) (Poll handles) poll(2) . c-ares libssh2. uv_poll_t uv_tcp_t <#c.uv_tcp_t> uv_udp_t <#c.uv_udp_t> uv_poll_t . . EAGAIN . (busyloop) libuv . . . uv_poll_stop() uv_close() <#c.uv_close> . : . poll(2) . : AIX (disconnection) . (Data types) type uv_poll_t (Poll handle). typedef void (*uv_poll_cb)(uv_poll_t <#c.uv_poll_t> *handle, int status, int events) uv_poll_start(). enum uv_poll_event (Poll event types) enum uv_poll_event { UV_READABLE = 1, UV_WRITABLE = 2, UV_DISCONNECT = 4, UV_PRIORITIZED = 8 }; (Public members) (N/A) : uv_handle_t <#c.uv_handle_t> . (API) int uv_poll_init(uv_loop_t <#c.uv_loop_t> *loop, uv_poll_t <#c .uv_poll_t> *handle, int fd) (file descriptor). 1.2.2: (non-blocking) . int uv_poll_init_socket(uv_loop_t <#c.uv_loop_t> *loop, uv_poll_t <#c .uv_poll_t> *handle, uv_os_sock_t <#c.uv_os_sock_t> socket) . uv_poll_init() . SOCKET . 1.2.2: (non-blocking) . int uv_poll_start(uv_poll_t <#c.uv_poll_t> *handle, int events, uv_poll_cb <#c.uv_poll_cb> cb) . events UV_READABLE UV_WRITABLE UV_PRIORITIZED UV_DISCONNECT . 0 status events . UV_PRIORITIZED sysfs (out-of-band) TCP . UV_DISCONNECT . status 0 UV_E* ( <# errors> ). . . status == UV_EBADF . uv_close() <#c.uv_close> . : uv_poll_start() . . : UV_DISCONNECT AIX events . : UV_READABLE UV_WRITABLE / : o / / . o ( UV_READABLE ). o ( UV_WRITABLE ). o uv_poll_start() / . ( ). (level triggering) . 1.9.0: UV_DISCONNECT . 1.14.0: UV_PRIORITIZED . int uv_poll_stop(uv_poll_t <#c.uv_poll_t> *poll) . : uv_poll_stop() : . : uv_handle_t <#c.uv_handle_t> . uv_signal_t --- (Signal handle) . (Windows notes) : o SIGINT CTRL+C . (terminal raw mode) . o SIGBREAK CTRL + BREAK . o SIGHUP . SIGHUP . . o SIGWINCH libuv . libuv libuv SIGWINCH . SIGWINCH . uv_tty_t <#c.uv_tty_t> libuv . uv_tty_t <#c.uv_tty_t> (raw mode) . o (watchers) . : SIGILL SIGABRT SIGFPE SIGSEGV SIGTERM SIGKILL. o raise() abort() libuv . 1.15.0: SIGWINCH . 1.31.0: libuv SIGWINCH . (Unix notes) o SIGKILL SIGSTOP . o SIGBUS SIGFPE SIGILL SIGSEGV libuv . o SIGABRT abort() ( assert()) libuv . o SIGRT0 SIGRT1 ( ) NPTL pthreads . . libuv . (Data types) type uv_signal_t (Signal handle). typedef void (*uv_signal_cb)(uv_signal_t <#c.uv_signal_t> *handle, int signum) uv_signal_start(). (Public members) int uv_signal_t <#c.uv_signal_t>.signum . . : uv_handle_t <#c.uv_handle_t> . (API) int uv_signal_init(uv_loop_t <#c.uv_loop_t> *loop, uv_signal_t <#c .uv_signal_t> *signal) . int uv_signal_start(uv_signal_t <#c.uv_signal_t> *signal, uv_signal_cb <#c.uv_signal_cb> cb, int signum) . int uv_signal_start_oneshot(uv_signal_t <#c.uv_signal_t> *signal, uv_signal_cb <#c.uv_signal_cb> cb, int signum) 1.12.0. uv_signal_start() . int uv_signal_stop(uv_signal_t <#c.uv_signal_t> *signal) . : uv_handle_t <#c.uv_handle_t> . uv_process_t --- (Process handle) (spawn) (streams) . (Data types) type uv_process_t (Process handle). type uv_process_options_t ( uv_spawn()). typedef struct uv_process_options_s { uv_exit_cb exit_cb; const char* file; char** args; char** env; const char* cwd; unsigned int flags; int stdio_count; uv_stdio_container_t* stdio; uv_uid_t uid; uv_gid_t gid; } uv_process_options_t; typedef void (*uv_exit_cb)(uv_process_t <#c.uv_process_t>*, int64_t exit_status, int term_signal) uv_process_options_t . enum uv_process_flags flags uv_process_options_t . enum uv_process_flags { /* * Set the child process' user id. */ UV_PROCESS_SETUID = (1 << 0), /* * Set the child process' group id. */ UV_PROCESS_SETGID = (1 << 1), /* * Do not wrap any arguments in quotes, or perform any other escaping, when * converting the argument list into a command line string. This option is * only meaningful on Windows systems. On Unix it is silently ignored. */ UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = (1 << 2), /* * Spawn the child process in a detached state - this will make it a process * group leader, and will effectively enable the child to keep running after * the parent exits. Note that the child process will still keep the * parent's event loop alive unless the parent process calls uv_unref() on * the child's process handle. */ UV_PROCESS_DETACHED = (1 << 3), /* * Hide the subprocess window that would normally be created. This option is * only meaningful on Windows systems. On Unix it is silently ignored. */ UV_PROCESS_WINDOWS_HIDE = (1 << 4), /* * Hide the subprocess console window that would normally be created. This * option is only meaningful on Windows systems. On Unix it is silently * ignored. */ UV_PROCESS_WINDOWS_HIDE_CONSOLE = (1 << 5), /* * Hide the subprocess GUI window that would normally be created. This * option is only meaningful on Windows systems. On Unix it is silently * ignored. */ UV_PROCESS_WINDOWS_HIDE_GUI = (1 << 6), /* * On Windows, if the path to the program to execute, specified in * uv_process_options_t's file field, has a directory component, * search for the exact file name before trying variants with * extensions like '.exe' or '.cmd'. */ UV_PROCESS_WINDOWS_FILE_PATH_EXACT_NAME = (1 << 7) }; type uv_stdio_container_t stdio . typedef struct uv_stdio_container_s { uv_stdio_flags flags; union { uv_stream_t* stream; int fd; } data; } uv_stdio_container_t; enum uv_stdio_flags stdio . typedef enum { /* * The following four options are mutually-exclusive, and define * the operation to perform for the corresponding file descriptor * in the child process: */ /* * No file descriptor will be provided (or redirected to * `/dev/null` if it is fd 0, 1 or 2). */ UV_IGNORE = 0x00, /* * Open a new pipe into `data.stream`, per the flags below. The * `data.stream` field must point to a uv_pipe_t object that has * been initialized with `uv_pipe_init(loop, data.stream, ipc);`, * but not yet opened or connected. /* UV_CREATE_PIPE = 0x01, /* * The child process will be given a duplicate of the parent's * file descriptor given by `data.fd`. */ UV_INHERIT_FD = 0x02, /* * The child process will be given a duplicate of the parent's * file descriptor being used by the stream handle given by * `data.stream`. */ UV_INHERIT_STREAM = 0x04, /* * When UV_CREATE_PIPE is specified, UV_READABLE_PIPE and UV_WRITABLE_PIPE * determine the direction of flow, from the child process' perspective. Both * flags may be specified to create a duplex data stream. */ UV_READABLE_PIPE = 0x10, UV_WRITABLE_PIPE = 0x20, /* * When UV_CREATE_PIPE is specified, specifying UV_NONBLOCK_PIPE opens the * handle in non-blocking mode in the child. This may cause loss of data, * if the child is not designed to handle to encounter this mode, * but can also be significantly more efficient. */ UV_NONBLOCK_PIPE = 0x40 } uv_stdio_flags; (Public members) int uv_process_t <#c.uv_process_t>.pid (PID) . uv_spawn() . : uv_handle_t <#c.uv_handle_t> . uv_exit_cb <#c.uv_exit_cb> uv_process_options_t <#c .uv_process_options_t>.exit_cb . const char *uv_process_options_t <#c.uv_process_options_t>.file . char **uv_process_options_t <#c.uv_process_options_t>.args . args[0] . CreateProcess . UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS uv_process_flags . char **uv_process_options_t <#c.uv_process_options_t>.env . NULL . const char *uv_process_options_t <#c.uv_process_options_t>.cwd . unsigned int uv_process_options_t <#c.uv_process_options_t>.flags uv_spawn() . uv_process_flags . int uv_process_options_t <#c.uv_process_options_t>.stdio_count uv_stdio_container_t <#c.uv_stdio_container_t> *uv_process_options_t <# c.uv_process_options_t>.stdio stdio uv_stdio_container_t . stdio[0] (stdin) 1 (stdout) 2 (stderr) . : MSVCRT . uv_uid_t uv_process_options_t <#c.uv_process_options_t>.uid uv_gid_t uv_process_options_t <#c.uv_process_options_t>.gid libuv / . flags . : uv_spawn() UV_ENOTSUP . uv_stdio_flags <#c.uv_stdio_flags> uv_stdio_container_t <#c .uv_stdio_container_t>.flags stdio . union [anonymous] uv_stdio_container_t <#c.uv_stdio_container_t>.data (Union) stream fd . (API) void uv_disable_stdio_inheritance(void) / . . . : : libuv . . int uv_spawn(uv_loop_t <#c.uv_loop_t> *loop, uv_process_t <#c .uv_process_t> *handle, const uv_process_options_t <#c .uv_process_options_t> *options) . 0 . . ( ) setuid setgid . 1.24.0: UV_PROCESS_WINDOWS_HIDE_CONSOLE UV_PROCESS_WINDOWS_HIDE_GUI . 1.48.0: UV_PROCESS_WINDOWS_FILE_PATH_EXACT_NAME . int uv_process_kill(uv_process_t <#c.uv_process_t> *handle, int signum) . uv_signal_t --- Signal handle <#signal> . int uv_kill(int pid, int signum) (PID) . uv_signal_t --- Signal handle <#signal> . uv_pid_t <#c.uv_pid_t> uv_process_get_pid(const uv_process_t <#c .uv_process_t> *handle) handle->pid . 1.19.0. : uv_handle_t <#c.uv_handle_t> . uv_stream_t --- (Stream handle) (duplex) . uv_stream_t libuv uv_tcp_t <#c.uv_tcp_t> uv_pipe_t <#c .uv_pipe_t> uv_tty_t <#c.uv_tty_t> . (Data types) type uv_stream_t (Stream handle). type uv_connect_t (Connect request). type uv_shutdown_t / (Shutdown request). type uv_write_t (Write request). . (non-blocking) uv_write . . uv_write_t uv_write . typedef void (*uv_read_cb)(uv_stream_t <#c.uv_stream_t> *stream, ssize_t nread, const uv_buf_t <#c.uv_buf_t> *buf) . nread 0 0 . (EOF) nread UV_EOF . nread 0 buf buf.len buf.base 0 . : nread 0 . EAGAIN EWOULDBLOCK read(2) . / uv_read_stop() uv_close() <#c .uv_close> . . libuv . ( buf->base == NULL buf->len == 0 ) . typedef void (*uv_write_cb)(uv_write_t <#c.uv_write_t> *req, int status) . status 0 0 . typedef void (*uv_connect_cb)(uv_connect_t <#c.uv_connect_t> *req, int status) uv_connect() . status 0 0 . typedef void (*uv_shutdown_cb)(uv_shutdown_t <#c.uv_shutdown_t> *req, int status) (shutdown). status 0 0 . typedef void (*uv_connection_cb)(uv_stream_t <#c.uv_stream_t> *server, int status) . uv_accept() . status 0 0 . (Public members) size_t uv_stream_t <#c.uv_stream_t>.write_queue_size . . uv_stream_t <#c.uv_stream_t> *uv_connect_t <#c.uv_connect_t>.handle . uv_stream_t <#c.uv_stream_t> *uv_shutdown_t <#c.uv_shutdown_t>.handle . uv_stream_t <#c.uv_stream_t> *uv_write_t <#c.uv_write_t>.handle . uv_stream_t <#c.uv_stream_t> *uv_write_t <#c.uv_write_t>.send_handle . : uv_handle_t <#c.uv_handle_t> . (API) int uv_shutdown(uv_shutdown_t <#c.uv_shutdown_t> *req, uv_stream_t <#c .uv_stream_t> *handle, uv_shutdown_cb <#c.uv_shutdown_cb> cb) () (duplex). . handle . req . cb . int uv_listen(uv_stream_t <#c.uv_stream_t> *stream, int backlog, uv_connection_cb <#c.uv_connection_cb> cb) . backlog listen(2) . uv_connection_cb . int uv_accept(uv_stream_t <#c.uv_stream_t> *server, uv_stream_t <#c .uv_stream_t> *client) uv_listen() . uv_connection_cb . . 0 . uv_connection_cb . . uv_connection_cb . : server client . int uv_read_start(uv_stream_t <#c.uv_stream_t> *stream, uv_alloc_cb <#c .uv_alloc_cb> alloc_cb, uv_read_cb <#c.uv_read_cb> read_cb) . uv_read_cb uv_read_stop() . 1.38.0: uv_read_start() UV_EALREADY UV_EINVAL . libuv UV_EALREADY UV_EINVAL . int uv_read_stop(uv_stream_t <#c.uv_stream_t>*) . uv_read_cb . (idempotent) . . TTY . int uv_write(uv_write_t <#c.uv_write_t> *req, uv_stream_t <#c .uv_stream_t> *handle, const uv_buf_t <#c.uv_buf_t> bufs[], unsigned int nbufs, uv_write_cb <#c.uv_write_cb> cb) . . : void cb(uv_write_t* req, int status) { /* Logic which handles the write result */ } uv_buf_t a[] = { { .base = "1", .len = 1 }, { .base = "2", .len = 1 } }; uv_buf_t b[] = { { .base = "3", .len = 1 }, { .base = "4", .len = 1 } }; uv_write_t req1; uv_write_t req2; /* writes "1234" */ uv_write(&req1, stream, a, 2, cb); uv_write(&req2, stream, b, 2, cb); : . uv_write2() . int uv_write2(uv_write_t <#c.uv_write_t> *req, uv_stream_t <#c .uv_stream_t> *handle, const uv_buf_t <#c.uv_buf_t> bufs[], unsigned int nbufs, uv_stream_t <#c.uv_stream_t> *send_handle, uv_write_cb <#c .uv_write_cb> cb) (pipe). ipc == 1 . : send_handle TCP (pipe) UDP TCP ( ) . (bound) . int uv_try_write(uv_stream_t <#c.uv_stream_t> *handle, const uv_buf_t <#c.uv_buf_t> bufs[], unsigned int nbufs) uv_write() . : o 0: ( ). o 0: ( UV_EAGAIN ). int uv_try_write2(uv_stream_t <#c.uv_stream_t> *handle, const uv_buf_t <#c.uv_buf_t> bufs[], unsigned int nbufs, uv_stream_t <#c.uv_stream_t> *send_handle) uv_try_write() c:func:uv_write2 . UV_EAGAIN . 1.42.0. int uv_is_readable(const uv_stream_t <#c.uv_stream_t> *handle) 1 0 . int uv_is_writable(const uv_stream_t <#c.uv_stream_t> *handle) 1 0 . int uv_stream_set_blocking(uv_stream_t <#c.uv_stream_t> *handle, int blocking) (blocking mode) . . . : . uv_pipe_t <#c.uv_pipe_t> . uv_stream_t . libuv . . 1.4.0: . size_t uv_stream_get_write_queue_size(const uv_stream_t <#c .uv_stream_t> *stream) stream->write_queue_size . 1.19.0. : uv_handle_t <#c.uv_handle_t> . uv_tcp_t --- (TCP handle) TCP TCP . uv_tcp_t uv_stream_t <#c.uv_stream_t> . (Data types) type uv_tcp_t TCP (TCP handle). enum uv_tcp_flags uv_tcp_bind(). enum uv_tcp_flags { /* Used with uv_tcp_bind, when an IPv6 address is used. */ UV_TCP_IPV6ONLY = 1, /* Enable SO_REUSEPORT socket option when binding the handle. * This allows completely duplicate bindings by multiple processes * or threads if they all set SO_REUSEPORT before binding the port. * Incoming connections are distributed across the participating * listener sockets. * * This flag is available only on Linux 3.9+, DragonFlyBSD 3.6+, * FreeBSD 12.0+, Solaris 11.4, and AIX 7.2.5+ for now. */ UV_TCP_REUSEPORT = 2, }; (Public members) (N/A) : uv_stream_t <#c.uv_stream_t> . (API) int uv_tcp_init(uv_loop_t <#c.uv_loop_t> *loop, uv_tcp_t <#c.uv_tcp_t> *handle) . . int uv_tcp_init_ex(uv_loop_t <#c.uv_loop_t> *loop, uv_tcp_t <#c .uv_tcp_t> *handle, unsigned int flags) . flags (socket domain) . . AF_UNSPEC uv_tcp_init(). 1.7.0. int uv_tcp_open(uv_tcp_t <#c.uv_tcp_t> *handle, uv_os_sock_t <#c .uv_os_sock_t> sock) SOCKET TCP. 1.2.1: (non-blocking) . : SOCKET (stream socket) . int uv_tcp_nodelay(uv_tcp_t <#c.uv_tcp_t> *handle, int enable) TCP_NODELAY Nagle . int uv_tcp_keepalive(uv_tcp_t <#c.uv_tcp_t> *handle, int enable, unsigned int delay) / TCP keep-alive. delay enable . delay . UV_ETIMEDOUT . delay UV_EINVAL . 1.49.0: delay UV_EINVAL` . int uv_tcp_keepalive_ex(uv_tcp_t <#c.uv_tcp_t> *handle, int on, unsigned int idle, unsigned int intvl, unsigned int cnt) / TCP keep-alive : TCP_KEEPIDLE TCP_KEEPINTVL TCP_KEEPCNT. idle TCP_KEEPIDLE intvl TCP_KEEPINTVL cnt TCP_KEEPCNT on . TCP keep-alive idle ( ) keep-alive TCP . intvl ( ) . TCP cnt UV_ETIMEDOUT . idle intvl cnt UV_EINVAL . 1.52.0: TCP_KEEPINTVL TCP_KEEPCNT . : . : o AIX o DragonFlyBSD o FreeBSD o illumos o Linux o macOS o NetBSD o Solaris o Windows int uv_tcp_simultaneous_accepts(uv_tcp_t <#c.uv_tcp_t> *handle, int enable) / (simultaneous accepts) TCP . TCP . ( ) . int uv_tcp_bind(uv_tcp_t <#c.uv_tcp_t> *handle, const struct sockaddr *addr, unsigned int flags) (bind) . UV_EADDRINUSE uv_listen() <#c.uv_listen> uv_tcp_connect() UV_TCP_REUSEPORT flags . uv_listen() <#c.uv_listen> uv_tcp_connect() . o handle -- TCP. uv_tcp_init() . o addr -- . struct sockaddr_in struct sockaddr_in6 . o flags -- . UV_TCP_IPV6ONLY flags (dual-stack) IPv6 . UV_TCP_REUSEPORT flags SO_REUSEPORT . 0 0 . 1.49.0: UV_TCP_REUSEPORT . : UV_TCP_REUSEPORT Linux 3.9+ DragonFlyBSD 3.6+ FreeBSD 12.0+ Solaris 11.4 AIX 7.2.5+ . UV_ENOTSUP . int uv_tcp_getsockname(const uv_tcp_t <#c.uv_tcp_t> *handle, struct sockaddr *name, int *namelen) . name struct sockaddr_storage IPv4 IPv6 . int uv_tcp_getpeername(const uv_tcp_t <#c.uv_tcp_t> *handle, struct sockaddr *name, int *namelen) (peer). name struct sockaddr_storage IPv4 IPv6 . int uv_tcp_connect(uv_connect_t <#c.uv_connect_t> *req, uv_tcp_t <#c .uv_tcp_t> *handle, const struct sockaddr *addr, uv_connect_cb <#c .uv_connect_cb> cb) TCP IPv4 IPv6. TCP uv_connect_t <#c.uv_connect_t> . addr struct sockaddr_in struct sockaddr_in6 . addr (0.0.0.0 ::) localhost . . . 1.19.0: 0.0.0.0 :: localhost . : uv_stream_t <#c.uv_stream_t> . int uv_tcp_close_reset(uv_tcp_t <#c.uv_tcp_t> *handle, uv_close_cb <#c .uv_close_cb> close_cb) TCP RST. SO_LINGER (linger interval) uv_close() <#c .uv_close> . uv_shutdown() <#c.uv_shutdown> uv_tcp_close_reset() . 1.32.0. int uv_socketpair(int type, int protocol, uv_os_sock_t <#c .uv_os_sock_t> socket_vector[2], int flags0, int flags1) . uv_tcp_open uv_spawn . flags0 flags1 : o UV_NONBLOCK_PIPE: / OVERLAPPED FIONBIO/O_NONBLOCK . libuv . socketpair(2) AF_UNIX. 1.41.0. uv_pipe_t --- (Pipe handle) ( FIFO) . uv_pipe_t <<>> uv_stream_t <#c .uv_stream_t> . (Data types) type uv_pipe_t . (Public members) int uv_pipe_t <#c.uv_pipe_t>.ipc . uv_accept . (See also): uv_stream_t <#c.uv_stream_t> . (API) int uv_pipe_init(uv_loop_t <#c.uv_loop_t> *loop, uv_pipe_t <#c .uv_pipe_t> *handle, int ipc) . ipc ( ). uv_accept . int uv_pipe_open(uv_pipe_t <#c.uv_pipe_t> *handle, uv_file <#c.uv_file> file) HANDLE . 1.2.1: (non-blocking) . : HANDLE . int uv_pipe_bind(uv_pipe_t <#c.uv_pipe_t> *handle, const char *name) ( ) ( ). uv_pipe_bind2() (abstract namespace) . uv_pipe_bind2(handle, name, strlen(name), 0). : sizeof(sockaddr_un.sun_path) (truncate) . int uv_pipe_bind2(uv_pipe_t <#c.uv_pipe_t> *handle, const char *name, size_t namelen, unsigned int flags) ( ) ( ). flags UV_PIPE_NO_TRUNCATE . bind UV_EINVAL . . namelen nul nul . 1.46.0. : sizeof(sockaddr_un.sun_path) UV_PIPE_NO_TRUNCATE UV_EINVAL . void uv_pipe_connect(uv_connect_t <#c.uv_connect_t> *req, uv_pipe_t <#c .uv_pipe_t> *handle, const char *name, uv_connect_cb <#c.uv_connect_cb> cb) . uv_pipe_connect2() . uv_pipe_connect2(req, handle, name, strlen(name), 0, cb). : sizeof(sockaddr_un.sun_path) . int uv_pipe_connect2(uv_connect_t <#c.uv_connect_t> *req, uv_pipe_t <#c .uv_pipe_t> *handle, const char *name, size_t namelen, unsigned int flags, uv_connect_cb <#c.uv_connect_cb> cb) . flags UV_PIPE_NO_TRUNCATE . UV_EINVAL . . namelen nul nul . 1.46.0. : sizeof(sockaddr_un.sun_path) UV_PIPE_NO_TRUNCATE UV_EINVAL . int uv_pipe_getsockname(const uv_pipe_t <#c.uv_pipe_t> *handle, char *buffer, size_t *size) . . size . UV_ENOBUFS len . 1.3.0: (null) null . int uv_pipe_getpeername(const uv_pipe_t <#c.uv_pipe_t> *handle, char *buffer, size_t *size) . . size . UV_ENOBUFS len . 1.3.0. void uv_pipe_pending_instances(uv_pipe_t <#c.uv_pipe_t> *handle, int count) . : . int uv_pipe_pending_count(uv_pipe_t <#c.uv_pipe_t> *handle) uv_handle_type <#c.uv_handle_type> uv_pipe_pending_type(uv_pipe_t <#c .uv_pipe_t> *handle) IPC . uv_pipe_pending_count() (type) uv_pipe_pending_type() uv_accept(pipe, handle) . (See also): API uv_stream_t <#c .uv_stream_t> . int uv_pipe_chmod(uv_pipe_t <#c.uv_pipe_t> *handle, int flags) . . UV_WRITABLE UV_READABLE UV_WRITABLE | UV_READABLE . (blocking) . 1.16.0. int uv_pipe(uv_file <#c.uv_file> fds[2], int read_flags, int write_flags) . fds[1] fds[0] . uv_pipe_open uv_spawn . flags : o UV_NONBLOCK_PIPE: / OVERLAPPED FIONBIO/O_NONBLOCK . libuv . pipe(2) O_CLOEXEC. 1.41.0. uv_tty_t --- TTY (TTY handle) TTY . uv_tty_t <<>> uv_stream_t <#c .uv_stream_t> . (Data types) type uv_tty_t TTY. enum uv_tty_mode_t 1.2.0. TTY: typedef enum { /* / */ UV_TTY_MODE_NORMAL, /* * ( ENABLE_WINDOW_INPUT ). * libuv UV_TTY_MODE_RAW_VT . */ UV_TTY_MODE_RAW, /* / IPC ( ) */ UV_TTY_MODE_IO, /* . ENABLE_VIRTUAL_TERMINAL_INPUT . */ UV_TTY_MODE_RAW_VT } uv_tty_mode_t; enum uv_tty_vtermstate_t : typedef enum { /* * * ( ConEmu) */ UV_TTY_SUPPORTED, /* . ( ) */ UV_TTY_UNSUPPORTED } uv_tty_vtermstate_t (Public members) (N/A) (See also): uv_stream_t <#c.uv_stream_t> . (API) int uv_tty_init(uv_loop_t <#c.uv_loop_t> *loop, uv_tty_t <#c.uv_tty_t> *handle, uv_file <#c.uv_file> fd, int unused) TTY . : o 0 = (stdin) o 1 = (stdout) o 2 = (stderr) fd ttyname_r(3) TTY . libuv TTY TTY . ioctl TIOCGPTN TIOCPTYGNAME ( OpenBSD Solaris) (thread-safe) . : TTY libuv (blocking) . 1.23.1: readable . . 1.9.0: TTY ttyname_r(3) . libuv /dev/tty . 1.5.0: TTY UV_EINVAL . int uv_tty_set_mode(uv_tty_t <#c.uv_tty_t> *handle, uv_tty_mode_t <#c .uv_tty_mode_t> mode) 1.2.0: uv_tty_mode_t . TTY . int uv_tty_reset_mode(void) . TTY . async signal-safe uv_tty_set_mode() UV_EBUSY . int uv_tty_get_winsize(uv_tty_t <#c.uv_tty_t> *handle, int *width, int *height) . . (See also): API uv_stream_t <#c .uv_stream_t> . void uv_tty_set_vterm_state(uv_tty_vtermstate_t <#c .uv_tty_vtermstate_t> state) libuv . ConEmu ANSI X3.64 Xterm . . . . 1.33.0. int uv_tty_get_vterm_state(uv_tty_vtermstate_t <#c.uv_tty_vtermstate_t> *state) libuv . UV_ENOTSUP . 1.33.0. uv_udp_t --- UDP (UDP handle) UDP UDP . (Data types) type uv_udp_t UDP. type uv_udp_send_t UDP. enum uv_udp_flags uv_udp_bind() uv_udp_recv_cb.. enum uv_udp_flags { /* dual stack */ UV_UDP_IPV6ONLY = 1, /* * . * . uv_udp_recv_cb . */ UV_UDP_PARTIAL = 2, /* * bind SO_REUSEADDR . * BSD ( DragonFlyBSD) OS X SO_REUSEPORT * SO_REUSEPORT * ( UV_UDP_REUSEPORT). SO_REUSEADDR * . * ( ) * <<>>. */ UV_UDP_REUSEADDR = 4, /* * recvmmsg * recv_cb . */ UV_UDP_MMSG_CHUNK = 8, /* * recvmmsg * recv_cb . uv_udp_recv_cb * nread 0 addr NULL . */ UV_UDP_MMSG_FREE = 16, /* * bind IP_RECVERR/IPV6_RECVERR . * IP_RECVERR IPv4 IPV6_RECVERR IPv6 * . ICMP * ICMP . * (no-op) . */ UV_UDP_LINUX_RECVERR = 32, /* * bind SO_REUSEPORT . * SO_REUSEPORT . * UV_UDP_REUSEADDR * << >> * . * * +3.9 +3.6 * +12.0 11.4 AIX +7.2.5 . */ UV_UDP_REUSEPORT = 64, /* * recvmmsg . */ UV_UDP_RECVMMSG = 256 }; typedef void (*uv_udp_send_cb)(uv_udp_send_t <#c.uv_udp_send_t> *req, int status) uv_udp_send() . typedef void (*uv_udp_recv_cb)(uv_udp_t <#c.uv_udp_t> *handle, ssize_t nread, const uv_buf_t <#c.uv_buf_t> *buf, const struct sockaddr *addr, unsigned flags) uv_udp_recv_start() . o handle: UDP o nread: . . ( addr NULL ). recvmmsg(2) . o buf: uv_buf_t <#c.uv_buf_t> . o addr: struct sockaddr* . NULL . . o flags: UV_UDP_* OR . libuv . ( buf->base == NULL buf->len == 0 ). recvmmsg(2) UV_UDP_MMSG_CHUNK . nread addr NULL UV_UDP_MMSG_CHUNK UV_UDP_MMSG_FREE . UDP nread . . 1.40.0: UV_UDP_MMSG_FREE . : nread == 0 addr == NULL UDP nread == 0 addr != NULL . enum uv_membership (multicast). typedef enum { UV_LEAVE_GROUP = 0, UV_JOIN_GROUP } uv_membership; (Public members) size_t uv_udp_t <#c.uv_udp_t>.send_queue_size . . size_t uv_udp_t <#c.uv_udp_t>.send_queue_count . uv_udp_t <#c.uv_udp_t> *uv_udp_send_t <#c.uv_udp_send_t>.handle UDP . (See also): uv_handle_t <#c.uv_handle_t> . (API) int uv_udp_init(uv_loop_t <#c.uv_loop_t> *loop, uv_udp_t <#c.uv_udp_t> *handle) UDP . (lazily) . . int uv_udp_init_ex(uv_loop_t <#c.uv_loop_t> *loop, uv_udp_t <#c .uv_udp_t> *handle, unsigned int flags) . flags (domain) . . AF_UNSPEC uv_udp_init() . : o UV_UDP_RECVMMSG: recvmmsg(2) . 1.7.0. 1.37.0: UV_UDP_RECVMMSG . int uv_udp_open_ex(uv_udp_t <#c.uv_udp_t> *handle, uv_os_sock_t <#c .uv_os_sock_t> sock, unsigned int flags) SOCKET UDP. (Parameters) o handle -- UDP. uv_udp_init() . o sock -- . o flags -- UV_UDP_REUSEADDR UV_UDP_REUSEPORT . (Returns) . 1.52.0. int uv_udp_open(uv_udp_t <#c.uv_udp_t> *handle, uv_os_sock_t <#c .uv_os_sock_t> sock) SOCKET UDP. : sock ( sendmsg()/recvmsg() ). raw sockets netlink sockets . 1.2.1: . : SOCKET . SO_REUSEADDR . . uv_udp_open_ex() . int uv_udp_bind(uv_udp_t <#c.uv_udp_t> *handle, const struct sockaddr *addr, unsigned int flags) UDP IP . (Parameters) o handle -- UDP. uv_udp_init() . o addr -- struct sockaddr_in struct sockaddr_in6 . o flags -- bind UV_UDP_IPV6ONLY UV_UDP_REUSEADDR UV_UDP_REUSEPORT UV_UDP_RECVERR . (Returns) . 1.49.0: UV_UDP_REUSEPORT . : UV_UDP_REUSEPORT +3.9 +3.6 +12.0 11.4 AIX +7.2.5 . UV_ENOTSUP . SO_REUSEPORT UV_UDP_REUSEADDR UV_UDP_REUSEPORT flags SO_REUSEPORT SO_REUSEADDR (override) . SO_REUSEPORT UV_UDP_REUSEADDR UV_UDP_REUSEPORT UV_ENOTSUP . int uv_udp_connect(uv_udp_t <#c.uv_udp_t> *handle, const struct sockaddr *addr) UDP . addr NULL . uv_udp_connect() UV_EISCONN . UV_ENOTCONN . (Parameters) o handle -- UDP. uv_udp_init() . o addr -- struct sockaddr_in struct sockaddr_in6 . (Returns) . 1.27.0. int uv_udp_getpeername(const uv_udp_t <#c.uv_udp_t> *handle, struct sockaddr *name, int *namelen) IP UDP. UV_ENOTCONN . (Parameters) o handle -- UDP. uv_udp_init() bind . o name -- . IPv4 IPv6 struct sockaddr_storage . o namelen -- name . . (Returns) . 1.27.0. int uv_udp_getsockname(const uv_udp_t <#c.uv_udp_t> *handle, struct sockaddr *name, int *namelen) IP UDP. (Parameters) o handle -- UDP. uv_udp_init() bind . o name -- . IPv4 IPv6 struct sockaddr_storage . o namelen -- name . . (Returns) . int uv_udp_set_membership(uv_udp_t <#c.uv_udp_t> *handle, const char *multicast_addr, const char *interface_addr, uv_membership <#c .uv_membership> membership) (multicast). (Parameters) o handle -- UDP. uv_udp_init() . o multicast_addr -- . o interface_addr -- (interface). o membership -- UV_JOIN_GROUP UV_LEAVE_GROUP . (Returns) . int uv_udp_set_source_membership(uv_udp_t <#c.uv_udp_t> *handle, const char *multicast_addr, const char *interface_addr, const char *source_addr, uv_membership <#c.uv_membership> membership) (source-specific multicast). (Parameters) o handle -- UDP. uv_udp_init() . o multicast_addr -- . o interface_addr -- . o source_addr -- . o membership -- UV_JOIN_GROUP UV_LEAVE_GROUP . (Returns) . 1.32.0. int uv_udp_set_multicast_loop(uv_udp_t <#c.uv_udp_t> *handle, int on) IP (multicast loop). . (Parameters) o handle -- UDP. uv_udp_init_ex() AF_INET AF_INET6 uv_udp_bind() uv_udp_send() uv_udp_recv_start() . o on -- . (Returns) . int uv_udp_set_multicast_ttl(uv_udp_t <#c.uv_udp_t> *handle, int ttl) TTL . (Parameters) o handle -- UDP. uv_udp_init_ex() AF_INET AF_INET6 uv_udp_bind() uv_udp_send() uv_udp_recv_start() . o ttl -- . (Returns) . int uv_udp_set_multicast_interface(uv_udp_t <#c.uv_udp_t> *handle, const char *interface_addr) . (Parameters) o handle -- UDP. uv_udp_init_ex() AF_INET AF_INET6 uv_udp_bind() uv_udp_send() uv_udp_recv_start() . o interface_addr -- . (Returns) . int uv_udp_set_broadcast(uv_udp_t <#c.uv_udp_t> *handle, int on) (broadcast). (Parameters) o handle -- UDP. uv_udp_init_ex() AF_INET AF_INET6 uv_udp_bind() uv_udp_send() uv_udp_recv_start() . o on -- . (Returns) . int uv_udp_set_ttl(uv_udp_t <#c.uv_udp_t> *handle, int ttl) (Time To Live / TTL). (Parameters) o handle -- UDP. uv_udp_init_ex() AF_INET AF_INET6 uv_udp_bind() uv_udp_send() uv_udp_recv_start() . o ttl -- . (Returns) . int uv_udp_send(uv_udp_send_t <#c.uv_udp_send_t> *req, uv_udp_t <#c .uv_udp_t> *handle, const uv_buf_t <#c.uv_buf_t> bufs[], unsigned int nbufs, const struct sockaddr *addr, uv_udp_send_cb <#c.uv_udp_send_cb> send_cb) UDP. uv_udp_bind() 0.0.0.0 ( IPv4 << >>) . addr (0.0.0.0 ::) localhost . UDP addr NULL UV_EISCONN . UDP addr NULL UV_EDESTADDRREQ . (Parameters) o req -- UDP. . o handle -- UDP. uv_udp_init() . o bufs -- . o nbufs -- bufs. o addr -- struct sockaddr_in struct sockaddr_in6 . o send_cb -- . (Returns) . 1.19.0: 0.0.0.0 :: localhost . 1.27.0: . int uv_udp_try_send(uv_udp_t <#c.uv_udp_t> *handle, const uv_buf_t <#c .uv_buf_t> bufs[], unsigned int nbufs, const struct sockaddr *addr) uv_udp_send() . UDP addr NULL UV_EISCONN . UDP addr NULL UV_EDESTADDRREQ . (Returns) >= 0: ( ). < 0: ( UV_EAGAIN ). 1.27.0: . int uv_udp_try_send2(uv_udp_t <#c.uv_udp_t> *handle, unsigned int count, uv_buf_t <#c.uv_buf_t> *bufs[/*count*/], unsigned int nbufs[/*count*/], struct sockaddr *addrs[/*count*/], unsigned int flags) uv_udp_try_send() . sendmmsg(2) sendmsg(2) . uv_udp_bind . (Returns) >= 0: . count . < 0: . . UV_EAGAIN uv_udp_send() . 1.50.0. int uv_udp_recv_start(uv_udp_t <#c.uv_udp_t> *handle, uv_alloc_cb <#c .uv_alloc_cb> alloc_cb, uv_udp_recv_cb <#c.uv_udp_recv_cb> recv_cb) . uv_udp_bind() 0.0.0.0 ( IPv4 << >>) . (Parameters) o handle -- UDP. uv_udp_init() . o alloc_cb -- . o recv_cb -- . (Returns) . : recvmmsg(2) alloc_cb suggested_size alloc_cb udp_recv . 1.35.0: recvmmsg(2) . 2 * 64KB alloc_cb . 1.37.0: recvmmsg(2) UV_UDP_RECVMMSG uv_udp_init_ex() . 1.39.0: uv_udp_using_recvmmsg() alloc_cb recvmmsg(2) / . int uv_udp_using_recvmmsg(uv_udp_t <#c.uv_udp_t> *handle) UDP UV_UDP_RECVMMSG recvmmsg(2) . 1.39.0. int uv_udp_recv_stop(uv_udp_t <#c.uv_udp_t> *handle) . (Parameters) o handle -- UDP. uv_udp_init() . (Returns) . size_t uv_udp_get_send_queue_size(const uv_udp_t <#c.uv_udp_t> *handle) handle->send_queue_size . 1.19.0. size_t uv_udp_get_send_queue_count(const uv_udp_t <#c.uv_udp_t> *handle) handle->send_queue_count . 1.19.0. (See also): API uv_handle_t <#c .uv_handle_t> . uv_fs_event_t --- (FS Event handle) FS Event . . : AIX IBM bos.ahafs . AIX (ahafs) : o ahafs (thread-safe) . . o ( ) . . z/OS . . (Data types) type uv_fs_event_t FS Event. typedef void (*uv_fs_event_cb)(uv_fs_event_t <#c.uv_fs_event_t> *handle, const char *filename, int events, int status) uv_fs_event_start() . filename NULL . events OR uv_fs_event . : FreeBSD NULL . enum uv_fs_event uv_fs_event_t . enum uv_fs_event { UV_RENAME = 1, UV_CHANGE = 2 }; enum uv_fs_event_flags uv_fs_event_start() . enum uv_fs_event_flags { /* * * . * fs_event . * . * . */ UV_FS_EVENT_WATCH_ENTRY = 1, /* * uv_fs_event inotify * kqueue . * NFS . fs_event * stat() . * . */ UV_FS_EVENT_STAT = 2, /* * * ( ). * . */ UV_FS_EVENT_RECURSIVE = 4 }; (Public members) (N/A) (See also): uv_handle_t <#c.uv_handle_t> . (API) int uv_fs_event_init(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_event_t <#c .uv_fs_event_t> *handle) . int uv_fs_event_start(uv_fs_event_t <#c.uv_fs_event_t> *handle, uv_fs_event_cb <#c.uv_fs_event_cb> cb, const char *path, unsigned int flags) path . flags OR uv_fs_event_flags . : UV_FS_EVENT_RECURSIVE macOS . : macOS uv_fs_event_start uv_fs_event_cb . int uv_fs_event_stop(uv_fs_event_t <#c.uv_fs_event_t> *handle) . int uv_fs_event_getpath(uv_fs_event_t <#c.uv_fs_event_t> *handle, char *buffer, size_t *size) . . . buffer size . UV_ENOBUFS size null . 1.3.0: (null) null . 1.9.0: UV_ENOBUFS null . (See also): API uv_handle_t <#c .uv_handle_t> . uv_fs_poll_t --- (FS Poll handle) FS Poll . uv_fs_event_t <#c.uv_fs_event_t> fs poll stat fs event . (Data types) type uv_fs_poll_t FS Poll. typedef void (*uv_fs_poll_cb)(uv_fs_poll_t <#c.uv_fs_poll_t> *handle, int status, const uv_stat_t <#c.uv_stat_t> *prev, const uv_stat_t <#c .uv_stat_t> *curr) uv_fs_poll_start() . path status < 0 . ( ) . status == 0 uv_stat_t <#c.uv_stat_t> . . (Public members) (N/A) (See also): uv_handle_t <#c.uv_handle_t> . (API) int uv_fs_poll_init(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_poll_t <#c .uv_fs_poll_t> *handle) . int uv_fs_poll_start(uv_fs_poll_t <#c.uv_fs_poll_t> *handle, uv_fs_poll_cb <#c.uv_fs_poll_cb> poll_cb, const char *path, unsigned int interval) path interval . : . . int uv_fs_poll_stop(uv_fs_poll_t <#c.uv_fs_poll_t> *handle) . int uv_fs_poll_getpath(uv_fs_poll_t <#c.uv_fs_poll_t> *handle, char *buffer, size_t *size) . . . buffer size . UV_ENOBUFS size . 1.3.0: (null) null . 1.9.0: UV_ENOBUFS null . (See also): API uv_handle_t <#c .uv_handle_t> . (File system operations) libuv (sync) (async) . (callback) NULL . NULL . . <#threadpool> . libuv v1.45.0 io_uring . ( ) / (throughput) . Libuv . libuv v1.49.0 Libuv . io_uring uv_loop_t <#c .uv_loop_t> UV_LOOP_USE_IO_URING_SQPOLL . : uv_fs_* utf-8 . (Data types) type uv_fs_t . type uv_timespec_t (Y2K38-unsafe) . libuv v2.0 uv_timespec64_t <#c.uv_timespec64_t> . typedef struct { long tv_sec; long tv_nsec; } uv_timespec_t; type uv_stat_t struct stat. typedef struct { uint64_t st_dev; uint64_t st_mode; uint64_t st_nlink; uint64_t st_uid; uint64_t st_gid; uint64_t st_rdev; uint64_t st_ino; uint64_t st_size; uint64_t st_blksize; uint64_t st_blocks; uint64_t st_flags; uint64_t st_gen; uv_timespec_t st_atim; uv_timespec_t st_mtim; uv_timespec_t st_ctim; uv_timespec_t st_birthtim; } uv_stat_t; enum uv_fs_type . typedef enum { UV_FS_UNKNOWN = -1, UV_FS_CUSTOM, UV_FS_OPEN, UV_FS_CLOSE, UV_FS_READ, UV_FS_WRITE, UV_FS_SENDFILE, UV_FS_STAT, UV_FS_LSTAT, UV_FS_FSTAT, UV_FS_FTRUNCATE, UV_FS_UTIME, UV_FS_FUTIME, UV_FS_ACCESS, UV_FS_CHMOD, UV_FS_FCHMOD, UV_FS_FSYNC, UV_FS_FDATASYNC, UV_FS_UNLINK, UV_FS_RMDIR, UV_FS_MKDIR, UV_FS_MKDTEMP, UV_FS_RENAME, UV_FS_SCANDIR, UV_FS_LINK, UV_FS_SYMLINK, UV_FS_READLINK, UV_FS_CHOWN, UV_FS_FCHOWN, UV_FS_REALPATH, UV_FS_COPYFILE, UV_FS_LCHOWN, UV_FS_OPENDIR, UV_FS_READDIR, UV_FS_CLOSEDIR, UV_FS_MKSTEMP, UV_FS_LUTIME } uv_fs_type; type uv_statfs_t struct statfs. uv_fs_statfs() . typedef struct uv_statfs_s { uint64_t f_type; uint64_t f_bsize; uint64_t f_blocks; uint64_t f_bfree; uint64_t f_bavail; uint64_t f_files; uint64_t f_ffree; uint64_t f_frsize; uint64_t f_spare[3]; } uv_statfs_t; enum uv_dirent_type_t (dirent). typedef enum { UV_DIRENT_UNKNOWN, UV_DIRENT_FILE, UV_DIRENT_DIR, UV_DIRENT_LINK, UV_DIRENT_FIFO, UV_DIRENT_SOCKET, UV_DIRENT_CHAR, UV_DIRENT_BLOCK } uv_dirent_type_t; type uv_dirent_t () struct dirent. uv_fs_scandir_next() . typedef struct uv_dirent_s { const char* name; uv_dirent_type_t type; } uv_dirent_t; type uv_dir_t . uv_fs_opendir() uv_fs_readdir() uv_fs_closedir() . dirents uv_dirent_t`s . `nentries dirents . typedef struct uv_dir_s { uv_dirent_t* dirents; size_t nentries; } uv_dir_t; typedef void (*uv_fs_cb)(uv_fs_t <#c.uv_fs_t> *req) . (Public members) uv_loop_t <#c.uv_loop_t> *uv_fs_t <#c.uv_fs_t>.loop . . uv_fs_type <#c.uv_fs_type> uv_fs_t <#c.uv_fs_t>.fs_type FS. const char *uv_fs_t <#c.uv_fs_t>.path . ssize_t uv_fs_t <#c.uv_fs_t>.result . . uv_fs_read() uv_fs_write() . uv_stat_t <#c.uv_stat_t> uv_fs_t <#c.uv_fs_t>.statbuf uv_fs_stat() stat . void *uv_fs_t <#c.uv_fs_t>.ptr uv_fs_readlink() uv_fs_realpath() (alias) statbuf . : uv_req_t <#c.uv_req_t> . (API) void uv_fs_req_cleanup(uv_fs_t <#c.uv_fs_t> *req) . libuv . int uv_fs_close(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, uv_file <#c.uv_file> file, uv_fs_cb <#c.uv_fs_cb> cb) close(2) . int uv_fs_open(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *path, int flags, int mode, uv_fs_cb <#c.uv_fs_cb> cb) open(2) . : libuv CreateFileW (binary) . O_BINARY O_TEXT . int uv_fs_read(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, uv_file <#c.uv_file> file, const uv_buf_t <#c.uv_buf_t> bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb <#c.uv_fs_cb> cb) preadv(2) . offset -1 . : MSVC ( GCC Clang libuv ) UV_FS_O_FILEMAP . int uv_fs_unlink(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *path, uv_fs_cb <#c.uv_fs_cb> cb) unlink(2) . int uv_fs_write(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, uv_file <#c.uv_file> file, const uv_buf_t <#c.uv_buf_t> bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb <#c.uv_fs_cb> cb) pwritev(2) . offset -1 . : MSVC ( GCC Clang libuv ) UV_FS_O_FILEMAP . int uv_fs_mkdir(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *path, int mode, uv_fs_cb <#c.uv_fs_cb> cb) mkdir(2) . : mode . int uv_fs_mkdtemp(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *tpl, uv_fs_cb <#c.uv_fs_cb> cb) mkdtemp(3) . null req->path . int uv_fs_mkstemp(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *tpl, uv_fs_cb <#c.uv_fs_cb> cb) mkstemp(3) . null req->path . (file descriptor) req->result . 1.34.0. int uv_fs_rmdir(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *path, uv_fs_cb <#c.uv_fs_cb> cb) rmdir(2) . int uv_fs_opendir(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *path, uv_fs_cb <#c.uv_fs_cb> cb) path . uv_dir_t req->ptr . uv_fs_req_cleanup() req->ptr NULL . uv_fs_closedir() . . uv_dir_t uv_fs_readdir() . 1.28.0. int uv_fs_closedir(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, uv_dir_t <#c.uv_dir_t> *dir, uv_fs_cb <#c.uv_fs_cb> cb) dir uv_fs_opendir() . 1.28.0. int uv_fs_readdir(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, uv_dir_t <#c.uv_dir_t> *dir, uv_fs_cb <#c.uv_fs_cb> cb) dir uv_fs_opendir() . uv_fs_readdir() dir->dirents dir->nentries uv_dirent_t . >= 0 . 1.28.0. : uv_fs_readdir() (thread safe ). : "." ".." . : uv_fs_req_cleanup() . uv_fs_req_cleanup() uv_fs_closedir() . int uv_fs_scandir(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *path, int flags, uv_fs_cb <#c.uv_fs_cb> cb) int uv_fs_scandir_next(uv_fs_t <#c.uv_fs_t> *req, uv_dirent_t <#c .uv_dirent_t> *ent) scandir(3) API . uv_fs_scandir_next() ent . UV_EOF . : scandir(3) "." ".." . : (btrfs ext2 ext3 ext4 ) getdents(2) . int uv_fs_stat(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *path, uv_fs_cb <#c.uv_fs_cb> cb) int uv_fs_fstat(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, uv_file <#c.uv_file> file, uv_fs_cb <#c.uv_fs_cb> cb) int uv_fs_lstat(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *path, uv_fs_cb <#c.uv_fs_cb> cb) stat(2) fstat(2) lstat(2) . int uv_fs_statfs(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *path, uv_fs_cb <#c.uv_fs_cb> cb) statfs(2) . uv_statfs_t req->ptr . uv_fs_req_cleanup() . : uv_statfs_t . 1.31.0. int uv_fs_rename(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *path, const char *new_path, uv_fs_cb <#c.uv_fs_cb> cb) rename(2) . int uv_fs_fsync(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, uv_file <#c.uv_file> file, uv_fs_cb <#c.uv_fs_cb> cb) fsync(2) . : AIX uv_fs_fsync UV_EBADF . int uv_fs_fdatasync(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c .uv_fs_t> *req, uv_file <#c.uv_file> file, uv_fs_cb <#c.uv_fs_cb> cb) fdatasync(2) . int uv_fs_ftruncate(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c .uv_fs_t> *req, uv_file <#c.uv_file> file, int64_t offset, uv_fs_cb <#c .uv_fs_cb> cb) ftruncate(2) . int uv_fs_copyfile(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *path, const char *new_path, int flags, uv_fs_cb <#c .uv_fs_cb> cb) path new_path . flags . o UV_FS_COPYFILE_EXCL: uv_fs_copyfile() UV_EEXIST . . o UV_FS_COPYFILE_FICLONE: uv_fs_copyfile() (copy-on-write reflink) . copy-on-write uv_fs_sendfile() . o UV_FS_COPYFILE_FICLONE_FORCE: uv_fs_copyfile() (copy-on-write reflink) . copy-on-write . : . . 1.14.0. 1.20.0: UV_FS_COPYFILE_FICLONE UV_FS_COPYFILE_FICLONE_FORCE . 1.33.0: UV_FS_COPYFILE_FICLONE_FORCE . UV_ENOTSUP . int uv_fs_sendfile(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, uv_file <#c.uv_file> out_fd, uv_file <#c.uv_file> in_fd, int64_t in_offset, size_t length, uv_fs_cb <#c.uv_fs_cb> cb) sendfile(2) . int uv_fs_access(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *path, int mode, uv_fs_cb <#c.uv_fs_cb> cb) access(2) . GetFileAttributesW() . int uv_fs_chmod(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *path, int mode, uv_fs_cb <#c.uv_fs_cb> cb) int uv_fs_fchmod(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, uv_file <#c.uv_file> file, int mode, uv_fs_cb <#c.uv_fs_cb> cb) chmod(2) fchmod(2) . int uv_fs_utime(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *path, double atime, double mtime, uv_fs_cb <#c .uv_fs_cb> cb) int uv_fs_futime(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, uv_file <#c.uv_file> file, double atime, double mtime, uv_fs_cb <#c.uv_fs_cb> cb) int uv_fs_lutime(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *path, double atime, double mtime, uv_fs_cb <#c .uv_fs_cb> cb) utime(2) futimes(3) lutimes(3) . UV_FS_UTIME_NOW atime mtime . UV_FS_UTIME_OMIT atime mtime . : z/OS: uv_fs_lutime() z/OS . UV_ENOSYS . : AIX: uv_fs_futime() uv_fs_lutime() AIX 7.1 . UV_ENOSYS . 1.10.0: (sub-second precision) . int uv_fs_link(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *path, const char *new_path, uv_fs_cb <#c.uv_fs_cb> cb) link(2) . int uv_fs_symlink(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *path, const char *new_path, int flags, uv_fs_cb <#c .uv_fs_cb> cb) symlink(2) . : flags (symlink) : o UV_FS_SYMLINK_DIR: path . o UV_FS_SYMLINK_JUNCTION: (junction points) . int uv_fs_readlink(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *path, uv_fs_cb <#c.uv_fs_cb> cb) readlink(2) . req->ptr . int uv_fs_realpath(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *path, uv_fs_cb <#c.uv_fs_cb> cb) realpath(3) . GetFinalPathNameByHandleW . req->ptr . : Node . o macOS BSD: UV_ELOOP . . o : (corner case) : o (ramdisk) (Volume Manager) ( ImDisk) . o (drive letters). o subst . . . 1.8.0. int uv_fs_chown(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb <#c .uv_fs_cb> cb) int uv_fs_fchown(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, uv_file <#c.uv_file> file, uv_uid_t uid, uv_gid_t gid, uv_fs_cb <#c.uv_fs_cb> cb) int uv_fs_lchown(uv_loop_t <#c.uv_loop_t> *loop, uv_fs_t <#c.uv_fs_t> *req, const char *path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb <#c .uv_fs_cb> cb) chown(2) fchown(2) lchown(2) . : . 1.21.0: uv_fs_lchown . uv_fs_type <#c.uv_fs_type> uv_fs_get_type(const uv_fs_t <#c.uv_fs_t> *req) req->fs_type . 1.19.0. ssize_t uv_fs_get_result(const uv_fs_t <#c.uv_fs_t> *req) req->result . 1.19.0. int uv_fs_get_system_error(const uv_fs_t <#c.uv_fs_t> *req) - GetLastError() -(req->result) . 1.38.0. void *uv_fs_get_ptr(const uv_fs_t <#c.uv_fs_t> *req) req->ptr . 1.19.0. const char *uv_fs_get_path(const uv_fs_t <#c.uv_fs_t> *req) req->path . 1.19.0. uv_stat_t <#c.uv_stat_t> *uv_fs_get_statbuf(uv_fs_t <#c.uv_fs_t> *req) &req->statbuf . 1.19.0. : API uv_req_t <#c.uv_req_t> . (Helper functions) uv_os_fd_t <#c.uv_os_fd_t> uv_get_osfhandle(int fd) C . fd . _get_osfhandle . C fd . 1.12.0. int uv_open_osfhandle(uv_os_fd_t <#c.uv_os_fd_t> os_fd) C . os_fd . _open_osfhandle . . 1.23.0. (File open constants) UV_FS_O_APPEND (append) . . UV_FS_O_CREAT . UV_FS_O_DIRECT / (I/O) (user-space) (aligned) . . : UV_FS_O_DIRECT FILE_FLAG_NO_BUFFERING . UV_FS_O_DIRECT macOS . UV_FS_O_DIRECTORY . : UV_FS_O_DIRECTORY . UV_FS_O_DSYNC I/O . (metadata) . : UV_FS_O_DSYNC FILE_FLAG_WRITE_THROUGH . UV_FS_O_EXCL O_CREAT . : O_EXCL O_CREAT . : 2.6 O_EXCL O_CREAT . ( /mount ) EBUSY . UV_FS_O_EXLOCK (exclusive lock) . : UV_FS_O_EXLOCK macOS . 1.17.0: . UV_FS_O_FILEMAP . . : UV_FS_O_FILEMAP . UV_FS_O_NOATIME . : UV_FS_O_NOATIME . UV_FS_O_NOCTTY ( ). : UV_FS_O_NOCTTY . UV_FS_O_NOFOLLOW . : UV_FS_O_NOFOLLOW . UV_FS_O_NONBLOCK (nonblocking) . : UV_FS_O_NONBLOCK . UV_FS_O_RANDOM . (hint) . : UV_FS_O_RANDOM FILE_FLAG_RANDOM_ACCESS . UV_FS_O_RDONLY . UV_FS_O_RDWR . UV_FS_O_SEQUENTIAL . (hint) . : UV_FS_O_SEQUENTIAL FILE_FLAG_SEQUENTIAL_SCAN . UV_FS_O_SHORT_LIVED . : UV_FS_O_SHORT_LIVED FILE_ATTRIBUTE_TEMPORARY . UV_FS_O_SYMLINK . UV_FS_O_SYNC I/O . (metadata) . : UV_FS_O_SYNC FILE_FLAG_WRITE_THROUGH . UV_FS_O_TEMPORARY . : UV_FS_O_TEMPORARY FILE_ATTRIBUTE_TEMPORARY . UV_FS_O_TRUNC (truncate ). UV_FS_O_WRONLY . (Thread pool work scheduling) libuv (threadpool) (loop thread) . getaddrinfo getnameinfo . UV_THREADPOOL_SIZE ( ). 1.30.0: UV_THREADPOOL_SIZE . 1.45.0: ( ) (stack) . 1.50.0: libuv-worker . . ( uv_queue_work()) libuv UV_THREADPOOL_SIZE . (throughput) (memory footprint) . (lazily) . : (thread safe ). (Data types) type uv_work_t (work request). typedef void (*uv_work_cb)(uv_work_t <#c.uv_work_t> *req) uv_queue_work() . typedef void (*uv_after_work_cb)(uv_work_t <#c.uv_work_t> *req, int status) uv_queue_work() . uv_cancel() <#c.uv_cancel> status UV_ECANCELED . (Public members) uv_loop_t <#c.uv_loop_t> *uv_work_t <#c.uv_work_t>.loop . . : uv_req_t <#c.uv_req_t> . (API) int uv_queue_work(uv_loop_t <#c.uv_loop_t> *loop, uv_work_t <#c .uv_work_t> *req, uv_work_cb <#c.uv_work_cb> work_cb, uv_after_work_cb <#c.uv_after_work_cb> after_work_cb) work_cb . work_cb after_work_cb . uv_cancel() <#c.uv_cancel> . : API uv_req_t <#c.uv_req_t> . DNS (DNS utility functions) libuv getaddrinfo getnameinfo . (Data types) type uv_getaddrinfo_t getaddrinfo. typedef void (*uv_getaddrinfo_cb)(uv_getaddrinfo_t <#c .uv_getaddrinfo_t> *req, int status, struct addrinfo *res) getaddrinfo . status UV_ECANCELED . type uv_getnameinfo_t getnameinfo. typedef void (*uv_getnameinfo_cb)(uv_getnameinfo_t <#c .uv_getnameinfo_t> *req, int status, const char *hostname, const char *service) getnameinfo . status UV_ECANCELED . (Public members) uv_loop_t <#c.uv_loop_t> *uv_getaddrinfo_t <#c.uv_getaddrinfo_t>.loop getaddrinfo . . struct addrinfo <#c.uv_getaddrinfo_t.addrinfo> *uv_getaddrinfo_t <#c .uv_getaddrinfo_t>.addrinfo struct addrinfo . uv_freeaddrinfo() . 1.3.0: (public) . uv_loop_t <#c.uv_loop_t> *uv_getnameinfo_t <#c.uv_getnameinfo_t>.loop getnameinfo . . char[NI_MAXHOST] uv_getnameinfo_t.host . null . 1.3.0: (public) . char[NI_MAXSERV] uv_getnameinfo_t.service . null . 1.3.0: (public) . : uv_req_t <#c.uv_req_t> . (API) int uv_getaddrinfo(uv_loop_t <#c.uv_loop_t> *loop, uv_getaddrinfo_t <#c .uv_getaddrinfo_t> *req, uv_getaddrinfo_cb <#c.uv_getaddrinfo_cb> getaddrinfo_cb, const char *node, const char *service, const struct addrinfo *hints) getaddrinfo(3) . node service NULL . hints struct addrinfo NULL . man -s 3 getaddrinfo . . : o status == 0 res struct addrinfo o status < 0 res NULL . UV_EAI_* . addrinfo uv_freeaddrinfo() . 1.3.0: NULL . void uv_freeaddrinfo(struct addrinfo *ai) struct addrinfo . NULL (no-op). int uv_getnameinfo(uv_loop_t <#c.uv_loop_t> *loop, uv_getnameinfo_t <#c .uv_getnameinfo_t> *req, uv_getnameinfo_cb <#c.uv_getnameinfo_cb> getnameinfo_cb, const struct sockaddr *addr, int flags) getnameinfo(3) . . . man -s 3 getnameinfo . 1.3.0: NULL . : API uv_req_t <#c.uv_req_t> . (Shared library handling) libuv . (Data types) type uv_lib_t . (Public members) (N/A) (API) int uv_dlopen(const char *filename, uv_lib_t <#c.uv_lib_t> *lib) . utf-8 . 0 -1 . uv_dlerror() . void uv_dlclose(uv_lib_t <#c.uv_lib_t> *lib) . int uv_dlsym(uv_lib_t <#c.uv_lib_t> *lib, const char *name, void **ptr) . NULL . 0 -1 . const char *uv_dlerror(const uv_lib_t <#c.uv_lib_t> *lib) uv_dlopen() uv_dlsym() . (Threading and synchronization utilities) libuv . API (pthreads) . (Data types) type uv_thread_t (Thread). typedef void (*uv_thread_cb)(void *arg) (Callback) . arg uv_thread_create() . type uv_key_t (Thread-local key). type uv_once_t (Once-only initializer). type uv_mutex_t (Mutex). type uv_rwlock_t - (Read-write lock). type uv_sem_t (Semaphore). type uv_cond_t (Condition). type uv_barrier_t (Barrier). (API) (Threads) type uv_thread_options_t ( uv_thread_create_ex()). typedef struct uv_thread_options_s { enum { UV_THREAD_NO_FLAGS = 0x00, UV_THREAD_HAS_STACK_SIZE = 0x01 } flags; size_t stack_size; } uv_thread_options_t; . 1.26.0. int uv_thread_create(uv_thread_t <#c.uv_thread_t> *tid, uv_thread_cb <# c.uv_thread_cb> entry, void *arg) 1.4.1: UV_E* . int uv_thread_detach(uv_thread_t <#c.uv_thread_t> *tid) (Detach) . uv_thread_join . 1.50.0. int uv_thread_create_ex(uv_thread_t <#c.uv_thread_t> *tid, const uv_thread_options_t <#c.uv_thread_options_t> *params, uv_thread_cb <#c .uv_thread_cb> entry, void *arg) uv_thread_create() . UV_THREAD_HAS_STACK_SIZE stack_size . 0 ( ). . 1.26.0. int uv_thread_setaffinity(uv_thread_t <#c.uv_thread_t> *tid, char *cpumask, char *oldmask, size_t mask_size) (Affinity) cpumask . oldmask . pthread_getaffinity_np(3) cpu_set_t oldmask . cpumask cpu_set_t pthread_setaffinity_np(3) . cpumask SetThreadAffinityMask() . mask_size () cpumask / oldmask uv_cpumask_size() <#c.uv_cpumask_size> . : . macOS . 1.45.0. int uv_thread_getaffinity(uv_thread_t <#c.uv_thread_t> *tid, char *cpumask, size_t mask_size) . cpu_set_t pthread_getaffinity_np(3) cpumask . mask_size () cpumask uv_cpumask_size() <#c.uv_cpumask_size> . : . macOS . 1.45.0. int uv_thread_getcpu(void) (CPU) . : Windows Linux FreeBSD . 1.45.0. uv_thread_t <#c.uv_thread_t> uv_thread_self(void) int uv_thread_join(uv_thread_t <#c.uv_thread_t> *tid) int uv_thread_equal(const uv_thread_t <#c.uv_thread_t> *t1, const uv_thread_t <#c.uv_thread_t> *t2) int uv_thread_setname(const char *name) . : IBM i ( ) macOS ( ) ( ) NetBSD ( ) . name uv_thread_setname() (truncate) . Windows Server 2016 UV_ENOSYS . 1.50.0. int uv_thread_getname(uv_thread_t <#c.uv_thread_t> *tid, char *name, size_t *size) tid . NUL name . size name . NUL NUL . Windows Server 2016 UV_ENOSYS . 1.50.0. int uv_thread_setpriority(uv_thread_t <#c.uv_thread_t> tid, int priority) 0 . . tid . (Elevated) . : UV_THREAD_PRIORITY_HIGHEST UV_THREAD_PRIORITY_ABOVE_NORMAL UV_THREAD_PRIORITY_NORMAL UV_THREAD_PRIORITY_BELOW_NORMAL UV_THREAD_PRIORITY_LOWEST. int uv_thread_getpriority(uv_thread_t <#c.uv_thread_t> tid, int *priority) 0 . . tid . priority . SCHED_OTHER () 0 . (Thread-local storage) : . TLS . int uv_key_create(uv_key_t <#c.uv_key_t> *key) void uv_key_delete(uv_key_t <#c.uv_key_t> *key) void *uv_key_get(uv_key_t <#c.uv_key_t> *key) void uv_key_set(uv_key_t <#c.uv_key_t> *key, void *value) (Once-only initialization) . uv_once() ( ). UV_ONCE_INIT . void uv_once(uv_once_t <#c.uv_once_t> *guard, void (*callback)(void)) (Mutex locks) 0 0 ( void ). int uv_mutex_init(uv_mutex_t <#c.uv_mutex_t> *handle) int uv_mutex_init_recursive(uv_mutex_t <#c.uv_mutex_t> *handle) void uv_mutex_destroy(uv_mutex_t <#c.uv_mutex_t> *handle) void uv_mutex_lock(uv_mutex_t <#c.uv_mutex_t> *handle) int uv_mutex_trylock(uv_mutex_t <#c.uv_mutex_t> *handle) void uv_mutex_unlock(uv_mutex_t <#c.uv_mutex_t> *handle) - (Read-write locks) 0 0 ( void ). int uv_rwlock_init(uv_rwlock_t <#c.uv_rwlock_t> *rwlock) void uv_rwlock_destroy(uv_rwlock_t <#c.uv_rwlock_t> *rwlock) void uv_rwlock_rdlock(uv_rwlock_t <#c.uv_rwlock_t> *rwlock) int uv_rwlock_tryrdlock(uv_rwlock_t <#c.uv_rwlock_t> *rwlock) void uv_rwlock_rdunlock(uv_rwlock_t <#c.uv_rwlock_t> *rwlock) void uv_rwlock_wrlock(uv_rwlock_t <#c.uv_rwlock_t> *rwlock) int uv_rwlock_trywrlock(uv_rwlock_t <#c.uv_rwlock_t> *rwlock) void uv_rwlock_wrunlock(uv_rwlock_t <#c.uv_rwlock_t> *rwlock) (Semaphores) 0 0 ( void ). int uv_sem_init(uv_sem_t <#c.uv_sem_t> *sem, unsigned int value) void uv_sem_destroy(uv_sem_t <#c.uv_sem_t> *sem) void uv_sem_post(uv_sem_t <#c.uv_sem_t> *sem) void uv_sem_wait(uv_sem_t <#c.uv_sem_t> *sem) int uv_sem_trywait(uv_sem_t <#c.uv_sem_t> *sem) (Conditions) 0 0 ( void ). : 1. (Spurious wakeups) uv_cond_wait() uv_cond_timedwait() . 2. timeout uv_cond_timedwait() . 3. z/OS timeout uv_cond_timedwait() . ETIMEDOUT . . int uv_cond_init(uv_cond_t <#c.uv_cond_t> *cond) void uv_cond_destroy(uv_cond_t <#c.uv_cond_t> *cond) void uv_cond_signal(uv_cond_t <#c.uv_cond_t> *cond) void uv_cond_broadcast(uv_cond_t <#c.uv_cond_t> *cond) void uv_cond_wait(uv_cond_t <#c.uv_cond_t> *cond, uv_mutex_t <#c .uv_mutex_t> *mutex) int uv_cond_timedwait(uv_cond_t <#c.uv_cond_t> *cond, uv_mutex_t <#c .uv_mutex_t> *mutex, uint64_t timeout) (Barriers) 0 0 ( void ). : uv_barrier_wait() <<>> (Serializer) : if (uv_barrier_wait(&barrier) > 0) uv_barrier_destroy(&barrier); int uv_barrier_init(uv_barrier_t <#c.uv_barrier_t> *barrier, unsigned int count) void uv_barrier_destroy(uv_barrier_t <#c.uv_barrier_t> *barrier) int uv_barrier_wait(uv_barrier_t <#c.uv_barrier_t> *barrier) (Miscellaneous utilities) . (Data types) type uv_buf_t (Buffer). char *uv_buf_t.base . size_t uv_buf_t.len . : ULONG . typedef void *(*uv_malloc_func)(size_t size) malloc(3) . uv_replace_allocator() . typedef void *(*uv_realloc_func)(void *ptr, size_t size) realloc(3) . uv_replace_allocator() . typedef void *(*uv_calloc_func)(size_t count, size_t size) calloc(3) . uv_replace_allocator() . typedef void (*uv_free_func)(void *ptr) free(3) . uv_replace_allocator() . typedef void (*uv_random_cb)(uv_random_t <#c.uv_random_t> *req, int status, void *buf, size_t buflen) uv_random(). status . buf uv_random() . type uv_file (File handle). type uv_os_sock_t (Socket handle). type uv_os_fd_t (File descriptor). typedef int HANDLE . type uv_pid_t pid_t. 1.16.0. type uv_timeval_t (Y2K38-unsafe) . libuv v2.0 uv_timeval64_t . typedef struct { long tv_sec; long tv_usec; } uv_timeval_t; type uv_timeval64_t (Y2K38-safe) . typedef struct { int64_t tv_sec; int32_t tv_usec; } uv_timeval64_t; type uv_timespec64_t (Y2K38-safe) . typedef struct { int64_t tv_sec; int32_t tv_nsec; } uv_timespec64_t; enum uv_clock_id uv_clock_gettime(). typedef enum { UV_CLOCK_MONOTONIC, UV_CLOCK_REALTIME } uv_clock_id; type uv_rusage_t (Resource usage). typedef struct { uv_timeval_t ru_utime; /* user CPU time used */ uv_timeval_t ru_stime; /* system CPU time used */ uint64_t ru_maxrss; /* maximum resident set size */ uint64_t ru_ixrss; /* integral shared memory size (X) */ uint64_t ru_idrss; /* integral unshared data size (X) */ uint64_t ru_isrss; /* integral unshared stack size (X) */ uint64_t ru_minflt; /* page reclaims (soft page faults) (X) */ uint64_t ru_majflt; /* page faults (hard page faults) */ uint64_t ru_nswap; /* swaps (X) */ uint64_t ru_inblock; /* block input operations */ uint64_t ru_oublock; /* block output operations */ uint64_t ru_msgsnd; /* IPC messages sent (X) */ uint64_t ru_msgrcv; /* IPC messages received (X) */ uint64_t ru_nsignals; /* signals received (X) */ uint64_t ru_nvcsw; /* voluntary context switches (X) */ uint64_t ru_nivcsw; /* involuntary context switches (X) */ } uv_rusage_t; (X) . getrusage(2) . (RSS) . type uv_cpu_info_t (CPU). typedef struct uv_cpu_info_s { char* model; int speed; struct uv_cpu_times_s { uint64_t user; /* milliseconds */ uint64_t nice; /* milliseconds */ uint64_t sys; /* milliseconds */ uint64_t idle; /* milliseconds */ uint64_t irq; /* milliseconds */ } cpu_times; } uv_cpu_info_t; type uv_interface_address_t . typedef struct uv_interface_address_s { char* name; char phys_addr[6]; int is_internal; union { struct sockaddr_in address4; struct sockaddr_in6 address6; } address; union { struct sockaddr_in netmask4; struct sockaddr_in6 netmask6; } netmask; } uv_interface_address_t; type uv_passwd_t (Passwd). typedef struct uv_passwd_s { char* username; long uid; long gid; char* shell; char* homedir; } uv_passwd_t; type uv_group_t (Group). typedef struct uv_group_s { char* groupname; unsigned long gid; char** members; } uv_group_t; type uv_utsname_t . typedef struct uv_utsname_s { char sysname[256]; char release[256]; char version[256]; char machine[256]; } uv_utsname_t; type uv_env_item_t . typedef struct uv_env_item_s { char* name; char* value; } uv_env_item_t; type uv_random_t . (API) uv_handle_type <#c.uv_handle_type> uv_guess_handle(uv_file <#c.uv_file> file) . stdio . isatty(3) UV_TTY . int uv_replace_allocator(uv_malloc_func <#c.uv_malloc_func> malloc_func, uv_realloc_func <#c.uv_realloc_func> realloc_func, uv_calloc_func <#c.uv_calloc_func> calloc_func, uv_free_func <#c .uv_free_func> free_func) 1.6.0. malloc(3) calloc(3) realloc(3) free(3) . libuv libuv . 0 NULL UV_EINVAL . : . . : (Thread-safe) . void uv_library_shutdown(void); 1.38.0. libuv . libuv . : uv_library_shutdown() . : I/O uv_library_shutdown() . : uv_library_shutdown() libuv . uv_buf_t <#c.uv_buf_t> uv_buf_init(char *base, unsigned int len) uv_buf_t. base len uv_buf_t . base uv_buf_t . (by value) . char **uv_setup_args(int argc, char **argv) . / . libuv argv . . : argv = uv_setup_args(argc, argv); /* May return a copy of argv. */ int uv_get_process_title(char *buffer, size_t size) . Unix AIX uv_setup_args . uv_setup_args UV_ENOBUFS . buffer NULL size UV_EINVAL . size nul UV_ENOBUFS . : BSD uv_setup_args . uv_setup_args uv_set_process_title . 1.18.1: (Thread-safe) . 1.39.0: uv_setup_args . int uv_set_process_title(const char *title) . Unix AIX uv_setup_args . uv_setup_args UV_ENOBUFS . title (truncate) . title UV_ENOMEM . 1.18.1: (Thread-safe) . 1.39.0: uv_setup_args . int uv_resident_set_memory(size_t *rss) (RSS) . int uv_uptime(double *uptime) (Uptime) . . int uv_getrusage(uv_rusage_t <#c.uv_rusage_t> *rusage) . : . uv_rusage_t . int uv_getrusage_thread(uv_rusage_t <#c.uv_rusage_t> *rusage) . 1.50.0. : UV_ENOTSUP . macOS Windows . uv_rusage_t . uv_pid_t <#c.uv_pid_t> uv_os_getpid(void) (Process ID) . 1.18.0. uv_pid_t <#c.uv_pid_t> uv_os_getppid(void) (Parent Process ID) . 1.16.0. unsigned int uv_available_parallelism(void) . . CPU CPU (pin) . . (Online) . 1.44.0. int uv_cpu_info(uv_cpu_info_t <#c.uv_cpu_info_t> **cpu_infos, int *count) . cpu_infos count uv_free_cpu_info() . uv_available_parallelism() . void uv_free_cpu_info(uv_cpu_info_t <#c.uv_cpu_info_t> *cpu_infos, int count) cpu_infos uv_cpu_info() . int uv_cpumask_size(void) / UV_ENOTSUP . 1.45.0. int uv_interface_addresses(uv_interface_address_t <#c .uv_interface_address_t> **addresses, int *count) . count addresses . uv_free_interface_addresses() . void uv_free_interface_addresses(uv_interface_address_t <#c .uv_interface_address_t> *addresses, int count) uv_interface_address_t uv_interface_addresses() . void uv_loadavg(double avg[3]) (Load average) . : : [0,0,0] ( ). int uv_ip4_addr(const char *ip, int port, struct sockaddr_in *addr) IPv4 . int uv_ip6_addr(const char *ip, int port, struct sockaddr_in6 *addr) IPv6 . int uv_ip4_name(const struct sockaddr_in *src, char *dst, size_t size) IPv4 . int uv_ip6_name(const struct sockaddr_in6 *src, char *dst, size_t size) IPv6 . int uv_ip_name(const struct sockaddr *src, char *dst, size_t size) IPv4 IPv6 . int uv_inet_ntop(int af, const void *src, char *dst, size_t size) int uv_inet_pton(int af, const char *src, void *dst) IPv6 inet_ntop(3) inet_pton(3) . 0 . dst . UV_IF_NAMESIZE IPv6. IFNAMSIZ IF_NAMESIZE . 1.16.0. int uv_if_indextoname(unsigned int ifindex, char *buffer, size_t *size) IPv6 if_indextoname(3) . *size buffer . buffer *size buffer NUL . . buffer UV_ENOBUFS *size NUL . IPv6 fe80::abc:def1:2345%en0. fe80::abc:def1:2345%5. uv_if_indextoiid() . : char ifname[UV_IF_NAMESIZE]; size_t size = sizeof(ifname); uv_if_indextoname(sin6->sin6_scope_id, ifname, &size); 1.16.0. int uv_if_indextoiid(unsigned int ifindex, char *buffer, size_t *size) IPv6 . ifindex . uv_if_indextoname() . buffer *size buffer . buffer UV_ENOBUFS *size NUL . uv_if_indextoname . 1.16.0. int uv_exepath(char *buffer, size_t *size) . uv_setup_args . setuid . . . int uv_cwd(char *buffer, size_t *size) buffer . buffer UV_ENOBUFS size null . 1.1.0: . 1.9.0: UV_ENOBUFS null null . int uv_chdir(const char *dir) . int uv_os_homedir(char *buffer, size_t *size) . uv_os_homedir() USERPROFILE GetEnvironmentVariableW() . USERPROFILE GetUserProfileDirectoryW() . uv_os_homedir() HOME getenv(3) . HOME getpwuid_r(3) . buffer . uv_os_homedir() size buffer . size buffer . UV_ENOBUFS size buffer null . : uv_os_homedir() (Thread-safe) . 1.6.0. int uv_os_tmpdir(char *buffer, size_t *size) . uv_os_tmpdir() GetTempPathW() . uv_os_tmpdir() TMPDIR TMP TEMP TEMPDIR . "/tmp" "/data/local/tmp" . buffer . uv_os_tmpdir() size buffer . size buffer ( null ) . UV_ENOBUFS size buffer null . : uv_os_tmpdir() (Thread-safe) . 1.9.0. int uv_os_get_passwd(uv_passwd_t <#c.uv_passwd_t> *pwd) uid ( uid ) . euid gid . getpwuid_r(3) . uid gid -1 shell NULL . pwd uv_os_free_passwd() . 1.9.0. int uv_os_get_passwd2(uv_passwd_t <#c.uv_passwd_t> *pwd, uv_uid_t uid) uid . euid gid . getpwuid_r(3) . uid gid -1 shell NULL . pwd uv_os_free_passwd() . 1.45.0. int uv_os_get_group(uv_group_t <#c.uv_group_t> *group, uv_uid_t gid) uid . gid . getgrgid_r(3) . uid gid -1 . group uv_os_free_group() . 1.45.0. void uv_os_free_group(uv_passwd_t <#c.uv_passwd_t> *pwd) uv_os_get_group() . 1.45.0. void uv_os_free_passwd(uv_passwd_t <#c.uv_passwd_t> *pwd) pwd uv_os_get_passwd() . 1.9.0. uint64_t uv_get_free_memory(void) ( ) . 0 . uint64_t uv_get_total_memory(void) ( ) . 0 . uint64_t uv_get_constrained_memory(void) ( ) . 0 . UINT64_MAX . uv_get_total_memory() . : ( cgroups ) z/OS ( RLIMIT_MEMLIMIT) . 1.29.0. uint64_t uv_get_available_memory(void) ( ) . uv_get_free_memory() . uv_get_free_memory() . : uv_get_free_memory() ( cgroups ). 1.45.0. uint64_t uv_hrtime(void) (High-resolution timestamp) . . (Clock drift) . . : . int uv_clock_gettime(uv_clock_id <#c.uv_clock_id> clock_id, uv_timespec64_t <#c.uv_timespec64_t> *ts) (Real-time) (Monotonic) . (1970-01-01) . . 1.45.0. void uv_print_all_handles(uv_loop_t <#c.uv_loop_t> *loop, FILE *stream) loop stream . : uv_print_all_handles(uv_default_loop(), stderr); /* [--I] signal 0x1a25ea8 [-AI] async 0x1a25cf0 [R--] idle 0x1a7a8c8 */ [flags] handle-type handle-address . flags: o R o A o I : (Ad hoc) API/ABI . 1.8.0. void uv_print_active_handles(uv_loop_t <#c.uv_loop_t> *loop, FILE *stream) uv_print_all_handles() . : (Ad hoc) API/ABI . 1.8.0. int uv_os_environ(uv_env_item_t <#c.uv_env_item_t> **envitems, int *count) . uv_os_free_environ() . : (Thread-safe) . 1.31.0. void uv_os_free_environ(uv_env_item_t <#c.uv_env_item_t> *envitems, int count); uv_os_environ() . 1.31.0. int uv_os_getenv(const char *name, char *buffer, size_t *size) name buffer size . size buffer null . buffer UV_ENOBUFS size . UV_ENOENT . : (Thread-safe) . 1.12.0. int uv_os_setenv(const char *name, const char *value) name value . : (Thread-safe) . 1.12.0. int uv_os_unsetenv(const char *name) name . . : (Thread-safe) . 1.12.0. int uv_os_gethostname(char *buffer, size_t *size) (Hostname) null buffer size . size buffer null . buffer UV_ENOBUFS size . 1.12.0. 1.26.0: UV_MAXHOSTNAMESIZE buffer nul . int uv_os_getpriority(uv_pid_t <#c.uv_pid_t> pid, int *priority) pid . priority -20 ( ) 19 ( ) . : UV_PRIORITY . 1.23.0. int uv_os_setpriority(uv_pid_t <#c.uv_pid_t> pid, int priority) pid . priority -20 ( ) 19 ( ) . UV_PRIORITY_LOW UV_PRIORITY_BELOW_NORMAL UV_PRIORITY_NORMAL UV_PRIORITY_ABOVE_NORMAL UV_PRIORITY_HIGH UV_PRIORITY_HIGHEST . : SetPriorityClass() . priority . UV_PRIORITY priority . : PRIORITY_HIGHEST (Elevated) PRIORITY_HIGH . : IBM i PASE -10 . UV_PRIORITY_HIGHEST -10 UV_PRIORITY_HIGH -7 UV_PRIORITY_ABOVE_NORMAL -4 UV_PRIORITY_NORMAL 0 UV_PRIORITY_BELOW_NORMAL 15 UV_PRIORITY_LOW 39 . : IBM i PASE *JOBCTL ( ). 1.23.0. int uv_os_uname(uv_utsname_t <#c.uv_utsname_t> *buffer) buffer . (Release) . uv_os_uname() uname(2) . . 1.25.0. int uv_gettimeofday(uv_timeval64_t <#c.uv_timeval64_t> *tv) gettimeofday(2) . timezone gettimeofday() . 1.28.0. int uv_random(uv_loop_t <#c.uv_loop_t> *loop, uv_random_t <#c .uv_random_t> *req, void *buf, size_t buflen, unsigned int flags, uv_random_cb <#c.uv_random_cb> cb) buf buflen CSPRNG . flags 0 . (Short read) . buflen . . . : o : RtlGenRandom _. o : getrandom(2) urandom(4) /dev/random KERN_RANDOM sysctl(2) . o : getrandom(2) _ /dev/urandom /dev/random. o : KERN_ARND sysctl(7) _ o : getentropy(2) _ /dev/urandom /dev/random. o AIX: /dev/random. o IBM i: /dev/urandom. o : /dev/urandom /dev/random. (Returns) 0 0 . buf . : loop req NULL . 1.33.0. void uv_sleep(unsigned int msec) msec . 1.34.0. (String manipulation functions) (export) API libuv . size_t uv_utf16_length_as_wtf8(const uint16_t *utf16, ssize_t utf16_len) UTF-16 ( UCS-2) utf16 WTF-8 . utf16 NUL utf16_len -1 . 1.47.0. int uv_utf16_to_wtf8(const uint16_t *utf16, ssize_t utf16_len, char **wtf8_ptr, size_t *wtf8_len_ptr) UTF-16 ( UCS-2) utf16 WTF-8 *wtf8_ptr . utf16_len ( ) utf16 . utf16 NUL utf16_len -1 . wtf8_ptr NULL ( uv_utf16_length_as_wtf8) wtf8_len_ptr . *wtf8_ptr NULL wtf8_ptr wtf8_len_ptr . *wtf8_ptr wtf8_len_ptr . wtf8_ptr NUL . (truncated) UV_ENOBUFS wtf8_len_ptr wtf8_ptr . 1.47.0. ssize_t uv_wtf8_length_as_utf16(const char *wtf8) WTF-8 NUL wtf8 UTF-16 ( UCS-2) NUL . 1.47.0. void uv_wtf8_to_utf16(const char *utf8, uint16_t *utf16, size_t utf16_len) WTF-8 NUL wtf8 UTF-16 ( UCS-2) utf16 . utf16_len ( ) NUL . 1.47.0. (Metrics operations) libuv (Metrics API) . (Data types) type uv_metrics_t . uv_prepare_cb <#c.uv_prepare_cb> . typedef struct { uint64_t loop_count; uint64_t events; uint64_t events_waiting; /* private */ uint64_t* reserved[13]; } uv_metrics_t; (Public members) uint64_t uv_metrics_t <#c.uv_metrics_t>.loop_count . uint64_t uv_metrics_t <#c.uv_metrics_t>.events (Event handler) . uint64_t uv_metrics_t <#c.uv_metrics_t>.events_waiting . (API) uint64_t uv_metrics_idle_time(uv_loop_t <#c.uv_loop_t> *loop) ( epoll_wait) (Idle) . (Thread-safe) . uv_loop_t <#c.uv_loop_t> . : uv_loop_configure <#c .uv_loop_configure> UV_METRICS_IDLE_TIME . 1.39.0. int uv_metrics_info(uv_loop_t <#c.uv_loop_t> *loop, uv_metrics_t <#c .uv_metrics_t> *metrics) metrics . 1.45.0. : libuv . (issue) (pull request) ! <<>> libuv / (evented I/O) (API) . libuv . libuv . . : 1. (daemons) . (event loop) libuv . 2. node.js C ++C API JavaScript . libuv node.js . v8/node.js . C . node.js . V8 libev node.js I/O . node.js libev . kqueue epoll/poll IOCP . libuv libev IOCP ( ) API libev . node-v0.9.0 libuv libev . libuv . node.js Rust (language bindings) . v1.42.0 libuv . libuv . libuv : sh autogen.sh ./configure make make install . make docs/code/ . libuv libuv (asynchronous) (event-driven) . (callback) / . libuv . . libuv (callbacks) . (forever) . : while there are still events to process: e = get the next event if there is a callback associated with e: call the callback : o o o uv_run() -- libuv. . / (read fprintf ) (blocking) . . . / . (threads) . I/O ( ) . CPU . libuv (asynchronous, non-blocking) . . read . . ( ) . (asynchronous) ( ) . (non-blocking) . libuv libuv . [1]. : I/O libuv / / (polling) . (Bert Belder) libuv libuv . libuv libev . libuv . (Hello World) libuv . . helloworld/main.c #include #include #include int main() { uv_loop_t *loop = malloc(sizeof(uv_loop_t)); uv_loop_init(loop); printf("Now quitting.\n"); uv_run(loop, UV_RUN_DEFAULT); uv_loop_close(loop); free(loop); return 0; } . libuv API . libuv v1.0 uv_loop_init(uv_loop_t *) . . uv_loop_close(uv_loop_t *) . . . (Default loop) libuv uv_default_loop() . . default-loop/main.c #include #include 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; } : node.js . (bindings) . (Error handling) . (status) . UV_E* . uv_strerror(int) uv_err_name(int) const char * . I/O ( ) nread . nread (UV_EOF ). (Handles and Requests) libuv . (handle) I/O . (opaque structs) uv_TYPE_t type . libuv /* Handle types. */ typedef struct uv_loop_s uv_loop_t; typedef struct uv_handle_s uv_handle_t; typedef struct uv_dir_s uv_dir_t; typedef struct uv_stream_s uv_stream_t; typedef struct uv_tcp_s uv_tcp_t; typedef struct uv_udp_s uv_udp_t; typedef struct uv_pipe_s uv_pipe_t; typedef struct uv_tty_s uv_tty_t; typedef struct uv_poll_s uv_poll_t; typedef struct uv_timer_s uv_timer_t; typedef struct uv_prepare_s uv_prepare_t; typedef struct uv_check_s uv_check_t; typedef struct uv_idle_s uv_idle_t; typedef struct uv_async_s uv_async_t; typedef struct uv_process_s uv_process_t; typedef struct uv_fs_event_s uv_fs_event_t; typedef struct uv_fs_poll_s uv_fs_poll_t; typedef struct uv_signal_s uv_signal_t; /* Request types. */ typedef struct uv_req_s uv_req_t; typedef struct uv_getaddrinfo_s uv_getaddrinfo_t; typedef struct uv_getnameinfo_s uv_getnameinfo_t; typedef struct uv_shutdown_s uv_shutdown_t; typedef struct uv_write_s uv_write_t; typedef struct uv_connect_s uv_connect_t; 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; . (requests) . ( ) / . (context) . UDP uv_udp_t uv_udp_send_t . : uv_TYPE_init(uv_loop_t *, uv_TYPE_t *) libuv . . IO . (Idling) (idle handle) . . <> . uv_run() . uv_run() . idle-basic/main.c #include #include int64_t counter = 0; void wait_for_a_while(uv_idle_t* handle) { counter++; if (counter >= 10e6) uv_idle_stop(handle); } int main() { uv_idle_t idler; uv_idle_init(uv_default_loop(), &idler); uv_idle_start(&idler, wait_for_a_while); printf("Idling...\n"); uv_run(uv_default_loop(), UV_RUN_DEFAULT); uv_loop_close(uv_default_loop()); return 0; } (Storing context) << (context)>> -- -- . void* data . C . uv_loop_t . ---- [1] . (Filesystem) uv_fs_* uv_fs_t . : libuv <>. . (thread pool) . - (synchronous) (asynchronous). null ( ). libuv <#libuv-error-handling>. . 0 . / : int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb) flags mode . libuv . : int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) : void callback(uv_fs_t* req); cat . : uvcat/main.c - // The request passed to the callback is the same as the one the call setup // function was passed. assert(req == &open_req); if (req->result >= 0) { iov = uv_buf_init(buffer, sizeof(buffer)); uv_fs_read(uv_default_loop(), &read_req, req->result, &iov, 1, -1, on_read); } else { fprintf(stderr, "error opening file: %s\n", uv_strerror((int)req->result)); } } result uv_fs_t uv_fs_open . . uvcat/main.c - if (req->result < 0) { fprintf(stderr, "Read error: %s\n", uv_strerror(req->result)); } else if (req->result == 0) { uv_fs_t close_req; // synchronous uv_fs_close(uv_default_loop(), &close_req, open_req.result, NULL); } else if (req->result > 0) { iov.len = req->result; uv_fs_write(uv_default_loop(), &write_req, 1, &iov, 1, -1, on_write); } } . uv_fs_* POSIX (EOF) 0 result . UV_EOF . . uv_fs_close() . I/O / . . uv_fs_write() . . . . uvcat/main.c - if (req->result < 0) { fprintf(stderr, "Write error: %s\n", uv_strerror((int)req->result)); } else { uv_fs_read(uv_default_loop(), &read_req, open_req.result, &iov, 1, -1, on_read); } } : <<>> . main() : uvcat/main.c uv_fs_open(uv_default_loop(), &open_req, argv[1], O_RDONLY, 0, on_open); uv_run(uv_default_loop(), UV_RUN_DEFAULT); uv_fs_req_cleanup(&open_req); uv_fs_req_cleanup(&read_req); uv_fs_req_cleanup(&write_req); return 0; } : uv_fs_req_cleanup() libuv . unlink rmdir stat . read/write/open uv_fs_t.result . : (Filesystem operations) int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb); int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb); int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb); int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, 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_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); int uv_fs_opendir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, uv_dir_t* dir, uv_fs_cb cb); int uv_fs_closedir(uv_loop_t* loop, uv_fs_t* req, uv_dir_t* dir, uv_fs_cb cb); int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb); int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb); int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb); int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb); int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file, int64_t offset, uv_fs_cb cb); int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, uv_file in_fd, int64_t in_offset, size_t length, uv_fs_cb cb); int uv_fs_access(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_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); int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode, 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_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); I/O libuv (uv_stream_t) . TCP UDP (pipes) I/O IPC . : int uv_read_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read_cb read_cb); int uv_read_stop(uv_stream_t*); int uv_write(uv_write_t* req, uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb); libuv uv_read_start() uv_read_stop() . -- uv_buf_t. (uv_buf_t.base) (uv_buf_t.len) . uv_buf_t (by value) . . : uv_pipe_t . [2]. tee libuv . I/O . . : ./uvtee . libuv (bidirectional) . uvtee/main.c - loop = uv_default_loop(); uv_pipe_init(loop, &stdin_pipe, 0); uv_pipe_open(&stdin_pipe, 0); uv_pipe_init(loop, &stdout_pipe, 0); uv_pipe_open(&stdout_pipe, 1); uv_fs_t file_req; int fd = uv_fs_open(loop, &file_req, argv[1], O_CREAT | O_RDWR, 0644, NULL); uv_pipe_init(loop, &file_pipe, 0); uv_pipe_open(&file_pipe, fd); uv_read_start((uv_stream_t*)&stdin_pipe, alloc_buffer, read_stdin); uv_run(loop, UV_RUN_DEFAULT); return 0; } uv_pipe_init() IPC 1 . <> . uv_pipe_open() 0 ( ) . stdin . alloc_buffer . read_stdin . uvtee/main.c - *buf = uv_buf_init((char*) malloc(suggested_size), suggested_size); } void free_write_req(uv_write_t *req) { if (nread < 0){ if (nread == UV_EOF){ // end of file uv_close((uv_handle_t *)&stdin_pipe, NULL); uv_close((uv_handle_t *)&stdout_pipe, NULL); uv_close((uv_handle_t *)&file_pipe, NULL); } } else if (nread > 0) { write_data((uv_stream_t *)&stdout_pipe, nread, *buf, on_stdout_write); write_data((uv_stream_t *)&file_pipe, nread, *buf, on_file_write); } // OK to free buffer as write_data copies it. if (buf->base) free(buf->base); } malloc . node.js (slab allocator) V8 . nread 0 . EOF uv_close() . nread . . . UV_ENOBUFS . libuv uv_close() . nread = 0 . . uvtee/main.c - uv_write_t req; uv_buf_t buf; } write_req_t; uv_loop_t *loop; write_req_t *wr = (write_req_t*) req; free(wr->buf.base); free(wr); } void on_stdout_write(uv_write_t *req, int status) { free_write_req(req); } void on_file_write(uv_write_t *req, int status) { free_write_req(req); } void write_data(uv_stream_t *dest, size_t size, uv_buf_t buf, uv_write_cb cb) { write_req_t *req = (write_req_t*) malloc(sizeof(write_req_t)); req->buf = uv_buf_init((char*) malloc(size), size); memcpy(req->buf.base, buf.base, size); uv_write((uv_write_t*) req, (uv_stream_t*)dest, &req->buf, 1, cb); } write_data() . . write_req_t . write_data . . : . SIGPIPE . : signal(SIGPIPE, SIG_IGN) . API . libuv [1]. libuv . . : ./onchange [file2] ... : OSX Windows . uv_fs_event_start . uv_fs_event_init() : onchange/main.c - int main(int argc, char **argv) { if (argc <= 2) { fprintf(stderr, "Usage: %s [file2 ...]\n", argv[0]); return 1; } loop = uv_default_loop(); command = argv[1]; while (argc-- > 2) { fprintf(stderr, "Adding watch on %s\n", argv[argc]); uv_fs_event_t *fs_event_req = malloc(sizeof(uv_fs_event_t)); uv_fs_event_init(loop, fs_event_req); // The recursive flag watches subdirectories too. uv_fs_event_start(fs_event_req, run_command, argv[argc], UV_FS_EVENT_RECURSIVE); } return uv_run(loop, UV_RUN_DEFAULT); } . flags : /* * 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, UV_FS_EVENT_RECURSIVE = 4 }; UV_FS_EVENT_WATCH_ENTRY UV_FS_EVENT_STAT () . UV_FS_EVENT_RECURSIVE . : 1. uv_fs_event_t *handle - . path . 2. const char *filename - . null . null . 3. int events - UV_RENAME UV_CHANGE OR . 4. int status - status < 0 libuv <#libuv-error- handling>. system() . onchange/main.c - void run_command(uv_fs_event_t *handle, const char *filename, int events, int status) { char path[1024]; size_t size = 1023; // Does not handle error if path is longer than 1023. uv_fs_event_getpath(handle, path, &size); path[size] = '\0'; fprintf(stderr, "Change detected in %s: ", path); if (events & UV_RENAME) fprintf(stderr, "renamed"); if (events & UV_CHANGE) fprintf(stderr, "changed"); fprintf(stderr, " %s\n", filename ? filename : ""); system(command); } ---- [1] inotify FSEvents (Darwin) kqueue BSD ReadDirectoryChangesW (event ports) Cygwin [2] <#pipes> libuv BSD . libuv BSD DNS . uv_tcp_t uv_udp_t / . : API libuv . . . TCP TCP (stream) libuv . (Server) : 1. TCP uv_tcp_init . 2. uv_tcp_bind (bind) . 3. uv_listen . 4. uv_accept . 5. <#buffers- and-streams> . (echo server) : tcp-echo-server/main.c - uv_close((uv_handle_t*) client, on_close); } } int main() { loop = uv_default_loop(); uv_tcp_t server; uv_tcp_init(loop, &server); uv_ip4_addr("0.0.0.0", DEFAULT_PORT, &addr); uv_tcp_bind(&server, (const struct sockaddr*)&addr, 0); int r = uv_listen((uv_stream_t*) &server, DEFAULT_BACKLOG, on_new_connection); if (r) { fprintf(stderr, "Listen error %s\n", uv_strerror(r)); return 1; } return uv_run(loop, UV_RUN_DEFAULT); } uv_ip4_addr IP sockaddr_in API BSD . uv_ip4_name . : uv_ip6_* ip4 . (CPU-bound) . uv_listen libuv . backlog -- . uv_accept . . tcp-echo-server/main.c - free(buf->base); } void on_new_connection(uv_stream_t *server, int status) { if (status < 0) { fprintf(stderr, "New connection error %s\n", uv_strerror(status)); // error! return; } uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t)); uv_tcp_init(loop, client); if (uv_accept(server, (uv_stream_t*) client) == 0) { uv_read_start((uv_stream_t*) client, alloc_buffer, echo_read); } . uv_close . uv_listen . (Client) bind/listen/accept uv_tcp_connect . uv_connect_cb uv_listen uv_tcp_connect . : uv_tcp_t* socket = (uv_tcp_t*)malloc(sizeof(uv_tcp_t)); uv_tcp_init(loop, socket); uv_connect_t* connect = (uv_connect_t*)malloc(sizeof(uv_connect_t)); struct sockaddr_in dest; uv_ip4_addr("127.0.0.1", 80, &dest); uv_tcp_connect(connect, socket, (const struct sockaddr*)&dest, on_connect); on_connect . uv_connect_t .handle . UDP (User Datagram Protocol) . libuv . libuv UDP uv_udp_t ( ) uv_udp_send_t ( ) . / . UDP IP DHCP -- DHCP Discover. : udp-dhcp root 1024 . udp-dhcp/main.c - UDP uv_loop_t *loop; uv_udp_t send_socket; uv_udp_t recv_socket; int main() { loop = uv_default_loop(); uv_udp_init(loop, &recv_socket); struct sockaddr_in recv_addr; uv_ip4_addr("0.0.0.0", 68, &recv_addr); uv_udp_bind(&recv_socket, (const struct sockaddr *)&recv_addr, UV_UDP_REUSEADDR); uv_udp_recv_start(&recv_socket, alloc_buffer, on_read); uv_udp_init(loop, &send_socket); struct sockaddr_in broadcast_addr; uv_ip4_addr("0.0.0.0", 0, &broadcast_addr); uv_udp_bind(&send_socket, (const struct sockaddr *)&broadcast_addr, 0); uv_udp_set_broadcast(&send_socket, 1); uv_udp_send_t send_req; uv_buf_t discover_msg = make_discover_msg(); struct sockaddr_in send_addr; uv_ip4_addr("255.255.255.255", 67, &send_addr); uv_udp_send(&send_req, &send_socket, &discover_msg, 1, (const struct sockaddr *)&send_addr, on_send); return uv_run(loop, UV_RUN_DEFAULT); } : IP 0.0.0.0 . IP 255.255.255.255 ( ) . 0 . 68 ( DHCP) . DHCP . UV_UDP_REUSEADDR DHCP . uv_udp_send 67 ( DHCP) . EACCES [1]. . 0 . UDP (peer) . nread . addr NULL ( ) NULL addr . flags UV_UDP_PARTIAL . ( UDP !). udp-dhcp/main.c - void on_read(uv_udp_t *req, ssize_t nread, const uv_buf_t *buf, const struct sockaddr *addr, unsigned flags) { if (nread < 0) { fprintf(stderr, "Read error %s\n", uv_err_name(nread)); uv_close((uv_handle_t*) req, NULL); free(buf->base); return; } char sender[17] = { 0 }; uv_ip4_name((const struct sockaddr_in*) addr, sender, 16); fprintf(stderr, "Recv from %s\n", sender); // ... DHCP specific code unsigned int *as_integer = (unsigned int*)buf->base; unsigned int ipbin = ntohl(as_integer[4]); unsigned char ip[4] = {0}; int i; for (i = 0; i < 4; i++) ip[i] = (ipbin >> i*8) & 0xff; fprintf(stderr, "Offered IP %d.%d.%d.%d\n", ip[3], ip[2], ip[1], ip[0]); free(buf->base); uv_udp_recv_stop(req); } UDP (Time-to-live) TTL uv_udp_set_ttl . IPv6 IPv6 IPv4 IPv6 . IPv6 UV_UDP_IPV6ONLY uv_udp_bind . (Multicast) (multicast) : membership UV_JOIN_GROUP UV_LEAVE_GROUP . . [2] uv_udp_set_multicast_loop . uv_udp_set_multicast_ttl . DNS (Querying DNS) libuv DNS . getaddrinfo [3]. . DNS Libera.chat . dns/main.c int main() { loop = uv_default_loop(); struct addrinfo hints; hints.ai_family = PF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = 0; uv_getaddrinfo_t resolver; fprintf(stderr, "irc.libera.chat is... "); int r = uv_getaddrinfo(loop, &resolver, on_resolved, "irc.libera.chat", "6667", &hints); if (r) { fprintf(stderr, "getaddrinfo call error %s\n", uv_err_name(r)); return 1; } return uv_run(loop, UV_RUN_DEFAULT); } uv_getaddrinfo . uv_getaddrinfo . hostname servname hints getaddrinfo . NULL . IP struct addrinfo(s) . uv_tcp_connect . uv_freeaddrinfo . dns/main.c void on_resolved(uv_getaddrinfo_t *resolver, int status, struct addrinfo *res) { if (status < 0) { fprintf(stderr, "getaddrinfo callback error %s\n", uv_err_name(status)); return; } char addr[17] = {'\0'}; uv_ip4_name((struct sockaddr_in*) res->ai_addr, addr, 16); fprintf(stderr, "%s\n", addr); uv_connect_t *connect_req = (uv_connect_t*) malloc(sizeof(uv_connect_t)); uv_tcp_t *socket = (uv_tcp_t*) malloc(sizeof(uv_tcp_t)); uv_tcp_init(loop, socket); uv_tcp_connect(connect_req, socket, (const struct sockaddr*) res->ai_addr, on_connect); uv_freeaddrinfo(res); } libuv uv_getnameinfo . (Network interfaces) libuv uv_interface_addresses . . IP . interfaces/main.c #include #include int main() { char buf[512]; uv_interface_address_t *info; int count, i; uv_interface_addresses(&info, &count); i = count; printf("Number of interfaces: %d\n", count); while (i--) { uv_interface_address_t interface_a = info[i]; printf("Name: %s\n", interface_a.name); printf("Internal? %s\n", interface_a.is_internal ? "Yes" : "No"); if (interface_a.address.address4.sin_family == AF_INET) { uv_ip4_name(&interface_a.address.address4, buf, sizeof(buf)); printf("IPv4 address: %s\n", buf); } else if (interface_a.address.address4.sin_family == AF_INET6) { uv_ip6_name(&interface_a.address.address6, buf, sizeof(buf)); printf("IPv6 address: %s\n", buf); } printf("\n"); } uv_free_interface_addresses(info, count); return 0; } is_internal (loopback) true . IPv4/IPv6 . ---- [1] [2] [3] libuv getaddrinfo libuv . v0.8.0 libuv c-ares v0.9.0 . (Threads) ! (web-scale programming) ... . . . . libuv ( ) (blocking) . : pthreads(7) POSIX . libuv API pthreads . libuv libuv . (callback) . libuv . : ( ) . ( uv_async_send). (Core thread operations) uv_thread_create() uv_thread_join() . thread-create/main.c int tracklen = 10; uv_thread_t hare_id; uv_thread_t tortoise_id; uv_thread_create(&hare_id, hare, &tracklen); uv_thread_create(&tortoise_id, tortoise, &tracklen); uv_thread_join(&hare_id); uv_thread_join(&tortoise_id); return 0; } : uv_thread_t pthread_t . void * . hare (pre-emptively) : thread-create/main.c int tracklen = *((int *) arg); while (tracklen) { tracklen--; uv_sleep(1000); fprintf(stderr, "Hare ran another step\n"); } fprintf(stderr, "Hare done running!\n"); } pthread_join() uv_thread_join() . . (Synchronization Primitives) . libuv . pthreads(7) . (Mutexes) pthread . libuv int uv_mutex_init(uv_mutex_t* handle); int uv_mutex_init_recursive(uv_mutex_t* handle); void uv_mutex_destroy(uv_mutex_t* handle); void uv_mutex_lock(uv_mutex_t* handle); int uv_mutex_trylock(uv_mutex_t* handle); void uv_mutex_unlock(uv_mutex_t* handle); uv_mutex_init() uv_mutex_init_recursive() uv_mutex_trylock() 0 . libuv uv_mutex_destroy() uv_mutex_lock() uv_mutex_unlock() abort() . uv_mutex_trylock() EAGAIN EBUSY . (Recursive mutexes) . uv_cond_t . BSD . : uv_mutex_init(a_mutex); uv_mutex_lock(a_mutex); uv_thread_create(thread_id, entry, (void *)a_mutex); uv_mutex_lock(a_mutex); // more things here a_mutex (debug) uv_mutex_lock() . : . (Locks) - (Read-write locks) . . . . - . . locks/main.c - rwlock #include #include uv_barrier_t blocker; uv_rwlock_t numlock; int shared_num; void reader(void *n) { int num = *(int *)n; int i; for (i = 0; i < 20; i++) { uv_rwlock_rdlock(&numlock); printf("Reader %d: acquired lock\n", num); printf("Reader %d: shared num = %d\n", num, shared_num); uv_rwlock_rdunlock(&numlock); printf("Reader %d: released lock\n", num); } uv_barrier_wait(&blocker); } void writer(void *n) { int num = *(int *)n; int i; for (i = 0; i < 20; i++) { uv_rwlock_wrlock(&numlock); printf("Writer %d: acquired lock\n", num); shared_num++; printf("Writer %d: incremented shared num = %d\n", num, shared_num); uv_rwlock_wrunlock(&numlock); printf("Writer %d: released lock\n", num); } uv_barrier_wait(&blocker); } int main() { uv_barrier_init(&blocker, 4); shared_num = 0; uv_rwlock_init(&numlock); uv_thread_t threads[3]; int thread_nums[] = {1, 2, 1}; uv_thread_create(&threads[0], reader, &thread_nums[0]); uv_thread_create(&threads[1], reader, &thread_nums[1]); uv_thread_create(&threads[2], writer, &thread_nums[2]); uv_barrier_wait(&blocker); uv_barrier_destroy(&blocker); uv_rwlock_destroy(&numlock); return 0; } . . (barriers) . (Others) libuv (semaphores) (condition variables) (barriers) pthread . libuv uv_once() . uv_once() : /* Initialize guard */ static uv_once_t once_only = UV_ONCE_INIT; int i = 0; void increment() { i++; } void thread1() { /* ... work */ uv_once(once_only, increment); } void thread2() { /* ... work */ uv_once(once_only, increment); } int main() { /* ... spawn threads */ } i == 1 . v0.11.11 libuv API uv_key_t (thread-local storage) . libuv (libuv work queue) uv_queue_work() . uv_queue_work() . I/O CPU . ( I/O ) ( << >>) . libuv . node.js is cancer . (sleep) . queue-work/main.c - void fib(uv_work_t *req) { int n = *(int *) req->data; if (random() % 2) sleep(1); else sleep(3); long fib = fib_(n); fprintf(stderr, "%dth fibonacci is %lu\n", n, fib); } void after_fib(uv_work_t *req, int status) { fprintf(stderr, "Done calculating %dth fibonacci\n", *(int *) req->data); } . uv_work_t . void* data . . uv_queue_work : queue-work/main.c int main() { loop = uv_default_loop(); int data[FIB_UNTIL]; uv_work_t req[FIB_UNTIL]; int i; for (i = 0; i < FIB_UNTIL; i++) { data[i] = i; req[i].data = (void *) &data[i]; uv_queue_work(loop, &req[i], fib, after_fib); } return uv_run(loop, UV_RUN_DEFAULT); } uv_work_t after . . (wrappers) <#baton> (baton) . 0.9.4 libuv uv_cancel() . libuv . . uv_cancel() . uv_cancel() . . . uv_cancel() . . queue-cancel/main.c int main() { loop = uv_default_loop(); int data[FIB_UNTIL]; int i; for (i = 0; i < FIB_UNTIL; i++) { data[i] = i; fib_reqs[i].data = (void *) &data[i]; uv_queue_work(loop, &fib_reqs[i], fib, after_fib); } uv_signal_t sig; uv_signal_init(loop, &sig); uv_signal_start(&sig, signal_handler, SIGINT); return uv_run(loop, UV_RUN_DEFAULT); } Ctrl+C uv_cancel() (workers) . uv_cancel() 0 . queue-cancel/main.c void signal_handler(uv_signal_t *req, int signum) { printf("Signal received!\n"); int i; for (i = 0; i < FIB_UNTIL; i++) { uv_cancel((uv_req_t*) &fib_reqs[i]); } uv_signal_stop(req); } after status UV_ECANCELED . queue-cancel/main.c void after_fib(uv_work_t *req, int status) { if (status == UV_ECANCELED) fprintf(stderr, "Calculation of %d cancelled.\n", *(int *) req->data); } uv_cancel() uv_fs_t uv_getaddrinfo_t . uv_fs_t.errorno UV_ECANCELED . : . . (Inter-thread communication) . ( uv_queue_work) . . progress/main.c uv_loop_t *loop; uv_async_t async; int main() { loop = uv_default_loop(); uv_work_t req; int size = 10240; req.data = (void*) &size; uv_async_init(loop, &async, print_progress); uv_queue_work(loop, &req, fake_download, after); return uv_run(loop, UV_RUN_DEFAULT); } libuv ( ). libuv (print_progress) . : uv_async_send . libuv uv_async_send . libuv : uv_async_send . uv_async_send . libuv uv_async_send . . progress/main.c double percentage; void fake_download(uv_work_t *req) { int size = *((int*) req->data); int downloaded = 0; while (downloaded < size) { percentage = downloaded*100.0/size; async.data = (void*) &percentage; uv_async_send(&async); sleep(1); downloaded += (200+random())%1000; // can only download max 1000bytes/sec, // but at least a 200; } } uv_async_send . : uv_async_send . progress/main.c void print_progress(uv_async_t *handle) { double percentage = *((double*) handle->data); fprintf(stderr, "Downloaded %.2f%%\n", percentage); } libuv . . progress/main.c void after(uv_work_t *req, int status) { fprintf(stderr, "Download complete\n"); uv_close((uv_handle_t*) &async, NULL); } data bnoordhuis data (thread safe) uv_async_send() . rwlock . : rwlock uv_async_send . uv_async_send (thread affinity) . node.js v8 v8 . v8 . node.js . : 1. node : var lib = require('lib'); lib.on_progress(function() { console.log("Progress"); }); lib.do(); // do other stuff 2. lib.do uv_queue_work . 3. v8 . uv_async_send . 4. ( v8 ) v8 . ---- (Processes) libuv (streams) . . ( ). . . . . . (Spawning child processes) . uv_spawn . spawn/main.c uv_loop_t *loop; uv_process_t child_req; uv_process_options_t options; int main() { loop = uv_default_loop(); char* args[3]; args[0] = "mkdir"; args[1] = "test-dir"; args[2] = NULL; options.exit_cb = on_exit; options.file = "mkdir"; options.args = args; int r; if ((r = uv_spawn(loop, &child_req, &options))) { fprintf(stderr, "%s\n", uv_strerror(r)); return 1; } else { fprintf(stderr, "Launched process with ID %d\n", child_req.pid); } return uv_run(loop, UV_RUN_DEFAULT); } : options . options : uv_process_options_t options = {0}; uv_process_t uv_process_options_t . file args . file . uv_spawn execvp(3) . NULL . uv_spawn uv_process_t.pid (PID) . . uv_close . spawn/main.c void on_exit(uv_process_t *req, int64_t exit_status, int term_signal) { fprintf(stderr, "Process exited with status %" PRId64 ", signal %d\n", exit_status, term_signal); uv_close((uv_handle_t*) req, NULL); . (Changing process parameters) uv_process_options_t . (Change execution directory) uv_process_options_t.cwd . (Set environment variables) uv_process_options_t.env null VAR=VALUE . ( ) NULL . (Option flags) uv_process_options_t.flags OR : o UV_PROCESS_SETUID - uv_process_options_t.uid . o UV_PROCESS_SETGID - uv_process_options_t.gid . UID/GID uv_spawn UV_ENOTSUP . o UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS - uv_process_options_t.args . . o UV_PROCESS_DETACHED - (session) . . (Detaching processes) UV_PROCESS_DETACHED (daemons) . detach/main.c int main() { loop = uv_default_loop(); char* args[3]; args[0] = "sleep"; args[1] = "100"; args[2] = NULL; options.exit_cb = NULL; options.file = "sleep"; options.args = args; options.flags = UV_PROCESS_DETACHED; int r; if ((r = uv_spawn(loop, &child_req, &options))) { fprintf(stderr, "%s\n", uv_strerror(r)); return 1; } fprintf(stderr, "Launched sleep with PID %d\n", child_req.pid); uv_unref((uv_handle_t*) &child_req); return uv_run(loop, UV_RUN_DEFAULT); . (fire-and-forget) uv_unref() . (Sending signals to processes) libuv kill(2) : SIGTERM SIGINT SIGKILL . uv_kill : uv_err_t uv_kill(int pid, int signum); libuv uv_process_kill pid uv_process_t . uv_close _ _ . (Signals) libuv . uv_signal_init() . uv_signal_start() . uv_signal_start() . uv_signal_stop() . : signal/main.c #include #include #include #include uv_loop_t* create_loop() { uv_loop_t *loop = malloc(sizeof(uv_loop_t)); if (loop) { uv_loop_init(loop); } return loop; } void signal_handler(uv_signal_t *handle, int signum) { printf("Signal received: %d\n", signum); uv_signal_stop(handle); } // two signal handlers in one loop void thread1_worker(void *userp) { uv_loop_t *loop1 = create_loop(); uv_signal_t sig1a, sig1b; uv_signal_init(loop1, &sig1a); uv_signal_start(&sig1a, signal_handler, SIGUSR1); uv_signal_init(loop1, &sig1b); uv_signal_start(&sig1b, signal_handler, SIGUSR1); uv_run(loop1, UV_RUN_DEFAULT); } // two signal handlers, each in its own loop void thread2_worker(void *userp) { uv_loop_t *loop2 = create_loop(); uv_loop_t *loop3 = create_loop(); uv_signal_t sig2; uv_signal_init(loop2, &sig2); uv_signal_start(&sig2, signal_handler, SIGUSR1); uv_signal_t sig3; uv_signal_init(loop3, &sig3); uv_signal_start(&sig3, signal_handler, SIGUSR1); while (uv_run(loop2, UV_RUN_NOWAIT) || uv_run(loop3, UV_RUN_NOWAIT)) { } } int main() { printf("PID %d\n", getpid()); uv_thread_t thread1, thread2; uv_thread_create(&thread1, thread1_worker, 0); uv_thread_create(&thread2, thread2_worker, 0); uv_thread_join(&thread1); uv_thread_join(&thread2); return 0; } : uv_run(loop, UV_RUN_NOWAIT) uv_run(loop, UV_RUN_ONCE) . UV_RUN_ONCE UV_RUN_NOWAIT . NOWAIT (starvation) . SIGUSR1 uv_signal_t. . . SIGINT . / (Child Process I/O) 0 1 2 stdin stdout stderr . . stdout . stderr stderr . libuv . : proc-streams/test.c #include int main() { fprintf(stderr, "This is stderr\n"); printf("This is stdout\n"); return 0; } proc-streams stderr . stdio uv_process_options_t . stdio_count . uv_process_options_t.stdio uv_stdio_container_t : typedef struct uv_stdio_container_s { uv_stdio_flags flags; union { uv_stream_t* stream; int fd; } data; } uv_stdio_container_t; flags . UV_IGNORE . stdio UV_IGNORE /dev/null . UV_INHERIT_FD . fd stderr . proc-streams/main.c int main() { loop = uv_default_loop(); /* ... */ options.stdio_count = 3; uv_stdio_container_t child_stdio[3]; child_stdio[0].flags = UV_IGNORE; child_stdio[1].flags = UV_IGNORE; child_stdio[2].flags = UV_INHERIT_FD; child_stdio[2].data.fd = 2; options.stdio = child_stdio; options.exit_cb = on_exit; options.file = args[0]; options.args = args; int r; if ((r = uv_spawn(loop, &child_req, &options))) { fprintf(stderr, "%s\n", uv_strerror(r)); return 1; } return uv_run(loop, UV_RUN_DEFAULT); } proc-stream "This is stderr" . stdout . . flags UV_INHERIT_STREAM data.stream / . CGI . / CGI : cgi/tick.c #include #include int main() { int i; for (i = 0; i < 10; i++) { printf("tick\n"); fflush(stdout); sleep(1); } printf("BOOM!\n"); return 0; } CGI tick . cgi/main.c void on_new_connection(uv_stream_t *server, int status) { if (status == -1) { // error! return; } uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t)); uv_tcp_init(loop, client); if (uv_accept(server, (uv_stream_t*) client) == 0) { invoke_cgi_script(client); } else { uv_close((uv_handle_t*) client, NULL); } TCP (stream) invoke_cgi_script . cgi/main.c args[1] = NULL; /* ... finding the executable path and setting up arguments ... */ options.stdio_count = 3; uv_stdio_container_t child_stdio[3]; child_stdio[0].flags = UV_IGNORE; child_stdio[1].flags = UV_INHERIT_STREAM; child_stdio[1].data.stream = (uv_stream_t*) client; child_stdio[2].flags = UV_IGNORE; options.stdio = child_stdio; options.exit_cb = cleanup_handles; options.file = args[0]; options.args = args; // Set this so we can close the socket after the child process exits. child_req.data = (void*) client; int r; if ((r = uv_spawn(loop, &child_req, &options))) { fprintf(stderr, "%s\n", uv_strerror(r)); stdout CGI . / . . (Parent-child IPC) uv_stdio_container_t.flags UV_CREATE_PIPE UV_READABLE_PIPE UV_WRITABLE_PIPE . / . uv_stream_t* stream uv_pipe_t . stdio (New stdio Pipes) uv_pipe_t pipe(7) ( |) . Named Pipe . Unix Domain Socket mkfifo(1) pipe(7) . uv_spawn uv_pipe_t UV_CREATE_PIPE socketpair(2) . libuv IPC . (Arbitrary process IPC) [1] IPC . D-BUS . . MySQL . - / . TCP . pipe-echo-server/main.c void remove_sock(int sig) { uv_fs_t req; uv_fs_unlink(loop, &req, PIPENAME, NULL); exit(0); } int main() { loop = uv_default_loop(); uv_pipe_t server; uv_pipe_init(loop, &server, 0); signal(SIGINT, remove_sock); int r; if ((r = uv_pipe_bind(&server, PIPENAME))) { fprintf(stderr, "Bind error %s\n", uv_err_name(r)); return 1; } if ((r = uv_listen((uv_stream_t*) &server, 128, on_new_connection))) { fprintf(stderr, "Listen error %s\n", uv_err_name(r)); return 2; } return uv_run(loop, UV_RUN_DEFAULT); } echo.sock . API TCP . socat : $ socat - /path/to/socket : void uv_pipe_connect(uv_connect_t *req, uv_pipe_t *handle, const char *name, uv_connect_cb cb); name echo.sock . name ( /tmp/echo.sock). name \\?\pipe\echo.sock . (Sending file descriptors over pipes) . / . (load-balancing) . libuv TCP . (round-robin) . . (master) . multi-echo-server/worker.c uv_loop_t *loop; uv_pipe_t queue; int main() { loop = uv_default_loop(); uv_pipe_init(loop, &queue, 1 /* ipc */); uv_pipe_open(&queue, 0); uv_read_start((uv_stream_t*)&queue, alloc_buffer, on_new_connection); return uv_run(loop, UV_RUN_DEFAULT); } queue . ipc uv_pipe_init 1 ! uv_pipe_open stdin . multi-echo-server/worker.c void on_new_connection(uv_stream_t *q, ssize_t nread, const uv_buf_t *buf) { if (nread < 0) { if (nread != UV_EOF) fprintf(stderr, "Read error %s\n", uv_err_name(nread)); uv_close((uv_handle_t*) q, NULL); return; } uv_pipe_t *pipe = (uv_pipe_t*) q; if (!uv_pipe_pending_count(pipe)) { fprintf(stderr, "No pending count\n"); return; } uv_handle_type pending = uv_pipe_pending_type(pipe); assert(pending == UV_TCP); uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t)); uv_tcp_init(loop, client); if (uv_accept(q, (uv_stream_t*) client) == 0) { uv_os_fd_t fd; uv_fileno((const uv_handle_t*) client, &fd); fprintf(stderr, "Worker %d: Accepted fd %d\n", getpid(), fd); uv_read_start((uv_stream_t*) client, alloc_buffer, echo_read); } else { uv_close((uv_handle_t*) client, NULL); } } uv_pipe_pending_count() . uv_pipe_pending_type() . accept . accept () ( ) : (client) queue. . (master) . multi-echo-server/main.c struct child_worker { uv_process_t req; uv_process_options_t options; uv_pipe_t pipe; } *workers; child_worker . multi-echo-server/main.c void setup_workers() { round_robin_counter = 0; // ... // launch same number of workers as number of CPUs uv_cpu_info_t *info; int cpu_count; uv_cpu_info(&info, &cpu_count); uv_free_cpu_info(info, cpu_count); child_worker_count = cpu_count; workers = calloc(cpu_count, sizeof(struct child_worker)); while (cpu_count--) { struct child_worker *worker = &workers[cpu_count]; uv_pipe_init(loop, &worker->pipe, 1); uv_stdio_container_t child_stdio[3]; child_stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; child_stdio[0].data.stream = (uv_stream_t*) &worker->pipe; child_stdio[1].flags = UV_IGNORE; child_stdio[2].flags = UV_INHERIT_FD; child_stdio[2].data.fd = 2; worker->options.stdio = child_stdio; worker->options.stdio_count = 3; worker->options.exit_cb = close_process_handle; worker->options.file = args[0]; worker->options.args = args; uv_spawn(loop, &worker->req, &worker->options); fprintf(stderr, "Started worker %d\n", worker->req.pid); } } uv_cpu_info libuv . IPC 1 . stdin ( ). . . on_new_connection ( TCP main() ) . multi-echo-server/main.c void on_new_connection(uv_stream_t *server, int status) { if (status == -1) { // error! return; } uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t)); uv_tcp_init(loop, client); if (uv_accept(server, (uv_stream_t*) client) == 0) { uv_write_t *write_req = (uv_write_t*) malloc(sizeof(uv_write_t)); dummy_buf = uv_buf_init("a", 1); struct child_worker *worker = &workers[round_robin_counter]; uv_write2(write_req, (uv_stream_t*) &worker->pipe, &dummy_buf, 1, (uv_stream_t*) client, NULL); round_robin_counter = (round_robin_counter + 1) % child_worker_count; } else { uv_close((uv_handle_t*) client, NULL); } } uv_write2 (client) . . Kyle uv_write2() . ---- [1] . (Advanced event loops) libuv . libuv -- Qt Qt libuv . (Stopping an event loop) uv_stop() . (iteration) . uv_stop() (kill switch) . uv_stop() I/O (block) . uv_run() . src/unix/core.c - uv_run uv_signal_t* sh; /* Note: while the handle is in the UV_HANDLE_CLOSING state now, it's still * possible for it to be active in the sense that uv__is_active() returns * true. * * A good example is when the user calls uv_shutdown(), immediately followed * by uv_close(). The handle is considered active at this point because the * completion of the shutdown req is still pending. */ assert(handle->flags & UV_HANDLE_CLOSING); assert(!(handle->flags & UV_HANDLE_CLOSED)); handle->flags |= UV_HANDLE_CLOSED; switch (handle->type) { case UV_PREPARE: case UV_CHECK: case UV_IDLE: case UV_ASYNC: case UV_TIMER: case UV_PROCESS: stop_flag uv_stop() . (callbacks) libuv uv_stop() . libuv idle prepare I/O . uv_stop() stop_flag . uv_backend_timeout() 0 I/O . uv_stop() check I/O . uv_stop() . . uvstop/main.c #include #include int64_t counter = 0; void idle_cb(uv_idle_t *handle) { printf("Idle callback\n"); counter++; if (counter >= 5) { uv_stop(uv_default_loop()); printf("uv_stop() called\n"); } } void prep_cb(uv_prepare_t *handle) { printf("Prep callback\n"); } int main() { uv_idle_t idler; uv_prepare_t prep; uv_idle_init(uv_default_loop(), &idler); uv_idle_start(&idler, idle_cb); uv_prepare_init(uv_default_loop(), &prep); uv_prepare_start(&prep, prep_cb); uv_run(uv_default_loop(), UV_RUN_DEFAULT); return 0; } (Utilities) . libev libuv . API libuv . (Timers) (callback) . libuv . (watcher) timeout repeat . . uv_timer_t timer_req; uv_timer_init(loop, &timer_req); uv_timer_start(&timer_req, callback, 5000, 2000); ( timeout) uv_timer_start ( repeat) . : uv_timer_stop(&timer_req); . . : uv_timer_set_repeat(uv_timer_t *timer, int64_t repeat); . : o . uv_timer_start . o . : int uv_timer_again(uv_timer_t *) timeout repeat repeat . ( UV_EINVAL) -1 . . (Event loop reference count) . (reference count) . : void uv_ref(uv_handle_t*); void uv_unref(uv_handle_t*); . . (garbage collector) X (heartbeat) . . unref uv_run . node.js libuv JavaScript API . JS uv_handle_t ( ) ref unref . ref-timer/main.c uv_loop_t *loop; uv_timer_t gc_req; uv_timer_t fake_job_req; int main() { loop = uv_default_loop(); uv_timer_init(loop, &gc_req); uv_unref((uv_handle_t*) &gc_req); uv_timer_start(&gc_req, gc, 0, 2000); // could actually be a TCP download or something uv_timer_init(loop, &fake_job_req); uv_timer_start(&fake_job_req, fake_job, 9000, 0); return uv_run(loop, UV_RUN_DEFAULT); } unref . . (Idler pattern) idle . idle . SETI :) idle (GUI) . . TCP (block) . idle . idle-compute/main.c uv_loop_t *loop; uv_fs_t stdin_watcher; uv_idle_t idler; char buffer[1024]; int main() { loop = uv_default_loop(); uv_idle_init(loop, &idler); uv_buf_t buf = uv_buf_init(buffer, 1024); uv_fs_read(loop, &stdin_watcher, 0, &buf, 1, -1, on_type); uv_idle_start(&idler, crunch_away); return uv_run(loop, UV_RUN_DEFAULT); } idle . crunch_away Return . idle . idle-compute/main.c void crunch_away(uv_idle_t* handle) { // Compute extra-terrestrial life // fold proteins // computer another digit of PI // or similar fprintf(stderr, "Computing PI...\n"); // just to avoid overwhelming your terminal emulator uv_idle_stop(handle); } (Passing data to worker thread) uv_queue_work . struct uv_work_t.data . uv_work_t ( baton [1] ). free . struct ftp_baton { uv_work_t req; char *host; int port; char *username; char *password; } ftp_baton *baton = (ftp_baton*) malloc(sizeof(ftp_baton)); baton->req.data = (void*) baton; baton->host = strdup("my.webhost.com"); baton->port = 21; // ... uv_queue_work(loop, &baton->req, ftp_session, ftp_cleanup); baton . : void ftp_session(uv_work_t *req) { ftp_baton *baton = (ftp_baton*) req->data; fprintf(stderr, "Connecting to %s\n", baton->host); } void ftp_cleanup(uv_work_t *req) { ftp_baton *baton = (ftp_baton*) req->data; free(baton->host); // ... free(baton); } baton . / Polling (External I/O with polling) I/O . I/O libuv . . I/O . <#threadpool> . . uv_poll libuv . I/O libuv uv_poll . libuv . libcurl . libcurl libuv multi libuv I/O . uvwget/main.c - #include #include #include #include #include uv_loop_t *loop; CURLM *curl_handle; uv_timer_t timeout; int main(int argc, char **argv) { loop = uv_default_loop(); if (argc <= 1) return 0; if (curl_global_init(CURL_GLOBAL_ALL)) { fprintf(stderr, "Could not init cURL\n"); return 1; } uv_timer_init(loop, &timeout); curl_handle = curl_multi_init(); curl_multi_setopt(curl_handle, CURLMOPT_SOCKETFUNCTION, handle_socket); curl_multi_setopt(curl_handle, CURLMOPT_TIMERFUNCTION, start_timeout); while (argc-- > 1) { add_download(argv[argc], argc); } uv_run(loop, UV_RUN_DEFAULT); curl_multi_cleanup(curl_handle); return 0; } libuv . libcurl . handle_socket . start_timeout libcurl (timeout) I/O libcurl . libcurl . : $ ./uvwget [url1] [url2] ... (URL) : uvwget/main.c - (URLs) void add_download(const char *url, int num) { char filename[50]; sprintf(filename, "%d.download", num); FILE *file; file = fopen(filename, "w"); if (file == NULL) { fprintf(stderr, "Error opening %s\n", filename); return; } CURL *handle = curl_easy_init(); curl_easy_setopt(handle, CURLOPT_WRITEDATA, file); curl_easy_setopt(handle, CURLOPT_URL, url); curl_multi_add_handle(curl_handle, handle); fprintf(stderr, "Added download %s -> %s\n", url, filename); } libcurl . start_timeout libcurl . libuv <#timers> curl_multi_socket_action CURL_SOCKET_TIMEOUT . curl_multi_socket_action libcurl . handle_socket (poll) . uvwget/main.c - (Polling) void start_timeout(CURLM *multi, long timeout_ms, void *userp) { if (timeout_ms <= 0) timeout_ms = 1; /* 0 means directly call socket_action, but we'll do it in a bit */ uv_timer_start(&timeout, on_timeout, timeout_ms, 0); } int handle_socket(CURL *easy, curl_socket_t s, int action, void *userp, void *socketp) { curl_context_t *curl_context; if (action == CURL_POLL_IN || action == CURL_POLL_OUT) { if (socketp) { curl_context = (curl_context_t*) socketp; } else { curl_context = create_curl_context(s); curl_multi_assign(curl_handle, s, (void *) curl_context); } } switch (action) { case CURL_POLL_IN: uv_poll_start(&curl_context->poll_handle, UV_READABLE, curl_perform); break; case CURL_POLL_OUT: uv_poll_start(&curl_context->poll_handle, UV_WRITABLE, curl_perform); break; case CURL_POLL_REMOVE: if (socketp) { uv_poll_stop(&((curl_context_t*)socketp)->poll_handle); destroy_curl_context((curl_context_t*) socketp); curl_multi_assign(curl_handle, s, NULL); } break; default: abort(); } return 0; } s action . uv_poll_t curl_multi_assign . socketp . libcurl . poll . libcurl UV_READABLE UV_WRITABLE . libuv poll . uv_poll_start . curl_perform . uvwget/main.c - libcurl void curl_perform(uv_poll_t *req, int status, int events) { uv_timer_stop(&timeout); int running_handles; int flags = 0; if (status < 0) flags = CURL_CSELECT_ERR; if (!status && events & UV_READABLE) flags |= CURL_CSELECT_IN; if (!status && events & UV_WRITABLE) flags |= CURL_CSELECT_OUT; curl_context_t *context; context = (curl_context_t*)req; curl_multi_socket_action(curl_handle, context->sockfd, flags, &running_handles); check_multi_info(); } . . curl_multi_socket_action . libcurl . libcurl . . . uvwget/main.c - void check_multi_info(void) { char *done_url; CURLMsg *message; int pending; while ((message = curl_multi_info_read(curl_handle, &pending))) { switch (message->msg) { case CURLMSG_DONE: curl_easy_getinfo(message->easy_handle, CURLINFO_EFFECTIVE_URL, &done_url); printf("%s DONE\n", done_url); curl_multi_remove_handle(curl_handle, message->easy_handle); curl_easy_cleanup(message->easy_handle); break; default: fprintf(stderr, "CURLMSG default\n"); abort(); } } } Check Prepare (Check & Prepare watchers) (TODO) (Loading libraries) libuv . // node.js require() . (symbols) . . . . plugin/plugin.h #ifndef UVBOOK_PLUGIN_SYSTEM #define UVBOOK_PLUGIN_SYSTEM // Plugin authors should use this to register their plugins with mfp. void mfp_register(const char *name); #endif [2]. : plugin/hello.c #include "plugin.h" void initialize() { mfp_register("Hello World!"); } initialize . : $ ./plugin libhello.dylib Loading libhello.dylib Registered plugin "Hello World!" : . libhello.so . uv_dlopen libhello.dylib . uv_dlsym initialize . plugin/main.c #include "plugin.h" typedef void (*init_plugin_function)(); void mfp_register(const char *name) { fprintf(stderr, "Registered plugin \"%s\"\n", name); } int main(int argc, char **argv) { if (argc == 1) { fprintf(stderr, "Usage: %s [plugin1] [plugin2] ...\n", argv[0]); return 0; } uv_lib_t lib; while (--argc) { fprintf(stderr, "Loading %s\n", argv[argc]); if (uv_dlopen(argv[argc], &lib)) { fprintf(stderr, "Error: %s\n", uv_dlerror(&lib)); continue; } init_plugin_function init_plugin; if (uv_dlsym(&lib, "initialize", (void **) &init_plugin)) { fprintf(stderr, "dlsym error: %s\n", uv_dlerror(&lib)); continue; } init_plugin(); } return 0; } uv_dlopen uv_lib_t . 0 -1 . uv_dlerror . uv_dlsym . init_plugin_function . TTY . . grep --colour. libuv uv_tty_t ( stream) ANSI . libuv ANSI . uv_tty_t . : int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int unused) unused . uv_read_start() stream . uv_tty_set_mode normal TTY . . uv_tty_reset_mode . (redirection) . grep . TTY uv_guess_handle UV_TTY . : tty/main.c #include #include #include #include uv_loop_t *loop; uv_tty_t tty; int main() { uv_write_t req; uv_buf_t buf; uv_write_t req1; uv_buf_t buf1; loop = uv_default_loop(); uv_tty_init(loop, &tty, STDOUT_FILENO, 0); uv_tty_set_mode(&tty, UV_TTY_MODE_NORMAL); if (uv_guess_handle(1) == UV_TTY) { buf1.base = "\033[41;37m"; buf1.len = strlen(buf1.base); uv_write(&req1, (uv_stream_t*) &tty, &buf1, 1, NULL); } buf.base = "Hello TTY\n"; buf.len = strlen(buf.base); uv_write(&req, (uv_stream_t*) &tty, &buf, 1, NULL); uv_tty_reset_mode(); return uv_run(loop, UV_RUN_DEFAULT); } TTY uv_tty_get_winsize() 0 . . tty-gravity/main.c #include #include #include #include uv_loop_t *loop; uv_tty_t tty; uv_timer_t tick; uv_write_t write_req; int width, height; int pos = 0; char *message = " Hello TTY "; void update(uv_timer_t *req) { char data[500]; uv_buf_t buf; buf.base = data; buf.len = sprintf(data, "\033[2J\033[H\033[%dB\033[%luC\033[42;37m%s", pos, (unsigned long) (width-strlen(message))/2, message); uv_write(&write_req, (uv_stream_t*) &tty, &buf, 1, NULL); pos++; if (pos > height) { uv_tty_reset_mode(); uv_timer_stop(&tick); } } int main() { loop = uv_default_loop(); uv_tty_init(loop, &tty, STDOUT_FILENO, 0); uv_tty_set_mode(&tty, 0); if (uv_tty_get_winsize(&tty, &width, &height)) { fprintf(stderr, "Could not get TTY information\n"); uv_tty_reset_mode(); return 1; } fprintf(stderr, "Width %d, height %d\n", width, height); uv_timer_init(loop, &tick); uv_timer_start(&tick, update, 200, 200); return uv_run(loop, UV_RUN_DEFAULT); } : +-------+----------------------------+ | | | +-------+----------------------------+ |2 J | | | | | | | | | | 2 | | | | +-------+----------------------------+ |H | | | | | | | | | | | | | | | | | | | - | +-------+----------------------------+ |n B | | | | | | | | | | | | | n | +-------+----------------------------+ |n C | | | | | | | | | | n | | | | +-------+----------------------------+ |m | | | | | | | | | | | | | | | | | | | | | | (40+2) | | | | | | (30+7) | +-------+----------------------------+ . ncurses . 1.23.1:: readable . . ---- [1] baton Konstantin Kafer node.js -- [2] mfp My Fancy Plugin . (About) Nikhil Marathe ( ) . node-taglib libuv . . . . Pull Request . Marc Lehmann libev . Sphinx vim . : libuv Nikhil . (Upgrading) libuv 1.0. libuv 0.10 1.0.0 (libuv 0.10 -> 1.0.0 migration guide) API 1.0.0 . 0.10 . (Loop initialization and closing) libuv 0.10 ( ) uv_loop_new uv_loop_delete . 1.0 . libuv 0.10 uv_loop_t* loop = uv_loop_new(); ... uv_loop_delete(loop); libuv 1.0 uv_loop_t* loop = malloc(sizeof *loop); uv_loop_init(loop); ... uv_loop_close(loop); free(loop); : . uv_loop_init() <#c.uv_loop_init> uv_loop_close() <#c.uv_loop_close> . (Error handling) libuv 1.0 . libuv 0.10 0 -1 uv_last_error . 1.0 0 . libuv 0.10 ... assume 'server' is a TCP server which is already listening r = uv_listen((uv_stream_t*) server, 511, NULL); if (r == -1) { uv_err_t err = uv_last_error(uv_default_loop()); /* err.code contains UV_EADDRINUSE */ } libuv 1.0 ... assume 'server' is a TCP server which is already listening r = uv_listen((uv_stream_t*) server, 511, NULL); if (r < 0) { /* r contains UV_EADDRINUSE */ } (Threadpool changes) libuv 0.10 threadpool API QueueUserWorkItem threadpool . 1.0 . threadpool UV_THREADPOOL_SIZE . <#threadpool> . (Allocation callback API change) libuv 0.10 uv_buf_t <#c.uv_buf_t> (by value) : uv_buf_t alloc_cb(uv_handle_t* handle, size_t size) { return uv_buf_init(malloc(size), size); } libuv 1.0 : void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { buf->base = malloc(size); buf->len = size; } IPv4 IPv6 (Unification of IPv4 / IPv6 APIs) 1.0 libuv IPv4 IPv6 . uv_tcp_bind uv_tcp_bind6 uv_tcp_bind() <#c.uv_tcp_bind> . IPv4 struct sockaddr_in IPv6 struct sockaddr_in6 . struct sockaddr* ( ) . (stack) . libuv 0.10 struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", 1234); ... uv_tcp_bind(&server, addr) libuv 1.0 struct sockaddr_in addr; uv_ip4_addr("0.0.0.0", 1234, &addr) ... uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); IPv4 IPv6 ( uv_ip4_addr() <#c.uv_ip4_addr> uv_ip6_addr() <#c.uv_ip6_addr>) . ..note:: IPv4 IPv6 . Streams UDP streams UDP uv_buf_t <#c.uv_buf_t> . libuv 0.10 void on_read(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) { ... } void recv_cb(uv_udp_t* handle, ssize_t nread, uv_buf_t buf, struct sockaddr* addr, unsigned flags) { ... } libuv 1.0 void on_read(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { ... } void recv_cb(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags) { ... } Pipe libuv 0.10 ( ) uv_read2_start pipe . : void on_read(uv_pipe_t* pipe, ssize_t nread, uv_buf_t buf, uv_handle_type pending) { ... } libuv 1.0 uv_read2_start uv_pipe_pending_count() <#c .uv_pipe_pending_count> uv_pipe_pending_type() <#c .uv_pipe_pending_type> : void on_read(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { ... while (uv_pipe_pending_count((uv_pipe_t*) handle) != 0) { pending = uv_pipe_pending_type((uv_pipe_t*) handle); ... } ... } (Extracting the file descriptor out of a handle) API libuv TCP . fd = handle->io_watcher.fd; uv_fileno() <#c.uv_fileno> . uv_fs_readdir uv_fs_readdir libuv 0.10 req->ptr . 1.0 uv_fs_scandir() <#c.uv_fs_scandir> scandir(3) . uv_fs_scandir_next() <#c.uv_fs_scandir_next> . threadpool libuv dents scandir(3) . (DOWNLOADS) libuv . (INSTALLATION) README . (AUTHOR) libuv (COPYRIGHT) 2014-present, libuv 1.52.1 August 26, 2026 LIBUV(1)