찾다
웹 프론트엔드JS 튜토리얼Node.js와 Electron이 프로세스 간 통신하는 방법에 대해 자세히 알아보세요.

이 글에서는 Node.js와 Electron 간의 프로세스 통신 원리를 살펴보고, Electron이 어떻게 통신을 처리하는지, nodejs의 child_process와 클러스터가 어떻게 통신을 처리하는지 소개하고, 프로세스 통신의 본질을 이해합니다.

Node.js와 Electron이 프로세스 간 통신하는 방법에 대해 자세히 알아보세요.

프런트엔드가 프로세스 통신을 이해해야 하는 이유:

프론트엔드 필드는 더 이상 브라우저에서 실행되는 페이지 작성뿐만 아니라 전자, nodejs 등도 담당하며 두 기술 모두 마스터링이 필요합니다. 프로세스 커뮤니케이션.

nodejs는 브라우저와 달리 프로세스 및 스레드 관련 API를 포함하여 운영 체제 기능을 캡슐화하는 많은 API를 확장합니다. 프로세스 API를 학습하려면 프로세스 간 통신 메커니즘을 배워야 합니다.

electron은 chromium과 nodejs를 기반으로 하는 데스크톱 개발 솔루션입니다. 그 아키텍처는 주요 프로세스이며 여러 렌더링 프로세스도 필요합니다. 전자의 프로세스 통신 메커니즘을 배워야 합니다. [추천 학습: "nodejs Tutorial"]

이 글에서는 프로세스 커뮤니케이션에 대해 더 자세히 살펴보겠습니다.

이 기사에서는 다음 지식 포인트를 설명합니다.

  • 프로세스란 무엇입니까?
  • 로컬 프로세스 통신의 네 가지 방법
  • ipc, lpc, rpc는 무엇입니까
  • electron은 프로세스 통신을 어떻게 수행합니까?
  • child_process 및 Cluster of nodejs 프로세스 통신
  • 프로세스 통신의 본질

Process

우리가 작성한 코드는 하드웨어 리소스를 더 잘 활용하기 위해 운영 체제에서 실행되어야 하며, 운영 체제는 여러 프로그램의 동시성을 지원하고 하드웨어 자원의 사용, 할당 단위는 프로세스이고, 이 프로세스는 프로그램의 실행 프로세스입니다. 예를 들어, 프로그램이 어떤 단계를 실행했는지, 어떤 하드웨어 리소스가 적용되었는지, 어떤 포트가 사용되었는지 등을 기록합니다.

프로세스에는 실행될 코드, 코드에 의해 작동되는 데이터, 프로세스 제어 블록 PCB(Processing Control Block)가 포함됩니다. 왜냐하면 프로그램은 데이터 세트에 대한 코드의 실행 프로세스이고 프로세스의 상태이기 때문입니다. 실행 프로세스와 요청된 리소스는 데이터 구조(PCB)에 기록되어야 합니다. 따라서 프로세스는 코드, 데이터, PCB로 구성됩니다.

Node.js와 Electron이 프로세스 간 통신하는 방법에 대해 자세히 알아보세요.

pcb는 pid, 실행된 코드 주소, 프로세스 상태(차단, 실행 중, 준비 등)는 물론 통신에 사용되는 세마포어, 파이프, 메시지 큐와 같은 데이터 구조를 기록합니다.

Node.js와 Electron이 프로세스 간 통신하는 방법에 대해 자세히 알아보세요.

코드 생성부터 지속적인 실행, 하드웨어 리소스(메모리, 하드디스크 파일, 네트워크 등) 적용까지 프로세스가 중간에 차단될 수 있으며, 실행 후 결국 프로세스가 소멸됩니다. 이것이 프로세스의 생명주기입니다.

프로세스는 요청된 리소스에만 독점적입니다. 각 프로세스는 자신의 리소스에만 액세스할 수 있습니다. 그러면 프로세스는 어떻게 서로 통신합니까?

프로세스 통신

프로세스마다 사용 가능한 메모리가 다르기 때문에 중간 매체를 통해 통신해야 합니다.

Semaphore

숫자로 표시되고 PCB의 속성에 배치되는 간단한 표시인 경우 이를 Semaphore라고 합니다. 신호량을 통해 구현됩니다. 信号量,比如锁的实现就可以通过信号量。

这种信号量的思想我们写前端代码也经常用,比如实现节流的时候,也要加一个标记变量。

管道

但是信号量不能传递具体的数据啊,传递具体数据还得用别的方式。比如我们可以通过读写文件的方式来通信,这就是管道,如果是在内存中的文件,叫做匿名管道,没有文件名,如果是真实的硬盘的文件,是有文件名的,叫做命名管道。

文件需要先打开,然后再读和写,之后再关闭,这也是管道的特点。管道是基于文件的思想封装的,之所以叫管道,是因为只能一个进程读、一个进程写,是单向的(半双工)。而且还需要目标进程同步的消费数据,不然就会阻塞住。

这种管道的方式实现起来很简单,就是一个文件读写,但是只能用在两个进程之间通信,只能同步的通信。其实管道的同步通信也挺常见的,就是 stream 的 pipe 方法。

消息队列

管道实现简单,但是同步的通信比较受限制,那如果想做成异步通信呢?加个队列做缓冲(buffer)不就行了,这就是消息队列

이 세마포어 아이디어는 프런트 엔드 코드를 작성할 때도 자주 사용됩니다. 예를 들어 조절을 구현할 때 마커 변수도 추가해야 합니다.

Pipeline

하지만 세마포어는 특정 데이터를 전송할 수 없으며 특정 데이터를 전송하려면 다른 방법을 사용해야 합니다. 예를 들어 파일을 읽고 쓰는 방식으로 통신할 수 있습니다. 이것이 파이프라인입니다. 메모리에 있는 파일이면 익명 파이프라고 하며 파일 이름이 없습니다. 실제 하드디스크에는 Named Pipe라는 파일이 있습니다. 🎜🎜파일을 먼저 열고 읽고 쓴 다음 다시 닫아야 하는 것도 파이프라인의 특징입니다. 파이프는 파일이라는 개념을 기반으로 캡슐화됩니다. 단방향(반이중)이므로 하나의 프로세스에서만 읽고 쓸 수 있기 때문에 파이프라고 합니다. 또한 대상 프로세스도 데이터를 동기식으로 소비해야 합니다. 그렇지 않으면 차단됩니다. 🎜🎜이 파이프라인 방법은 구현이 매우 간단하지만 파일 읽기 및 쓰기이지만 두 프로세스 간의 통신에만 사용할 수 있으며 동기식으로만 통신할 수 있습니다. 실제로 파이프의 동기식 통신도 매우 일반적이며 이는 스트림의 파이프 방식입니다. 🎜🎜🎜🎜Message Queue🎜🎜🎜🎜파이프라인 구현은 간단하지만 동기 통신은 상대적으로 제한적입니다. 큐를 버퍼로 추가하면 됩니다. 이것이 메시지 큐입니다. 🎜🎜메시지 큐도 두 프로세스 간의 통신이지만 파일 기반 아이디어를 기반으로 하지 않지만 단방향이지만 어느 정도 비동기 특성을 가지며 많은 메시지를 넣어 모두 소비할 수 있습니다. 한 번. 🎜🎜🎜🎜공유 메모리🎜🎜🎜

파이프라인과 메시지 큐가 두 프로세스 사이에 있으면 어떻게 될까요?

우리는 共享内存라는 여러 프로세스에서 작동할 수 있는 메모리를 적용하여 이러한 방식으로 통신할 수 있습니다. 각 프로세스는 이 메모리에 데이터를 읽고 쓸 수 있으며 이는 상대적으로 효율적입니다.

공유 메모리는 효율적이고 여러 프로세스 간의 통신에 사용할 수 있지만 여러 프로세스가 읽고 쓸 수 있기 때문에 모두 좋은 것은 아니므로 혼동되기 쉽습니다. 제어할 프로세스의 세마포어(표시 변수)입니다.

공유 메모리는 중간 매체를 거치지 않고 여러 프로세스 간 통신에 적합하므로 더 효율적이지만 사용하기가 더 복잡합니다.

위에서 언급한 방법은 로컬 프로세스 통신을 위한 거의 모든 방법입니다. 로컬을 추가하는 이유는 무엇입니까?

ipc, rpc, lpc

프로세스 통신은 ipc(Inter-Process Communication)입니다. 두 프로세스는 한 컴퓨터에 속할 수도 있고 네트워크에 있는 다른 컴퓨터의 프로세스일 수도 있으므로 두 가지 처리 방법이 있습니다. 통신 :

로컬 프로시저 호출 LPC(로컬 프로시저 호출), 원격 프로시저 호출 RPC(원격 프로시저 호출).

로컬 프로시저 호출은 위에서 언급한 세마포어, 파이프, 메시지 대기열 및 공유 메모리의 통신 방법입니다. 그러나 네트워크에 있는 경우 실제로는 다음과 같은 네트워크 프로토콜을 통해 통신해야 합니다. http, 웹소켓.

그러므로 누군가 ipc를 언급한다면 로컬과 원격이라는 두 가지 방식으로 논의할 수 있는 프로세스 통신에 대해 이야기하는 것입니다.

원격은 네트워크 프로토콜을 기반으로 캡슐화되는 반면, 로컬은 세마포어, 파이프, 메시지 큐 및 공유 메모리(electron 및 nodejs와 같은)를 기반으로 캡슐화됩니다. 이에 대해서는 다음에 설명하겠습니다.

전자 프로세스 통신

electron은 먼저 기본 프로세스를 시작한 다음 BrowserWindow를 통해 렌더링 프로세스를 생성하고 렌더링을 위한 HTML 페이지를 로드합니다. 두 프로세스 간의 통신은 Electron이 제공하는 ipc API를 통해 이루어집니다.

ipcMain, ipcRenderer

메인 프로세스에서는 ipcMain의 on 메소드를 통해 이벤트를 모니터링합니다

import { ipcMain } from 'electron';

ipcMain.on('异步事件', (event, arg) => {
  event.sender.send('异步事件返回', 'yyy');
})

렌더링 프로세스에서는 ipcRenderer의 on 메소드를 통해 이벤트를 모니터링하고, send를 통해 메시지를 보냅니다

import { ipcRenderer } from 'electron';

ipcRender.on('异步事件返回', function (event, arg) {
  const message = `异步消息: ${arg}`
})

ipcRenderer.send('异步事件', 'xxx')

api는 비교적 사용이 간단합니다. C++ 계층이 캡슐화되어 JS의 이벤트 형식 API에 노출되는 프로세스입니다.

어떤 메커니즘에 기반을 두고 있는지 생각해 볼 수 있나요?

분명히 어느 정도 비동기적인 성격이 있고, 상위 프로세스와 하위 프로세스 간의 통신이므로 메시지 큐 형식으로 구현됩니다.

remote

전자는 이벤트 기반 API 외에도 원격 메소드 호출 RMI(원격 메소드 호출) API도 제공합니다.

사실 이는 메시지를 더욱 캡슐화한 것입니다. 즉, 전달된 메시지에 따라 다른 메소드를 호출하는 것입니다. 형식적으로는 이 프로세스의 메소드를 호출하는 것과 같지만 실제로는 메시지를 전송하여 수행됩니다. 다른 프로세스로, ipcMain, ipcRenderer 형식은 본질적으로 동일합니다.

예를 들어 렌더링 프로세스에서 원격을 사용하여 기본 프로세스에서만 사용할 수 있는 BrowserWindow API를 직접 호출할 수 있습니다.

const { BrowserWindow } = require('electron').remote;

let win = new BrowserWindow({ width: 800, height: 600 });
win.loadURL('https://github.com');

요컨대 전자의 상위-하위 프로세스 통신 방식은 메시지 큐 캡슐화를 기반으로 합니다. 하나는 ipcMain과 ipcRenderer의 API를 통해 사용되는 이벤트 방식입니다. 메소드 호출(rmi) 역시 하단의 메시지를 기반으로 하지만 원격 메소드를 실행하지만 로컬 메소드를 실행하는 것처럼 보입니다.

nodejs

nodejs는 child_process와 Cluster라는 두 가지 모듈을 사용하여 프로세스 생성을 위한 API를 제공합니다. 분명히 하나는 상위-하위 프로세스의 생성 및 통신을 위한 것이고, 다른 하나는 다중 프로세스를 위한 것입니다.

child_process

child_process는 다양한 프로세스를 생성하는 데 사용되는 generate, exec, execFile 및 fork API를 제공합니다.

spawn, exec

셸을 통해 명령을 실행하려면 다음을 사용하세요. 생성 또는 실행. 일반적으로 명령을 실행하려면 반환 값이 필요하기 때문에 두 API는 값을 반환하는 방식이 다릅니다.

spawn은 데이터 이벤트를 통해 검색된 스트림을 반환하고 exec는 사용하기 더 간단하지만 maxBuffer를 초과할 수 있는 버퍼로 더 나누어집니다.

const { spawn } = require('child_process'); 

var app = spawn('node','main.js' {env:{}});

app.stderr.on('data',function(data) {
  console.log('Error:',data);
});

app.stdout.on('data',function(data) {
  console.log(data);
});

실제로 exec는 spwan을 기반으로 캡슐화되어 있으며 간단한 시나리오에서 사용할 수 있습니다. 때로는 maxBuffer를 설정해야 합니다.

const { exec } = require('child_process'); 

exec('find . -type f', { maxBuffer: 1024*1024 }(err, stdout, stderr) => { 
    if (err) { 
        console.error(`exec error: ${err}`); return; 
    }   
    console.log(stdout); 
});

execFile

명령 실행 외에도 실행 파일을 실행하려면 execFile api를 사용하세요.

const { execFile } = require('child_process'); 

const child = execFile('node', ['--version'], (error, stdout, stderr) => { 
    if (error) { throw error; } 
    console.log(stdout); 
});

fork

js를 실행하려면 fork를 사용하세요.

const { fork } = require('child_process');	

const xxxProcess = fork('./xxx.js');	
xxxProcess.send('111111');	
xxxProcess.on('message', sum => {	
    res.end('22222');	
});

요약

child_process의 네 가지 API에 대한 간략한 요약:

셸 명령을 실행하려면 generate와 exec를 사용하여 스트림을 반환하고 exec는 버퍼에 추가로 캡슐화됩니다. exec가 때때로 maxBuffer를 설정해야 한다는 점을 제외하면 차이가 없습니다.

실행 파일을 실행하려면 execFile을 사용하세요.

js 파일을 실행하려면 포크를 사용하세요.

child_process 的进程通信

说完了 api 我们来说下 child_process 创建的子进程怎么和父进程通信,也就是怎么做 ipc。

pipe

首先,支持了 pipe,很明显是通过管道的机制封装出来的,能同步的传输流的数据。

const { spawn } = require('child_process'); 

const find = spawn('cat', ['./aaa.js']);
const wc = spawn('wc', ['-l']);  find.stdout.pipe(wc.stdin);

比如上面通过管道把一个进程的输出流传输到了另一个进程的输入流,和下面的 shell 命令效果一样:

cat ./aaa.js | wc -l

message

spawn 支持 stdio 参数,可以设置和父进程的 stdin、stdout、stderr 的关系,比如指定 pipe 或者 null。还有第四个参数,可以设置 ipc,这时候就是通过事件的方式传递消息了,很明显,是基于消息队列实现的。

const { spawn } = require('child_process');

const child = spawn('node', ['./child.js'], {
    stdio: ['pipe', 'pipe', 'pipe', 'ipc'] 
}); 
child.on('message', (m) => { 
    console.log(m); 
}); 
child.send('xxxx');

而 fork 的 api 创建的子进程自带了 ipc 的传递消息机制,可以直接用。

const { fork } = require('child_process');	

const xxxProcess = fork('./xxx.js');	
xxxProcess.send('111111');	
xxxProcess.on('message', sum => {	
    res.end('22222');	
});

cluster

cluster 不再是父子进程了,而是更多进程,也提供了 fork 的 api。

比如 http server 会根据 cpu 数启动多个进程来处理请求。

import cluster from 'cluster';
import http from 'http';
import { cpus } from 'os';
import process from 'process';

const numCPUs = cpus().length;

if (cluster.isPrimary) {
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
} else {
  const server = http.createServer((req, res) => {
    res.writeHead(200);
    res.end(&#39;hello world\n&#39;);
  })
  
  server.listen(8000);
  
  process.on(&#39;message&#39;, (msg) => {
    if (msg === &#39;shutdown&#39;) {
       server.close();
    }
  });
}

它同样支持了事件形式的 api,用于多个进程之间的消息传递,因为多个进程其实也只是多个父子进程的通信,子进程之间不能直接通信,所以还是基于消息队列实现的。

共享内存

子进程之间通信还得通过父进程中转一次,要多次读写消息队列,效率太低了,就不能直接共享内存么?

现在 nodejs 还是不支持的,可以通过第三方的包 shm-typed-array 来实现,感兴趣可以看一下。

https://www.npmjs.com/package/shm-typed-array

总结

进程包括代码、数据和 PCB,是程序的一次执行的过程,PCB 记录着各种执行过程中的信息,比如分配的资源、执行到的地址、用于通信的数据结构等。

进程之间需要通信,可以通过信号量、管道、消息队列、共享内存的方式。

  • 信号量就是一个简单的数字的标记,不能传递具体数据。

  • 管道是基于文件的思想,一个进程写另一个进程读,是同步的,适用于两个进程。

  • 消息队列有一定的 buffer,可以异步处理消息,适用于两个进程。

  • 共享内存是多个进程直接操作同一段内存,适用于多个进程,但是需要控制访问顺序。

这四种是本地进程的通信方式,而网络进程则基于网络协议的方式也可以做进程通信。

进程通信叫做 ipc,本地的叫做 lpc,远程的叫 rpc。

其中,如果把消息再封装一层成具体的方法调用,叫做 rmi,效果就像在本进程执行执行另一个进程的方法一样。

electron 和 nodejs 都是基于上面的操作系统机制的封装:

  • elctron 支持 ipcMain 和 ipcRenderer 的消息传递的方式,还支持了 remote 的 rmi 的方式。

  • nodejs 有 child_process 和 cluster 两个模块和进程有关,child_process 是父子进程之间,cluster 是多个进程:

    • child_process 提供了用于执行 shell 命令的 spawn、exec,用于执行可执行文件的 execFile,用于执行 js 的 fork。提供了 pipe 和 message 两种 ipc 方式。

    • cluster 也提供了 fork,提供了 message 的方式的通信。

当然,不管封装形式是什么,都离不开操作系统提供的信号量、管道、消息队列、共享内存这四种机制。

ipc 是开发中频繁遇到的需求,希望这篇文章能够帮大家梳理清楚从操作系统层到不同语言和运行时的封装层次的脉络。

原文地址:https://juejin.cn/post/6988484297485189127

作者:zxg_神说要有光

更多编程相关知识,请访问:编程视频!!

위 내용은 Node.js와 Electron이 프로세스 간 통신하는 방법에 대해 자세히 알아보세요.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명
이 기사는 掘金--zxg_神说要有光에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제
Vercel是什么?怎么部署Node服务?Vercel是什么?怎么部署Node服务?May 07, 2022 pm 09:34 PM

Vercel是什么?本篇文章带大家了解一下Vercel,并介绍一下在Vercel中部署 Node 服务的方法,希望对大家有所帮助!

node.js gm是什么node.js gm是什么Jul 12, 2022 pm 06:28 PM

gm是基于node.js的图片处理插件,它封装了图片处理工具GraphicsMagick(GM)和ImageMagick(IM),可使用spawn的方式调用。gm插件不是node默认安装的,需执行“npm install gm -S”进行安装才可使用。

一文解析package.json和package-lock.json一文解析package.json和package-lock.jsonSep 01, 2022 pm 08:02 PM

本篇文章带大家详解package.json和package-lock.json文件,希望对大家有所帮助!

分享一个Nodejs web框架:Fastify分享一个Nodejs web框架:FastifyAug 04, 2022 pm 09:23 PM

本篇文章给大家分享一个Nodejs web框架:Fastify,简单介绍一下Fastify支持的特性、Fastify支持的插件以及Fastify的使用方法,希望对大家有所帮助!

怎么使用pkg将Node.js项目打包为可执行文件?怎么使用pkg将Node.js项目打包为可执行文件?Jul 26, 2022 pm 07:33 PM

如何用pkg打包nodejs可执行文件?下面本篇文章给大家介绍一下使用pkg将Node.js项目打包为可执行文件的方法,希望对大家有所帮助!

node爬取数据实例:聊聊怎么抓取小说章节node爬取数据实例:聊聊怎么抓取小说章节May 02, 2022 am 10:00 AM

node怎么爬取数据?下面本篇文章给大家分享一个node爬虫实例,聊聊利用node抓取小说章节的方法,希望对大家有所帮助!

手把手带你使用Node.js和adb开发一个手机备份小工具手把手带你使用Node.js和adb开发一个手机备份小工具Apr 14, 2022 pm 09:06 PM

本篇文章给大家分享一个Node实战,介绍一下使用Node.js和adb怎么开发一个手机备份小工具,希望对大家有所帮助!

图文详解node.js如何构建web服务器图文详解node.js如何构建web服务器Aug 08, 2022 am 10:27 AM

先介绍node.js的安装,再介绍使用node.js构建一个简单的web服务器,最后通过一个简单的示例,演示网页与服务器之间的数据交互的实现。

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

ZendStudio 13.5.1 맥

ZendStudio 13.5.1 맥

강력한 PHP 통합 개발 환경

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse를 SAP NetWeaver 애플리케이션 서버와 통합합니다.

mPDF

mPDF

mPDF는 UTF-8로 인코딩된 HTML에서 PDF 파일을 생성할 수 있는 PHP 라이브러리입니다. 원저자인 Ian Back은 자신의 웹 사이트에서 "즉시" PDF 파일을 출력하고 다양한 언어를 처리하기 위해 mPDF를 작성했습니다. HTML2FPDF와 같은 원본 스크립트보다 유니코드 글꼴을 사용할 때 속도가 느리고 더 큰 파일을 생성하지만 CSS 스타일 등을 지원하고 많은 개선 사항이 있습니다. RTL(아랍어, 히브리어), CJK(중국어, 일본어, 한국어)를 포함한 거의 모든 언어를 지원합니다. 중첩된 블록 수준 요소(예: P, DIV)를 지원합니다.

SecList

SecList

SecLists는 최고의 보안 테스터의 동반자입니다. 보안 평가 시 자주 사용되는 다양한 유형의 목록을 한 곳에 모아 놓은 것입니다. SecLists는 보안 테스터에게 필요할 수 있는 모든 목록을 편리하게 제공하여 보안 테스트를 더욱 효율적이고 생산적으로 만드는 데 도움이 됩니다. 목록 유형에는 사용자 이름, 비밀번호, URL, 퍼징 페이로드, 민감한 데이터 패턴, 웹 셸 등이 포함됩니다. 테스터는 이 저장소를 새로운 테스트 시스템으로 간단히 가져올 수 있으며 필요한 모든 유형의 목록에 액세스할 수 있습니다.