匿名管道
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 4096key_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 2static 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";}elsestd::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";}}