Node.js 子進(jìn)程(exec、spawn、fork)
Node.js 是以單線程的模式運(yùn)行的,但它使用的是事件驅(qū)動來處理并發(fā),這樣有助于我們在多核 cpu 的系統(tǒng)上創(chuàng)建多個子進(jìn)程,從而提高性能。
每個子進(jìn)程總是帶有三個流對象:child.stdin, child.stdout 和child.stderr。他們可能會共享父進(jìn)程的 stdio 流,或者也可以是獨(dú)立的被導(dǎo)流的流對象。
Node 提供了 child_process 模塊來創(chuàng)建子進(jìn)程,方法有:
exec - child_process.exec 使用子進(jìn)程執(zhí)行命令,緩存子進(jìn)程的輸出,并將子進(jìn)程的輸出以回調(diào)函數(shù)參數(shù)的形式一次性返回。exec方法會從子進(jìn)程中返回一個完整的buffer。默認(rèn)情況下,這個buffer的大小應(yīng)該是200k。如果子進(jìn)程返回的數(shù)據(jù)大小超過了200k,程序?qū)罎ⅲ瑫r顯示錯誤信息“Error:maxBuffer exceeded”。你可以通過在exec的可選項中設(shè)置一個更大的buffer體積來解決這個問題,但是你不應(yīng)該這樣做,因為exec本來就不是用來返回很多數(shù)據(jù)的方法。
spawn - child_process.spawn 使用指定的命令行參數(shù)創(chuàng)建新進(jìn)程。spawn 會返回一個帶有stdout和stderr流的對象。你可以通過stdout流來讀取子進(jìn)程返回給Node.js的數(shù)據(jù)。stdout擁有’data’,’end’以及一般流所具有的事件。當(dāng)你想要子進(jìn)程返回大量數(shù)據(jù)給Node時,比如說圖像處理,讀取二進(jìn)制數(shù)據(jù)等等,你最好使用spawn方法。
fork - child_process.fork 是 spawn()的特殊形式,用于在子進(jìn)程中運(yùn)行的模塊,如 fork(‘./son.js’) 相當(dāng)于 spawn(‘node’, [‘./son.js’]) 。與spawn方法不同的是,fork會在父進(jìn)程與子進(jìn)程之間,建立一個通信管道,用于進(jìn)程之間的通信。
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('子進(jìn)程已退出, 退出碼 ' + 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
分為 “父進(jìn)程”(parent.js) 和”子進(jìn)程”(child.js)。在命令行執(zhí)行的時候要切換到上述文件的目錄中,否則會找不到子進(jìn)程。
parent.js
console.log('parent pid: ' + process.pid); var fork = require('child_process').fork; //fork方法返回的是子進(jìn)程 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)可以被用于發(fā)送:
net.Native,原生的 C++ TCP socket 或者管道
net.Server,TCP 服務(wù)器
net.Socket,TCP socket
dgram.Native,原生的 C++ UDP socket
dgram.Socket,UDP socket
send 發(fā)送 sendHandle 時實際上不是(也不能)直接發(fā)送 javaScript 對象,而是發(fā)送文件描述符(最終以 JSON 字符串發(fā)送),其他進(jìn)程能夠通過這個文件描述符還原出對應(yīng)對象。
注意: send方法是同步的因此不建議發(fā)送大量數(shù)據(jù), 發(fā)送大量的數(shù)據(jù)可以使用 pipe 來代替
javaScript Node.js 任務(wù)調(diào)度
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。