zoukankan      html  css  js  c++  java
  • child_process小解

    js是一种单进程单线程的语言,但现行的cpu都是多核的,为了解决单进程单线程对多核使用不足的问题,child_process应运而生,理想情况下每个进程各自利用一个内核。

    主要有四种方法来创建子进程,每个子进程带有3个流对象child.stdin, child.stdout, child.stderr。

    exec 从子进程中返回一个完整的buffer,默认情况下为200k,若数据大于200k,会导致程序崩溃,适用于少量数据返回的情况,属于“同步中的异步”,即直到完全读取到内容,才会从子进程返回数据

    execFile 与exec类似,不同之处就是它创建子进程只需要指定要执行的文件模块即可

    spawn(大量生产) 返回一个stream对象,因此当你想要子进程返回大量数据时,例如图像处理,读取二进制数据等,最好使用此方法,此方法属于“异步中的异步”,这意味着从子进程开始执行开始,就开始有数据流从子进程传输给node

    fork(分配) 与spawn类似,不同之处就是它创建子进程只需要指定要执行的文件模块即可,而且它会在父进程和子进程之间建立一个通信通道

    对于child.stdin, child.stdout, child.stderr,都是stream对象,其具备stream对象的所有时间,data,error等

    对于进程,拥有close,exit,error等事件

    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    child_process.exec(command[, options], callback)

    解析:

    command 将要运行的命令

    options 可以是

     cwd 当前子进程的目录

     env  环境变量键值对

     encoding 编码方式,默认‘utf-8’

     shell 将要执行命令的shell

     timeout 超时时间,默认0

     maxBuffer 数字,stdout与stderr中允许的最大缓存(二进制),超过此值子进程会被杀死,默认200k

     killSignal 字符串,结束信号

     uid 数字,设置用户进程id

     gid 数字,设置进程组id

    callback回调函数,包含三个参数(err, stdout, stderr) stdout子进程标准输出,stderr子进程错误输出

    注: command与options各参数之间用空格分开,共同拼接成一个字符串

    eg:

    support.js 文件代码:
    //子进程输出 console.log(
    "进程 " + process.argv[2] + " 执行。" );
    master.js 文件代码: const fs
    = require('fs'); const child_process = require('child_process'); for(var i=0; i<3; i++) {
      //执行node命令, 当前子进程目录为support.js,用户进程id为当前的i,用空格隔开
    var workerProcess = child_process.exec('node support.js '+i, function (error, stdout, stderr) { if (error) { console.log(error.stack); console.log('Error code: '+error.code); console.log('Signal received: '+error.signal); } console.log('stdout: ' + stdout); console.log('stderr: ' + stderr); }); workerProcess.on('exit', function (code) { console.log('子进程已退出,退出码 '+code); }); } 执行以上代码,输出结果为: $ node master.js 子进程已退出,退出码 0 stdout: 进程 1 执行。 stderr: 子进程已退出,退出码 0 stdout: 进程 0 执行。 stderr: 子进程已退出,退出码 0 stdout: 进程 2 执行。 stderr:

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

     child_process.execFile(file[, args][, options][, callback])

    file: 子进程将要执行的文件目录

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    child_process.spawn(command [, args][, options])

    args 参数数组

    options

     cwd 当前子进程目录

     env 环境变量键值对

     stdio Array|String 子进程的 stdio 配置

     detached Boolean 这个子进程将会变成进程组的领导

     uid Number 设置用户进程的 ID

     gid Number 设置进程组的 ID

    注: command为字符串,options为数组

    eg: 

    //support.js 文件代码:
    console.log("进程 " + process.argv[2] + " 执行。" );
    //master.js 文件代码:
    const fs = require('fs');
    const child_process = require('child_process');
     
    for(var i=0; i<3; i++) {
      //command为node, 当前子进程文件为support.js, 进程id为当前i
    var workerProcess = child_process.spawn('node', ['support.js', i]);   //不可采用workProcess.on('data', function(){})的写法,这是常见概念错误 workerProcess.stdout.on('data', function (data) { console.log('stdout: ' + data); }); workerProcess.stderr.on('data', function (data) { console.log('stderr: ' + data); }); workerProcess.on('close', function (code) { console.log('子进程已退出,退出码 '+code); }); } 执行以上代码,输出结果为: $ node master.js stdout: 进程 0 执行。 子进程已退出,退出码 0 stdout: 进程 1 执行。 子进程已退出,退出码 0 stdout: 进程 2 执行。 子进程已退出,退出码 0

    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    child_process.fork(modulePath[, args][, options])

    modulePath: string,将要运行的模块

    options:Object

     cwd String 子进程的当前工作目录

     env Object 环境变量键值对

     execPath String 创建子进程的可执行文件

     execArgv Array 子进程的可执行文件的字符串参数数组(默认: process.execArgv)

     silent Boolean 如果为true,子进程的stdinstdoutstderr将会被关联至父进程,否则,它们将会从父进程中继承。(默认为:false

     uid Number 设置用户进程的 ID

     gid Number 设置进程组的 ID

    eg:

    //support.js 文件代码:
    console.log("进程 " + process.argv[2] + " 执行。" );
    //master.js 文件代码:
    const fs = require('fs');
    const child_process = require('child_process');
     
    for(var i=0; i<3; i++) {
       var worker_process = child_process.fork("support.js", [i]);    
    
       worker_process.on('close', function (code) {
          console.log('子进程已退出,退出码 ' + code);
       });
    }
    执行以上代码,输出结果为:
    $ node master.js 
    进程 0 执行。
    子进程已退出,退出码 0
    进程 1 执行。
    子进程已退出,退出码 0
    进程 2 执行。
    子进程已退出,退出码 0

    进程间通信

    通过fork()或者其他API,创建子进程后,为了实现父子进程的通信,两者之间会建立IPC通道,通过此通道,父子进程之间才能通过send()与message()传递信息

    eg:

    //parent.js

    var cp= require('child_process');

    //创建子进程后n成为父进程

    var n= cp.fork(__dirname+ '/sub.js');

    n.on('message', function(m){

      console.log('parent got message:', m);

    })

    n.send({hello: 'world'})

    //sub.js

    //process对象代表当前进程

    process.on('message', function(m){

      console.log('child got message:', m);

    });

    process.send({foo: 'bar'});

    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    句柄传递

    什么是句柄?句柄是一种用来标识资源的引用,它的内部包含指向对象的文件描述符,例如它能标识socket对象,UDP套接字,管道

    传递方法: 利用send()

    child.send(message, [,sendHandle])

    目前send()可发送的句柄类型有以下几种:

     net.Socket TCP套接字

     net.Server TCP服务器

     net.Native C++层面的TCP套接字或IPC管道

     dgram.Socket UDP套接字

     dgram.Native C++层面的UDP套接字

    eg:

    //创建服务器代理
    //parent.js
    var cp= require("child_process");
    var child1= cp.fork("child.js");
    var child2= cp.fork("child.js");

    var server= require("net").createServer();
    server.listen(1337, function(){
      //将tcp服务器传递给子进程
      child1.send('server', server);
      child2.send('server', server);
      //关闭父进程
      server.close();
    })


    //child.js
    var http= require('http');
    var server= http.createServer(function (req, res){
      //connection事件触发时输出
      res.writeHead(200, {'Content-Type': 'text/plain'});
      res.end('handled by child, pid is'+ process.pid+ ' ');
    });

    process.on("message", function(m, tcp){
      if(m== "server"){
        tcp.on("connection", function(socket){
          //http服务器发送connection事件
          server.emit('connection', socket);
        })
      }
    })

     ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    进程事件

    kill()并不能真正地将通过IPC相连的子进程杀死,而只是给子进程发送一个系统信号,默认情况下,父进程会通过此方法给子进程发送SIGTERM信号(signal terminate终结信号),子进程收到此信号后应当自己退出

    主要有两种形式

    //结束子进程

    child.kill([signal]);

    //结束当前进程

    process.kill(pid, [signal])

    eg:

    process.on('SIGTERM', function(){
    
      console.log('GOT a SIGTERM, exiting...');
    
      process.exit(1);
    
    });
    
    process.kill(process.pid, 'SIGTERM');
  • 相关阅读:
    how to pass a Javabean to server In Model2 architecture.
    What is the Web Appliation Archive, abbreviation is "WAR"
    Understaning Javascript OO
    Genetic Fraud
    poj 3211 Washing Clothes
    poj 2385 Apple Catching
    Magic Star
    关于memset的用法几点
    c++ 函数
    zoj 2972 Hurdles of 110m
  • 原文地址:https://www.cnblogs.com/yanze/p/6137682.html
Copyright © 2011-2022 走看看