Linux 進程 | 進程間的通信方式

文章目錄

  • 管道
    • 匿名管道 pipe
    • 命名管道 FIFO
  • 共享內存
    • 共享內存的使用流程:
  • 消息隊列
  • 信號量
  • 套接字


在之前的博客中講過,虛擬空間出現的其中一個目的就是解決 進程沒有獨立性,可能訪問同一塊物理內存 的問題。因為這種獨立性,進程之間無法直接進行通信,操作系統為了解決這種問題,提出了多種適用于不同情境下的通信方式:

  • 數據傳輸:管道、消息隊列
  • 數據共享:共享內存
  • 進程控制:信號量

管道

管道的本質其實就是內核中的一塊緩沖區,多個進程通過訪問同一個緩沖區就可以實現進程間的通信。自 Linux 2.6.11 內核起,管道容量的大小默認是 65536 字節,但可以通過 fcntl函數 來修改管道容量。

在這里插入圖片描述

管道分為兩種:匿名管道、命名管道


匿名管道 pipe

因為沒有具體的文件描述符,所以只能用于具有親緣(父子)關系的進程之間的通信。

原理: 父進程在創建管道的時候操作系統會返回管道的文件描述符,然后生成子進程時子進程會通過拷貝父進程的 pcb 來獲取到這個管道的描述符,所以他們可以通過這個文件描述符來訪問同一個管道,來實現進程間的通信。而不具備親緣關系的進程則無法通過這個文件描述符來訪問同一個管道。

在這里插入圖片描述
返回值:成功返回 0,失敗返回 -1

在這里插入圖片描述
也就是說讀/寫操作的流程是:

  1. 關閉 讀/寫 端
  2. 進行 寫/讀 操作
  3. 寫/讀 完關閉 寫/讀 端

圖解父子進程通過管道通信的流程:

一開始父進程創建管道
在這里插入圖片描述
父進程fork創建子進程

在這里插入圖片描述

關閉多余描述符

在這里插入圖片描述
代碼示例:示例一 示例二

如果沒有特意規定,那么父子進程究竟是誰先執行是不確定的,假設如果子進程還沒寫入,父進程卻已經開始讀了,這時候應該是會讀不到東西的,會在屏幕上輸出空行,但是這種情況并沒有發生,這里就牽扯到了管道的讀寫特性:

  • 如果管道中沒有數據,則調用 read 讀取數據會阻塞。
  • 如果管道中數據滿了,則調用 write 寫入數據會阻塞。
  • 如果管道的所有 讀端 被關閉,繼續調用 write 時,會因為無法讀出而產生異常導致進程退出。
  • 如果管道的所有 寫端 被關閉,繼續調用 read 時,read 讀完管道中的所有數據后不再阻塞,返回 0 退出。

命名管道 FIFO

命名管道也是內核中的一塊緩沖區,但是它 具有標識符 。這個標識符是一個可見于文件系統的管道文件,能夠被其他進程找到并打開管道文件來獲取管道的操作句柄,多個進程可以通過打開這個管道文件來訪問同一塊緩沖區來實現通信。

  • 可以在沒有親緣關系(非父子)的進程之間進行通信,這是與無名管道最大的區別。
  • 他是以一個特性的文件存儲在文件系統中, 所以對他的操作與其路徑名有關聯。

接口:

int mkfifo(const char *filename,mode_t mode);

filename——管道的標識符,通過這個標識符來訪問管道,創建之前這個標識符必須不存在。
mode——權限掩碼。
返回值——若成功則返回 0,否則返回 -1

代碼示例: 命名管道實現進程的信息傳遞【mkfifo函數、open函數】

open 打開命名管道的特性:

  1. 若文件以只讀打開,則會阻塞,直到文件被以寫的方式打開。
  2. 若文件以只寫打開,則會阻塞,直到文件被以讀的方式打開。

管道的特性:

  1. 管道是半雙工通信(可以選擇方向的單向傳輸),這個可以從上面的示意圖看出來。
  2. 管道的讀寫特性(無論命名匿名都一樣)。
  3. 管道聲明周期隨進程,打開管道的所有進程退出后管道就會被釋放。
  4. 管道提供字節流傳輸服務。
  5. 命名管道額外有一個打開特性,只讀打開會阻塞直到被以寫打開,只寫打開會阻塞直到被以讀打開。
  6. 管道自帶同步和互斥。

共享內存

共享內存即在 物理內存 上開辟一塊空間,然后 多個進程 通過 頁表 將這 同一個物理內存 映射到自己的 虛擬地址空間 中,通過自己的 虛擬地址空間 來訪問這塊 物理內存 ,達到了數據共享的目的。

在這里插入圖片描述
也正是因為這種特性,使得 共享內存成為了最快的進程間通信的方式 ,因為它 直接通過虛擬地址來訪問物理內存,比前面的管道和后面的消息隊列 少了內核態和用戶態的幾次數據拷貝和交互

特點:

  1. 生命周期隨內核。
  2. 由于多個進程可以同時操作,因此需要進行同步。但不自帶同步與互斥,而是借助信號量來實現同步與互斥。

共享內存的使用流程:

1. 創建共享內存

頭文件:
#include <sys/ipc.h>
#include <sys/shm.h>
定義函數:
int shmget(key_t key, size_t size, int shmflg)
參數:
key:這個共享內存段名字
size:共享內存大小
shmflg:由九個權限標志構成,它們的用法和創建文件時使用的mode模式標志是一樣的。返回值:成功返回共享內存標識符,失敗返回-1

2. 將共享內存映射到虛擬地址空間

頭文件:
#include <sys/types.h>
#include <sys/shm.h>
定義函數:
void *shmat(int shmid, const void *shmaddr, int shmflg)
參數:
shmid: 共享內存標識
shmaddr:指定連接的地址
shmflg:權限標志返回值:成功返回指向共享內存映射在虛擬地址空間的指針(即首地址),失敗返回-1

3. 共享內存管理

頭文件:
#include <sys/types.h>
#include <sys/shm.h>
定義函數:
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
參數:
shmid:由shmget返回的共享內存標識碼
cmd:將要采取的動作
buf:指向一個保存著共享內存的模式狀態和訪問權限的數據結構返回值:成功返回0,失敗返回-1

4. 解除映射關系

頭文件:
#include <sys/types.h>
#include <sys/shm.h>
定義函數:
int shmdt(const void *shmaddr)
參數:shmaddr: 由shmat所返回的指針
返回值:成功返回0,失敗返回-1

消息隊列

概念:

  1. 消息隊列是內核中的一個優先級隊列,多個進程通過訪問同一個隊列,進行添加節點或者獲取節點來實現通信。
  2. 消息隊列是消息的連接表, 放在內核中, 一個消息隊列由一個標識符表示。
  3. 消息隊列是面向記錄的, 其中的消息具有特定的格式以及特定的優先級。
  4. 消息隊列獨立于發送和接受進程中, 也就是當一個進程被銷毀, 他在消息隊列中的信息是不會被刪除的。
  5. 消息隊列中的內容可以實現隨機查詢, 也就是消息不一定要以 FIFO 讀取, 也可以按消息的類型讀取。

特性:

  • 自帶同步與互斥
  • 生命周期隨內核

流程:

1. 創建消息隊列

頭文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
定義函數:
int msgget(key_t key, int msgflg)
參數:
key:消息隊列對象的關鍵字
msgflg:消息隊列的建立標志和存取權限返回值:成功執行時,返回消息隊列標識值。失敗返回-1

2. 進程可以向隊列中添加/獲取節點

頭文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
添加節點:
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
獲取節點:
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
參數:
msqid:消息隊列對象的標識符
msgp:消息緩沖區指針
msgsz:消息數據的長度
msgtyp:決定從隊列中返回哪條消息
msgflg:消息隊列狀態返回值:成功執行時,返回0。失敗返回-1

3. 刪除消息隊列

頭文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
定義函數:
int msgctl(int msqid, int cmd, struct msqid_ds *buf)
參數:
msqid:消息隊列對象的標識符
cmd:函數要對消息隊列進行的操作
buf:取出系統保存的消息隊列的 msqid_ds 數據,并將其存入參數 buf 指向的 msqid_ds 結構中返回值:成功執行時,返回0。失敗返回-1

信號量

概念:

  • 信號量與IPC結構不同,它其實是 內核中的一個計數器和阻塞隊列 ,通過信號量來對 臨界資源的訪問進行控制,來 實現進程間的同步與互斥 ,而不是用于進程間消息的通信的。
  • 信號量用于進程間同步,若要在進程間傳遞數據需要結合共享內存。
  • 信號量基于操作系統的 PV 操作,程序對信號量的操作都是原子操作。
  • 每次對信號量的 PV 操作不僅限于對信號量值加 1 或減 1,而且可以加減任意正整數。

例如:有一個能容納 n 人的餐廳,用一個計數器表示 n,如果有人進入則 n - 1,如果有人出來則 n + 1,只有 n > 0 時才能進入,如果 n <= 0 時,則說明沒有位置,需要將進程掛起并放入阻塞隊列中,直到有人出來使資源釋放時,才能將后續進程從阻塞隊列中喚醒獲取資源。

  • 同步:通過條件判斷實現臨界資源訪問的合理性
  • 互斥:通過同一時間的唯一訪問來實現臨界資源訪問的安全性

POSIX信號量: POSIX 信號量和 SystemV 信號量作用相同,都是用于同步操作,達到無沖突的訪問共享資源目的。 但 POSIX 可以用于線程間同步。

流程:

#include <semaphore.h>//初始化信號量
int sem_init(sem_t *sem, int pshared, unsigned int value);
/*
參數:
pshared:0表示線程間共享,非零表示進程間共享
value:信號量初值
*///銷毀信號量
int sem_destroy(sem_t *sem);//等待信號量
int sem_wait(sem_t *sem);
//功能:等待信號量,會將信號量的值減1//發布信號量
int sem_post(sem_t *sem);
//功能:發布信號量,表示資源使用完畢,可以歸還資源了。將信號量值加1。

套接字

使用套接字也可以實現進程間的通信,與其他機制不同的是,它可以實現不同機器之前的進程間的通信。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/443767.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/443767.shtml
英文地址,請注明出處:http://en.pswp.cn/news/443767.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux網絡編程 | socket介紹、網絡字節序與主機字節序概念與兩者的轉換、TCP/UDP 連接中常用的 socket 接口

文章目錄套接字socket 地址通用 socket 地址專用 socket 地址網絡字節序與主機字節序地址轉換TCP/UDP 連接中常用的 socket 接口套接字 什么是套接字&#xff1f; 所謂 套接字 (Socket) &#xff0c;就是對網絡中 不同主機 上的應用進程之間進行雙向通信的端點的抽象。 UNIX/L…

網絡協議分析 | 傳輸層 :史上最全UDP、TCP協議詳解,一篇通~

文章目錄UDP概念格式UDP如何實現可靠傳輸基于UDP的應用層知名協議TCP概念格式保證TCP可靠性的八種機制確認應答、延時應答與捎帶應答超時重傳滑動窗口滑動窗口協議后退n協議選擇重傳協議流量控制擁塞控制發送窗口、接收窗口、擁塞窗口快速重傳和快速恢復連接管理機制三次握手連…

JDom,jdom解析xml文件

1.要解析的文件模板如下&#xff1a; <?xml version"1.0" encoding"GBK"?> <crsc> <data><舉報信息反饋><R index"1"><舉報編號>1</舉報編號><狀態>1</狀態><答復意見>填寫…

網絡協議分析 | 應用層:HTTP協議詳解、HTTP代理服務器

文章目錄概念URLHTTP協議的特點HTTP協議版本格式請求報文首行頭部空行正文響應報文首行頭部空行正文Cookie與SessionHTTP代理服務器正向代理服務器反向代理服務器透明代理服務器概念 先了解一下 因特網&#xff08;Internet&#xff09; 與 萬維網&#xff08;World Wide Web&…

MySQL命令(一)| 數據類型、常用命令一覽、庫的操作、表的操作

文章目錄數據類型數值類型字符串類型日期/時間類型常用命令一覽庫的操作顯示當前數據庫創建數據庫使用數據庫刪除數據庫表的操作創建表顯示當前庫中所有表查看表結構刪除表數據類型 mysql 的數據類型主要分為 數值類型、日期/時間類型、字符串類型 三種。 數值類型 數值類型可…

C++ 繼承 | 對象切割、菱形繼承、虛繼承、對象組合

文章目錄繼承繼承的概念繼承方式及權限using改變成員的訪問權限基類與派生類的賦值轉換回避虛函數機制派生類的默認成員函數友元與靜態成員多繼承菱形繼承虛繼承組合繼承 繼承的概念 繼承可以使得子類具有父類的屬性和方法或者重新定義、追加屬性和方法等。 當創建一個類時&…

博弈論 | 博弈論簡談、常見的博弈定律、巴什博弈

文章目錄博弈論什么是博弈論&#xff1f;博弈的前提博弈的要素博弈的分類非合作博弈——有限兩人博弈囚徒困境合作博弈——無限多人博弈囚徒困境常見的博弈定律零和博弈重復博弈智豬博弈斗雞博弈獵鹿博弈蜈蚣博弈酒吧博弈槍手博弈警匪博弈海盜分金巴什博弈博弈論 什么是博弈論…

MySQL命令(二)| 表的增刪查改、聚合函數(復合函數)、聯合查詢

文章目錄新增 (Create)全列插入指定列插入查詢 (Retrieve)全列查詢指定列查詢條件查詢關系元素運算符模糊查詢分頁查詢去重&#xff1a;DISTINCT別名&#xff1a;AS升序 or 降序更新 (Update)刪除 (Delete)分組&#xff08;GROUP BY&#xff09;聯合查詢內連接&#xff08;inne…

Spring3.1+Quertz1.8實現多個計劃任務

1.主要是配置文件&#xff1a;如下&#xff1a;(這里說明一下主要是看紅色部分的配置&#xff0c;其他的可以根據自己的實際情況修改&#xff0c;這里只是個思路。) <?xml version"1.0"?> <beans xmlns"http://www.springframework.org/schema/beans…

MySQL | 數據庫的六種約束、表的關系、三大范式

文章目錄數據庫約束NOT NULL&#xff08;非空約束&#xff09;UNIQUE&#xff08;唯一約束&#xff09;DEFAULT&#xff08;缺省約束&#xff09;PRIMARY KEY&#xff08;主鍵約束&#xff09;AUTO_INCREMENT 自增FOREIGN KEY&#xff08;外鍵約束&#xff09;CHECK&#xff08…

哈希 :哈希沖突、負載因子、哈希函數、哈希表、哈希桶

文章目錄哈希哈希&#xff08;散列&#xff09;函數常見的哈希函數字符串哈希函數哈希沖突閉散列&#xff08;開放地址法&#xff09;開散列&#xff08;鏈地址法/拉鏈法&#xff09;負載因子以及增容對于閉散列對于開散列結構具體實現哈希表&#xff08;閉散列&#xff09;創建…

C++ 泛型編程(一):模板基礎:函數模板、類模板、模板推演成函數的機制、模板實例化、模板匹配規則

文章目錄泛型編程函數模板函數模板實例化隱式實例化顯式實例化函數模板的匹配規則類模板類模板的實例化泛型編程 泛型編程旨在削減重復工作&#xff0c;如&#xff1a; 將一個函數多次重載不如將他寫成泛型。 void Swap(int& left, int& right) {int temp left;lef…

你真的了解靜態變量、常量的存儲位置嗎?

文章目錄引言C對內存的劃分如何落實在Linux上自由存儲區和堆之間的問題棧常量區靜態存儲區靜態局部變量靜態局部變量、靜態全局變量、全局變量的異同macOS系統的測試結果總結引言 在動態內存的博客中&#xff0c;我提到&#xff1a; 在Linux 內存管理的博客中&#xff0c;我提…

C++ 泛型編程(二):非類型模板參數,模板特化,模板的分離編譯

文章目錄非類型模板參數函數模板的特化類模板的特化全特化偏特化部分參數特化參數修飾特化模板分離編譯解決方法非類型模板參數 模板的參數分為兩種&#xff1a; 類型參數&#xff1a; 則是我們通常使用的方式&#xff0c;就是在模板的參數列表中在 class 后面加上參數的類型…

Java操作——獲取文件擴展名,去掉文件擴展名

昨天收郵件&#xff0c;得知要參加一個產品部的會議&#xff0c;猜想&#xff0c;也許是因為我做的這個產品demo問題。于是昨天忙活到凌晨3點半&#xff0c;結果早上一來才知道又被調戲了。發郵件的MM把郵件誤發給我了。悲催啊有木有&#xff0c;困啊有木有&#xff01;自己還是…

數據結構 | B樹、B+樹、B*樹

文章目錄搜索結構B樹B樹的插入B樹的遍歷B樹的性能B樹B樹的插入B樹的遍歷B*樹B*樹的插入總結搜索結構 如果我們有大量的數據需要永久存儲&#xff0c;就需要存儲到硬盤之中。但是硬盤的訪問速度遠遠小于內存&#xff0c;并且由于數據量過大&#xff0c;無法一次性加載到內存中。…

MySQL 索引 :哈希索引、B+樹索引、全文索引

文章目錄索引引言常見的索引哈希索引自適應哈希索引B樹索引聚集索引非聚集索引使用方法聯合索引最左前綴匹配規則覆蓋索引全文索引使用方法索引 引言 為什么需要索引&#xff1f; 倘若不使用索引&#xff0c;查找數據時&#xff0c;MySQL必須遍歷整個表。而表越大&#xff0c;…

服裝店怎么引流和吸引顧客 服裝店鋪收銀系統來配合

實體店的同城引流和經營是實體經濟的一個重要的一環&#xff0c;今天我們來分享服裝行業的實體店鋪怎么引流和吸引、留住顧客&#xff0c;并實現復購。大家點個收藏&#xff0c;不然劃走就再也找不到了&#xff0c;另外可以點個關注&#xff0c;下次有新的更好的招&#xff0c;…

約瑟夫環(丟手絹問題)

文章目錄問題描述思路代碼實現問題描述 有 1~N 個數字&#xff0c;從 1~m 依次報數&#xff0c;數到 m 的數字要被刪掉&#xff0c;求最后剩下的數字是&#xff1f; 思路 第一次報數第二次報數1n-m12n-m2……m-2n-2m-1n-1m被刪掉了m11m22……n-1n-1-mnn-m 通過上面的表格&…

MySQL 鎖的相關知識 | lock與latch、鎖的類型、簡談MVCC、鎖算法、死鎖、鎖升級

文章目錄lock與latch鎖的類型MVCC一致性非鎖定讀&#xff08;快照讀&#xff09;一致性鎖定讀&#xff08;當前讀&#xff09;鎖算法死鎖鎖升級lock與latch 在了解數據庫鎖之前&#xff0c;首先就要區分開 lock 和 latch。在數據庫中&#xff0c;lock 和 latch 雖然都是鎖&…