이 글에서는 Node.js와 Electron 간의 프로세스 통신 원리를 살펴보고, Electron이 어떻게 통신을 처리하는지, nodejs의 child_process와 클러스터가 어떻게 통신을 처리하는지 소개하고, 프로세스 통신의 본질을 이해합니다.
프런트엔드가 프로세스 통신을 이해해야 하는 이유:
프론트엔드 필드는 더 이상 브라우저에서 실행되는 페이지 작성뿐만 아니라 전자, 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로 구성됩니다.
pcb는 pid, 실행된 코드 주소, 프로세스 상태(차단, 실행 중, 준비 등)는 물론 통신에 사용되는 세마포어, 파이프, 메시지 큐와 같은 데이터 구조를 기록합니다.
코드 생성부터 지속적인 실행, 하드웨어 리소스(메모리, 하드디스크 파일, 네트워크 등) 적용까지 프로세스가 중간에 차단될 수 있으며, 실행 후 결국 프로세스가 소멸됩니다. 이것이 프로세스의 생명주기입니다.
프로세스는 요청된 리소스에만 독점적입니다. 각 프로세스는 자신의 리소스에만 액세스할 수 있습니다. 그러면 프로세스는 어떻게 서로 통신합니까?
프로세스 통신
프로세스마다 사용 가능한 메모리가 다르기 때문에 중간 매체를 통해 통신해야 합니다.
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('hello world\n'); }) server.listen(8000); process.on('message', (msg) => { if (msg === 'shutdown') { 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

Python 또는 JavaScript는 경력 개발, 학습 곡선 및 생태계를 기반으로해야합니다. 1) 경력 개발 : Python은 데이터 과학 및 백엔드 개발에 적합한 반면 JavaScript는 프론트 엔드 및 풀 스택 개발에 적합합니다. 2) 학습 곡선 : Python 구문은 간결하며 초보자에게 적합합니다. JavaScript Syntax는 유연합니다. 3) 생태계 : Python에는 풍부한 과학 컴퓨팅 라이브러리가 있으며 JavaScript는 강력한 프론트 엔드 프레임 워크를 가지고 있습니다.

JavaScript 프레임 워크의 힘은 개발 단순화, 사용자 경험 및 응용 프로그램 성능을 향상시키는 데 있습니다. 프레임 워크를 선택할 때 : 1. 프로젝트 규모와 복잡성, 2. 팀 경험, 3. 생태계 및 커뮤니티 지원.

서론 나는 당신이 이상하다는 것을 알고 있습니다. JavaScript, C 및 Browser는 정확히 무엇을해야합니까? 그들은 관련이없는 것처럼 보이지만 실제로는 현대 웹 개발에서 매우 중요한 역할을합니다. 오늘 우리는이 세 가지 사이의 밀접한 관계에 대해 논의 할 것입니다. 이 기사를 통해 브라우저에서 JavaScript가 어떻게 실행되는지, 브라우저 엔진의 C 역할 및 웹 페이지의 렌더링 및 상호 작용을 유도하기 위해 함께 작동하는 방법을 알게됩니다. 우리는 모두 JavaScript와 브라우저의 관계를 알고 있습니다. JavaScript는 프론트 엔드 개발의 핵심 언어입니다. 브라우저에서 직접 실행되므로 웹 페이지를 생생하고 흥미롭게 만듭니다. 왜 Javascr

Node.js는 크림 덕분에 효율적인 I/O에서 탁월합니다. 스트림은 메모리 오버로드를 피하고 큰 파일, 네트워크 작업 및 실시간 애플리케이션을위한 메모리 과부하를 피하기 위해 데이터를 점차적으로 처리합니다. 스트림을 TypeScript의 유형 안전과 결합하면 Powe가 생성됩니다

파이썬과 자바 스크립트 간의 성능과 효율성의 차이는 주로 다음과 같이 반영됩니다. 1) 해석 된 언어로서, 파이썬은 느리게 실행되지만 개발 효율이 높고 빠른 프로토 타입 개발에 적합합니다. 2) JavaScript는 브라우저의 단일 스레드로 제한되지만 멀티 스레딩 및 비동기 I/O는 Node.js의 성능을 향상시키는 데 사용될 수 있으며 실제 프로젝트에서는 이점이 있습니다.

JavaScript는 1995 년에 시작하여 Brandon Ike에 의해 만들어졌으며 언어를 C로 실현했습니다. 1.C Language는 JavaScript의 고성능 및 시스템 수준 프로그래밍 기능을 제공합니다. 2. JavaScript의 메모리 관리 및 성능 최적화는 C 언어에 의존합니다. 3. C 언어의 크로스 플랫폼 기능은 자바 스크립트가 다른 운영 체제에서 효율적으로 실행하는 데 도움이됩니다.

JavaScript는 브라우저 및 Node.js 환경에서 실행되며 JavaScript 엔진을 사용하여 코드를 구문 분석하고 실행합니다. 1) 구문 분석 단계에서 초록 구문 트리 (AST)를 생성합니다. 2) 컴파일 단계에서 AST를 바이트 코드 또는 기계 코드로 변환합니다. 3) 실행 단계에서 컴파일 된 코드를 실행하십시오.

Python 및 JavaScript의 미래 추세에는 다음이 포함됩니다. 1. Python은 과학 컴퓨팅 분야에서의 위치를 통합하고 AI, 2. JavaScript는 웹 기술의 개발을 촉진하고, 3. 교차 플랫폼 개발이 핫한 주제가되고 4. 성능 최적화가 중점을 둘 것입니다. 둘 다 해당 분야에서 응용 프로그램 시나리오를 계속 확장하고 성능이 더 많은 혁신을 일으킬 것입니다.


핫 AI 도구

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

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

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

ZendStudio 13.5.1 맥
강력한 PHP 통합 개발 환경

MinGW - Windows용 미니멀리스트 GNU
이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

에디트플러스 중국어 크랙 버전
작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음
