当前位置: 首页 > news >正文

Linux 命名管道+日志

一、命名管道

1.1 进程通信的前提:先让不同进程看到同一份资源;
1.2 如何确保两个进程打开的是同一个文件:同路径下同一文件名;
1.3 命名管道:通过路径+文件名确保这个份资源的唯一性;
1.4 接口:
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char* pathname, mode_t mode);
pathname-> 路径; mode -> 权限  int ->成功返回0,失败返回 -1
1.5 两个不相干的进程通过命名管道实现通信:
//comm.hpp
#pragma once
#define FILE_NAME "myfifo"
#define MODE 0666
#define SIZE 1024
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <fcntl.h>
//processA.cc
//进程A读取进程B写的内容
#include "comm.hpp"
int main()
{//创建管道文件int retmk=mkfifo(FILE_NAME,MODE);if(retmk<0){perror("mkfifo");exit(1);}//打开管道文件int fd=open(FILE_NAME,O_RDONLY);//因为A只做读取工作if(fd<0){perror("open");exit(3);}std::cout<<"process A open done!!"<<std::endl;//开始通信char buffer[SIZE]={0};while(true){ssize_t n=  read(fd,buffer,sizeof(buffer));if(n>0){buffer[n]='\0';//读到了把n位置写入'\0'打印结束标识符printf("%s\n",buffer);}else if(n==0){printf("写端关闭,读取到文件末尾!!\n");break;//退出}else break;//读取失败}//关闭文件close(fd);//删除管道文件int retlink=unlink(FILE_NAME);if(retlink==-1){perror("ulink");exit(2);}return 0;
}
//processB.cc
#include "comm.hpp"
int main()
{//打开文件int fd =open(FILE_NAME,O_WRONLY);//以写的方式打开if(fd<0){perror("open");exit(4);}//开始通信while(true){std::string line;getline(std::cin,line);//从键盘获取整行到linewrite(fd,line.c_str(),line.size());}//关闭文件close(fd);return 0;
}
//makefile
.PHONY:all
all:processA processB
processA:processA.ccg++ -o $@ $^ -std=c++11
processB:processB.ccg++ -o $@ $^ -std=c++11
.PHONY:clean
clean:rm -f processA processB

运行A:(A进程在等待读)

运行B:(B在等待键盘输入,且A打印了一句)

我在A进程代码中打开文件后写的一句:

说明:读取方等待写入方打开文件后才会自己打开,向后执行,如果写入方不打开文件,读取方会open阻塞了!!

接下来,在进程B中输入点信息再关闭看看:

进程A、B之间实现了通信,当写端关闭后B读到文件末尾返回值0退出循环;

二、加入日志

2.1日志一般需要的内容:

①日志时间;②日志内容;④文件名称和行号

③日志等级:日志等级一般有:

 Info :常规消息;

Debug:调试信息;

Warning : 报警信息 ;

Error :比较严重需要立即处理 ;

Fatal:致命信息;

2.2  实现简易的日志功能

例如:当程序运行发生错误时,这是一个Error消息,把错误信息的等级、发生时间、错误内容、错误码按照自己的需求打印出来(可以打印到屏幕或者某个文件,也可以根据日志等级把信息分类打印到不同的文件);

2.3 日志类的实现
//log.hpp
#pragma once
#include "comm.hpp"
#include <time.h>
#include <stdarg.h>
#include <cstring>
#define Info 1
#define Debug 2
#define Warning 3
#define Error 4
#define Fatal 5
#define SCREEN 1 //屏幕打印
#define ONEFILE 2  //打印某个文件
#define CLASSFILE 3  //分类打印
#define FILE_NAME "log.txt"
#define PATH "./log/"
class Log
{public:Log(){printmethod=SCREEN;//默认向屏幕打印path=PATH;}void Enable(int method){printmethod=method;}
std::string leveltoString(int level)
{switch(level){case 1:return "Info";case 2:return "Debug";case 3:return "Warning";case 4:return "Error";case 5:return "Fatal";default:return "None";}
}
void printOnefile(const std::string&filename,const std::string&logtxt)//向一个文件打印
{std::string Filename=path+filename;int fd=open(Filename.c_str(),O_CREAT|O_WRONLY|O_APPEND);write(fd,logtxt.c_str(),logtxt.size());close(fd);
}
void printClassfile(int level,const std::string&logtxt)
{std::string filename=FILE_NAME;filename+=".";filename+=leveltoString(level);printOnefile(filename,logtxt);
}
void logprint(int level,const std::string&logtxt)
{switch(printmethod){case SCREEN:std::cout<<logtxt.c_str()<<std::endl;break;case ONEFILE:printOnefile(FILE_NAME,logtxt);break;case CLASSFILE:printClassfile(level,logtxt);break;}
}
void operator()(int level,const char*format,...)
{time_t t=time(nullptr);//获取时间戳struct tm*ctime=localtime(&t);//通过时间戳获取想要的时间//leftbuffer为默认信息包括:日志等级、日志时间char leftbuffer[SIZE]={0};snprintf(leftbuffer,sizeof(leftbuffer),"[%s][%d-%d-%d %d:%d:%d]",leveltoString(level).c_str(),ctime->tm_year+1900,ctime->tm_mon+1,ctime->tm_mday,ctime->tm_hour,ctime->tm_min,ctime->tm_sec);//rightbuffer 为自定义消息char rightbuffer[SIZE]={0};va_list s;//相当于char*va_start(s,format);//取format内容后s指针往上走,相当于走到可变参数的起始位置vsnprintf(rightbuffer,sizeof(rightbuffer),format,s);//左右buffer拼接char logtxt[SIZE*2]={0};snprintf(logtxt,sizeof(logtxt),"%s %s\n",leftbuffer,rightbuffer);logprint(level,logtxt);}
private:int printmethod;std::string path;
};
在makefile中提前创好一个log文件用来存放日志文件:

2.4 进程里面使用日志

所有想要显示的消息都可以往日志里面打印;

2.5运行后输出的日志消息(以分类文件打印方法)

可以看到三条日志消息都分类打印到不同的文件中!

今天分享到这里,如果对你有所帮助麻烦点赞收藏+关注哦!!谢谢!!!

咱下期见!!!

http://www.xdnf.cn/news/217099.html

相关文章:

  • 婴幼儿托育实训室生活照料流程标准化设计
  • Flowable7.x学习笔记(十五)动态指定用户分配参数启动工作流程
  • AutogenStudio使用
  • 快速掌握向量数据库-Milvus探索2_集成Embedding模型
  • AI技术前沿:Function Calling、RAG与MCP的深度解析与应用实践
  • 基于PyTorch的图像分类特征提取与模型训练文档
  • 集群系统的五大核心挑战与困境解析
  • EtherCAT转CANopen方案落地:推动运动控制器与传感器通讯的工程化实践
  • CKESC Breeze 6S 40A_4S 50A FOC BEC电调测评:全新vfast 技术赋能高效精准控制
  • 低代码平台部署方案解析:百特搭四大部署方式
  • 大模型推理:Qwen3 32B vLLM Docker本地部署
  • 强化学习贝尔曼方程推导
  • 流量守门员:接口限流艺术
  • Manus AI多语言手写识别技术全解析:从模型架构到实战部署
  • JavaScript 中深拷贝浅拷贝的区别?如何实现一个深拷贝?
  • 信雅达 AI + 悦数 Graph RAG | 大模型知识管理平台在金融行业的实践
  • C# 类的基本概念(实例成员)
  • 【2024-NIPS-版权】Evaluating Copyright Takedown Methods for Language Models
  • 《云原生》核心内容梳理和分阶段学习计划
  • Alibaba第四版JDK源码学习笔记2025首次开源
  • HCIP【VLAN技术(详解)】
  • Java高频面试之并发编程-11
  • 第三部分:赋予网页灵魂 —— JavaScript(下)
  • Spring Boot - 配置管理与自动化配置进阶
  • 【Bash】可以请您解释性地说明一下“2>1”这个语法吗?
  • Windows 系统下使用 Docker 搭建Redis 集群(6 节点,带密码)
  • C++日更八股--first
  • SpringBoot应用:Docker与Kubernetes全栈实战秘籍
  • git fetch和git pull的区别
  • 域对齐是什么