node.js中process进程的概念和child_process子进程模块的使用方法示例
本文实例讲述了node.js中process进程的概念和child_process子进程模块的使用方法。分享给大家供大家参考,具体如下:
进程,你可以把它理解成一个正在运行的程序。node.js中每个应用程序都是进程类的实例对象。
node.js中有一个process全局对象,通过它我们可以获取,运行该程序的用户,环境变量等信息。
一、process对象
console.log('可执行文件绝对路径',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('命令行参数数组',process.argv); console.log('系统环境变量',process.env); console.log('进程ID',process.pid); console.log('标题',process.title); console.log('处理器架构',process.arch);
通过memoryUsage()查看内存使用量:
console.log(process.memoryUsage());
- rss表示进程占用的内存,包括堆,栈,代码段。
- heapTotal表示堆占用的内存。
- heapUsed表示堆使用的部分。
- external表示外部使用的部分,C++对象占用的。
对象,字符串,闭包存放于堆内存,变量存放于栈内存,js源代码存放于代码段。
console.log(process.memoryUsage()); letbuf=Buffer.alloc(1024*1024*1024); console.log(process.memoryUsage());
当我们通过Buffer创建一个足够大的变量时,这时只能借助于外部内存,使用C++去完成。node.js能够使用的内存上限是1.7G。
使用chdir()修改程序当前的工作目录,通过cwd()获取当前工作目录。
console.log(process.cwd()); //修改程序当前的工作目录 process.chdir('../'); console.log(process.cwd());
通过exit()来结束进程
process.exit(0);
调用exit()结束进程时,会触发'exit'事件。
process.on('exit',function(){ console.log('程序退出了'); }); process.exit(0);
通过kill()给指定进程发送信号
SIGINT程序终止信号,当用户按下ctrl+c时发出,将通知进程终止。
SIGTERM程序结束信号,通知程序正常退出,kill()方法默认就是这个信号。
process.kill(process.pid,'SIGINT');
通过uptime()返回程序运行的时间
console.log(process.uptime());
通过hrtime()计算代码段运行时间,hrtime()返回一个数组,第一个表示秒,第二个表示纳秒
letstart=process.hrtime(); letsum=0; for(i=0;i<1000000000;i++){ sum+=i; } letend=process.hrtime(start); console.log('耗时:',end[0],'秒');
当程序抛出一个没有被捕获的异常时,触发'uncaughtException'事件。
process.on('uncaughtException',function(err){ console.log('捕获了一个未被处理的异常'); console.log(err); }); //调用一个未定义的函数 test();
进程接收到一个信号时,会触发信号事件,我们可以监听到该事件。
//让标准输入流处于流动模式,让程序无法退出 process.stdin.resume(); process.on('SIGINT',function(){ console.log('程序退出'); process.exit(0); }); process.on('SIGTERM',function(){ console.log('程序结束'); });
二、子进程模块child_process的使用
我们都知道node.js是单线程的,如果某一个操作需要消耗大量资源和时间,会导致程序整体性能下降。
我们可以创建子进程,让子进程去跑那些费时费力的操作,而主线程该干嘛干嘛。
子进程间可以共享内存,通过互相通信来完成数据的交换。
1、通过spawn()创建子进程
const{spawn}=require('child_process'); //参数一表示,要执行的命令 //参数二表示,运行该命令的参数 //参数三表示,创建子进程的配置 letcp1=spawn('node',['1.js'],{ //cwd表示当前子进程的工作目录 cwd:process.cwd(), //子进程的环境变量 env:process.env, //子进程的标准输入,标准输出,错误,的配置 //pipe表示,父进程与子进程间建立管道,父进程可以访问子进程对应的输入,输出,和错误 //ipc表示,父进程与子进程间建立一个专门用来传递消息的IPC通道,子进程调用send()方法向子进程发送消息,并触发'message'事件 //ignore表示,忽略子进程的标准输入,标准输出,错误。 //inherit表示,子进程共享父进程的标准输入,标准输出,错误。 //stream表示,父进程与子进程共享一个流,比如文件流或socket。 //正整数表示,父进程打开的文件描述符,与子进程共享,比如文件的fd。类似stream流对象共享。 //null或undefined表示,父进程与子进程间创建管道 stdio:['pipe',process.stdout,'pipe'], //子进程是否独立于父进程运行 detached:false });
1.js的代码:
console.log('hello');
运行代码后,我们可以看到子进程的'hello',出现在了父进程的标准输出上。因为stdio的配置,我们让子进程与父进程共享标准输出。
spawn()会返回一个子进程对象,我们可以监听该对象的一些事件。
const{spawn}=require('child_process'); letcp1=spawn('node',['1.js'],{ cwd:process.cwd(), env:process.env, stdio:['pipe',process.stdout,'pipe'], detached:false }); //子进程所有输入/输出终止时,会触发子进程的'close'事件 cp1.on('close',function(code,signal){ //当父进程关闭子进程时,signal表示父进程发送给子进程的信号名称 console.log('子进程关闭了',code,signal); }); //子进程退出时,会触发'exit'事件 //注意,子进程退出,子进程的输入/输出有可能并未关闭。因为输入/输出有可能多个进程共享。 cp1.on('exit',function(code,signal){ console.log('子进程退出',code,signal); }); //子进程出错时,触发 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'); letcp1=spawn('node',['1.js'],{ cwd:process.cwd(), env:process.env, stdio:['pipe','pipe','pipe'], detached:false }); //监听子进程标准输入,输出,错误的数据。 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的代码:
//往子进程标准输出中写入数据 console.log('我是标准输出'); //往子进程错误中写入数据 console.error('我是一个错误'); //往子进程标准输入中写入数据 process.stdin.write('我是标准输入');
当我们设置stdio为ipc时,会创建一个父进程与子进程传递消息的IPC通道。
const{spawn}=require('child_process'); letcp1=spawn('node',['1.js'],{ cwd:process.cwd(), env:process.env, //注意这里,子进程只能有一个IPC通道 stdio:['pipe','ipc','pipe'], detached:false }); //注意这里要用子进程对象进行监听 //监听有没有消息 cp1.on('message',function(data){ console.log('子进程发送的:',data.toString()); }); cp1.send('你好,子进程');
1.js的代码:
process.on('message',function(data){ console.log('父进程发送的:',data.toString()); }); //向父进程发送消息 process.send('你好,父进程');
默认情况下,只有子进程全部退出了,父进程才能退出。我们希望父进程退出了,子进程仍然独立运行。可以通过设置detached为true。
默认情况下,父进程会等待所有子程退出后,才退出。通过使用unref()让父进程无需等待子进程就可直接退出。
const{spawn}=require('child_process'); constfs=require('fs'); letfd=fs.openSync('./1.txt','w',0o666); letcp1=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的代码:
leti=0; lettimer=setInterval(function(){ if(i>20){ clearInterval(timer); } process.stdout.write('写入数据'+i+'\r\n'); i++; },1000);
2、通过fork()创建子进程
fork()是spawn()的特殊情况,用于创建新的进程,默认建立一个IPC通信通道,允许父进程与子进程进行消息传递。
fork()返回一个子进程对象,子进程输入/输出操作执行完毕后,父进程不退出,子进程不会自动退出,需调用exit()显式退出。
const{fork}=require('child_process'); //参数一表示,运行的模块 //参数二表示,参数列表 //参数三表示,创建子进程的配置 letcp1=fork('2.js',['1','2','3'],{ //子进程的工作目录 cwd:process.cwd(), //子进程的环境变量 env:process.env, //运行模块的可执行文件 execPath:process.execPath, //传递给可执行文件的参数列表 execArgv:process.execArgv, //为false表示父进程与子进程共享标准(输入/输出),为true时不共享。 silent:false }); cp1.on('error',function(err){ console.log(err); });
2.js的代码:
for(leti=0;i父进程与子进程间,通过send()和'message'事件来传递消息。
const{fork}=require('child_process'); letcp1=fork('2.js',[],{ cwd:process.cwd(), env:process.env, silent:false }); //接收消息 cp1.on('message',function(data){ console.log('父进程收到:',JSON.stringify(data)); process.exit(0); }); //发送消息 cp1.send({name:'你好子进程'});2.js的代码:
process.on('message',function(data){ console.log('子进程收到:',JSON.stringify(data)); process.send({name:'你好父进程'}); });3、通过exec()创建子进程
exec()可以开启一个子进程运行命令,并缓存子进程的输出结果。
const{exec}=require('child_process'); //参数一表示,要运行的命令 //参数二表示,配置选项 //参数三表示,进程终止时的回调 exec('dir',{ //子进程的工作目录 cwd:process.cwd(), //子进程的环境变量 env:process.env, //输出的编码 encoding:'utf8', //超时时间 timeout:60*1000, //缓存stdout,stderr最大的字节数 maxBuffer:1024*1024, //关闭子进程的信号 killSignal:'SIGTERM' },function(err,stdout,stderr){ console.log(stdout.toString()); });4、通过execFile()创建子进程
使用execFile()开启一个运行可执行文件的子进程。
const{execFile}=require('child_process'); //参数一表示,可执行文件的名称或路径 //参数二表示,参数列表 //参数三表示,配置选项 //参数四表示,进程终止时的回调 letcp1=execFile('node',['3.js','1','2','3'],{ //子进程的工作目录 cwd:process.cwd(), //子进程的环境变量 env:process.env, //输出的编码 encoding:'utf8', //超时时间 timeout:60*1000, //缓存stdout,stderr最大的字节数 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程序设计有所帮助。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。