linux进程通信



匿名管道

struct_file的两套资源

管道只能单向通信

特征

1.如果管道没有数据 读端在读 默认会直接阻塞正在读取的进程

2.写端写满 在写会阻塞 等待对方读取

管道设计

命名管道

实现管道通信

#pragma once
#include<iostream>
#include<string>
#include<sys/types.h>
#include<sys/stat.h>
#include<cerrno>
#include<cstring>
#include<cassert>
#include<unistd.h>
#include<fcntl.h>

using namespace std;
#define NAME_PIPE "/home/ls/lesson24/tmp2"

bool createFifo(const string& path){
    int n=mkfifo(path.c_str(),0777);
    if(n==0)
        return true;
    else{
        cout<<"errno:"<<errno<<"err string"<<strerror(errno)<<endl;
        return false;
    }
}

void removeFifo(const string& path){
    int n=unlink(path.c_str());
    assert(n==0);
    (void)n;

}


#include"comm.hpp"

int main(){
    bool r=createFifo(NAME_PIPE);
    assert(r);

    int rfd=open(NAME_PIPE,O_RDONLY);
    if(rfd<0)
        exit(0);
    char buffer[1024];
    while(true){
        ssize_t s=read(rfd,buffer,sizeof(buffer));
        if(s>0){
            buffer[s]=0;
            cout<<"client->server#"<<buffer<<endl;
        }
        else if(s==0){
            cout<<"client quit me too"<<endl;
            break;
        }
        else{
            cout<<"err string:"<<strerror(errno)<<endl;
            break;
        }
    }
    close(rfd);

    remove(NAME_PIPE);
    return 0;
}

#include"comm.hpp"

using namespace std;
int main(){
   
    int wfd=open(NAME_PIPE,O_WRONLY);
    if(wfd<0)
        exit(0);
    char buffer[1024];
    while(true){
        cout<<"Please Say#";
        fgets(buffer,sizeof(buffer),stdin);
        ssize_t n=write(wfd,buffer,strlen(buffer));
        assert(n==strlen(buffer));
        (void)n;
    }
    close(wfd);
    return 0;
}

共享内存

原理

接口的认识

共享内存的优缺点

和管道对比拷贝次数

实现通信

//comm.hpp
#pragma once
#include<sys/ipc.h>
#include<sys/shm.h>
#include<cerrno>
#include<cstring>
#include<iostream>
#include<unistd.h>

#define PATHNAME "."
#define PROJ_ID 0x66
#define MAX_SIZE 4096

key_t getkey(){

    key_t k=ftok(PATHNAME,PROJ_ID);
    if(k<0){
        std::cerr<<errno<<":"<<strerror(errno)<<std::endl;
        exit(1);
    }
    return k;
}

int getShmHelper(key_t k,int flags){
    int shmid=shmget(k,MAX_SIZE,flags);
    if(shmid<0){
        std::cerr<<errno<<":"<<strerror(errno)<<std::endl;
        exit(2);
    }
    return shmid;
}

int getShm(key_t k){
    return getShmHelper(k,IPC_CREAT);
}

int createShm(key_t k){
    return getShmHelper(k,IPC_CREAT|IPC_EXCL|0666);
}



void* attachShm(int shmid){
    void* mem=shmat(shmid,nullptr,0);
    if((long long)mem==-1){
         std::cerr<<errno<<":"<<strerror(errno)<<std::endl;
         exit(3);
    }
    return mem;
}

void detachShm(void* start){
    if(shmdt(start)==-1){
        std::cerr<<errno<<":"<<strerror(errno)<<std::endl;
    }
}


void delShm(int shmid){
    if(shmctl(shmid,IPC_RMID,nullptr)==-1){
        std::cerr<<errno<<":"<<strerror(errno)<<std::endl;
    }
}

//shm_client.cpp
#include<iostream>
#include"comm.hpp"

int main(){
    key_t k=getkey();
    printf("key:0x%x\n",k);
    int shmid=getShm(k);
    printf("shmid:%d\n",shmid);

    sleep(5);
    char* start=(char*)attachShm(shmid);  //关联共享内存
    printf("attch sucess,address start:%p\n",start);

    const char* message="hello server,我是另一个进程 正在和你通信";
    pid_t id=getpid();
    int cnt=1;
    while(true){
        sleep(1);
        snprintf(start,MAX_SIZE,"%s[pid:%d][消息编号:%d]",message,id,cnt++);
    }

    detachShm(start);  //去关联

    sleep(5);

    return 0;
}

//shm_server.cpp
#include<iostream>
#include"comm.hpp"

int main(){
    key_t k=getkey();
    printf("key:0x%x\n",k);
    int shmid=createShm(k);
    printf("shmid:%d\n",shmid);

    sleep(5);
    //关联共享内存
    char *start=(char*)attachShm(shmid);
    printf("attch sucess,address start:%p\n",start);
    //使用
    while(true){
        printf("client say:%s\n",start);
        sleep(1);
    }
    //去关联
    detachShm(start);
    sleep(10);

    //删除共享内存
    delShm(shmid);

    return 0;
}

消息队列(了解)

信号量

为什么要有信号量

信号

实现kill

#include<iostream>
#include<unistd.h>
#include<signal.h>
#include<cstdio>
#include<cstring>
#include<string>

static void Usage(const std::string &proc){
    std::cout<<"Usage:"<<proc<<"pid signo\n"<<std::endl;
}

int main(int argc,char *argv[]){
    if(argc!=3){
        Usage(argv[0]);
        exit(1);
    }
    pid_t pid=atoi(argv[1]);
    int signo=atoi(argv[2]);
    int n=kill(pid,signo);
    if(n!=0)
        perror("kill");

    while(true){
        std::cout<<"hello"<<std::endl;
        sleep(1);
    }
}

产生信号的方式

除0的理解

软件条件

#include<iostream>
#include<unistd.h>
#include<signal.h>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>

/* static void Usage(const std::string &proc){
    std::cout<<"Usage:"<<proc<<"pid signo\n"<<std::endl;
} */
int cnt=0;
void catchSig(int signo){

    std::cout<<"获取一个信号 信号编号:"<<cnt<<std::endl;
    exit(1);
}

int main(int argc,char *argv[]){

    signal(SIGALRM,catchSig);
    alarm(1);
    while(true){
       cnt++;
    }
}

闹钟管理

核心转储

阻塞信号

信号捕捉流程

状态切换

实验

#include<iostream>
#include<unistd.h>
#include<signal.h>
#include<vector>

#define MAX_SIGNUM 31
#define BLOCK_SIGNAL 2

static std::vector<int> sigarr={2,3};

static void show_pending(const sigset_t &pending){
    for(int signo=MAX_SIGNUM;signo>0;signo--){
        if(sigismember(&pending,signo)){
            std::cout<<"1";
        }
        else
            std::cout<<"0";
    }
    std::cout<<"\n";
}

static void myhandler(int signo){
    std::cout<<signo<<"号信号已经被递达"<<std::endl;
}

int main(){
    for(const auto &sig:sigarr){
        signal(sig,myhandler);
    }
    sigset_t block,oblock,pending;
    //初始化
    sigemptyset(&block);
    sigemptyset(&oblock);
    sigemptyset(&pending);
    //增加要屏蔽的信号
    for(const auto &sig:sigarr){
        sigaddset(&block,sig);
    }
    //开始屏蔽 设置进内核(进程)
    sigprocmask(SIG_SETMASK,&block,&oblock);
    //遍历打印pending信号集
    while(true){
        //初始化
        sigemptyset(&pending);
        //获取它
        sigpending(&pending);
        //打印
        show_pending(pending);

        sleep(1);
    }
    int cnt=10;
    if(cnt--==0){
        sigprocmask(SIG_SETMASK,&oblock,&block);
        std::cout<<"恢复信号屏蔽\n";
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/225410.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python获取js data.now同款时间戳

import requestsimport time from datetime import datetimecu_t datetime.now() se cu_t.timestamp()*1000 se int(se) print(se)#cur_time time.time()*1000 #seconds int(cur_time) #print(seconds)

Kmeans聚类模型可视化大合集

Kmeans聚类模型可视化大合集&#xff1a; ​ 当对K-means聚类模型进行可视化时&#xff0c;有多种展示形式可以帮助我们理解和分析聚类结果。以下是一些常见的K-means聚类模型可视化形式&#xff1a; kmeans构建&#xff1a; import pandas as pd from sklearn.cluster impo…

vue3.2版本setup语法糖

setup语法糖&#xff1a; 一、Vue3.0 <script>里定义的变量、属性和方法必须 return 出来&#xff0c;<template>中才能使用&#xff1b;这样会导致在页面上变量会出现很多次。vue3.2只需在script标签中添加setup&#xff0c;就可以帮助我们解决这个问题,无需再写…

用 PHP和html做一个简单的注册页面

用 PHP和html做一个简单的注册页面 index.html的设计 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title…

springboot 2.4.4集成 hikari连接池多数据源实例

文章目录 前言一、配置步骤1.1 pom配置1.2 application.properties配置1.3 DataSourceContextHolder类1.4 DynamicDataSource1.5 DataSourceconfig类配置1.6 配置TargetDataSource注解1.7 切面方法1.8 dao的写法 二、测试验证2.1 启动springboot项目2.2 检查数据库连接2.3 debu…

Name or service not knownstname

Name or service not knownstname Hadoop 或 Spark 集群启动时 报错 Name or service not knownstname 原因时因为 workers 文件在windows 使用图形化工具打开过 操作系统类型不对引发的 在Linux系统上删除 workers 文件 使用 vim 重新编辑后分发即可

无公网IP,从公网SSH远程访问家中的树莓派

下午好&#xff0c;我的网工朋友。 今天说点好玩的啊。树莓派 (Raspberry Pi) 可以做事情很多&#xff0c;用作家庭网络中的服务器&#xff0c;是非常流行的一种。 因为它微小的占地面积和低功耗使其成为运行轻量级服务器的完美设备。 在这种情况下&#xff0c;你可以在树莓派…

C# Onnx 百度飞桨开源PP-YOLOE-Plus目标检测

目录 效果 模型信息 项目 代码 下载 C# Onnx 百度飞桨开源PP-YOLOE-Plus目标检测 效果 模型信息 Inputs ------------------------- name&#xff1a;image tensor&#xff1a;Float[1, 3, 640, 640] name&#xff1a;scale_factor tensor&#xff1a;Float[1, 2] ----…

CentOS系统中设置反向代理服务器的步骤

在CentOS系统中设置反向代理服务器可以帮助你隐藏原始服务器的细节&#xff0c;并提高服务器的安全性。以下是在CentOS系统中设置反向代理服务器的步骤概述&#xff1a; 安装反向代理软件&#xff1a; 常见的反向代理软件包括Nginx和Apache。你可以选择其中之一来作为你的反向…

基于gitlab的webhook集成jenkins,并在gitlab流水线中展示jenkins的job状态信息

文章目录 1. 环境信息2. gitlab 部署3. jenkins部署4. gitlab集成jenkins4.1 jenkins的凭据上保存gitlab的账号信息4.2 jenkins中配置gitlab的连接信息4.3 编写jenkins上pipeline文件4.4 jenkins上创建pipeline项目4.5 gitlab上配置webhooks事件4.6 测试 1. 环境信息 gitlab服…

数据结构复习:链表、数组、栈、队列、哈希表、堆、二叉树

数据结构复习&#xff1a;链表、数组、栈、队列、哈希表、堆、二叉树 时间复杂度 链表 在链表中&#xff0c;数据的添加和删除都较为方便&#xff0c;访问比较耗时间 每个数字都有一个“指针”&#xff0c;指向下一个数据内存地址。 数据无需存储在连续空间 访问某个数据&a…

高精度加法,减法,乘法,除法(上)(C语言)

前言 加&#xff0c;减&#xff0c;乘&#xff0c;除这些运算我们自然信手捏来&#xff0c;就拿加法来说&#xff0c;我们要用c语言编程算ab的和&#xff0c;只需让sum ab即可&#xff0c;可是这是局限的&#xff0c;我们都知道int的表示的最大值为2147483647&#xff08;32位…

java单人聊天

服务端 package 单人聊天;import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import…

23款奔驰E350eL升级小柏林音响 13个扬声器 590w

小柏林之声音响是13个喇叭1个功放&#xff0c;功率是590W&#xff0c;对应普通音响来说&#xff0c;已经是上等了。像著名的哈曼卡顿音响&#xff0c;还是丹拿音响&#xff0c;或者是BOSE音响&#xff0c;论地位&#xff0c;论音质柏林之声也是名列前茅。 升级小柏林音响&#…

LC-1466. 重新规划路线(DFS、BFS)

1466. 重新规划路线 中等 n 座城市&#xff0c;从 0 到 n-1 编号&#xff0c;其间共有 n-1 条路线。因此&#xff0c;要想在两座不同城市之间旅行只有唯一一条路线可供选择&#xff08;路线网形成一颗树&#xff09;。去年&#xff0c;交通运输部决定重新规划路线&#xff0c…

相交链表(LeetCode 160)

文章目录 1.问题描述2.难度等级3.热门指数4.解题思路方法一&#xff1a;暴力法方法二&#xff1a;哈希表方法三&#xff1a;双栈方法四&#xff1a;双指针&#xff1a;记录链表长度方法五&#xff1a;双指针&#xff1a;互换遍历 5.实现示例参考文献 1.问题描述 给两个单链表的…

短视频账号剪辑矩阵+无人直播系统源头开发

抖去推爆款视频生成器&#xff0c;通过短视频矩阵、无人直播&#xff0c;文案引流等&#xff0c;打造实体商家员工矩阵、用户矩阵、直播矩阵&#xff0c;辅助商家品牌曝光&#xff0c;团购转化等多功能赋能商家拓客引流。 短视频矩阵通俗来讲就是批量剪辑视频和批量发布视频&am…

Java 对接智谱 AI(官方 sdk 是真垃圾)

官方 sdk 狗屎。 一堆密钥不知道啥玩意&#xff0c;文档也没写好。 python 版本的就不清楚&#xff0c;应该支持会比较好&#xff0c;果然做 ai 应用后端开发还是得使用 python 比较好。 那么要如何对接智谱 AI 呢&#xff1f;用小博哥的这个版本&#xff0c;虽然不是官方的…

光伏基础知识

快速了解国内光伏历史 美国是最早制定光伏发电的发展规划的国家&#xff0c;国内从1958年开始专注于太阳电池的研究&#xff0c;到1971年3月首次将太阳电池成功地应用于我国第2颗卫星上&#xff0c;再到1979年开始生产单晶硅太阳电池&#xff0c;直到20世纪90年代中期后光伏发…

ElasticSearch篇---第六篇

系列文章目录 文章目录 系列文章目录前言一、ElasticSearch中的副本是什么?二、ElasticSearch中的分析器是什么?三、什么是ElasticSearch中的编译器?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女…