国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【Linux】匿名管道與命名管道,進程池的簡易實現(xiàn)

這篇具有很好參考價值的文章主要介紹了【Linux】匿名管道與命名管道,進程池的簡易實現(xiàn)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。


前言

一、匿名管道

#include <unistd.h>
功能:創(chuàng)建一無名管道
原型
int pipe(int fd[2]);
參數(shù):
fd:文件描述符數(shù)組,其中fd[0]表示讀端, fd[1]表示寫端
返回值:成功返回0,失敗返回錯誤代碼

1.管道原理

【Linux】匿名管道與命名管道,進程池的簡易實現(xiàn),linux,運維,服務器
【Linux】匿名管道與命名管道,進程池的簡易實現(xiàn),linux,運維,服務器

本質是先讓不同的進程看到同一份資源,也就是兩個進程都能對管道文件的緩沖區(qū)進行操作

這里我們pipe的時候,會使用兩個文件描述符,這兩個文件描述里面存的file結構體是同一個,也就是管道文件的file結構體,file結構體中存儲有inode以及系統(tǒng)緩沖區(qū),此時fork一個子進程,子進程有著和父進程一樣的結構,
這里有一個非常重要的點雖然子進程有著自己的進程地址空間,也有著自己存儲file結構體的指針數(shù)組,但是其數(shù)組里面的內容是和父進程一樣的,也就是子進程里面pipe對應的文件描述符位置指向的file結構體(管道文件)是同一個,至此我們父子進程就看到了同一個資源,可以利用這個資源進行通信

兩個不同的進程打開同一份文件的時候,在內核中,操作系統(tǒng)只會打開一個
【Linux】匿名管道與命名管道,進程池的簡易實現(xiàn),linux,運維,服務器

2.管道的四種情況

1.讀寫端正常,管道如果為空,讀端就要阻塞
讀寫端正常,管道如果被寫滿,寫端就要阻塞
2.讀端正常讀,寫端關閉,讀端就會讀到0,表明讀到了管道文件的結尾,不會被阻塞,如果我們打印讀端讀到的內容,顯示器會一直顯示0
3.寫端正常寫入,讀端關閉,操作系統(tǒng)會殺掉此時正在寫入的進程(通過信號來殺掉)
4.因為操作系統(tǒng)不會做低效,浪費的事情,我讀端都不讀了,你寫入再多數(shù)據(jù)到一個管道里面有什么用,因為管道不占用磁盤內存,所以程序結束后,就沒有管道的存在了。

當要寫入的數(shù)據(jù)量不大于PIPE_BUF時,linux將保證寫入的原子性。
當要寫入的數(shù)據(jù)量大于PIPE_BUF時,linux將不再保證寫入的原子性。

3.管道的特點

1.只能用于具有共同祖先的進程(具有親緣關系的進程)之間進行通信;通常,一個管道由一個進程創(chuàng)建,然后該進程調用fork,此后父、子進程之間就可應用該管道。
2.管道提供流式服務
3.一般而言,進程退出,管道釋放,所以管道的生命周期隨進程
4.一般而言,內核會對管道操作進行同步與互斥
5.管道是半雙工的,數(shù)據(jù)只能向一個方向流動;需要雙方通信時,需要建立起兩個管道

二、命名管道

1. 特點

1.管道應用的一個限制就是只能在具有共同祖先(具有親緣關系)的進程間通信。
2.如果我們想在不相關的進程之間交換數(shù)據(jù),可以使用FIFO文件來做這項工作,它經(jīng)常被稱為命名管道
3.命名管道是一種特殊類型的文件

2.創(chuàng)建命名管道

1.在命令行上

 mkfifo  +文件名

2.在程序中

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

int main(int argc, char *argv[])
{
 mkfifo("p2", 0644);
 return 0;
}

3.一個程序執(zhí)行打開管道并不會真正打卡

【Linux】匿名管道與命名管道,進程池的簡易實現(xiàn),linux,運維,服務器
【Linux】匿名管道與命名管道,進程池的簡易實現(xiàn),linux,運維,服務器

我們執(zhí)行這個程序發(fā)現(xiàn)并沒有打印那句話,說明管道文件并沒有真正打開,只有當我們執(zhí)行另一個我們要通信的文件的時候,管道才會真正打開
【Linux】匿名管道與命名管道,進程池的簡易實現(xiàn),linux,運維,服務器

三、進程池簡易實現(xiàn)

1.makefile

ProcessPool:ProcessPool.cpp
	g++ -o $@ $^ -std=c++11  -g

.PHONY:clean
clean:
	rm -rf ProcessPool

2.Task.hpp

 #pragma once
#include<functional>
 #include<vector>
 #include<iostream>
 using namespace std;
 

void task1()
{
    std::cout << "lol 刷新日志" << std::endl;
}
void task2()
{
    std::cout << "lol 更新野區(qū),刷新出來野怪" << std::endl;
}
void task3()
{
    std::cout << "lol 檢測軟件是否更新,如果需要,就提示用戶" << std::endl;
}
void task4()
{
    std::cout << "lol 用戶釋放技能,更新用的血量和藍量" << std::endl;
}


void LoadTask(vector<function<void()>>*tasks){
tasks->push_back(task1);
tasks->push_back(task2);
tasks->push_back(task3);
tasks->push_back(task4);
return ;
}

3.ProcessPool.cpp

【Linux】匿名管道與命名管道,進程池的簡易實現(xiàn),linux,運維,服務器

我們創(chuàng)建processnum個子進程,讓父進程來寫,子進程來讀,子進程讀到任務號后進行對應的處理。

#include <iostream>
#include "Task.hpp"
#include <assert.h>
#include <vector>
#include <string>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>

using namespace std;
vector<function<void()>> tasks;
const int processnum = 10;//創(chuàng)建的子進程數(shù)
class channel
{
public:
    channel(  string processname,  pid_t slaverid,int cmdcode)
        : _processname(processname), _cmdfd(cmdcode), _slaverid(slaverid)
    {
    }

public:
    string _processname;//執(zhí)行任務的進程名

    pid_t _slaverid;//執(zhí)行任務的進程pid

    int _cmdfd;//朝幾號管道去操作
};

void Menu()
{
    std::cout << "################################################" << std::endl;
    std::cout << "# 1. 刷新日志             2. 刷新出來野怪        #" << std::endl;
    std::cout << "# 3. 檢測軟件是否更新      4. 更新用的血量和藍量  #" << std::endl;
    std::cout << "#                         0. 退出               #" << std::endl;
    std::cout << "#################################################" << std::endl;
}

void slaver()
{
    int cmdcode;
    while (true)
    {
        int n = read(0, &cmdcode, sizeof(int));//讀取任務碼
        if (n == sizeof(int))
        {
            cout << "slaver say get a command " << getpid() << " cmdcode:  " << cmdcode << endl;
            if (cmdcode >= 0 && cmdcode < tasks.size())
                tasks[cmdcode]();//執(zhí)行任務
        }
        else if (n == 0)//為0,說明讀到文件末尾,之間break
            break;
    }
}
void InitProcessPool(vector<channel> *channels)
{
    for (int i = 0; i < processnum; i++)
    {
        int pipefd[2] = {0};
        int n = pipe(pipefd);
        //使用兩個文件描述符指向同一個管道文件
        assert(!n);
        pid_t id = fork();

        if (id == 0)//子進程
        {
            close(pipefd[1]);//關閉寫文件
            dup2(pipefd[0], 0);//將讀文件重定向到標準輸入的位置
            close(pipefd[0]);//關閉當前讀文件,因為我們后續(xù)用標準輸入的下標就行了
            slaver();//子進程讀取任務碼
            exit(0);
        }
        string name = "processname " + to_string(i);//子進程名字
        channels->push_back(channel(name, id, pipefd[1]));//子進程pid,這個子進程
        //與父進程之間的管道文件描述符下標記錄下來

        // father
        close(pipefd[0]);//關閉讀文件
    }
}

void ctrlProcess(vector<channel> &channels)
{
    int which = 0;
//我們循環(huán)調用各個子進程,which為子進程的下標
    while (true)
    {
         Menu();
        int select = 0;
        cin >> select;
        
        cout << "Please Enter@ ";
        if (select <= 0 || select >= 5)
            break;
        int cmdcode = select - 1;

        cout << "father say task have sent to " << channels[which]._processname << "  cmdcode : " << cmdcode << endl;
        write(channels[which]._cmdfd, &cmdcode, sizeof(int));//寫入指令
        which++;
        which %= channels.size();
    }
}

void QuitProcess(const vector<channel> channels)
{
    //方法一:
    for (const auto &c : channels)
        close(c._cmdfd);

    for (const auto &c : channels)
        waitpid(c._slaverid, nullptr, 0);

    //方法二:
    //for(int i=channels.size()-1;i>=0;i--){
      //  close(channels[i]._cmdfd);
        //waitpid(channels[i]._slaverid,nullptr,0);//阻塞等待
    //}
}

int main()
{

    vector<channel> channels;//管理管道的數(shù)組
    LoadTask(&tasks);//加載任務
    InitProcessPool(&channels);//初始化進程池
    ctrlProcess(channels);//輸入任務命令
    QuitProcess(channels);//中止進程
    return 0;
}

如果等待和close在一個循環(huán)中會發(fā)生阻塞,因為我一號管道雖然父進程那里寫關閉了,但依舊有子進程2,3指向這個管道為寫

【Linux】匿名管道與命名管道,進程池的簡易實現(xiàn),linux,運維,服務器文章來源地址http://www.zghlxwxcb.cn/news/detail-754336.html

到了這里,關于【Linux】匿名管道與命名管道,進程池的簡易實現(xiàn)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • [Linux]進程間通信(上篇)——匿名管道(管道原理,實現(xiàn)示例,端口情況探究!?。? decoding=
  • 【Linux從入門到精通】通信 | 管道通信(匿名管道 & 命名管道)

    【Linux從入門到精通】通信 | 管道通信(匿名管道 & 命名管道)

    ? ? 本派你文章主要是對進程通信進行詳解。主要內容是介紹 為什么通信、怎么進行通信。其中本篇文章主要講解的是管道通信。希望本篇文章會對你有所幫助。 文章目錄 一、進程通信簡單介紹 1、1 什么是進程通信 1、2?為什么要進行通信 ?1、3 進程通信的方式 二、匿名管

    2024年02月09日
    瀏覽(19)
  • 【LInux】進程間通信 -- 匿名管道

    【LInux】進程間通信 -- 匿名管道

    我們在學習進程管理,進程替換時,都強調了 進程的獨立性 ,那進程間通信是什么?這好像和進程的獨立性 相矛盾 吧? 那么今天,我們就來學習 進程間通信 ,和第一種通信方式 – 管道 進程間通信,并沒有破壞進程的獨立性這一特點,這點我們在 管道 講解 而進程通信的

    2023年04月19日
    瀏覽(23)
  • Linux進程間通信【匿名管道】

    Linux進程間通信【匿名管道】

    ?個人主頁: 北 海 ??所屬專欄: Linux學習之旅 ??操作環(huán)境: CentOS 7.6 阿里云遠程服務器 進程間通信簡稱為 IPC (Interprocess communication),是兩個不同進程間進行任務協(xié)同的必要基礎。進行通信時,首先需要確保不同進程之間構建聯(lián)系,其次再根據(jù)不同的使用場景選擇不同

    2024年02月08日
    瀏覽(48)
  • 【Linux】進程通信之匿名管道通信

    【Linux】進程通信之匿名管道通信

    我們往往需要多個進程協(xié)同,共同完成一些事情。 數(shù)據(jù)傳輸:一個進程需要將它的數(shù)據(jù)發(fā)送給另一個進程 資源共享:多個進程之間共享同樣的資源。 通知事件:一個進程需要向另一個或一組進程發(fā)送消息,通知它(它們)發(fā)生了某種事件(如進程終止 時要通知父進程)。

    2024年04月14日
    瀏覽(24)
  • Linux--進程間的通信-匿名管道

    Linux--進程間的通信-匿名管道

    進程間通信(IPC,Interprocess Communication)是指在不同進程之間傳輸數(shù)據(jù)和交換信息的一種機制。它允許多個進程在同一操作系統(tǒng)中同時運行,并實現(xiàn)彼此之間的協(xié)作 。 進程間通信方式: 管道(Pipe) : 管道是最基本的進程間通信方式 ,它是一種 半雙工 的通信方式,通過管

    2024年04月14日
    瀏覽(28)
  • 【Linux】進程間通信 -- 命名管道

    【Linux】進程間通信 -- 命名管道

    在管道的通信中,除了 匿名管道 ,還有一個 命名管道 。 匿名管道只支持具有 “親戚關系” 的進程間通信,而命名管道就可以支持不同的,任意的進程通信。 那就下來就開始我們今天的學習。 匿名管道的兩種使用方式: 指令的 \\\' | \\\' 和pipe()函數(shù) 命名管道也有兩種使用方式

    2023年04月20日
    瀏覽(17)
  • linux——進程間通信——命名管道

    linux——進程間通信——命名管道

    ??1主頁::我的代碼愛吃辣 ??2知識講解:Linux——進程間通信——命名管道 ??3開發(fā)環(huán)境:Centos7 ??4前言:命名管道是一種特殊的文件存放在文件系統(tǒng)中,而不是像管道那樣存放在內核中。命名管道可以用于任何兩個進程間的通信,而不限于同源的兩個進程。當進程對

    2024年02月08日
    瀏覽(18)
  • Linux進程間通信【命名管道】

    Linux進程間通信【命名管道】

    ?個人主頁: 北 海 ??所屬專欄: Linux學習之旅 ??操作環(huán)境: CentOS 7.6 阿里云遠程服務器 命名管道通信屬于 IPC 的其中一種方式,作為管道家族,命名管道的特點就是 自帶同步與互斥機制、數(shù)據(jù)單向流通 ,與匿名管道不同的是:命名管道有自己的名字,因此可以被沒有血

    2024年02月08日
    瀏覽(41)
  • 【Linux】進程間通信——命名管道

    【Linux】進程間通信——命名管道

    匿名管道只能用來進行進程間通信,讓具有血緣關系的進程進行通信 讓毫不相關的進程之間進行通信,就需要采用命名管道通信 因為該文件有文件名稱的,而且必須要有,所以叫做命名管道 mkfifo函數(shù) 輸入 man mkfifo 指令 制作一個 FIFOS ,表示命名管道 mkfifo fifo 制作一個管道

    2023年04月15日
    瀏覽(19)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包