匿名管道
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";
}
}