検索
ホームページウェブフロントエンドjsチュートリアルNode.js と Electron がプロセス間でどのように通信するかについて詳しく学ぶ

Node.js と Electron がプロセス間でどのように通信するかについて詳しく学ぶ

Jul 26, 2021 am 10:11 AM
electronnode.jsプロセスコミュニケーション

この記事では、Node.js と Electron 間のプロセス通信の原理を探り、Electron がプロセス通信を行う方法、nodejs の child_process とクラスターがプロセス通信を行う方法を紹介し、プロセス通信の本質を理解します。

Node.js と Electron がプロセス間でどのように通信するかについて詳しく学ぶ

フロントエンドがプロセス通信を理解する必要がある理由:

フロントエンドの分野は、もはやブラウザーで実行されるページを作成するだけではありません。ただし、Electron、nodejs などの知識も必要であり、どちらのテクノロジもプロセス通信を習得する必要があります。

Nodejs は、js のランタイムです。ブラウザとは異なり、プロセスやスレッド関連の API など、オペレーティング システムの機能をカプセル化する多くの API を拡張します。プロセス API を学習するには、プロセス間の相互作用を学習する必要があります。通信メカニズム。

Electron は chromium と Nodejs をベースとしたデスクトップ開発ソリューションです。そのアーキテクチャはメインプロセスと複数のレンダリングプロセスで構成されています。これら 2 つのプロセス間でも通信が必要です。Electron のプロセス通信メカニズムを学ぶ必要があります。 [推奨される学習: "nodejs チュートリアル "]

この記事では、プロセス通信について詳しく見ていきます。

この記事では、次の知識ポイントについて説明します:

  • プロセスとは
  • ローカル プロセス通信の 4 つの方法
  • ipc、lpc、 rpc とは何ですか
  • electron がプロセス通信を行う方法
  • Nodejs の child_process とクラスターでプロセス通信を行う方法
  • プロセス通信の本質

プロセス

#私たちが作成したコードはオペレーティング システム上で実行する必要があります。ハードウェア リソースをより有効に活用するために、オペレーティング システムは複数のプログラムの同時実行とハードウェア リソースの割り当てをサポートしています。割り当ての単位はプロセスであり、このプロセスがプログラムの実行プロセスになります。たとえば、プログラムが実行したステップ、どのハードウェア リソースが適用されたか、どのポートが占有されているかなどを記録します。

プログラムはデータセット上のコードの実行プロセスであるため、プロセスには、実行されるコード、コードによって操作されるデータ、およびプロセス制御ブロックPCB (Processing Control Block)が含まれます。実行プロセスのステータスと適用されたリソースをデータ構造 (PCB) に記録する必要があります。したがって、プロセスはコード、データ、PCB で構成されます。

Node.js と Electron がプロセス間でどのように通信するかについて詳しく学ぶ

pcb は、pid、実行されたコード アドレス、プロセスのステータス (ブロック、実行中、準備完了など)、およびセマフォ、パイプ、メッセージを記録します。通信に使用されるキューやその他のデータ構造。

Node.js と Electron がプロセス間でどのように通信するかについて詳しく学ぶ

プロセスは、ハードウェア リソース (メモリ、ハードディスク ファイル、ネットワークなど) の作成からアプリケーションへの継続的なコード実行までブロックされる可能性があり、最終的にプロセスは実行後は破棄されます。これがプロセスのライフサイクルです。

プロセスは、要求されたリソースに排他的にアクセスできます。各プロセスは、自分のリソースのみにアクセスできます。プロセスはどのように相互に通信しますか?

プロセス通信

利用可能なメモリはプロセスごとに異なるため、プロセスは中間媒体を介して通信する必要があります。

セマフォ

数値で表され、PCB の属性に配置される単純なマークの場合、これは ## と呼ばれます。 #Semaphore、たとえば、ロックはセマフォを通じて実装できます。

このセマフォのアイデアは、フロントエンド コードを記述するときによく使用されます。たとえば、スロットリングを実装する場合は、マーク変数も追加する必要があります。

パイプライン

ただし、セマフォでは特定のデータを転送できないため、特定のデータを転送するには他の方法を使用する必要があります。たとえば、

パイプラインというファイルを読み書きすることで通信できますが、メモリ内のファイルの場合は匿名パイプと呼ばれ、ファイル名はありません。ハードディスクには、名前付きパイプと呼ばれるファイル名が付いています。

ファイルは最初に開いてから読み取りと書き込みを行ってから閉じる必要がありますが、これはパイプラインの特性でもあります。パイプはファイルの概念に基づいてカプセル化されており、1 つのプロセスでのみ読み取り、1 つのプロセスで書き込むことができるため、パイプと呼ばれます。一方向 (半二重) です。さらに、ターゲット プロセスはデータを同期的に消費する必要もあります。そうしないとブロックされてしまいます。

このパイプ メソッドは実装が非常に簡単で、ファイルの読み取りと書き込みを行いますが、2 つのプロセス間の通信にのみ使用でき、同期通信のみが可能です。実際、ストリームのパイプメソッドであるパイプの同期通信も非常に一般的です。

Message Queue

パイプラインの実装はシンプルですが、同期通信は比較的制限されています。非同期通信を行いたい場合はどうすればよいでしょうか?バッファとしてキューを追加するだけです。これは

Message Queue です。

メッセージ キューも 2 つのプロセス間の通信ですが、ファイルベースの考え方に基づいたものではなく、やはり一方向ですが、ある種の非同期的な性質があり、大量のメッセージを入れることができます。そしてそれらを一度にすべて消費します。 ############共有メモリ#########

パイプラインとメッセージ キューは 2 つのプロセス間にあります。複数のプロセスがある場合はどうなりますか?

共有メモリと呼ばれる、複数のプロセスで操作できるメモリを申請することで、この方法で通信できます。各プロセスはこのメモリに対してデータを読み書きできるため、比較的効率的です。

共有メモリは効率が高く、複数のプロセス間の通信に使用できますが、複数のプロセスが読み書きできるため混乱しやすく、良いことばかりではありません。順序を自分で制御する必要があります。などによりプロセスのセマフォ(マーク変数)を制御します。

共有メモリは、中間媒体を介さずに複数のプロセス間の通信に適しているため、より効率的ですが、使用方法も複雑になります。

上記は、ローカル プロセス通信のほぼすべての方法ですが、なぜローカル プロセスを追加するのでしょうか?

ipc、rpc、lpc

プロセス通信は ipc (プロセス間通信) です。2 つのプロセスは同じコンピュータ上に存在する場合もあれば、異なるコンピュータ上に存在する場合もあります。コンピュータプロセスの通信方式は、

ローカルプロシージャコールLPC(ローカルプロシージャコール)とリモートプロシージャコールRPC(リモートプロシージャコール)の2種類に分けられます。

ローカル プロシージャ コールは、上で説明したセマフォ、パイプ、メッセージ キュー、共有メモリの通信方法です。しかし、それがネットワーク上にある場合は、ネットワーク プロトコルを介して通信する必要があります。これが実際に使用されるものです。 http や websocket など、たくさんあります。

つまり、誰かが ipc について言及するとき、彼らはプロセス通信について話しているのですが、これはローカルとリモートの 2 つの方法で議論できます。

リモートのものはネットワーク プロトコルに基づいてカプセル化されますが、ローカルのものはセマフォ、パイプ、メッセージ キュー、次に説明する Electron や Nodejs などの共有メモリに基づいてカプセル化されます。

electron プロセス通信

electron は最初にメイン プロセスを開始し、次に BrowserWindow を通じてレンダリング プロセスを作成し、レンダリング用の HTML ページを読み込みます。 2 つのプロセス間の通信は、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 に加えて、electron はリモート メソッド呼び出し rmi (リモート) の形式でも API を提供します。メソッドの呼び出し)。

実際には、これはメッセージをさらにカプセル化したもので、渡されたメッセージに応じてさまざまなメソッドを呼び出します。形式的には、このプロセスのメソッドを呼び出すのとまったく同じですが、実際には、メッセージを別のプロセスに送信することで実行され、その形式は基本的に ipcMain および ipcRenderer と同じです。

たとえば、レンダリング プロセスでは、メイン プロセスでのみ使用できる BrowserWindow API がリモート経由で直接呼び出されます。

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

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

electron の親子プロセス通信方式はメッセージキューのカプセル化に基づいており、カプセル化形式は 2 つあり、1 つは ipcMain と ipcRenderer の API を介して使用されるイベントメソッド、もう 1 つはイベントメソッドです。もう 1 つはさらに詳細で、さまざまなメソッド (rmi) の呼び出しにカプセル化されています。最下層もメッセージに基づいており、リモート メソッドを実行しますが、ローカル メソッドを実行しているように見えます。

nodejs

nodejs は、child_process とクラスターの 2 つのモジュールを備えたプロセスを作成するための API を提供します。明らかに、1 つは親子プロセスの作成と通信用であり、もう 1 つは複数のプロセス用です。

child_process

child_process は、さまざまなプロセスの作成に使用される spawn、exec、execFile、および fork API を提供します。

spawn、exec

シェルを通じてコマンドを実行する場合は、spawn または exec を使用します。一般にコマンドの実行には戻り値が必要なため、2 つの 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');	
});

要約

次の 4 つの API の簡単な概要child_process:

シェル コマンドを実行する場合は、spawn と exec を使用します。spawn はストリームを返し、exec はそれをさらにバッファにカプセル化します。 exec が maxBuffer を設定する必要があることを除けば、違いはありません。

実行可能ファイルを実行する場合は、execFile を使用します。

js ファイルを実行したい場合は、fork を使用します。

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 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事は掘金--zxg_神说要有光で複製されています。侵害がある場合は、admin@php.cn までご連絡ください。
JavaScriptフレームワーク:最新のWeb開発のパワーJavaScriptフレームワーク:最新のWeb開発のパワーMay 02, 2025 am 12:04 AM

JavaScriptフレームワークのパワーは、開発を簡素化し、ユーザーエクスペリエンスとアプリケーションのパフォーマンスを向上させることにあります。フレームワークを選択するときは、次のことを検討してください。1。プロジェクトのサイズと複雑さ、2。チームエクスペリエンス、3。エコシステムとコミュニティサポート。

JavaScript、C、およびブラウザの関係JavaScript、C、およびブラウザの関係May 01, 2025 am 12:06 AM

はじめに私はあなたがそれを奇妙に思うかもしれないことを知っています、JavaScript、C、およびブラウザは正確に何をしなければなりませんか?彼らは無関係であるように見えますが、実際、彼らは現代のウェブ開発において非常に重要な役割を果たしています。今日は、これら3つの間の密接なつながりについて説明します。この記事を通して、JavaScriptがブラウザでどのように実行されるか、ブラウザエンジンでのCの役割、およびそれらが協力してWebページのレンダリングと相互作用を駆動する方法を学びます。私たちは皆、JavaScriptとブラウザの関係を知っています。 JavaScriptは、フロントエンド開発のコア言語です。ブラウザで直接実行され、Webページが鮮明で興味深いものになります。なぜJavascrを疑問に思ったことがありますか

node.jsは、型を使用してストリーミングしますnode.jsは、型を使用してストリーミングしますApr 30, 2025 am 08:22 AM

node.jsは、主にストリームのおかげで、効率的なI/Oで優れています。 ストリームはデータを段階的に処理し、メモリの過負荷を回避します。大きなファイル、ネットワークタスク、リアルタイムアプリケーションの場合。ストリームとTypeScriptのタイプの安全性を組み合わせることで、パワーが作成されます

Python vs. JavaScript:パフォーマンスと効率の考慮事項Python vs. JavaScript:パフォーマンスと効率の考慮事項Apr 30, 2025 am 12:08 AM

PythonとJavaScriptのパフォーマンスと効率の違いは、主に以下に反映されています。1)解釈された言語として、Pythonはゆっくりと実行されますが、開発効率が高く、迅速なプロトタイプ開発に適しています。 2)JavaScriptはブラウザ内の単一のスレッドに限定されていますが、マルチスレッドおよび非同期I/Oを使用してnode.jsのパフォーマンスを改善でき、両方とも実際のプロジェクトで利点があります。

JavaScriptの起源:その実装言語の調査JavaScriptの起源:その実装言語の調査Apr 29, 2025 am 12:51 AM

JavaScriptは1995年に発信され、Brandon Ikeによって作成され、言語をCに実現しました。 2。JavaScriptのメモリ管理とパフォーマンスの最適化は、C言語に依存しています。 3. C言語のクロスプラットフォーム機能は、さまざまなオペレーティングシステムでJavaScriptを効率的に実行するのに役立ちます。

舞台裏:JavaScriptをパワーする言語は何ですか?舞台裏:JavaScriptをパワーする言語は何ですか?Apr 28, 2025 am 12:01 AM

JavaScriptはブラウザとnode.js環境で実行され、JavaScriptエンジンに依存してコードを解析および実行します。 1)解析段階で抽象的構文ツリー(AST)を生成します。 2)ASTをコンパイル段階のバイトコードまたはマシンコードに変換します。 3)実行段階でコンパイルされたコードを実行します。

PythonとJavaScriptの未来:傾向と予測PythonとJavaScriptの未来:傾向と予測Apr 27, 2025 am 12:21 AM

PythonとJavaScriptの将来の傾向には、1。Pythonが科学コンピューティングの分野での位置を統合し、AI、2。JavaScriptはWebテクノロジーの開発を促進します。どちらもそれぞれのフィールドでアプリケーションシナリオを拡大し続け、パフォーマンスをより多くのブレークスルーを行います。

Python vs. JavaScript:開発環境とツールPython vs. JavaScript:開発環境とツールApr 26, 2025 am 12:09 AM

開発環境におけるPythonとJavaScriptの両方の選択が重要です。 1)Pythonの開発環境には、Pycharm、Jupyternotebook、Anacondaが含まれます。これらは、データサイエンスと迅速なプロトタイピングに適しています。 2)JavaScriptの開発環境には、フロントエンドおよびバックエンド開発に適したnode.js、vscode、およびwebpackが含まれます。プロジェクトのニーズに応じて適切なツールを選択すると、開発効率とプロジェクトの成功率が向上する可能性があります。

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衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

Dreamweaver Mac版

Dreamweaver Mac版

ビジュアル Web 開発ツール

SublimeText3 Linux 新バージョン

SublimeText3 Linux 新バージョン

SublimeText3 Linux 最新バージョン