中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

太原網(wǎng)站推廣服務(wù)seo推廣seo技術(shù)培訓(xùn)

太原網(wǎng)站推廣服務(wù),seo推廣seo技術(shù)培訓(xùn),重慶網(wǎng)站建設(shè) 制作 設(shè)計(jì) 優(yōu)惠價(jià),wordpress 角色管理文章目錄 一、管道1. 匿名管道2. 命名管道 進(jìn)程具有獨(dú)立性,因此進(jìn)程間通信的前提是兩個(gè)進(jìn)程能看到同一份資源 一、管道 對(duì)于進(jìn)程打開的內(nèi)存文件,操作系統(tǒng)是以引用計(jì)數(shù)的方式創(chuàng)建的 file 結(jié)構(gòu)體,如果讓兩個(gè)進(jìn)程與同一個(gè) file 結(jié)構(gòu)體關(guān)聯(lián)&…

文章目錄

  • 一、管道
    • 1. 匿名管道
    • 2. 命名管道

進(jìn)程具有獨(dú)立性,因此進(jìn)程間通信的前提是兩個(gè)進(jìn)程能看到同一份資源

一、管道

對(duì)于進(jìn)程打開的內(nèi)存文件,操作系統(tǒng)是以引用計(jì)數(shù)的方式創(chuàng)建的 file 結(jié)構(gòu)體,如果讓兩個(gè)進(jìn)程與同一個(gè) file 結(jié)構(gòu)體關(guān)聯(lián),便可以讓兩個(gè)進(jìn)程看到同一份資源

由于 file 結(jié)構(gòu)體的緩沖區(qū)只有一個(gè),因此只能讓一個(gè)進(jìn)程以寫的方式,另一個(gè)進(jìn)程以讀的方式打開同一個(gè)文件,這樣便實(shí)現(xiàn)了單向的進(jìn)程間通信
在這里插入圖片描述
操作系統(tǒng)提供了僅在內(nèi)存中創(chuàng)建 file 結(jié)構(gòu)體(不在磁盤上創(chuàng)建對(duì)應(yīng)的文件),這種特殊的文件稱為管道文件,其中沒(méi)有名字的稱為 匿名管道,有名字的稱為 命名管道

1. 匿名管道

進(jìn)程創(chuàng)建匿名管道成功后,會(huì)以讀和寫兩種方式打開管道文件,因此匿名管道通常用于父子進(jìn)程的進(jìn)程間通信

系統(tǒng)調(diào)用 pipe,頭文件 unistd.h

  • int pipe(int pipefd[2]),創(chuàng)建匿名管道

返回值:匿名管道創(chuàng)建成功返回 0,出錯(cuò)返回 -1,并且 errno 被設(shè)置為相應(yīng)的出錯(cuò)信息

參數(shù):pipefd 為輸出型參數(shù),pipefd[0] 存儲(chǔ)讀端文件描述符,pipefd[1] 存儲(chǔ)寫端文件描述符

父子進(jìn)程通信的步驟:

  • 父進(jìn)程創(chuàng)建管道
    父進(jìn)程以讀和寫兩種方式打開管道文件
  • 創(chuàng)建子進(jìn)程
    子進(jìn)程會(huì)拷貝父進(jìn)程的文件描述符表,因此子進(jìn)程也會(huì)以讀和寫兩種方式打開同一個(gè)管道文件
  • 父進(jìn)程和子進(jìn)程分別關(guān)閉自己不需要的讀端或?qū)懚?/strong>
    一個(gè)進(jìn)程向管道中寫入,另一個(gè)進(jìn)程從管道中讀取

子進(jìn)程向匿名管道寫入,父進(jìn)程從匿名管道讀取

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cerrno>
#include <cassert>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>using namespace std;int main()
{// 創(chuàng)建匿名管道// pipefd[0] 表示讀// pipefd[1] 表示寫int pipefd[2] = { 0 };if (pipe(pipefd) < 0){// 創(chuàng)建匿名管道失敗cout << "匿名管道創(chuàng)建失敗: " << errno << " " << strerror(errno) << endl;exit(1);}// 創(chuàng)建子進(jìn)程pid_t id = fork();assert(id != -1);if (id == 0){// 子進(jìn)程向匿名管道寫入,需要關(guān)閉讀close(pipefd[0]);// 開始通信int cnt = 0;char buffer[64];while (true){snprintf(buffer, sizeof(buffer), "我是子進(jìn)程,這是我給你發(fā)的第 %d 個(gè)信息", ++cnt);// 向匿名管道中寫入write(pipefd[1], buffer, strlen(buffer));cout << cnt << endl;// sleep(1); // 讓寫端慢一點(diǎn)// if (cnt == 3) break; // 模擬寫端關(guān)閉}close(pipefd[1]);exit(0);}// 父進(jìn)程從匿名管道讀取,需要關(guān)閉寫close(pipefd[1]);// 開始通信char buffer[64];while (true){// 從匿名管道中讀取// sleep(3); // 讓讀端慢一點(diǎn)// sleep(3); break; // 模擬讀端關(guān)閉int n = read(pipefd[0], buffer, sizeof(buffer) - 1);if (n > 0){        buffer[n] = '\0';cout << buffer << endl;}else if (n == 0){cout << "寫端已經(jīng)關(guān)閉,我讀到文件結(jié)尾了" << endl;break;}else{cout << "讀取錯(cuò)誤" << endl;break;}}close(pipefd[0]);// 讀端關(guān)閉,寫端會(huì)收到 13 號(hào)信號(hào) SIGPIPEint status;waitpid(id, &status, 0);cout << "子進(jìn)程退出信號(hào): " << (status & 0x7F) << endl;return 0;
}
  • 放開子進(jìn)程代碼中的 sleep(1),讓寫端慢一點(diǎn),匿名管道中沒(méi)有數(shù)據(jù)時(shí),讀端會(huì)等待寫端寫入
    在這里插入圖片描述
  • 放開父進(jìn)程中的 sleep(3),讓讀端慢一點(diǎn),匿名管道中寫滿數(shù)據(jù)時(shí),寫端會(huì)等待讀端讀取
    在這里插入圖片描述
  • 放開子進(jìn)程中模擬寫端關(guān)閉的代碼,并且讓寫端慢一點(diǎn),寫端關(guān)閉后,讀端讀取完匿名管道中的數(shù)據(jù)后,讀端會(huì)讀取到文件結(jié)尾
    在這里插入圖片描述
  • 放開子進(jìn)程中模擬讀端關(guān)閉的代碼,并且讓寫端慢一點(diǎn),讀端關(guān)閉時(shí),此時(shí)匿名管道無(wú)意義,操作系統(tǒng)會(huì)向?qū)懚税l(fā)送 SIGPIPE 13 號(hào)信號(hào)
    在這里插入圖片描述

命令行中的 | 即為匿名管道,| 會(huì)將前一個(gè)進(jìn)程的標(biāo)準(zhǔn)輸出重定向到匿名管道,后一個(gè)進(jìn)程的標(biāo)準(zhǔn)輸入重定向到匿名管道

在這里插入圖片描述

通過(guò)匿名管道創(chuàng)建進(jìn)程池:

// processpool.hpp
#include <iostream>
#include <vector>
#include <functional>
#include <cstring>
#include <cerrno>
#include <cassert>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>namespace starrycat
{class EndPoint{public:EndPoint(){}EndPoint(pid_t cid, int wfd) : _cid(cid), _wfd(wfd){}~EndPoint(){}public:pid_t _cid;int _wfd;};const int NUM = 5;class ProcessPool{using fun_t = std::function<void(int)>;public:ProcessPool(fun_t Command, int num = NUM){std::vector<int> tmpfd; // 保存子進(jìn)程不需要的父進(jìn)程的文件描述符for (int i = 0; i < num; ++i){// 創(chuàng)建管道int pipefd[2] = {0};if (pipe(pipefd) < 0){std::cout << "創(chuàng)建管道失敗: " << errno << " " << strerror(errno) << std::endl;exit(1);}// 創(chuàng)建子進(jìn)程int id = fork();assert(id != -1);if (id == 0){// 子進(jìn)程從管道中讀取,需要關(guān)閉寫close(pipefd[1]);for (auto e : tmpfd) close(e); // 關(guān)閉不需要的文件描述符// 開始通信while (true){// 讀取四字節(jié)整數(shù)的命令int cmd = 0;int n = read(pipefd[0], &cmd, sizeof(int));if (n == sizeof(int)){// 測(cè)試std::cout << getpid() << " ";// 執(zhí)行命令Command(cmd);}else if (n == 0){// 測(cè)試std::cout << getpid() << " 讀取到文件結(jié)尾了" << std::endl;break;}else{std::cout << "讀取異常" << std::endl;break;}}close(pipefd[0]);exit(0);}// 父進(jìn)程向管道中寫入,需要關(guān)閉讀close(pipefd[0]);_endPoints.push_back(EndPoint(id, pipefd[1]));tmpfd.push_back(pipefd[1]);}}ProcessPool(const ProcessPool &p) = delete;ProcessPool &operator=(const ProcessPool &p) = delete;~ProcessPool(){for (auto& e : _endPoints) {close(e._wfd);waitpid(e._cid, nullptr, 0);// 測(cè)試std::cout << "等待子進(jìn)程:" << e._cid  << "成功" << std::endl;sleep(1);}}// 規(guī)定命令為四字節(jié)整數(shù)void push(int command){// 以輪訓(xùn)的方式調(diào)用子進(jìn)程static int index = 0;write(_endPoints[index]._wfd, &command, sizeof(int));index++;index %= _endPoints.size();}private:std::vector<EndPoint> _endPoints;};
}// myctrlprocess.cc
#include "processpool.hpp"
#include <iostream>
#include <string>using namespace std;// 子進(jìn)程個(gè)數(shù)
const int num = 5;void PrintLog()
{cout << "打印日志任務(wù),正在被執(zhí)行..." << endl;
}void InsertMySQL()
{cout << "執(zhí)行數(shù)據(jù)庫(kù)任務(wù),正在被執(zhí)行..." << endl;
}void NetQuest()
{cout << "執(zhí)行網(wǎng)絡(luò)請(qǐng)求任務(wù),正在被執(zhí)行..." << endl;
}void CommandError()
{cout << "任務(wù)不存在" << endl;
}void Command(int cmd)
{switch (cmd){case 0:PrintLog();break;case 1:InsertMySQL();break;case 2:NetQuest();break;default:CommandError();break;}
}int main()
{starrycat::ProcessPool ppool(Command);int command = 0;while (true){cout << "請(qǐng)輸入命令: ";cin >> command;// 測(cè)試if (command == -1) break;ppool.push(command);sleep(1);}return 0;
}

2. 命名管道

命名管道支持兩個(gè)毫不相關(guān)的進(jìn)程通信,其使用和文件一樣

系統(tǒng)調(diào)用 mkfifo,頭文件 sys/types.h、sys/stat.h

  • int mkfifo(const char *pathname, mode_t mode),創(chuàng)建命名管道

返回值:命名管道創(chuàng)建成功返回 0,出錯(cuò)返回 -1,并且 errno 被設(shè)置為相應(yīng)的出錯(cuò)信息

參數(shù):

  • pathname 表示創(chuàng)建命名管道的路徑名(如果只有文件名,則表示在進(jìn)程所在的路徑下創(chuàng)建)
  • mode 表示創(chuàng)建命名管道的文件權(quán)限,受 umask 影響

客戶端向命名管道寫入,服務(wù)端從命名管道讀取

// namepipe.h
#pragma once// 命名管道文件名
const char* const fifoname = "fifo";// client.cc
#include "namepipe.h"
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cerrno>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>using namespace std;int main()
{// 以寫方式打開命名管道int wfd = open(fifoname, O_WRONLY);if (wfd < 0){cout << "打開文件失敗" << errno << " " << strerror(errno) << endl;exit(1);}// 開始通信char buffer[1024];while (true){cout << "請(qǐng)輸入: ";char* str = fgets(buffer, sizeof(buffer), stdin);if (str == NULL){cout << "客戶端退出" << endl;break;}buffer[strlen(buffer) - 1] = '\0'; // 去掉輸入的回車符// 輸入 quit 表示客戶端退出if(strcmp(buffer, "quit") == 0) {cout << "客戶端退出" << endl;break;}// 向命名管道寫入write(wfd,  buffer, strlen(buffer));}close(wfd);return 0;
}// server.cc
#include "namepipe.h"
#include <iostream>
#include <cerrno>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>using namespace std;int main()
{// 創(chuàng)建命名管道umask(0);  // 設(shè)置進(jìn)程的權(quán)限掩碼if (mkfifo(fifoname, 0666) < 0){cout << "創(chuàng)建管道失敗: " << errno << " " << strerror(errno) << endl;exit(1);}// 以讀方式打開命名管道int rfd = open(fifoname, O_RDONLY);if (rfd < 0){cout << "打開文件失敗" << errno << " " << strerror(errno) << endl;}// 開始通信char buffer[1024];while (true){// 從命名管道讀取int n = read(rfd, buffer, sizeof(buffer) - 1);if (n > 0){buffer[n] = '\0';cout << "客戶端: " << buffer << endl;}else if (n == 0){cout << "客戶端退出了,服務(wù)端也退出" << endl;break;}else{cout << "讀取異常" << endl;break;}}close(rfd); unlink(fifoname); // 刪除命名管道return 0;
}

先啟動(dòng) myserver,在啟動(dòng) myclient

在這里插入圖片描述

命名管道和匿名管道的通信特性是一樣的

mkfifo 文件名
功能:創(chuàng)建命名管道

在這里插入圖片描述

http://www.risenshineclean.com/news/44469.html

相關(guān)文章:

  • wordpress 騰訊云成都外貿(mào)seo
  • 網(wǎng)站建設(shè)公司起名百度廣告聯(lián)盟怎么賺錢
  • 聊城做網(wǎng)站最好的網(wǎng)絡(luò)公司哪里有永久免費(fèi)建站
  • 網(wǎng)站建設(shè)進(jìn)什么分錄百度賬號(hào)一鍵登錄
  • 政府網(wǎng)站建設(shè)意見(jiàn)權(quán)威發(fā)布
  • 深圳高端網(wǎng)站制作公司線上推廣如何引流
  • 網(wǎng)站制作建設(shè)怎么收費(fèi)百度問(wèn)一問(wèn)付費(fèi)咨詢
  • 云購(gòu)網(wǎng)站開發(fā)百度建站云南服務(wù)中心
  • 有關(guān)做生態(tài)環(huán)境的官方網(wǎng)站小程序推廣引流
  • 網(wǎng)站用哪種語(yǔ)言簡(jiǎn)述提升關(guān)鍵詞排名的方法
  • 班級(jí)網(wǎng)站模板銷售找客戶的app
  • wordpress模板網(wǎng)站優(yōu)化大師免費(fèi)安裝下載
  • 網(wǎng)站建設(shè)費(fèi)做什么科目如何免費(fèi)發(fā)布廣告
  • 建設(shè)銀行信用卡網(wǎng)站登錄seo優(yōu)化方向
  • 企業(yè)頭像logo設(shè)計(jì)免費(fèi)seo免費(fèi)入門教程
  • wordpress文章采集插件信陽(yáng)搜索引擎優(yōu)化
  • 做中英文網(wǎng)站的合肥網(wǎng)站seo整站優(yōu)化
  • 做外貿(mào)英文網(wǎng)站網(wǎng)站推廣seo優(yōu)化
  • 24小時(shí)二手表網(wǎng)站小紅書搜索關(guān)鍵詞排名
  • 小型網(wǎng)絡(luò)公司是干嘛的深圳谷歌seo推廣
  • 網(wǎng)站開發(fā)需要的編程軟件杭州百度快速排名提升
  • dw網(wǎng)站制作效果怎么做html網(wǎng)頁(yè)制作模板
  • 企業(yè)網(wǎng)站色彩搭配手機(jī)怎么制作網(wǎng)站
  • 公司建站多少錢電腦優(yōu)化用什么軟件好
  • 自己做的網(wǎng)站如何在百度搜到自助建站官網(wǎng)
  • 移動(dòng)網(wǎng)站開發(fā)教程下載重慶seo報(bào)價(jià)
  • 怎么打開自己做的網(wǎng)站視頻剪輯培訓(xùn)
  • 網(wǎng)站 做實(shí)名認(rèn)證嗎域名注冊(cè)阿里云
  • 如何做cad圖紙模板下載網(wǎng)站軟文代寫多少錢一篇
  • 成都網(wǎng)站建設(shè)優(yōu)惠活動(dòng)免費(fèi)站長(zhǎng)統(tǒng)計(jì)工具