【每日一題】Node進程間通信

人生苦短,總需要一點儀式感。比如學前端~
進程間通信分類
每個進程都有各自不同的用戶地址空間,任何一個進程的全局變量在另一個進程中看不到,所以進程之間要交換數(shù)據(jù)必須通過內(nèi)核,在內(nèi)核中開辟一個緩存區(qū),進程 A 把數(shù)據(jù)從用戶空間拷貝到內(nèi)核緩存區(qū),進程 B 再從該緩沖區(qū)把數(shù)據(jù)讀走,內(nèi)核提供的這種機制稱為進程間通信
實現(xiàn)進程間通信(IPC)的方式
匿名通道
管道是一種半雙工的通信方式,數(shù)據(jù)只能單向流動,而且只能在具有親緣關(guān)系”的進程間調(diào)用。進程的親緣關(guān)系通常是指父子進程關(guān)系。
半雙工通信:支持數(shù)據(jù)在兩個方向上互相傳輸,可以實現(xiàn)雙向通信。但同一時刻只允許數(shù)據(jù)在一個方向上傳輸。比如對講機的模式。
有點類似vue中props之于父子組件的存在。
命名管道
命名管道也是半雙工的通信方式,但是它允許無親緣關(guān)系進程間通信。
有點類似vue中 中央總線 的存在。
信號量
信號量是一個計數(shù)器,可以用來控制多個進程對共享資源的訪問。它常作為一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。因此,主要作為進程間以及同一進程內(nèi)不同線程之間同步的手段。
消息隊列
消息隊列是由消息的鏈表存放在內(nèi)核中并由消息隊列標識符標識。
消息隊列克服了信號傳遞信息少、管道只能承載無格式字節(jié)流以及緩存區(qū)大小受限等缺點。
信號
信號是一種比較復(fù)雜的通信方式,用于通知接收進程某個事件已經(jīng)發(fā)生。
共享內(nèi)存
共享內(nèi)存就是映射一段能被其他進程所訪問的內(nèi)存,這段共享內(nèi)存由一個進程創(chuàng)建,但多個進程都可以訪問。
共享內(nèi)容是最快的IPC方式,它是針對其他進程間通信方式運行效率低而專門設(shè)計的。它往往與其他通信機制,如信號量配合使用,來實現(xiàn)進程間的同步和通信。
套接字
套接字也是一種進程間通信機制,與其他通信機制不同的是,它可用于不同機器間的進程通信。
從技術(shù)上可以劃分四種:
【消息傳遞】:管道、FIFO、消息隊列 【同步】:互斥量、條件變量、讀寫鎖等 【共享內(nèi)存】:匿名的、命名的 【遠程過程調(diào)用】
node 進程間通信方式
nodeIPC 通過通道技術(shù) + 事件循環(huán)方式進行通信。
管道技術(shù)在 Windows 下由命名管道實現(xiàn);
在*nix系統(tǒng)則由 Unix Domain Socket 實現(xiàn),提供給我們簡單的 message事件和 send方法。
我們通過on('message',function(m,setHandle){})和send(message,[sendHandle])來實現(xiàn)IPC。
Node中父子進程的IPC通道建立
父進程和子進程之間建立 IPC 通道:
child_process.spawn(command[, args][, options])
??
child_process.spawn()方法使用給定的 command 和 args 中的命令行參數(shù)衍生新進程。
可通過配置options.stdio來指定額外的文件描述符以在父進程和子進程之間創(chuàng)建額外的管道。
child_process.fork()
??
child_process.fork()方法是 child_process.spawn() 的特例,專門用于衍生新的 Node.js 進程。與 child_process.spawn() 一樣,返回 ChildProcess 對象。返回的 ChildProcess 將有額外的內(nèi)置通信通道,允許消息在父進程和子進程之間來回傳遞。詳見 subprocess.send()
http://nodejs.cn/api/child_process.html#child_process_child_process_fork_modulepath_args_options
管道
管道實際上是在內(nèi)核中開辟一塊緩沖區(qū),它有一個讀端、一個寫端,并傳給用戶程序兩個文件描述符,一個指向讀端,一個指向?qū)懚?。然后該緩沖存儲不同進程間寫入的內(nèi)容,并供不同進程讀取內(nèi)容,進而達到通信的目的。
管道又分為匿名管道和命名管道:
匿名管道常見于一個進程fork出一個子進程,只能親緣進程通信;
而命名管道可以讓非親緣進程進行通信。
其實本質(zhì)上來說進程間通信是利用內(nèi)核管理一塊內(nèi)存,不同進程可以讀寫這塊內(nèi)容,進而可以互相通信。
文件描述符
在 linux 中一切皆文件,linux 會給每個文件分配一個 id,這個 id 就是文件描述符,指針也是文件描述符的一種。這個很好理解,不過我們可以深入說說,一個進程啟動后,會在內(nèi)核空間(虛擬空間的一部分)創(chuàng)建一個 PCB 控制塊,PCB 內(nèi)部有一個文件描述符表,記錄著當前進程所有可用的文件描述符(即當前進程所有打開的文件)。系統(tǒng)除了維護文件描述符表外,還需要維護打開文件表(Open file table)和 i-node(i-node table)
文件打開表(Open file table)包含文件偏移量,狀態(tài)標志,i-node表指針等信息
i-node 表(i-node table)包括文件類型、文件大小、時間戳、文件鎖等信息
文件描述符不是一對一的,它可以:
同一進程的不同文件描述符指向同一文件 不同進程可以擁有相同的文件描述符---比如 fork 出的子進程擁有父進程一樣的文件描述符,或者不同進程打開同一文件 不同進程的同一文件描述符也可以指向不同的文件 不同進程的不同文件描述符也可以指向同一個文件

讓我們一起攜手同走前端路!
關(guān)注公眾號回復(fù)【加群】即可
