node 怎样解决多进程问题

什么是进程

定义: 进程是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体

既然进程是系统进行资源分配和调度的基本单位, 那么在进程出现切换的时候必定会出现重新分配资源,进行上下文切换。 这样会导致cpu进行大量处理。

node 进程

node最让人莫名的就是单进程驱动了。这个单进程是指v8运行js代码的部分是单进程。单进程的好处是不必出现cpu经常切换。 但是因为这个特性导致多进程cpu无法并发处理。 而且, 只有一个核在跑, 其他的核在睡着, 并不能很好的利用好计算机。

怎样创建进程

在linux下,可以使用进程创建另外的进程, 既然可以自己创建, 那么肯定会有第一个爸爸级别的进程, 该结构可以使用pstree来查看, linux在开机的时候首先进入/etc/init里面,所以最上面的systemd应该是init的进程。

linux可以通过fork, exec*, 来创建进程。该函数在unistd.h库中。

下面是c创建fork()

#include <stdio.h> 
#include <unistd.h> 
#include <stdlib.h> 
  
int main() 
{ 
    pid_t pid = fork(); 
  
    if( !pid ){ 
        printf( "子进程id:%d\n" ,getpid() ); 
    }else if( pid>0 ){ 
        printf( "父进程id:%d,子进程ID:%d\n",getpid(),pid ); 
    }else{ 
        printf( "pass" ); 
        exit(1); 
    } 
    return 1; 
}
复制代码

fork(): 执行一次但有两个返回值. 在父进程中,返回值是子进程的进程号;在子进程中,返回值为0。因此可通过返回值来判断当前进程是父进程还是子进程。

使用fork函数得到的子进程是父进程的一个复制品,它从父进程处复制了整个进程的地址空间,包括进程上下文,进程堆栈,内存信息,打开的文件描述符,信 号控制设定,进程优 先级,。而子进程所独有的只是它的进程号器等。可以看出,使用 fork函数的代价是很大的,它复制了 父进程中的代码段,数据段和堆栈段里的大部分内容,使得fork函数的执行速度并不快。

c创建exec*()

首先, fork是一个复制品, 但是我们需要自己的进程, 这样可以使用exec* 函数实现。

#include <stdio.h> 
#include <unistd.h> 
int main() 
{ 
    execl("/bin/ls","ls","-l",NULL); 
    printf("如果execl执行失败, pass \n"); 
    return 1; 
}
复制代码

用exec函数可以把当前进程替换为一个新进程,且新进程与原进程有相同的PID。

int execl(const char *path, const char *arg, ...);

int execlp(const char *file, const char *arg, ...);

int execle(const char *path, const char *arg, ..., char * const envp[]);

int execv(const char *path, char *const argv[]);

int execvp(const char *file, char *const argv[]);
复制代码

path参数表示你要启动程序的名称包括路径名

arg参数表示启动程序所带的参数,一般第一个参数为要执行命令名,不是带路径且arg必须以NULL结束

返回值:成功返回0,失败返回-1

exce相当于覆盖了当前的进程, 那么怎样建立一个独立的进程且不影响原来的进程呢

fork() + exec*()

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
  
int main() 
{ 
    pid_t pid = fork(); 
    switch( pid ) 
    { 
    case 0: 
        execl("/bin/ls","ls","-l",NULL); 
    case -1: 
        exit(1); 
    default: 
        wait(NULL); 
        exit(0); 
    } 
}
复制代码

wait(null) 让父进程等待子进程结束.

node 多进程架构

上面为什么要介绍c创建进程的方法, 因为node的本质是调用的cpp, 他创建进程的方法跟c一样像。 虽然node是单进程, 但是他提供child_process这个模块。

fork() 创建

创建master.js

var fork = require('child_process').fork;
for(var i = 0; i < 2; i++){
    fork('./worker.js')
}
复制代码

创建worker.js

setInterval(function(){ 
    console.log(Math.random())
},200)
复制代码

然后运行master.js 这时候两个进程都会工作。 可以使用

ps aux | grep worker.js
复制代码

命令查看有几个进程在运行。 因为我们用node执行的mastes.js文件, 而创建时用的fork创建的, 所以worker.js也用node执行。

spawn() 启动子进程来执行命令

exec() 启用子进程来执行命令, 但是他有回调

execFile(): 启用子进程来执行可执行文件

注意后面三个的区别, 前两个是命令, 最后一个是可执行文件 也就是说在调用的时候要这么写

fork.exec('node worker.js', function(){//node worker.js 是在command line 中执行js文件
    
});

fork.execFile('worker.js',function(){//worker.js 需要时可执行文件
    
})
复制代码

node文件变成可执行文件可以再第一行添加

#!/usr/local/bin/node
复制代码

转载于:https://juejin.im/post/5a3dec0d51882538d31022b6

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值