Node.js 子进程(exec、spawn、fork)
Node.js 是以单线程的模式运行的,但它使用的是事件驱动来处理并发,这样有助于我们在多核 cpu 的系统上创建多个子进程,从而提高性能。
每个子进程总是带有三个流对象:child.stdin, child.stdout 和child.stderr。他们可能会共享父进程的 stdio 流,或者也可以是独立的被导流的流对象。
Node 提供了 child_process 模块来创建子进程,方法有:
exec - child_process.exec 使用子进程执行命令,缓存子进程的输出,并将子进程的输出以回调函数参数的形式一次性返回。exec方法会从子进程中返回一个完整的buffer。默认情况下,这个buffer的大小应该是200k。如果子进程返回的数据大小超过了200k,程序将会崩溃,同时显示错误信息“Error:maxBuffer exceeded”。你可以通过在exec的可选项中设置一个更大的buffer体积来解决这个问题,但是你不应该这样做,因为exec本来就不是用来返回很多数据的方法。
spawn - child_process.spawn 使用指定的命令行参数创建新进程。spawn 会返回一个带有stdout和stderr流的对象。你可以通过stdout流来读取子进程返回给Node.js的数据。stdout拥有’data’,’end’以及一般流所具有的事件。当你想要子进程返回大量数据给Node时,比如说图像处理,读取二进制数据等等,你最好使用spawn方法。
fork - child_process.fork 是 spawn()的特殊形式,用于在子进程中运行的模块,如 fork(‘./son.js’) 相当于 spawn(‘node’, [‘./son.js’]) 。与spawn方法不同的是,fork会在父进程与子进程之间,建立一个通信管道,用于进程之间的通信。
1、exec
require('child_process').exec('dir', {encoding: ‘utf-8’}, function(err, stdout, stderr) { if (err) { console.log(error.stack); console.log('Error code: ' + error.code); console.log('Signal received: ' + error.signal); } //console.log(err, stdout, stderr); console.log('data : ' + stdout); }).on('exit', function (code) { console.log('子进程已退出, 退出码 ' + code); });
1
2
3
4
5
6
7
8
9
10
11
2、spawn
var child_process = require('child_process'); var spawnObj = child_process.spawn('ping', ['127.0.0.1'], {encoding: 'utf-8'}); spawnObj.stdout.on('data', function(chunk) { console.log(chunk.toString()); }); spawnObj.stderr.on('data', (data) => { console.log(data); }); spawnObj.on('close', function(code) { console.log('close code : ' + code); } spawnObj.on('exit', (code) => { console.log('exit code : ' + code); fs.close(fd, function(err) { if(err) { console.error(err); } }); });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
3、fork
分为 “父进程”(parent.js) 和”子进程”(child.js)。在命令行执行的时候要切换到上述文件的目录中,否则会找不到子进程。
parent.js
console.log('parent pid: ' + process.pid); var fork = require('child_process').fork; //fork方法返回的是子进程 var child = fork('./child.js'); console.log('fork return pid: ' + child.pid); child.on('message', function(msg){ console.log('parent get message: ' + JSON.stringify(msg)); }); child.send({key: 'parent value'});
1
2
3
4
5
6
7
8
9
child.js
console.log('child pid: ' + process.pid); process.on('message', function(msg){ console.log('child get message: ' + JSON.stringify(msg)); }); process.send({key: 'child value'});
1
2
3
4
5
send 方法的原型为:
send(message, [sendHandle])
1
这里,sendHandle(handle)可以被用于发送:
net.Native,原生的 C++ TCP socket 或者管道
net.Server,TCP 服务器
net.Socket,TCP socket
dgram.Native,原生的 C++ UDP socket
dgram.Socket,UDP socket
send 发送 sendHandle 时实际上不是(也不能)直接发送 javaScript 对象,而是发送文件描述符(最终以 JSON 字符串发送),其他进程能够通过这个文件描述符还原出对应对象。
注意: send方法是同步的因此不建议发送大量数据, 发送大量的数据可以使用 pipe 来代替
JavaScript Node.js 任务调度
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。