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. 我的TDD实践---SVN架设篇

    我的TDD实践---SVN架设篇 “我的TDD实践”系列之SVN架设 写在前面: 我的TDD实践这几篇文章主要是围绕测试驱动开发所展开的,其中涵盖了一小部分测试理论,更多的则是关注工具的使用及环境的搭 ...

  2. c# AutoResetEvent和ManualResetEvent

    网上有很多AutoResetEvent和ManualResetEvent的详细介绍,在这里不做过多详细的解释,写下自己的一点心得留作备忘. AutoResetEvent和ManualResetEven ...

  3. sql连接查询 2011-10-10 23:13 (QQ空间)

    在关系数据库管理系统中,表建立时各数据之间的关系不必确定,常把一个实体的所有信息存放在一个表中,通过连接运算符可以实现多个表查询.连接是关系数据库模型的主要特点,也是它区别于其它类型数据库管理系统的一 ...

  4. 用python写爬虫

    Python提供了许多Module,通过这些Module,可以很简单的做一些工作.比如,要获得cloga这个词在百度搜索结果页中的排名结果(排名结果+URL),这就是一个很简单的爬虫需求. 首先,要通 ...

  5. 使用mysqldump 对数据库进行备份的乱码问题

    最近在做项目的工程中,由于系统中需要提供数据库备份的功能,经过网上一番搜索,觉得采用简单的mysqldump (1)java代码 String backupSQL = "cmd /c mys ...

  6. EF 下的code fist 模式编程

    EF 分两种模式 codefirst(就是不知道数据是啥,也没有数据库)  和 database fist (数据已经设计好了) 首先打开vs  新建一个项目 创建一个控制台程序 然后 新建一个Tea ...

  7. JavaScript中SetInterval与setTimeout的用法详解

    setTimeout 描述 setTimeout(code,millisec) setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式. 注:调用过程中,可以使用clearTimeou ...

  8. PHP连接MSSQL数据库案例,PHPWAMP多个PHP版本连接SQL Server数据库

    课前小知识普及:MSSQL和SQL Server是同一个软件,叫法不同而已,MSSQL全称是Microsoft SQL Server,MSSQL是简写,有些人则喜欢直接叫SQL Server,我就比较 ...

  9. USACO 4.2 The Perfect Stall(二分图匹配匈牙利算法)

    The Perfect StallHal Burch Farmer John completed his new barn just last week, complete with all the ...

  10. response.addCookie(cookie)添加cookie失败.

    两个if循环能进来,创建的两个cookie也能通过控制台输出.  但是却添加失败. 原因是:request.getRequestDispatcher("/MainFrame").f ...