从零开始实现一个C++高性能服务器框架----环境变量模块
此项目是根据sylar框架实现,是从零开始重写sylar,也是对sylar丰富与完善
项目地址:https://gitee.com/lzhiqiang1999/server-framework
简介
项目介绍:实现了一个基于协程的服务器框架,支持多线程、多协程协同调度;支持以异步处理的方式提高服务器性能;封装了网络相关的模块,包括socket、http、servlet等,支持快速搭建HTTP服务器或WebSokcet服务器。
详细内容:日志模块,使用宏实现流式输出,支持同步日志与异步日志、自定义日志格式、日志级别、多日志分离等功能。线程模块,封装pthread相关方法,封装常用的锁包括(信号量,读写锁,自旋锁等)。IO协程调度模块,基于ucontext_t实现非对称协程模型,以线程池的方式实现多线程,多协程协同调度,同时依赖epoll实现了事件监听机制。定时器模块,使用最小堆管理定时器,配合IO协程调度模块可以完成基于协程的定时任务调度。hook模块,将同步的系统调用封装成异步操作(accept, recv, send等),配合IO协程调度能够极大的提升服务器性能。Http模块,封装了sokcet常用方法,支持http协议解析,客户端实现连接池发送请求,服务器端实现servlet模式处理客户端请求,支持单Reator多线程,多Reator多线程模式的服务器。
环境变量模块
- 提供程序运行时的环境变量管理功能。这里的环境变量不仅包括系统环境变量,还包括程序自定义环境变量,命令行参数,帮助选项与描述,以及程序运行路径相关的信息。
1. 主要功能
- 解析命令行参数,并提供参数的帮助描述
- 获取系统环境变量
- 获取当前程序运行的绝对路径,工作路径及配置文件的路径
2. 功能演示
int main(int argc, char** argv)
{
johnsonli::EnvMgr::GetInstance()->addHelp("d", "run in daemon");
johnsonli::EnvMgr::GetInstance()->addHelp("p", "print help");
johnsonli::EnvMgr::GetInstance()->addHelp("s", "start in terminal");
if(!johnsonli::EnvMgr::GetInstance()->init(argc, argv))
{
johnsonli::EnvMgr::GetInstance()->printHelp();
return 0;
}
LOG_INFO(g_logger) << "exe: " << johnsonli::EnvMgr::GetInstance()->getExe();
LOG_INFO(g_logger) << "cwd: " << johnsonli::EnvMgr::GetInstance()->getCwd();
LOG_INFO(g_logger) << "path: " << johnsonli::EnvMgr::GetInstance()->getEnv("PATH", "XXX");
if(johnsonli::EnvMgr::GetInstance()->has("p"))
{
johnsonli::EnvMgr::GetInstance()->printHelp();
}
return 0;
}
3. 模块介绍
3.1 Env
- 处理当前命令行参数,系统环境变量,路径等问题。是一个单例模式
class Env
{
public:
typedef RWMutex RWMutexType;
bool init(int argc, char** argv);
void add(const std::string& key, const std::string& val);
bool has(const std::string& key);
void del(const std::string& key);
std::string get(const std::string& key, const std::string& default_value = "");
void addHelp(const std::string& key, const std::string& desc);
void removeHelp(const std::string& key);
void printHelp();
const std::string& getExe() const { return m_exe;}
const std::string& getCwd() const { return m_cwd;}
bool setEnv(const std::string& key, const std::string& val);
std::string getEnv(const std::string& key, const std::string& default_value = "");
std::string getAbsolutePath(const std::string& path) const;
std::string getAbsoluteWorkPath(const std::string& path) const;
std::string getConfigPath();
private:
RWMutexType m_mutex;
std::map<std::string, std::string> m_args;
std::vector<std::pair<std::string, std::string> > m_helps;
std::string m_program; // 启动程序的名称
std::string m_exe; // 程序执行的绝对路径
std::string m_cwd; // 绝对路径的上一级路径
};
typedef johnsonli::Singleton<Env> EnvMgr;
- 解析命令行参数。双指针的思路。调用
readlink()
系统调用,可以获取/proc/$pid/exe
软链接文件指向的路径,该路径就是当前文件执行的绝对路径。
std::map<std::string, std::string> m_args; // 存环境变量参数
// 初始化,解析
bool init(int argc, char** argv);
// 添加到m_args
void add(const std::string& key, const std::string& val);
// 判断m_args有无该参数
bool has(const std::string& key);
// 删除
void del(const std::string& key);
// 获取
std::string get(const std::string& key, const std::string& default_value = "");
- 获取/设置系统环境变量。主要使用
getenv()
和setenv()
两个系统调用
// 设置系统环境变量
bool Env::setEnv(const std::string& key, const std::string& val)
{
return !setenv(key.c_str(), val.c_str(), 1);
}
// 获取系统环境变量
std::string Env::getEnv(const std::string& key, const std::string& default_value)
{
const char* v = getenv(key.c_str());
if(v == nullptr)
{
return default_value;
}
return v;
}
- 设置命令行参数帮助信息
std::vector<std::pair<std::string, std::string> > m_helps; // 存帮助信息
void addHelp(const std::string& key, const std::string& desc);
void removeHelp(const std::string& key);
void printHelp();
getAbsolutePath
方法,传入一个相对于执行文件的路径,返回这个路径的绝对路径。比如默认的配置文件路径就是通过getAbsolutePath(get(“c”, “conf”))来获取的,也就是配置文件夹默认在执行文件所在目录的conf文件夹。
std::string Env::getAbsolutePath(const std::string& path) const
{
if(path.empty())
{
return "/";
}
if(path[0] == '/')
{
return path;
}
return m_cwd + path;
}
std::string Env::getAbsoluteWorkPath(const std::string& path) const {
if(path.empty()) {
return "/";
}
if(path[0] == '/') {
return path;
}
static johnsonli::ConfigVar<std::string>::ptr g_server_work_path =
johnsonli::Config::Lookup<std::string>("server.work_path");
return g_server_work_path->getValue() + "/" + path;
}
std::string Env::getConfigPath()
{
return getAbsolutePath(get("c", "conf"));
}