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+ '\n');
}); 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');

child_process小解的更多相关文章

  1. NodeJs之child_process

    一.child_process child_process是NodeJs的重要模块.帮助我们创建多进程任务,更好的利用了计算机的多核性能. 当然也支持线程间的通信. 二.child_process的几 ...

  2. nodejs的child_process同步异步

    nodejs是一种单线程模型,但是,使用nodejs的child_process模块可以实现多进程任务.利用child_process可以创建子进程,实现子进程和主进程之间的通信. nodejs v0 ...

  3. Nodejs进阶:如何玩转子进程(child_process)

    本文摘录自个人总结<Nodejs学习笔记>,更多章节及更新,请访问 github主页地址.欢迎加群交流,群号 197339705. 模块概览 在node中,child_process这个模 ...

  4. selection伪元素小解

    上一篇:<RGBA与Opacity区别小解> p{font-size:14px;} 今天说一个简单的伪元素::selection,它的用武之地仅在于改变选中文本时文本的颜色和文本背景颜色. ...

  5. node.js(七) 子进程 child_process模块

    众所周知node.js是基于单线程模型架构,这样的设计可以带来高效的CPU利用率,但是无法却利用多个核心的CPU,为了解决这个问题,node.js提供了child_process模块,通过多进程来实现 ...

  6. node之子线程child_process模块

    node.js是基于单线程模型架构,这样的设计可以带来高效的CPU利用率,但是无法却利用多个核心的CPU,为了解决这个问题,node.js提供了child_process模块,用于新建子进程,子进程的 ...

  7. BASE64Decoder小解

    BASE64Decoder小解 Base64 是网络上最常见的用于传输8Bit 字节代码的编码方式之一,大家可以查看RFC2045 -RFC2049 ,上面有MIME 的详细规范. Base64 要求 ...

  8. jsonp跨域获取数据小解

    jsonp跨域获取数据小解 由于浏览器有同源策略,所以要想获取非同源(协议,域名,端口三者有一不同都算非同源)的页面的数据,就得进行跨域 (1) jsonp原理 由于script标签的src属性可以访 ...

  9. child_process 子进程

    创建子进程,使其可以在进程中执行操作,应用系统命令等.nodejs创建子进程有四种方法,分别是spawn,fork,exec,execFile. 区别 : 格式 : spawn和execFile的格式 ...

随机推荐

  1. C++输入一个字符串,把其中的字符按照逆序输出的两种方法

    用字符数组方法: 基本思路是,先判断字符的结束标志'\0',然后从该位置向前输出. 实现代码: #include<iostream> using namespace std; int ma ...

  2. sharepoint 2013 自定义列表eventhandle权限控制

    记录一下如何在sharepoint server 2013自定义列表中,使用eventhandle控制自定义列表custom list的条目item权限. ///<summary> /// ...

  3. outlook gmail setting

    smtp.gmail.com pop.gmail.com SMTP服务器端口 465  要求安全连接打钩 POP3服务器端口 995  要求安全连接打钩

  4. building android/ubuntu-touch on 32bit machine

    host C: libhost <= build/libs/host/CopyFile.c host StaticLib: libhost (/media/linux/1/touch/expor ...

  5. 设计模式:Prototype 原型模式 - 同学你抄过别人的作业么?-clone()方法的使用

    原型模式: 通过某个类的实例来创建对象 使用原型模式的好处: 好处是什么呢?当我们需要多次重复的创建一个类的示例的时候,我们可以使用new但是,new不仅仅耗费内存而且,如果new 某个类的构造方法中 ...

  6. java基础知识拾遗(三)

    1.类加载 bootstrap classloader -引导(也称为原始)类加载器,它负责加载Java的核心类. extension classloader -扩展类加载器,它负责加载JRE的扩展目 ...

  7. mysql数据库 触发器简单实例

    触发器(trigger):监视某种情况,并触发某种操作. 触发器创建语法四要素:1.监视地点(table) 2.监视事件(insert/update/delete) 3.触发时间(after/befo ...

  8. 用Vue中遇到的问题和处理方法(一)

    用Vue开发项目有一段时间,在实际项目中遇到一些问题,在里把问题记录下来,并附上解决方案,给遇到同样的问题的码友提供一个解决思路吧: 测试部抛出问题一:在Vue1.0路由vue-router中,当点击 ...

  9. Python各种花式截图工具,截到你手软

    前言: 最近,项目中遇到了一个关于实现通过给定URL,实现对网页屏幕进行截图的一个功能,前面代码中已经用python的第三方库实现了截图功能,但在上线以后出现了一些bug,所以就改bug的任务就落在了 ...

  10. C语言之scarf函数

    一 基本用法 scanf函数:接收用户的输入 语法: scanf("格式化控制符",地址列表); 例: int num; scanf("%d",&num ...