add old lci module

This commit is contained in:
qing committed 2026-08-02 20:15:07 +08:00
1 parent 38a6e815f0
commit 8499631091
171 files changed
+25562

No files matched your search

+41
View File
@@ -0,0 +1,41 @@
# dahun
大顺脚本是进程托管程序,能够创建子进程并且管理。
## 使用方法
### 核心服务
```
./dashun --daemon --to=test
```
### 启动进程
```
./dashun --to=test --msg='path/to/bat'
```
### 列举进程
```
./dashun --to=test --msg=list
```
### 杀死进程
```
./dashun --to=test --msg=kill <pid>
```
### 清理进程
```
./dashun --to=test --msg=clear
```
## 编译过程
1.首先安装依赖(boost、openuv)
2.使用管理员模式打开Visual Studio,编译程序
3.使用管理员模式打开两个powershell,并且切换工作目录至生成的exe文件
4.在第一个powershell 中输入指令“./dashun --to=test --daemon”启动核心服务
5.在第二个powershell中输入指令“./dashun --to=test --msg=hello,world!”
+41
View File
@@ -0,0 +1,41 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.14.36401.2
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dashun", "dashun\dashun.vcxproj", "{A0E6A4C1-02B0-41F5-ABB7-33C6E4FB97F6}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dashun_to", "dashun_to\dashun_to.vcxproj", "{04D7A85C-43BB-4696-B9C8-F79C2252EDA1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A0E6A4C1-02B0-41F5-ABB7-33C6E4FB97F6}.Debug|x64.ActiveCfg = Debug|x64
{A0E6A4C1-02B0-41F5-ABB7-33C6E4FB97F6}.Debug|x64.Build.0 = Debug|x64
{A0E6A4C1-02B0-41F5-ABB7-33C6E4FB97F6}.Debug|x86.ActiveCfg = Debug|Win32
{A0E6A4C1-02B0-41F5-ABB7-33C6E4FB97F6}.Debug|x86.Build.0 = Debug|Win32
{A0E6A4C1-02B0-41F5-ABB7-33C6E4FB97F6}.Release|x64.ActiveCfg = Release|x64
{A0E6A4C1-02B0-41F5-ABB7-33C6E4FB97F6}.Release|x64.Build.0 = Release|x64
{A0E6A4C1-02B0-41F5-ABB7-33C6E4FB97F6}.Release|x86.ActiveCfg = Release|Win32
{A0E6A4C1-02B0-41F5-ABB7-33C6E4FB97F6}.Release|x86.Build.0 = Release|Win32
{04D7A85C-43BB-4696-B9C8-F79C2252EDA1}.Debug|x64.ActiveCfg = Debug|x64
{04D7A85C-43BB-4696-B9C8-F79C2252EDA1}.Debug|x64.Build.0 = Debug|x64
{04D7A85C-43BB-4696-B9C8-F79C2252EDA1}.Debug|x86.ActiveCfg = Debug|Win32
{04D7A85C-43BB-4696-B9C8-F79C2252EDA1}.Debug|x86.Build.0 = Debug|Win32
{04D7A85C-43BB-4696-B9C8-F79C2252EDA1}.Release|x64.ActiveCfg = Release|x64
{04D7A85C-43BB-4696-B9C8-F79C2252EDA1}.Release|x64.Build.0 = Release|x64
{04D7A85C-43BB-4696-B9C8-F79C2252EDA1}.Release|x86.ActiveCfg = Release|Win32
{04D7A85C-43BB-4696-B9C8-F79C2252EDA1}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {77387687-0520-4459-8BC7-D1A6C3C6CD58}
EndGlobalSection
EndGlobal
+76
View File
@@ -0,0 +1,76 @@
/* 有限状态机(Finite State Machine,FSM)是一种用于建模系统行为的抽象数学模型
* 它的核心思想是,系统在任何给定时刻都处于一个有限、预定义的“状态”中
* 并且会根据接收到的输入或事件,从一个状态切换到另一个状态
*/
#pragma once
#include <mutex>
#include <condition_variable>
namespace qing {
/* FiniteStateMachine有限状态机
* 每个数字代表一个状态
*/
class Fsm {
public:
/* 状态枚举
* 优化建议:多准备一些状态
*/
enum class Stat : int {
SHUT = -1,
STOP = 0,
START = 1,
RUNNING = 2
};
// 默认构造函数
Fsm() = default;
// 检查当前的状态,返回snum Stat
inline Stat check() {
//进入临界区
std::lock_guard<std::mutex> lk(mtx);
return stat;
}// check()
// 在不上锁的情况下设置一个状态
// 别在这里加条件唤醒
[[noreturn]] void set_without_lock(Stat stat) {
this->stat = stat;
}// set_without_lock()
// 带锁和条件唤醒的状态设置(正式)
[[noreturn]] void set(Stat stat) {
{
std::lock_guard<std::mutex> lk(mtx);
set_without_lock(stat);
ready = true;
}
cv.notify_all();
} // set()
//protected:
// 阻塞线程,等待事件唤醒
[[noreturn]] void suspend() {
std::unique_lock<std::mutex> lk(mtx);
ready = false;
cv.wait(lk, [this] { return ready; });
}// suspend()
private:
// 锁使得状态机线程安全
std::mutex mtx;
// 用于条件变量的阻塞唤醒
bool ready = false;
// 条件变量使得线程能够等待状态的改变
std::condition_variable cv;
// 主菜,状态机的状态变量
enum Stat stat = Stat::STOP;
};
}
+540
View File
@@ -0,0 +1,540 @@
#define _CRT_SECURE_NO_WARNINGS
#include "Th.hpp"
#include "Pls.hpp"
#include "args.hxx"
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <uv.h>
#ifdef _WIN32
#include <Windows.h>
#undef UNICODE
#undef _UNICODE
#endif
#include <iostream>
#include <memory>
#include <atomic>
using namespace boost::interprocess;
// 定义分配器类型
using CharAllocator = boost::interprocess::allocator<
char,
boost::interprocess::managed_shared_memory::segment_manager
>;
// 定义共享内存字符串类型
using SharedString = boost::interprocess::basic_string<
char,
std::char_traits<char>,
CharAllocator
>;
namespace qing {
// 监听线程
class LTh : public qing::Th {
public:
LTh(const std::string& name) {
this->name = name;
nameMem = name + "_MEM";
nameMtx = name + "_MTX";
namePtr = name + "_PTR";
nameRet = name + "_RET";
this->WakeEvent = [this] {
try {
// 先移除可能存在的旧共享内存
this->del_shared();
// 创建共享对象
this->create_shared();
// 线程进入运行态
this->run();
}
catch (interprocess_exception& ex) {
// 输出错误信息
std::cerr << ex.what() << std::endl;
// 线程静止
this->stop();
}
};
this->LoopEvent = [this] {
this->recv_shared_and_action();
// 等待
//
// 优化方案:使用信号,有新消息进来给沉默进程发送信号
// 而不是休眠定长时间检查
std::this_thread::sleep_for(std::chrono::milliseconds(10));
};
this->ClearEvent = [this] {
// 移除共享对象
this->del_shared();
};
}
[[noreturn]] static auto send_shared_msg(const std::string& to, const std::string& msg) -> void {
std::string nameMem = to + "_MEM";
std::string nameMtx = to + "_MTX";
std::string namePtr = to + "_PTR";
std::string nameRet = to + "_RET";
try {
// 打开共享内存
managed_shared_memory segment(open_only, nameMem.c_str());
// 构造一个命名互斥量
named_mutex mutex(open_or_create, nameMtx.c_str());
// 在共享内存中创建一个字符串
SharedString* str = segment.construct<SharedString>(namePtr.c_str())(
msg.c_str(), // 初始值(空字符串)
segment.get_allocator<char>() // 必须传入分配器
);
// 不延时的话可能会抢占,也许应该想一个两全其美的方法
std::this_thread::sleep_for(std::chrono::milliseconds(100));
{
// 加锁
std::lock_guard<named_mutex> lk(mutex);
// 获取消息
std::pair<SharedString*, std::size_t> msg = segment.find<SharedString>(nameRet.c_str());
if (msg.first) {
// 输出
std::cout << std::endl << *msg.first << std::endl;
// 销毁
segment.destroy<SharedString>(nameRet.c_str());
}
}
}
catch (interprocess_exception& ex) {
std::cerr << "Writer Error: " << ex.what() << std::endl;
}
}
private:
std::string name;
std::string nameMem;
std::string nameMtx;
std::string namePtr;
std::string nameRet;
std::unique_ptr<managed_shared_memory> segment;
std::unique_ptr<named_mutex> mutex;
std::pair<SharedString*, std::size_t> msg;
qing::Pls pls;
inline void create_shared() {
//////////////////////////////
// 删除可能存在的共享变量
this->del_shared();
//////////////////////////////
// 创建共享内存
segment = std::make_unique<managed_shared_memory>(create_only, (nameMem).c_str(), 65536);
// 创建互斥量
mutex = std::make_unique<named_mutex>(create_only, (nameMtx).c_str());
}
inline auto del_shared() -> void {
// 先移除可能存在的旧共享内存
shared_memory_object::remove(nameMem.c_str());
// 移除可能存在的互斥量
named_mutex::remove(nameMtx.c_str());
}
inline auto recv_shared_and_action() -> void
try {
// 加锁
std::lock_guard<named_mutex> lock(*mutex);
// 查找共享字符串
msg = segment->find<SharedString>(namePtr.c_str());
if (msg.first) { // 找到
std::cout << "Reader read: " << *msg.first << std::endl;
std::string ret = this->lexer(std::string((msg.first)->data(), (msg.first)->size()));
// 在共享内存中创建一个字符串
SharedString* str = segment->construct<SharedString>(nameRet.c_str())(
ret.c_str(), // 初始值(空字符串)
segment->get_allocator<char>() // 必须传入分配器
);
// 销毁writer创建的变量
segment->destroy<SharedString>(namePtr.c_str());
}
}
catch (interprocess_exception& ex) {
std::cerr << ex.what() << std::endl;
}
// 简易词法分析器
std::string lexer(std::string tmp) {
// 要返回的消息
std::string ret = "OK";
if (tmp == "list") {
ret = pls.initialize();
}
else if (tmp.starts_with("kill ")) {
pls.kill(std::stoi(tmp.substr(5)));
}
else if (tmp == "clear") {
pls.clear();
}
//else if (tmp == "shut") {
// this->shut();
//} //关闭不了程序
else {
// 这个分支最好返回自己是否出现了异常
pls.exec(tmp.c_str(), {});
}
// 返回消息
return ret;
}
};
}
// 线程指针
std::unique_ptr<qing::Th> th;
// 全局标志,指示是否应该退出
std::atomic<bool> should_exit(false);
// 子系统的名称(全局参数)
std::string name;
// 消息
std::string msg;
// Windows异步句柄,用于信号转发
#ifdef _WIN32
uv_async_t async_handle;
SERVICE_STATUS_HANDLE hStatus;
SERVICE_STATUS status;
#endif
////////////////////////
////////////////////////
// 解析命令行参数
//
//
// 创建参数解析器
args::ArgumentParser parser("这是一个脚本托管服务。", "请使用专门的通信程序(或本程序自己)进行操作。");
// 显示帮助信息的标志
args::HelpFlag help(parser, "帮助", "显示帮助信息", { 'h', "help" });
// 启用守护进程
args::Flag daemon(parser, "守护进程", "启动守护进程", { 'd', "daemon" });
// 子系统路径
args::ValueFlag<std::string> subSys(parser, "子系统", "输入子系统文件夹的路径", { 's', "sys" });
// 要发送的子系统名字
args::ValueFlag<std::string> arg_to(parser, "发送目标", "输入要发送的子系统路径", { 't', "to" });
// 要发送的信息
args::ValueFlag<std::string> arg_msg(parser, "消息", "输入要发送的消息(<path>|list|kill <pid>| clear)", { 'm', "msg" });
[[noreturn]] static auto parse_args(int argc, char** argv) -> void {
// 解析命令行参数
try {
parser.ParseCLI(argc, argv);
}
catch (const args::Help&) {
std::cout << parser;
exit(0);
}
catch (const args::ParseError& e) {
std::cerr << e.what() << std::endl;
std::cerr << parser;
exit(1);
}
catch (const args::ValidationError& e) {
std::cerr << e.what() << std::endl;
std::cerr << parser;
exit(1);
}
}
////////////////////////
////////////////////////
// 信号处理回调函数
[[noreturn]] static void on_signal(uv_signal_t* handle, int signum) {
std::cout << "\n收到退出信号 " << signum << std::endl;
// 防止重复处理退出信号
if (should_exit) return;
should_exit = true;
// 停止信号监听
uv_signal_stop(handle);
// 执行清理
if (th)
th->WaitClose();
// 关闭事件循环
uv_stop(uv_default_loop());
}
// Windows异步回调函数
#ifdef _WIN32
[[noreturn]] static void async_callback(uv_async_t* handle) {
std::cout << 1 << std::endl;
// 这里可以触发退出流程或其他需要在事件循环中处理的操作
if (!should_exit) {
on_signal(nullptr, SIGINT); // 模拟收到SIGINT信号
}
}
// Windows控制台事件处理程序
static BOOL WINAPI console_handler(DWORD signal) {
std::cout << 1 << std::endl;
switch (signal) {
case CTRL_C_EVENT:
case CTRL_BREAK_EVENT:
// 使用异步句柄将信号转发到libuv事件循环
uv_async_send(&async_handle);
return TRUE;
default:
return FALSE;
}
}
#endif
////////////////////////////////////
////////////////////////////////////
// 分支
//
//
// 发送消息分支
static inline auto SendMsgBranch() -> void {
qing::LTh::send_shared_msg(name, msg);
}
// 守护进程分支
static inline auto DaemonBranch() -> void {
th = std::make_unique<qing::LTh>(name);
th->Activate();
th->WaitStart();
//th->Wait();
}
//
// 分支选择器
[[noreturn]] static auto BranchSelector(uv_idle_t* handle) {
if (should_exit) {
uv_idle_stop(handle);
return;
}
if (th) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
return;
}
if (arg_to && arg_msg) { // 发送消息分支
name = args::get(arg_to);
msg = args::get(arg_msg);
SendMsgBranch();
// 退出
should_exit = true;
// 关闭事件循环
uv_stop(uv_default_loop());
}
else if ((daemon && arg_to) || 1) { // 守护进程分支
std::cout << "程序启动,开始运行..." << std::endl;
std::cout << "按下 CTRL+C 退出程序" << std::endl;
name = (arg_to) ? args::get(arg_to) : "test";
DaemonBranch();
}
else {
//输出帮助文本
std::cout << parser;
// 退出
should_exit = true;
// 关闭事件循环
uv_stop(uv_default_loop());
}
}
////////////////////////////////////
int MyMain(int argc, char** argv) {
parse_args(argc, argv);
//////////
// 信号
//
//
#ifdef _WIN32
// 初始化Windows异步句柄
uv_async_init(uv_default_loop(), &async_handle, async_callback);
// 设置控制台事件处理程序
if (!SetConsoleCtrlHandler(console_handler, TRUE)) {
std::cerr << "无法设置控制台控制处理程序" << std::endl;
return 1;
}
#else
// Unix平台:确保信号不会被忽略
signal(SIGINT, [](int signum) { /* 留给libuv处理 */ });
signal(SIGTERM, [](int signum) { /* 留给libuv处理 */ });
#endif
// 初始化信号处理器
uv_signal_t sig_int, sig_term;
// 监听SIGINT 信号(CTRL + C)
uv_signal_init(uv_default_loop(), &sig_int);
uv_signal_start(&sig_int, on_signal, SIGINT);
// 监听 SIGTERM信号
uv_signal_init(uv_default_loop(), &sig_term);
uv_signal_start(&sig_term, on_signal, SIGTERM);
#ifdef _WIN32
// WINDOWS平台特有的信号
uv_signal_t sig_break;
uv_signal_init(uv_default_loop(), &sig_break);
uv_signal_start(&sig_break, on_signal, SIGBREAK);
#endif
// 设置任务
uv_idle_t idle;
uv_idle_init(uv_default_loop(), &idle);
uv_idle_start(&idle, ::BranchSelector);
// 运行事件循环
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
// 释放资源
uv_close((uv_handle_t*)&sig_int, nullptr);
uv_close((uv_handle_t*)&sig_term, nullptr);
#ifdef _WIN32
uv_close((uv_handle_t*)&sig_break, nullptr);
uv_close((uv_handle_t*)&async_handle, nullptr);
// 移除控制台事件处理程序
SetConsoleCtrlHandler(console_handler, FALSE);
#endif
uv_close((uv_handle_t*)&idle, nullptr);
// 清理事件循环
uv_loop_close(uv_default_loop());
std::cout << "程序已经退出" << std::endl;
return 0;
}
#ifdef _WIN32
[[noreturn]] void ReportStatus(DWORD state) {
status.dwCurrentState = state;
SetServiceStatus(hStatus, &status);
}
[[noreturn]] void ServiceCtrlHandler(DWORD control) {
if (control == SERVICE_CONTROL_STOP) {
ReportStatus(SERVICE_STOP_PENDING);
// 执行清理
ReportStatus(SERVICE_STOPPED);
}
}
[[noreturn]] void WINAPI ServiceMain(DWORD argc, LPTSTR* argv) {
hStatus = RegisterServiceCtrlHandler(L"大顺脚本", ServiceCtrlHandler);
status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
ReportStatus(SERVICE_RUNNING); // 告诉SCM服务已启动
//服务主逻辑
MyMain(argc, argv);
}
#endif
+159
View File
@@ -0,0 +1,159 @@
/* 进程(Process)是计算机中正在执行的程序的一个实例,是
* 操作系统进行资源分配和调度的基本单位
*
* 你可以将其理解为程序的一次动态执行过程——程序
* 是静态的代码文件,而进程是程序运行时的动态实体。
*/
#pragma once
#ifdef _WIN32
#include <WinSock2.h>
#include <Windows.h>
#endif
#include <boost/process/process.hpp>
#include <boost/process/environment.hpp>
#include <boost/asio/io_context.hpp>
#include <list>
#include <memory>
#include <iostream>
namespace qing {
/* 进程列表类,这个类封装了一个
* 容纳Pls::subp的列表
*
* 以及基本的进程操作
*/
class Pls {
public:
// 命名子进程
struct subp {
std::unique_ptr<boost::process::process> p;
std::string name;
};
/* 创建子进程执行一个命令,并且
* 添加到进程列表。
*
* 接受一个std::string类型的文件路径,以及
* std::vector<std::string> 类型的参数列表(缺省)
*
* 优化方案:返回错误信息
*/
void exec(const std::string& path, const std::vector<std::string> &args)
try {
// 检查文件是否存在(好像不会在环境变量中寻找)
if (!boost::filesystem::exists(path)) {
std::cerr << "Error: File not found - " << path << std::endl;
return;
}
// 输入输出上下文
boost::asio::io_context io_ctx;
// 继承当前进程的所有环境变量(旧版)
//auto env = boost::process::environment::current;
// 错误码
boost::system::error_code ec;
// 构造子进程
subp p = { std::move(std::make_unique<boost::process::process>( io_ctx, path, args/*, env, ec*/)), mergeCmd(path, args)};
if (ec) {
std::cerr << "Failed to start process: " << ec.message() << std::endl;
return ;
}
else {
// 推入向量
vec.push_back(std::move(p));
}
}
catch (std::exception &e) {
std::cout << e.what() << std::endl;
}
/* 序列化进程列表 */
inline std::string initialize() {
std::string ret{ "" };
for (auto& item : vec) {
std::ostringstream oss;
ret += (ret == "") ? "" : "\n";
#ifdef _WIN32
DWORD pid = GetProcessId(item.p->native_handle());
oss << pid;
#else
oss << item.p->native_handle();
#endif
ret += oss.str();
ret += "\t";
ret += (item.p->running()) ? "Alive" : "Dead";
ret += "\t";
ret += item.name;
}
return ret;
}
// 杀死一个进程
[[noreturn]] void kill(int pid)
try {
for (auto it = vec.begin(); it != vec.end(); ++it)
if ((*it).p->id() == pid && (*it).p->running()) {
(*it).p->terminate();
//(*it).p->wait(); // 可能杀不死?
//vec.erase(it); // 清除
break;
}
}
catch (std::exception &ex) {
std::cout << ex.what() << std::endl;
}
// 清理死掉的进程
[[noreturn]] void clear() {
for (auto it = vec.begin(); it != vec.end();)
if (!(*it).p->running()) {
it = vec.erase(it);
}
else {
++it;
}
}
// 关闭所有进程
[[noreturn]] void closeAll() {
for (auto& item : vec)
if (item.p->running())
item.p->terminate();
// 加上这个似乎更清爽一些
clear();
}
private:
// 容纳子进程的链表
std::list<subp> vec{};
// 用于操作链表的锁
//std::mutex mtx{};
/* 将一个启动脚本地址,和一个
* 字符串向量组成的参数列表,组装
* 成一条完整的启动命令
*/
inline static std::string mergeCmd(const std::string& path, const std::vector<std::string>& args) {
std::string ret = path;
for (const auto& item : args) {
ret += " ";
ret += item;
}
return ret;
}
};
}
+189
View File
@@ -0,0 +1,189 @@
/* 线程(Thread)是操作系统能够进行运算调度的最小单元,被
* 包含在进程(Process)之中,是进程中的实际运作单元。
* 你可以将它理解为一条在啊代码中独立执行的路径。
*/
#pragma once
#include "Fsm.hpp"
#include <thread>
#include <memory>
#include <chrono>
#include <functional>
namespace qing {
/* 包含一个简易的多线程控制机制,需要共享的变量
* 和函数声明为成员。线程主函数包括了流程控制。
* 要使用需要实现其中的各个事件方法
*
* ?: 已经将fsm改为通用的
* 20250621: 从派生改为持有
*/
class Th {
public:
// 没有C原生的数据结构,可以直接使用缺省构造函数
Th() = default;
// 删除复制构造函数。因为
// 持有线程类,不要轻举妄动。
Th(const Th&) = delete;
// 虚析构函数。具体
// 有什么用忘了,好像是
// 通过析构函数关闭线程时用的
virtual ~Th() = default;
/////////////////////////////////////
// 检查状态,做成
// 虚函数,万一子类有特别要求呢?
virtual inline Fsm::Stat check() {
return fsm.check();
}
/////////////////////////////////////
// 变质——状态改变的方法
//
// 进入唤醒状态
// 1.这里的锁和条件变量是这个类中的。
// 2.唤醒函数不可以进行该类中的锁操作,否则会造成死锁。(忘了为啥,可能跟调用位置相关)
[[noreturn]] virtual void wake() {
fsm.set(Fsm::Stat::START);
} // wake()
// 进入静止状态
[[noreturn]] virtual void stop() {
{
std::lock_guard<std::mutex> lk(mtx_th);
fsm.set(Fsm::Stat::STOP);
ready = true;
}
// 可能会出现多个线程在等待的情况
cv.notify_all();
}// stop()
// 进入关闭状态
[[noreturn]] virtual void shut() {
{
std::lock_guard<std::mutex> lk(mtx_th);
fsm.set(Fsm::Stat::SHUT);
ready = true;
}
cv.notify_all();
}
// 进入运行状态
[[noreturn]] virtual void run() {
{
std::lock_guard<std::mutex> lk(mtx_th);
fsm.set(Fsm::Stat::RUNNING);
ready = true;
}
cv.notify_all();
}
/////////////////////////////////////
//控制
//
// 尝试唤醒线程并等待它开始,据说该函数有问题
[[noreturn]] void WaitStart() {
// 等待线程开始,wake()不可以加锁,否则会死锁
std::unique_lock<std::mutex> lk(mtx_th);
wake();
ready = false;
cv.wait(lk, [this] { return ready; });
}
// 等待线程关闭
[[noreturn]] void WaitClose() {
shut();
if (th->joinable())
th->join();
}
// 仅仅等待线程结束
[[noreturn]] void Wait() {
if (th->joinable())
th->join();
}
// 激活线程,申请线程对象,因为
// 需要确保对象已经被构造了,该函数不能放在构造函数内
[[noreturn]] void Activate() {
// 防止重复激活
if (th) return;
// 申请线程资源
th = std::make_unique<std::thread>(&Th::main, this);
}
protected:
/////////////////////////////////////
// 事件
//
//
// 静止事件
std::function<void()> StopEvent = [this] { fsm.suspend(); };
// 唤醒事件
std::function<void()> WakeEvent = [this] { this->run(); };
// 循环事件
std::function<void()> LoopEvent = [] {
std::this_thread::sleep_for(std::chrono::milliseconds(10L));
};
// 清理事件
std::function<void()> ClearEvent = [] {};
/////////////////////////////////////
// 循环
[[noreturn]] virtual void main() {
// 回字形循环
while (check() != Fsm::Stat::SHUT) {
// 静止状态
while (check() == Fsm::Stat::STOP) {
StopEvent();
}
// 开始事件
if (check() == Fsm::Stat::START) {
WakeEvent();
}
// (从设置阶段)进入运行态
while (check() == Fsm::Stat::RUNNING) {
LoopEvent();
}
// 清理事件,记得检查
// 成员变量有没有获取资源
ClearEvent();
}
}
private:
// 持有状态机类型
qing::Fsm fsm{};
// 持有线程类型
std::unique_ptr<std::thread> th;
// 持有锁类型
std::mutex mtx_th;
// 这里持有条件变量,用于阻塞以等待线程的关闭
std::condition_variable cv;
// 辅助条件变量的逻辑型
bool ready = false;
};
}
File diff suppressed because it is too large. Load diff
+141
View File
@@ -0,0 +1,141 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{a0e6a4c1-02b0-41f5-abb7-33c6e4fb97f6}</ProjectGuid>
<RootNamespace>dashun</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>C:\local\boost_1_88_0;C:\Program Files\libuv\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>C:\local\boost_1_88_0\lib64-msvc-14.3;C:\Program Files\libuv;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>libuv.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="Fsm.hpp" />
<ClCompile Include="Main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="args.hxx" />
<ClInclude Include="Pls.hpp" />
<ClInclude Include="Th.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Fsm.hpp">
<Filter>头文件</Filter>
</ClCompile>
<ClCompile Include="Main.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Th.hpp">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="args.hxx">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="Pls.hpp">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
</Project>
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>
+20
View File
@@ -0,0 +1,20 @@
// dashun_to.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门使用技巧:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件
@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{04d7a85c-43bb-4696-b9c8-f79c2252eda1}</ProjectGuid>
<RootNamespace>dashunto</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="dashun_to.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dashun_to.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
</Project>
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>
+1
View File
@@ -0,0 +1 @@
sc create 大顺脚本 binPath= "C:\Users\90999\Desktop\tws\dashun\x64\Debug\dashun.exe" start= auto DisplayName= "大顺脚本,进程托管服务"