進程間的IPC通信機制

一、介紹

進程與進程間的用戶空間相互獨立,內核空間共享。

1.傳統的進程間通信機制

? ? ? ? a.無名管道 pipe

? ? ? ? b.有名管道 fifo

? ? ? ? c.信號? ? ? ? ?signal

2.system V中的IPC對象

? ? ? ? a.消息隊列 message queue

? ? ? ? b.共享內存 shared memory

? ? ? ? c.信號燈集 semaphoare

3.可用于跨主機傳輸的通信機制

? ? ? ? a.套接字 socket

二、管道

1.管道可以看成是一個特殊文件,一般文件存儲在外存中,而管道內容存儲在內存中

2.管道遵循先進先出原則

3.管道的讀操作是一次性的,內容被讀出后就會從管道中刪除

4.管道是一種半雙工的通信方式

5.管道只能使用文件IO函數,因為需要直接操作內核空間,如open,close,read,write,但不能使用lseek

6.管道的大小為64k

2.1無名管道

無名管道即在文件系統(用戶系統)不可見的管道文件

無名管道不可以用open打開,因為不知道路徑以及名字

無名管道只能用于具有親緣關系的進程間通信。由于無名管道在文件系統中不可見,兩個無關的進程,無法拿到同一根管道的讀寫段,只有具有親緣關系的進程,在父進程中創建一根管道,拿到讀寫端后,調用fork函數,創建出來的子進程也會有該管道的讀寫端。

從管道中讀取數據:
1.讀寫端均存在時,當管道中沒有數據時,read會阻塞

2.當管道的寫端不存在時,若管道中有數據,會先將數據讀取完畢,沒有數據時,read函數不會阻塞,直接返回0

向管道中寫入數據:

1.讀寫段均存在時,write會阻塞

2.當管道的讀端不存在時,調用write函數,嘗試向管道中寫入數據會導致管道破裂。

#include <head.h>
int main(int argc, char const *argv[])
{// 管道的創建必須放在fork前// 若放在fork后,會導致父子進程各自創建一個內管道,無法通信int pfd[2] = {0};if (pipe(pfd) < 0) // pf[0]為讀的文件描述符,pf[1]為寫的文件描述符{perror("pipe");return -1;}printf("管道創建成功\n");pid_t pid = fork();if (pid > 0){// 父進程發數據給子進程char buf[128] = "";while (1){fgets(buf, sizeof(buf), stdin);buf[strlen(buf) - 1] = 0; // 從終端獲取數據,將最后獲取到的\n變成\0// 將數據寫入到管道中if (write(pfd[1], buf, sizeof(buf)) < 0){perror("write");return -1;}printf("寫入成功\n");}}else if (pid == 0){// 子進程接收父進程發送過來的數據char buf[128] = "";int res = 0;while (1){// 管道中沒有數據時,read會阻塞res = read(pfd[0], buf, sizeof(buf));printf("讀取成功\n");printf("%s\n", buf);}}else{perror("fork");return -1;}return 0;
}

?2.2有名管道

寫端

#include <head.h>
int main(int argc, char const *argv[])
{umask(0);// 創建有名管道if (mkfifo("./myfifo", 0664) < 0){if (errno != 17){ // 文件已存在的錯誤是一個合法的錯誤,需要排除,代碼允許正常運行perror("mkfifo");return -1;}}printf("有名管道創建成功\n");// 以只寫的方式打開有名管道int fd = open("./myfifo", O_WRONLY); // 當只有一個寫端時,open函數會阻塞if (fd < 0){perror("open");return -1;}printf("open succcess\n");char buf[128] = "";while (1){printf("請輸入>>>");fgets(buf, sizeof(buf), stdin);buf[strlen(buf) - 1] = 0;if (write(fd, buf, sizeof(buf)) < 0){perror("write");return -1;}if (strcmp(buf, "quit") == 0)break;printf("寫入成功\n");}close(fd);return 0;
}

讀端

#include <head.h>
int main(int argc, char const *argv[])
{umask(0);// 創建有名管道if (mkfifo("./myfifo", 0664) < 0){if (errno != 17){ // 文件已存在的錯誤是一個合法的錯誤,需要排除,代碼允許正常運行perror("mkfifo");return -1;}}printf("有名管道創建成功\n");// 以只讀的方式打開有名管道int fd = open("./myfifo", O_RDONLY); // 當只有一個讀端時,open函數會阻塞if (fd < 0){perror("open");return -1;}printf("open succcess\n");char buf[128] = "";int res = 0;while (1){bzero(buf, sizeof(buf));res = read(fd, buf, sizeof(buf));if (res < 0){perror("read");return -1;}else if ((res == 0) || strcmp(buf, "quit") == 0){printf("寫端退出\n");break;}printf("buf=%s\n", buf);}close(fd);return 0;
}

三、信號

原理

信號是一種異步通信的方式

異步:任務與任務之間無關系,根據CPU輪詢機制來運行多個任務

同步:任務與任務之間有先后關系,必須要等任務A結束2后才能執行任務B

1.signal

#include <head.h>void handler(int sig)
{printf("sig=%d\n", sig);return;
}
int main(int argc, char const *argv[])
{// 捕獲2)SIGINT信號if (signal(2, handler) == SIG_ERR)//第一個參數:指定要捕獲的信號,天對應的編號或宏//第二個參數:可以填SIG_IGN:忽略信號//SIG_DFL:執行默認操作//捕獲信號信號:填寫函數指針變量{perror("signal");return -1;}printf("捕獲信號成功\n");while (1){printf("主函數\n");sleep(1);}return 0;
}

?

練習:用信號的方式回收僵尸進程

#include <head.h>
int count = 0;void handler(int sig)
{while (waitpid(-1, NULL, WNOHANG) > 0);
}
int main(int argc, char const *argv[])
{// 捕獲17)SIGCHLD__sighandler_t s = signal(17, handler);if (SIG_ERR == s){perror("signal");return -1;}int i = 0;while (i < 100){int res = fork();if (res == 0)exit(0);i++;}while (1)sleep(1);return 0;
}

2.kill

當收到quit時,父子進程全部退出

#include <head.h>
int main(int argc, char const *argv[])
{pid_t pid = fork();if (pid > 0){while (1){printf("父進程 %d %d\n", getpid(), pid);sleep(1);}}else if (pid == 0){char buf[128] = "";bzero(buf, sizeof(buf));while (1){printf("請輸入>>>");fgets(buf, sizeof(buf), stdin);buf[strlen(buf) - 1] = 0;printf("buf=%s", buf);if (strcmp(buf, "quit") == 0){break;}}// 子進程給父進程發信號,請求父進程退出kill(getppid(), 9); // 9號是殺死信號}else{perror("fork");return -1;}return 0;
}

3.alarm

設置3秒的定時器

#include <head.h>
void callback(int sig)
{printf("超時了\n");alarm(3);return;
}
int main(int argc, char const *argv[])
{// 捕獲14號信號if (signal(14, callback) == SIG_ERR){perror("signal");return -1;}alarm(3);while (1){printf("signal....\n");sleep(1);}return 0;
}

四、消息隊列

消息隊列按照先進先出的原則,但也可以限制消息類型讀取

消息隊列獨立于進程,等進程結束后,消息隊列以及其中的內容不會刪除,除非重啟操作系統或手動刪除

發送數據

#include <head.h>
struct msgbuf
{long mtype;      // 消息類型,必須大于0char mtext[128]; // 消息內容
};
int main(int argc, char const *argv[])
{// 創建key值key_t key = ftok("/home/ubuntu/", 1);// 第二個參數:填非0if (key < 0){perror("ftok");return -1;}// 創建消息隊列int msqid = msgget(key, IPC_CREAT | 0664);if (msqid < 0){perror("msgget");return -1;}struct msgbuf sndbuf;while (1){printf("請輸入人消息類型>>>");scanf("%ld", &sndbuf.mtype);getchar();if (sndbuf.mtype == 0){ // 若輸入類型為0,退出循環break;}printf("請輸入消息內容>>>");fgets(sndbuf.mtext, sizeof(sndbuf.mtext), stdin);sndbuf.mtext[strlen(sndbuf.mtext) - 1] = 0;// 向消息隊列中發送數據if (msgsnd(msqid, &sndbuf, sizeof(sndbuf.mtext), 0) < 0){perror("msgsnd");return -1;}printf("發送成功\n");}// 刪除消息隊列if (msgctl(msqid, IPC_RMID, NULL) < 0){perror("msgctl");return -1;}printf("刪除消息隊列成功\n");return 0;
}

?

接收數據

#include <head.h>
struct msgbuf
{long mtype;      // 消息類型,必須大于0char mtext[128]; // 消息內容
};
int main(int argc, char const *argv[])
{// 創建key值key_t key = ftok("/home/ubuntu/", 1);// 第二個參數:填非0if (key < 0){perror("ftok");return -1;}// 創建消息隊列int msqid = msgget(key, IPC_CREAT | 0664);if (msqid < 0){perror("msgget");return -1;}struct msgbuf recvbuf;int res = 0;while (1){// 從指定的消息隊列中讀取數據// 讀取消息隊列中的第一條消息,先進先出res = msgrcv(msqid, &recvbuf, sizeof(recvbuf.mtext), 0, IPC_NOWAIT);if (res < 0){perror("msgrcv");return -1;}printf("接收到的消息為%s\n", recvbuf.mtext);}// 刪除消息隊列if (msgctl(msqid, IPC_RMID, NULL) < 0){perror("msgctl");return -1;}printf("刪除消息隊列成功\n");return 0;
}

五、共享內存

共享內存是最高效的進程間通信方式

多個進程可以同時訪問共享內存,修改其中的內容,所以共享內存其實是臨界資源,需要注意進程間的同步互斥

共享內存獨立于進程,等進程結束后,共享內存以及其中的內容不會刪除,除非重啟操作系統或者手動刪除

發送數據

#include <head.h>
int main(int argc, char const *argv[])
{// 創建key值key_t key = ftok("./", 10);if (key < 0){perror("ftok");return -1;}printf("key=%#x\n", key);// 創建共享內存,獲得shmid號int shmid = shmget(key, 32, IPC_CREAT | 0664);if (shmid < 0){perror("shmget");return -1;}printf("shmid=%d\n", shmid);// 映射共享內存到用戶空間void *addr = shmat(shmid, NULL, 0);if (addr == (void *)-1){perror("shmat");return -1;}// 先往共享內存中存儲一個int類型的數據*(int *)addr = 10;// 再往int類型數據后面存儲一個字符串char *ptr = (char *)addr + 4;strcpy(ptr, "hello world");return 0;
}

接收數據

#include <head.h>
int main(int argc, char const *argv[])
{// 創建key值key_t key = ftok("./", 10);if (key < 0){perror("ftok");return -1;}// 創建共享內存,獲得shmid號int shmid = shmget(key, 32, IPC_CREAT | 0664);if (shmid < 0){perror("shmget");return -1;}// 映射共享內存到用戶空間void *addr = shmat(shmid, NULL, 0);if (addr == (void *)-1){perror("shmat");return -1;}printf("%d\n", *(int *)addr);printf("%s\n", (char *)((int *)addr + 1));return 0;
}

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

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

相關文章

vue前端時間段選擇控件

實現效果: 可選具體的某天的某時某分某秒 vue前端代碼: <el-form-item label"日期"><el-date-pickerv-model"daterangerq"style"width: 240px"value-format"yyyy-MM-dd HH:mm:ss"type"datetimerange"range-separat…

JetsonNano —— 3、在Nano板卡編譯可硬件加速FFmpeg,測試FFmpeg調用nvmpi編解碼器加速

最終FFmpeg運行加速效果如下: FFmpeg 簡介 一個完整的跨平臺解決方案,用于錄制、轉換和流式傳輸音頻和視頻。 ? JetsonNano 簡介 NVIDIA Jetson Nano為數百萬臺高性能、低功耗設備提供前所未有的功能。這項技術創新為網絡錄像機、機器人或具有高級分析功能的智能家居網關等…

基于SPWM控制策略的二極管鉗位型NPC逆變器的并網simulink仿真

本人搭建了二極管鉗位型NPC并網逆變器simulink仿真模型&#xff0c;該模型型采用d、q軸&#xff0c;電壓前饋解耦控制&#xff0c;三相逆變并網&#xff0c;PI控制&#xff0c;仿真復現&#xff0c;效果優異&#xff0c;適合新手學習使用。 模型獲取鏈接&#xff1a;基于SPWM…

生成式AI崗位需求暴漲,可以入行嗎?

過去一年多來&#xff0c;人工智能應用的爆發&#xff0c;隨之生成式AI應用暴增&#xff0c;也使得相關人才需求“水漲船高”。 獵聘大數據顯示&#xff0c;2024年一季度&#xff0c;AIGC相關職位同比增長321.70%&#xff0c;呈現急劇增長態勢。同時&#xff0c;投遞該領域的人…

【MySQL探索之旅】JDBC (Java連接MySQL數據庫)

&#x1f4da;博客主頁&#xff1a;愛敲代碼的小楊. ?專欄&#xff1a;《Java SE語法》 | 《數據結構與算法》 | 《C生萬物》 |《MySQL探索之旅》 |《Web世界探險家》 ??感謝大家點贊&#x1f44d;&#x1f3fb;收藏?評論?&#x1f3fb;&#xff0c;您的三連就是我持續更…

探索免費靜態IP海外的奧秘

在數字化時代&#xff0c;網絡資源的獲取和利用對于個人和企業都至關重要。其中&#xff0c;獨立靜態IP地址更是因其穩定性和安全性備受青睞。本文將帶您深入了解“免費的獨立靜態IP海外”的奧秘&#xff0c;探討其背后的原理、優勢、獲取途徑以及使用場景。 一、獨立靜態IP的基…

XEChat-Idea:摸魚神器!!【送源碼】

XEChat-Idea ? 基于Netty的IDEA即時聊天插件 ? 項目介紹 主要功能&#xff1a; 即時聊天 游戲對戰 即時聊天 idea摸魚工具 idea斗地主 項目結構 . ├── LICENSE ├── README.md ├── xechat-commons //公共模塊 │ ├── pom.xml │ └── src ├── xech…

文本分類的深度注意圖擴散網絡 筆記

1 Title Deep Attention Diffusion Graph Neural Networks for Text Classification&#xff08;Yonghao Liu、Renchu Guan、Fausto Giunchiglia、Yanchun Liang、Xiaoyue Feng&#xff09;【EMnlp 2021】 2 Conclusion Text classification is a fundamental task with broad…

Linux-- 重定向緩沖區

目錄 0.接上篇文章 1.粗略的見一下這兩個問題 2.理解重定向 3.理解緩沖區 0.接上篇文章 Linux--基礎IO&#xff08;文件描述符fd&#xff09;-CSDN博客 1.粗略的見一下這兩個問題 先來了解幾個函數&#xff1a; stat()函數用于獲取指定文件或符號鏈接的元數據。如果文件是…

Android 系統省電軟件分析

1、硬件耗電 主要有&#xff1a; 1、屏幕 2、CPU 3、WLAN 4、感應器 5、GPS(目前我們沒有) 電量其實是目前手持設備最寶貴的資源之一&#xff0c;大多數設備都需要不斷的充電來維持繼續使用。不幸的是&#xff0c;對于開發者來說&#xff0c;電量優化是他們最后才會考慮的的事情…

排序實現題目:排序數組

文章目錄 題目標題和出處難度題目描述要求示例數據范圍 前言冒泡排序原理示例代碼復雜度分析穩定性分析 選擇排序原理示例代碼復雜度分析穩定性分析 插入排序原理示例代碼復雜度分析穩定性分析 希爾排序原理示例代碼復雜度分析穩定性分析 歸并排序原理示例代碼復雜度分析穩定性…

Jackson如何禁止在反序列化字符串為對應java bean時,字符串中的null被反序列成為NullNode

直接說應用場景,json文件中有一個如下配置: [{"name":"John Doe","age":28,"jsonNode":null},{"name":"John1","age":31}] 待反序列化類定義如下所示: @Data static class TestClass {/*** 名字.*…

【C++】詳解STL的適配器容器之一:優先級隊列 priority_queue

目錄 堆算法 概述 向下調整建堆 向上調整建堆 建堆算法 仿函數 概述 使用介紹 emtpy size top push pop 模擬實現 仿函數 框架 向下調整算法 向上調整算法 pop push empty top 要理解優先級隊列&#xff0c;需要有如下知識 STL容器之一的vector&#xf…

聚類分析 | 基于GA遺傳算法優化kmeans聚類(Matlab)

聚類分析 | 基于GA遺傳算法優化kmeans聚類&#xff08;Matlab&#xff09; 目錄 聚類分析 | 基于GA遺傳算法優化kmeans聚類&#xff08;Matlab&#xff09;效果一覽基本介紹程序設計參考資料 效果一覽 基本介紹 GA-kmeans聚類算法&#xff0c;通過GA遺傳算法優化kmeans聚類&…

序列化的不同格式:JSON、XML、TOML、CSON、YAML

前言 這篇文章參考于知乎&#xff0c;進行了一些總結。 正文 首先什么是序列化&#xff0c;數據序列化是從一個系統獲取一些信息&#xff0c;將其轉換為其它系統可以讀取的格式&#xff0c;然后將其傳遞給其它系統的過程。也就是可以讓不同系統“通信”。 序列化需要滿足兩…

JetPack Compose Navigation

1. 導入依賴 implementation("androidx.navigation:navigation-compose:2.7.7") 2.kotlin編譯版本升級 composeOptions {kotlinCompilerExtensionVersion "1.5.0"} 3.插件版本升級 // Top-level build file where you can add configuration options c…

學習筆記:IEEE 1003.13-2003【POSIX PSE51接口列表】

一、POSIX PSE51接口列表 根據IEEE 1003.13-2003&#xff0c;整理了POSIX PSE51接口API&#xff08;一共286個&#xff09;&#xff0c;每個API支持鏈接查看。 IEEE POSIX接口online搜索鏈接&#xff1a; The Open Group Base Specifications Issue 7, 2018 edition 詳細內…

【python】模塊與包

Python中的模塊和包是組織和管理代碼的重要工具。通過模塊和包&#xff0c;你可以更好地管理和重用你的代碼&#xff0c;使得代碼更加模塊化和可維護。 目錄 前言 正文 一、模塊 1、模塊的分類 1&#xff09;內置模塊 python解釋器中默認擁有的模塊可以直接使用&#xff08;…

用戶需求甄別和篩選的6大標準

產品經理日常經常接收到大量的需求&#xff0c;并不是所有的需求都需要開發&#xff0c;需要進行甄別和篩選&#xff0c;這樣有利于確保項目的成功、優化資源利用以及提高產品質量。 那么針對這些用戶需求進行甄別或篩選的評判標準是什么&#xff1f;需求篩選可以說是初步的需求…

代碼隨想錄-算法訓練營day31【貪心算法01:理論基礎、分發餅干、擺動序列、最大子序和】

代碼隨想錄-035期-算法訓練營【博客筆記匯總表】-CSDN博客 第八章 貪心算法 part01● 理論基礎 ● 455.分發餅干 ● 376. 擺動序列 ● 53. 最大子序和 貪心算法其實就是沒有什么規律可言&#xff0c;所以大家了解貪心算法 就了解它沒有規律的本質就夠了。 不用花心思去研究其…