溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

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

發(fā)布時間:2020-09-09 03:35:11 來源:腳本之家 閱讀:166 作者:懷素真 欄目:web開發(fā)

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

進程,你可以把它理解成一個正在運行的程序。node.js中每個應用程序都是進程類的實例對象。

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

一、process 對象

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

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

console.log(process.memoryUsage());

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

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

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

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

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

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

通過 exit() 來結束進程

process.exit(0);

調(diào)用 exit() 結束進程時,會觸發(fā) 'exit' 事件。

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

通過 kill() 給指定進程發(fā)送信號

SIGINT 程序終止信號,當用戶按下ctrl+c時發(fā)出,將通知進程終止。

SIGTERM 程序結束信號,通知程序正常退出,kill()方法默認就是這個信號。

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

通過 uptime() 返回程序運行的時間

console.log(process.uptime());

通過 hrtime() 計算代碼段運行時間,hrtime() 返回一個數(shù)組,第一個表示秒,第二個表示納秒

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

當程序拋出一個沒有被捕獲的異常時,觸發(fā) 'uncaughtException' 事件。

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

進程接收到一個信號時,會觸發(fā)信號事件,我們可以監(jiān)聽到該事件。

//讓標準輸入流處于流動模式,讓程序無法退出
process.stdin.resume();
process.on('SIGINT', function () {
  console.log('程序退出');
  process.exit(0);
});
process.on('SIGTERM', function () {
  console.log('程序結束');
});

二、子進程模塊child_process的使用

我們都知道node.js是單線程的,如果某一個操作需要消耗大量資源和時間,會導致程序整體性能下降。

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

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

1、通過 spawn() 創(chuàng)建子進程

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

1.js的代碼:

console.log('hello');

運行代碼后,我們可以看到子進程的 'hello',出現(xiàn)在了父進程的標準輸出上。因為 stdio 的配置,我們讓子進程與父進程共享標準輸出。

spawn() 會返回一個子進程對象,我們可以監(jiān)聽該對象的一些事件。

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

注意,stdio 設置成 pipe ,是把子進程的stdin,stdout,stderr導向了 spawn() 返回的子進程對象的stdin,stdout,stderr。

然后父進程就可以通過子進程對象訪問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)聽子進程標準輸入,輸出,錯誤的數(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的代碼:

//往子進程標準輸出中寫入數(shù)據(jù)
console.log('我是標準輸出');
//往子進程錯誤中寫入數(shù)據(jù)
console.error('我是一個錯誤');
//往子進程標準輸入中寫入數(shù)據(jù)
process.stdin.write('我是標準輸入');

當我們設置 stdio 為 ipc 時,會創(chuàng)建一個父進程與子進程傳遞消息的IPC通道。

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

1.js的代碼:

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

默認情況下,只有子進程全部退出了,父進程才能退出。我們希望父進程退出了,子進程仍然獨立運行??梢酝ㄟ^設置 detached 為 true。

默認情況下,父進程會等待所有子程退出后,才退出。通過使用 unref() 讓父進程無需等待子進程就可直接退出。

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(),
  //注意這里,把不需要的設置為ignore,不然主進程仍然會阻塞等待子進程
  stdio: ['ignore', fd, 'ignore'],
  detached: true
});
cp1.on('error', function (err) {
  console.log(err);
});
//解綁子進程,讓父進程不用等待子進程
cp1.unref();

1.js的代碼:

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

2、通過 fork() 創(chuàng)建子進程

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

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

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

父進程與子進程間,通過 send() 和 'message'事件來傳遞消息。

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('父進程收到 : ', JSON.stringify(data));
  process.exit(0);
});
//發(fā)送消息
cp1.send({name: '你好子進程'});

2.js的代碼:

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

3、通過exec() 創(chuàng)建子進程

exec() 可以開啟一個子進程運行命令,并緩存子進程的輸出結果。

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

4、通過 execFile() 創(chuàng)建子進程

使用 execFile() 開啟一個運行可執(zhí)行文件的子進程。

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

希望本文所述對大家node.js程序設計有所幫助。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI