Libuv教程
+ -

Libuv 进程

2019-09-09 0 0

libuv提供了相当多的子进程管理函数,并且是跨平台的,还允许使用stream,或者说pipe完成进程间通信。

在UNIX中有一个共识,就是进程只做一件事,并把它做好。因此,进程通常通过创建子进程来完成不同的任务(例如,在shell中使用pipe)。 一个多进程的,通过消息通信的模型,总比多线程的,共享内存的模型要容易理解得多。

当前一个比较常见的反对事件驱动编程的原因在于,其不能很好地利用现代多核计算机的优势。一个多线程的程序,内核可以将线程调度到不同的cpu核心中执行,以提高性能。但是一个event-loop的程序只有一个线程。实际上,工作区可以被分配到多进程上,每一个进程执行一个event-loop,然后每一个进程被分配到不同的cpu核心中执行。

创建子进程

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是全局变量,因此被初始化为0。如果你在局部变量中定义options,请记得将所有没用的域设为0

uv_process_options_t options = {0};

uv_process_t只是作为句柄,所有的选择项都通过uv_process_options_t设置,为了简单地开始一个进程,你只需要设置file和args,file是要执行的程序,args是所需的参数(和c语言中main函数的传入参数类似)。因为uv_spawn在内部使用了execvp,所以不需要提供绝对地址。遵从惯例,实际传入参数的数目要比需要的参数多一个,因为最后一个参数会被设为NULL。

在函数uv_spawn被调用之后,uv_process_t.pid会包含子进程的id。

回调函数on_exit()会在被调用的时候,传入exit状态和导致exit的信号。

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);

在进程关闭后,需要回收handler。

改变进程参数

在子进程开始执行前,你可以通过使用uv_process_options_t设置运行环境。

改变执行文件路径
设置uv_process_options_t.cwd,更改相应的目录。

设置环境变量
uv_process_options_t.env的格式是以null为结尾的字符串数组,其中每一个字符串的形式都是VAR=VALUE。这些值用来设置进程的环境变量。如果子进程想要继承父进程的环境变量,就将uv_process_options_t.env设为null。

可选标志

通过使用下面标识的按位或的值设置uv_process_options_t.flags的值,可以定义子进程的行为:

  • UV_PROCESS_SETUID-将子进程的执行用户id(UID)设置为uv_process_options_t.uid中的值。
  • UV_PROCESS_SETGID-将子进程的执行组id(GID)设置为uv_process_options_t.gid中的值。
  • 只有在unix系的操作系统中支持设置用户id和组id,在windows下设置会失败,uv_spawn会返回UV_ENOTSUP。
  • UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS-在windows上,uv_process_options_t.args参数不要用引号包裹。此标记对unix无效。
  • UV_PROCESS_DETACHED-在新会话(session)中启动子进程,这样子进程就可以在父进程退出后继续进行。请看下面的例子:

进程剥离

使用标识UV_PROCESS_DETACHED可以启动守护进程(daemon),或者是使得子进程从父进程中独立出来,这样父进程的退出就不会影响到它。

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);

记住一点,就是handle会始终监视着子进程,所以你的程序不会退出。uv_unref()会解除handle。

0 篇笔记 写笔记

CEF 多进程线程模型
CEF多进程由于CEF是基于chromium的封装开发,其本质不提供实质的额外关于浏览器的功能开发,只是对基于chromium接口的重新封装。所以cef和chromium的多进程一致。CEF3产生的独立进程使用进程间通信(IPC)进行通信.browser和render进程可以通过来回发送异步消息进行......
CEF 进程间通信(IPC)
由于CEF3在多个进程中运行,因此有必要提供在这些进程之间进行通信的机制。CefBrowser和CefFrame对象存在于浏览器和渲染过程中,这有助于促进此过程。每个CefBrowser和CefFrame对象还具有与其关联的唯一ID值,该值将在进程边界的两侧匹配。处理启动消息要在启动时为所有渲染进程......
Nginx conf文件进程ID指令pid
Nginx设计为多进程运行,其中一个守护进程即主进程,其它进程为工作进程。守护进程作为Nginx的管理进程,可通过Nginx服务器的conf文件的pid指令存放守护进程进程ID。语法pid file;file为守护进程存放的文件路径和文件名称。默认情况下,守护进程存放在/usr/local/ngi......
Libuv 子进程IO
一个正常的新产生的进程都有自己的一套文件描述符映射表,例如0,1,2分别对应stdin,stdout和stderr。有时候父进程想要将自己的文件描述符映射表分享给子进程。例如,你的程序启动了一个子命令,并且把所有的错误信息输出到log文件中,但是不能使用stdout。因此,你想要使得你的子进程和父进......
Perl 进程管理
Perl 中你可以以不同的方法来创建进程。本教程将讨论一些进程的管理方法。你可以使用特殊变量 $$ 或 $PROCESS_ID 来获取进程 ID。%ENV 哈希存放了父进程,也就是shell中的环境变量,在Perl中可以修改这些变量。exit() 通常用于退出子进程,主进程在子进程全部退出后再退出。......
Libuv 进程
libuv提供了相当多的子进程管理函数,并且是跨平台的,还允许使用stream,或者说pipe完成进程间通信。在UNIX中有一个共识,就是进程只做一件事,并把它做好。因此,进程通常通过创建子进程来完成不同的任务(例如,在shell中使用pipe)。 一个多进程的,通过消息通信的模型,总比多线程的,共......
Nginx conf文件进程指令process
每一次客户端的请求都有对应的工作进程(work process)来进行响应处理。Nginx服务器conf文件使用process来配置Nginx服务器的最大工作进程数量,其语法格式如下:process process_num | auto;process_num :是一个数字,表示工作进程(work ......
UNIX 进程管理
每当我们在Unix中发出命令时,它都会创建或启动一个新进程,比如使用 ls 命令列出目录内容时,系统就启动了一个进程。操作系统通过称为 pid 或进程ID 的五位数ID号跟踪进程,系统中的每个进程都有唯一的 pid 。由于所有可能的数字都用完,下一个pid滚动或重新开始,因此pid最终会重复。在任何......
CEF Chromium多进程线程模型
Chromium浏览器是采用多进程模型开发的。Browser进程:浏览器的主进程,负责浏览器界面的显示,各个页面的管理,它是所有其它类型进程的祖先,负责它们的创建和销毁工作,有仅只有一个。Render进程:网页的渲染进程,负责页面的渲染工作,Blink/Webkit的渲染工作主要在这个进程中完成,可......
Libuv 进程信号
进程发送信号libuv打包了unix标准的kill(2)系统调用,并且在windows上实现了一个类似用法的调用,但要注意:所有的SIGTERM,SIGINT和SIGKILL都会导致进程的中断。uv_kill函数如下所示:uv_err_t uv_kill(int pid, int signum);......
Java Java 9 改进的进程 API
在 Java 9 之前,Process API 仍然缺乏对使用本地进程的基本支持,例如获取进程的 PID 和所有者,进程的开始时间,进程使用了多少 CPU时间,多少本地进程正在运行等。Java 9 向 Process API 添加了一个名为 ProcessHandle 的接口来增强 java.lan......
Nginx 进程和运行时控制
本节介绍NGINX在运行时启动的过程以及如何控制它们。在这个部分中,主要涉及两个部分的内容:主进程和工作进程控制NGINX1. 主进程和工作进程NGINX有一个主进程和一个或多个工作进程。 如果启用缓存,缓存加载程序和缓存管理器进程也将在启动时运行。主程序的主要目的是读取和评估配置文件以及维护工作进......
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!