linux进程通信

2023-12-14 09:30:11



匿名管道

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";
    }

}

文章来源:https://blog.csdn.net/b1169909203/article/details/134583062
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。