node.js中process進(jìn)程的概念和child_process子進(jìn)程模塊的使用方法示例

本文實(shí)例講述了node.js中process進(jìn)程的概念和child_process子進(jìn)程模塊的使用方法。分享給大家供大家參考,具體如下:

10年積累的做網(wǎng)站、網(wǎng)站建設(shè)經(jīng)驗(yàn),可以快速應(yīng)對(duì)客戶對(duì)網(wǎng)站的新想法和需求。提供各種問(wèn)題對(duì)應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識(shí)你,你也不認(rèn)識(shí)我。但先做網(wǎng)站設(shè)計(jì)后付款的網(wǎng)站建設(shè)流程,更有呂梁免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

進(jìn)程,你可以把它理解成一個(gè)正在運(yùn)行的程序。node.js中每個(gè)應(yīng)用程序都是進(jìn)程類的實(shí)例對(duì)象。

node.js中有一個(gè) process 全局對(duì)象,通過(guò)它我們可以獲取,運(yùn)行該程序的用戶,環(huán)境變量等信息。

一、process 對(duì)象

console.log('可執(zhí)行文件絕對(duì)路徑', process.execPath);
console.log('版本號(hào)', process.version);
console.log('依賴庫(kù)的版本號(hào)', process.versions);
console.log('運(yùn)行平臺(tái)', process.platform);
console.log('標(biāo)準(zhǔn)輸入流', process.stdin);
console.log('標(biāo)準(zhǔn)輸出流', process.stdout);
console.log('標(biāo)準(zhǔn)錯(cuò)誤流', process.stderr);
console.log('命令行參數(shù)數(shù)組', process.argv);
console.log('系統(tǒng)環(huán)境變量', process.env);
console.log('進(jìn)程ID', process.pid);
console.log('標(biāo)題', process.title);
console.log('處理器架構(gòu)', process.arch);

通過(guò) memoryUsage() 查看內(nèi)存使用量:

console.log(process.memoryUsage());

  • rss 表示進(jìn)程占用的內(nèi)存,包括堆,棧,代碼段。
  • heapTotal 表示堆占用的內(nèi)存。
  • heapUsed 表示堆使用的部分。
  • external 表示外部使用的部分,C++對(duì)象占用的。

對(duì)象,字符串,閉包存放于堆內(nèi)存,變量存放于棧內(nèi)存,js源代碼存放于代碼段。

console.log(process.memoryUsage());
let buf = Buffer.alloc(1024 * 1024 * 1024);
console.log(process.memoryUsage());

當(dāng)我們通過(guò)Buffer創(chuàng)建一個(gè)足夠大的變量時(shí),這時(shí)只能借助于外部?jī)?nèi)存,使用C++去完成。node.js能夠使用的內(nèi)存上限是1.7G。

使用 chdir() 修改程序當(dāng)前的工作目錄,通過(guò) cwd() 獲取當(dāng)前工作目錄。

console.log(process.cwd());
//修改程序當(dāng)前的工作目錄
process.chdir('../');
console.log(process.cwd());

通過(guò) exit() 來(lái)結(jié)束進(jìn)程

process.exit(0);

調(diào)用 exit() 結(jié)束進(jìn)程時(shí),會(huì)觸發(fā) 'exit' 事件。

process.on('exit', function () {
  console.log('程序退出了');
});
process.exit(0);

通過(guò) kill() 給指定進(jìn)程發(fā)送信號(hào)

SIGINT 程序終止信號(hào),當(dāng)用戶按下ctrl+c時(shí)發(fā)出,將通知進(jìn)程終止。

SIGTERM 程序結(jié)束信號(hào),通知程序正常退出,kill()方法默認(rèn)就是這個(gè)信號(hào)。

process.kill(process.pid, 'SIGINT');

通過(guò) uptime() 返回程序運(yùn)行的時(shí)間

console.log(process.uptime());

通過(guò) hrtime() 計(jì)算代碼段運(yùn)行時(shí)間,hrtime() 返回一個(gè)數(shù)組,第一個(gè)表示秒,第二個(gè)表示納秒

let start = process.hrtime();
let sum = 0;
for (i = 0; i < 1000000000; i++) {
  sum += i;
}
let end = process.hrtime(start);
console.log('耗時(shí) : ', end[0], '秒');

當(dāng)程序拋出一個(gè)沒(méi)有被捕獲的異常時(shí),觸發(fā) 'uncaughtException' 事件。

process.on('uncaughtException', function (err) {
  console.log('捕獲了一個(gè)未被處理的異常');
  console.log(err);
});
//調(diào)用一個(gè)未定義的函數(shù)
test();

進(jìn)程接收到一個(gè)信號(hào)時(shí),會(huì)觸發(fā)信號(hào)事件,我們可以監(jiān)聽(tīng)到該事件。

//讓標(biāo)準(zhǔn)輸入流處于流動(dòng)模式,讓程序無(wú)法退出
process.stdin.resume();
process.on('SIGINT', function () {
  console.log('程序退出');
  process.exit(0);
});
process.on('SIGTERM', function () {
  console.log('程序結(jié)束');
});

二、子進(jìn)程模塊child_process的使用

我們都知道node.js是單線程的,如果某一個(gè)操作需要消耗大量資源和時(shí)間,會(huì)導(dǎo)致程序整體性能下降。

我們可以創(chuàng)建子進(jìn)程,讓子進(jìn)程去跑那些費(fèi)時(shí)費(fèi)力的操作,而主線程該干嘛干嘛。

子進(jìn)程間可以共享內(nèi)存,通過(guò)互相通信來(lái)完成數(shù)據(jù)的交換。

1、通過(guò) spawn() 創(chuàng)建子進(jìn)程

const {spawn} = require('child_process');
//參數(shù)一表示,要執(zhí)行的命令
//參數(shù)二表示,運(yùn)行該命令的參數(shù)
//參數(shù)三表示,創(chuàng)建子進(jìn)程的配置
let cp1 = spawn('node', ['1.js'], {
  //cwd表示當(dāng)前子進(jìn)程的工作目錄
  cwd: process.cwd(),
  //子進(jìn)程的環(huán)境變量
  env: process.env,
  //子進(jìn)程的標(biāo)準(zhǔn)輸入,標(biāo)準(zhǔn)輸出,錯(cuò)誤,的配置
  //pipe表示,父進(jìn)程與子進(jìn)程間建立管道,父進(jìn)程可以訪問(wèn)子進(jìn)程對(duì)應(yīng)的輸入,輸出,和錯(cuò)誤
  //ipc表示,父進(jìn)程與子進(jìn)程間建立一個(gè)專門(mén)用來(lái)傳遞消息的IPC通道,子進(jìn)程調(diào)用send()方法向子進(jìn)程發(fā)送消息,并觸發(fā)'message'事件
  //ignore表示,忽略子進(jìn)程的標(biāo)準(zhǔn)輸入,標(biāo)準(zhǔn)輸出,錯(cuò)誤。
  //inherit表示,子進(jìn)程共享父進(jìn)程的標(biāo)準(zhǔn)輸入,標(biāo)準(zhǔn)輸出,錯(cuò)誤。
  //stream表示,父進(jìn)程與子進(jìn)程共享一個(gè)流,比如文件流或socket。
  //正整數(shù)表示,父進(jìn)程打開(kāi)的文件描述符,與子進(jìn)程共享,比如文件的fd。類似stream流對(duì)象共享。
  //null或undefined表示,父進(jìn)程與子進(jìn)程間創(chuàng)建管道
  stdio: ['pipe', process.stdout, 'pipe'],
  //子進(jìn)程是否獨(dú)立于父進(jìn)程運(yùn)行
  detached: false
});

1.js的代碼:

console.log('hello');

運(yùn)行代碼后,我們可以看到子進(jìn)程的 'hello',出現(xiàn)在了父進(jìn)程的標(biāo)準(zhǔn)輸出上。因?yàn)?stdio 的配置,我們讓子進(jìn)程與父進(jìn)程共享標(biāo)準(zhǔn)輸出。

spawn() 會(huì)返回一個(gè)子進(jìn)程對(duì)象,我們可以監(jiān)聽(tīng)該對(duì)象的一些事件。

const {spawn} = require('child_process');
let cp1 = spawn('node', ['1.js'], {
  cwd: process.cwd(),
  env: process.env,
  stdio: ['pipe', process.stdout, 'pipe'],
  detached: false
});
//子進(jìn)程所有輸入/輸出終止時(shí),會(huì)觸發(fā)子進(jìn)程的 'close' 事件
cp1.on('close', function (code, signal) {
  //當(dāng)父進(jìn)程關(guān)閉子進(jìn)程時(shí),signal表示父進(jìn)程發(fā)送給子進(jìn)程的信號(hào)名稱
  console.log('子進(jìn)程關(guān)閉了', code, signal);
});
//子進(jìn)程退出時(shí),會(huì)觸發(fā) 'exit' 事件
//注意,子進(jìn)程退出,子進(jìn)程的輸入/輸出有可能并未關(guān)閉。因?yàn)檩斎?輸出有可能多個(gè)進(jìn)程共享。
cp1.on('exit', function (code, signal) {
  console.log('子進(jìn)程退出', code, signal);
});
//子進(jìn)程出錯(cuò)時(shí),觸發(fā)
cp1.on('error', function (err) {
  console.log(err);
});

注意,stdio 設(shè)置成 pipe ,是把子進(jìn)程的stdin,stdout,stderr導(dǎo)向了 spawn() 返回的子進(jìn)程對(duì)象的stdin,stdout,stderr。

然后父進(jìn)程就可以通過(guò)子進(jìn)程對(duì)象訪問(wèn)stdin,stdout,stderr。

const {spawn} = require('child_process');
let cp1 = spawn('node', ['1.js'], {
  cwd: process.cwd(),
  env: process.env,
  stdio: ['pipe', 'pipe', 'pipe'],
  detached: false
});
//監(jiān)聽(tīng)子進(jìn)程標(biāo)準(zhǔn)輸入,輸出,錯(cuò)誤的數(shù)據(jù)。
cp1.stdin.on('data', function (data) {
  console.log(data.toString());
});
cp1.stdout.on('data', function (data) {
  console.log(data.toString());
});
cp1.stderr.on('data', function (data) {
  console.log(data.toString());
});

1.js的代碼:

//往子進(jìn)程標(biāo)準(zhǔn)輸出中寫(xiě)入數(shù)據(jù)
console.log('我是標(biāo)準(zhǔn)輸出');
//往子進(jìn)程錯(cuò)誤中寫(xiě)入數(shù)據(jù)
console.error('我是一個(gè)錯(cuò)誤');
//往子進(jìn)程標(biāo)準(zhǔn)輸入中寫(xiě)入數(shù)據(jù)
process.stdin.write('我是標(biāo)準(zhǔn)輸入');

當(dāng)我們?cè)O(shè)置 stdio 為 ipc 時(shí),會(huì)創(chuàng)建一個(gè)父進(jìn)程與子進(jìn)程傳遞消息的IPC通道。

const {spawn} = require('child_process');
let cp1 = spawn('node', ['1.js'], {
  cwd: process.cwd(),
  env: process.env,
  //注意這里,子進(jìn)程只能有一個(gè)IPC通道
  stdio: ['pipe', 'ipc', 'pipe'],
  detached: false
});
//注意這里要用子進(jìn)程對(duì)象進(jìn)行監(jiān)聽(tīng)
//監(jiān)聽(tīng)有沒(méi)有消息
cp1.on('message', function (data) {
  console.log('子進(jìn)程發(fā)送的 : ', data.toString());
});
cp1.send('你好,子進(jìn)程');

1.js的代碼:

process.on('message', function (data) {
  console.log('父進(jìn)程發(fā)送的 : ', data.toString());
});
//向父進(jìn)程發(fā)送消息
process.send('你好,父進(jìn)程');

默認(rèn)情況下,只有子進(jìn)程全部退出了,父進(jìn)程才能退出。我們希望父進(jìn)程退出了,子進(jìn)程仍然獨(dú)立運(yùn)行??梢酝ㄟ^(guò)設(shè)置 detached 為 true。

默認(rèn)情況下,父進(jìn)程會(huì)等待所有子程退出后,才退出。通過(guò)使用 unref() 讓父進(jìn)程無(wú)需等待子進(jìn)程就可直接退出。

const {spawn} = require('child_process');
const fs = require('fs');
let fd = fs.openSync('./1.txt', 'w', 0o666);
let cp1 = spawn('node', ['1.js'], {
  cwd: process.cwd(),
  //注意這里,把不需要的設(shè)置為ignore,不然主進(jìn)程仍然會(huì)阻塞等待子進(jìn)程
  stdio: ['ignore', fd, 'ignore'],
  detached: true
});
cp1.on('error', function (err) {
  console.log(err);
});
//解綁子進(jìn)程,讓父進(jìn)程不用等待子進(jìn)程
cp1.unref();

1.js的代碼:

let i = 0;
let timer = setInterval(function () {
  if (i > 20) {
    clearInterval(timer);
  }
  process.stdout.write('寫(xiě)入數(shù)據(jù)' + i + '\r\n');
  i++;
}, 1000);

2、通過(guò) fork() 創(chuàng)建子進(jìn)程

fork() 是 spawn() 的特殊情況,用于創(chuàng)建新的進(jìn)程,默認(rèn)建立一個(gè)IPC通信通道,允許父進(jìn)程與子進(jìn)程進(jìn)行消息傳遞。

fork() 返回一個(gè)子進(jìn)程對(duì)象,子進(jìn)程輸入/輸出操作執(zhí)行完畢后,父進(jìn)程不退出,子進(jìn)程不會(huì)自動(dòng)退出,需調(diào)用 exit() 顯式退出。

const {fork} = require('child_process');
//參數(shù)一表示,運(yùn)行的模塊
//參數(shù)二表示,參數(shù)列表
//參數(shù)三表示,創(chuàng)建子進(jìn)程的配置
let cp1 = fork('2.js', ['1', '2', '3'], {
  //子進(jìn)程的工作目錄
  cwd: process.cwd(),
  //子進(jìn)程的環(huán)境變量
  env: process.env,
  //運(yùn)行模塊的可執(zhí)行文件
  execPath: process.execPath,
  //傳遞給可執(zhí)行文件的參數(shù)列表
  execArgv: process.execArgv,
  //為false表示父進(jìn)程與子進(jìn)程共享標(biāo)準(zhǔn)(輸入/輸出),為true時(shí)不共享。
  silent: false
});
cp1.on('error', function (err) {
  console.log(err);
});

2.js的代碼:

for (let i = 0; i < process.argv.length; i++) {
  process.stdout.write(process.argv[i] + '\r\n');
}

父進(jìn)程與子進(jìn)程間,通過(guò) send() 和 'message'事件來(lái)傳遞消息。

const {fork} = require('child_process');
let cp1 = fork('2.js', [], {
  cwd: process.cwd(),
  env: process.env,
  silent: false
});
//接收消息
cp1.on('message', function (data) {
  console.log('父進(jìn)程收到 : ', JSON.stringify(data));
  process.exit(0);
});
//發(fā)送消息
cp1.send({name: '你好子進(jìn)程'});

2.js的代碼:

process.on('message', function (data) {
  console.log('子進(jìn)程收到 : ', JSON.stringify(data));
  process.send({name: '你好父進(jìn)程'});
});

3、通過(guò)exec() 創(chuàng)建子進(jìn)程

exec() 可以開(kāi)啟一個(gè)子進(jìn)程運(yùn)行命令,并緩存子進(jìn)程的輸出結(jié)果。

const {exec} = require('child_process');
//參數(shù)一表示,要運(yùn)行的命令
//參數(shù)二表示,配置選項(xiàng)
//參數(shù)三表示,進(jìn)程終止時(shí)的回調(diào)
exec('dir', {
  //子進(jìn)程的工作目錄
  cwd: process.cwd(),
  //子進(jìn)程的環(huán)境變量
  env: process.env,
  //輸出的編碼
  encoding: 'utf8',
  //超時(shí)時(shí)間
  timeout: 60 * 1000,
  //緩存stdout,stderr最大的字節(jié)數(shù)
  maxBuffer: 1024 * 1024,
  //關(guān)閉子進(jìn)程的信號(hào)
  killSignal: 'SIGTERM'
}, function (err, stdout, stderr) {
  console.log(stdout.toString());
});

4、通過(guò) execFile() 創(chuàng)建子進(jìn)程

使用 execFile() 開(kāi)啟一個(gè)運(yùn)行可執(zhí)行文件的子進(jìn)程。

const {execFile} = require('child_process');
//參數(shù)一表示,可執(zhí)行文件的名稱或路徑
//參數(shù)二表示,參數(shù)列表
//參數(shù)三表示,配置選項(xiàng)
//參數(shù)四表示,進(jìn)程終止時(shí)的回調(diào)
let cp1 = execFile('node', ['3.js', '1', '2', '3'], {
  //子進(jìn)程的工作目錄
  cwd: process.cwd(),
  //子進(jìn)程的環(huán)境變量
  env: process.env,
  //輸出的編碼
  encoding: 'utf8',
  //超時(shí)時(shí)間
  timeout: 60 * 1000,
  //緩存stdout,stderr最大的字節(jié)數(shù)
  maxBuffer: 1024 * 1024,
  //關(guān)閉子進(jìn)程的信號(hào)
  killSignal: 'SIGTERM'
}, function (err, stdout, stderr) {
  if (err) {
    console.log(err);
    process.exit();
  }
  console.log('子進(jìn)程的輸出 : ', stdout.toString());
});
cp1.on('error', function (err) {
  console.log(err);
});

3.js的代碼:

process.argv.forEach(function (value) {
  process.stdout.write(value + '\r\n');
});

fork(),exec(),execFile() 都是基于 spawn() 的封裝。

希望本文所述對(duì)大家node.js程序設(shè)計(jì)有所幫助。

當(dāng)前名稱:node.js中process進(jìn)程的概念和child_process子進(jìn)程模塊的使用方法示例
文章轉(zhuǎn)載:http://muchs.cn/article42/pipjec.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站營(yíng)銷、建站公司、定制網(wǎng)站品牌網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)公司云服務(wù)器

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都seo排名網(wǎng)站優(yōu)化