添加cpp和Linux相关记录
This commit is contained in:
parent
3de0fd9fcb
commit
276e3411c6
44
cpp/C++_MJ.txt
Normal file
44
cpp/C++_MJ.txt
Normal file
@ -0,0 +1,44 @@
|
||||
1.sizeof 不是函数,是运算符。
|
||||
2.c++没有写构造函数,C++编译器不一定自动写一个默认构造函数。
|
||||
3.c++会对函数名符号进行改编,可以支持函数重载(name mangling)。
|
||||
4.被extern "C" { 修饰的代码会按照C语言的规则编译、声明被exeter "C"包含,CPP实现可以不要。
|
||||
5.函数调用要开辟会回收栈空间。
|
||||
6.incline 建议编译器 incline。
|
||||
[什么时候使用inline?]
|
||||
(1)函数体积不大
|
||||
(2)频繁调用
|
||||
7.汇编
|
||||
从上往下是向下兼容,实际比如影响AX也是会影响x64中的RAX
|
||||
x64
|
||||
RAX\RBX\RCX\RDX : 通用寄存器
|
||||
x86
|
||||
EAX\EBX\ECX\EDX : 通用寄存器
|
||||
16位
|
||||
AX\BX\CX\DX : 通用寄存器
|
||||
8位
|
||||
AH H High
|
||||
AL L Low
|
||||
8.C++中使用内联汇编
|
||||
汇编中没有;
|
||||
__asm {
|
||||
|
||||
}
|
||||
word 2字节.
|
||||
move dest, src
|
||||
[地址值]([]里面一定是地址值)
|
||||
call 调用
|
||||
字节占用都是低位=>高位占用,
|
||||
已经占用的内存,内部采集大小端方式:
|
||||
|
||||
int a = 3;
|
||||
(高 ----> 低)
|
||||
00000000 00000000 00000000 00000011
|
||||
[大小端] 一般来讲,大多数都是小端模式(低字节放低地址)。
|
||||
|
||||
lea dest, [地址值] (复制地址值)(load effect address)
|
||||
mov dest, [地址值] (复制地址值内容)
|
||||
xor a, b (a,b的异或结果复制给a)
|
||||
add 加, sub 减, inc 自增, dec 自减, jmp 跳转
|
||||
xor 异或
|
||||
|
||||
|
52
cpp/clangd.txt
Normal file
52
cpp/clangd.txt
Normal file
@ -0,0 +1,52 @@
|
||||
"C_Cpp.intelliSenseEngine": "Disabled", // 禁用微软 Cpptools 插件的提示功能
|
||||
"C_Cpp.codeAnalysis.runAutomatically": false,
|
||||
"C_Cpp.formatting": "Disabled",
|
||||
// clangd
|
||||
"clangd.path": "c:\\Users\\Sirius\\AppData\\Roaming\\Code\\User\\globalStorage\\llvm-vs-code-extensions.vscode-clangd\\install\\15.0.3\\clangd_15.0.3\\bin\\clangd.exe", // clangd 安装路径
|
||||
// Clangd 运行参数(在终端/命令行输入 clangd --help-list-hidden 可查看更多)
|
||||
"clangd.arguments": [
|
||||
"--all-scopes-completion", // 全局补全(补全建议会给出在当前作用域不可见的索引,插入后自动补充作用域标识符),例如在main()中直接写cout,即使没有`#include <iostream>`,也会给出`std::cout`的建议,配合"--header-insertion=iwyu",还可自动插入缺失的头文件
|
||||
"--background-index", // 后台分析并保存索引文件
|
||||
"--clang-tidy", // 启用 Clang-Tidy 以提供「静态检查」,下面设置 clang tidy 规则
|
||||
"--clang-tidy-checks=performance-*, bugprone-*, misc-*, google-*, modernize-*, readability-*, portability-*",
|
||||
"--compile-commands-dir=${workspaceFolder}/.vscode", // 编译数据库(例如 compile_commands.json 文件)的目录位置
|
||||
"--completion-parse=auto", // 当 clangd 准备就绪时,用它来分析建议
|
||||
"--completion-style=detailed", // 建议风格:打包(重载函数只会给出一个建议);还可以设置为 detailed
|
||||
// "--query-driver=/usr/bin/clang++", // MacOS 上需要设定 clang 编译器的路径,homebrew 安装的clang 是 /usr/local/opt/llvm/bin/clang++
|
||||
// 启用配置文件(YAML格式)项目配置文件是在项目文件夹里的“.clangd”,用户配置文件是“clangd/config.yaml”,该文件来自:Windows: %USERPROFILE%\AppData\Local || MacOS: ~/Library/Preferences/ || Others: $XDG_CONFIG_HOME, usually ~/.config
|
||||
"--enable-config",
|
||||
"--fallback-style=Webkit", // 默认格式化风格: 在没找到 .clang-format 文件时采用,可用的有 LLVM, Google, Chromium, Mozilla, Webkit, Microsoft, GNU
|
||||
"--function-arg-placeholders=true", // 补全函数时,将会给参数提供占位符,键入后按 Tab 可以切换到下一占位符,乃至函数末
|
||||
"--header-insertion-decorators", // 输入建议中,已包含头文件的项与还未包含头文件的项会以圆点加以区分
|
||||
"--header-insertion=iwyu", // 插入建议时自动引入头文件 iwyu
|
||||
"--include-cleaner-stdlib", // 为标准库头文件启用清理功能(不成熟!!!)
|
||||
"--log=verbose", // 让 Clangd 生成更详细的日志
|
||||
"--pch-storage=memory", // pch 优化的位置(Memory 或 Disk,前者会增加内存开销,但会提升性能)
|
||||
"--pretty", // 输出的 JSON 文件更美观
|
||||
"--ranking-model=decision_forest", // 建议的排序方案:hueristics (启发式), decision_forest (决策树)
|
||||
"-j=12" // 同时开启的任务数量
|
||||
],
|
||||
// Clangd 找不到编译数据库(例如 compile_flags.json 文件)时采用的设置,缺陷是不能直接索引同一项目的不同文件,只能分析系统头文件、当前文件和include的文件
|
||||
"clangd.fallbackFlags": [
|
||||
"-pedantic",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wcast-align",
|
||||
"-Wdouble-promotion",
|
||||
"-Wformat=2",
|
||||
"-Wimplicit-fallthrough",
|
||||
"-Wmisleading-indentation",
|
||||
"-Wnon-virtual-dtor",
|
||||
"-Wnull-dereference",
|
||||
"-Wold-style-cast",
|
||||
"-Woverloaded-virtual",
|
||||
"-Wpedantic",
|
||||
"-Wshadow",
|
||||
"-Wunused",
|
||||
"-pthread",
|
||||
"-fuse-ld=lld",
|
||||
"-fsanitize=address",
|
||||
"-fsanitize=undefined",
|
||||
"-stdlib=libc++",
|
||||
"-std=c++20"
|
||||
],
|
285
cpp/cmake.txt
Normal file
285
cpp/cmake.txt
Normal file
@ -0,0 +1,285 @@
|
||||
下面先介绍一些CMake项目通常都需要进行的配置。下面介绍的内容以make作为构建工具作为示例。
|
||||
|
||||
下面的示例代码可以在开源项目cmake-template(发布在Gitee平台)中查看(当前commit id:c7c6b15)。把仓库克隆下来结合源码阅读本文效果更佳,如果有帮助,请点下Star哟。
|
||||
|
||||
1 设置项目版本和生成version.h
|
||||
一般来说,项目一般需要设置一个版本号,方便进行版本的发布,也可以根据版本对问题或者特性进行追溯和记录。
|
||||
|
||||
通过project命令配置项目信息,如下:
|
||||
|
||||
project(CMakeTemplate VERSION 1.0.0 LANGUAGES C CXX)
|
||||
第一个字段是项目名称;通过VERSION指定版本号,格式为main.minor.patch.tweak,并且CMake会将对应的值分别赋值给以下变量(如果没有设置,则为空字符串):
|
||||
|
||||
PROJECT_VERSION, <PROJECT-NAME>_VERSION
|
||||
PROJECT_VERSION_MAJOR, <PROJECT-NAME>_VERSION_MAJOR
|
||||
PROJECT_VERSION_MINOR, <PROJECT-NAME>_VERSION_MINOR
|
||||
PROJECT_VERSION_PATCH, <PROJECT-NAME>_VERSION_PATCH
|
||||
PROJECT_VERSION_TWEAK, <PROJECT-NAME>_VERSION_TWEAK
|
||||
因此,结合前一篇文章提到的configure_file命令,可以配置自动生成版本头文件,将头文件版本号定义成对应的宏,或者定义成接口,方便在代码运行的时候了解当前的版本号。
|
||||
|
||||
比如:
|
||||
|
||||
configure_file(src/c/cmake_template_version.h.in "${PROJECT_SOURCE_DIR}/src/c/cmake_template_version.h")
|
||||
假如cmake_template_version.h.in内容如下:
|
||||
|
||||
#define CMAKE_TEMPLATE_VERSION_MAJOR @CMakeTemplate_VERSION_MAJOR@
|
||||
#define CMAKE_TEMPLATE_VERSION_MINOR @CMakeTemplate_VERSION_MINOR@
|
||||
#define CMAKE_TEMPLATE_VERSION_PATCH @CMakeTemplate_VERSION_PATCH@
|
||||
执行cmake配置构建系统后,将会自动生成文件:cmake_template_version.h,其中@<var-name>@将会被替换为对应的值:
|
||||
|
||||
#define CMAKE_TEMPLATE_VERSION_MAJOR 1
|
||||
#define CMAKE_TEMPLATE_VERSION_MINOR 0
|
||||
#define CMAKE_TEMPLATE_VERSION_PATCH 0
|
||||
|
||||
2 指定编程语言版本
|
||||
为了在不同机器上编译更加统一,最好指定语言的版本,比如声明C使用c99标准,C++使用c++11标准:
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
这里设置的变量都是CMAKE_开头(包括project命令自动设置的变量),这类变量都是CMake的内置变量,正是通过修改这些变量的值来配置CMake构建的行为。
|
||||
|
||||
CMAKE_、_CMAKE或者以下划线开头后面加上任意CMake命令的变量名都是CMake保留的。
|
||||
|
||||
3 配置编译选项
|
||||
通过命令add_compile_options命令可以为所有编译器配置编译选项(同时对多个编译器生效);通过设置变量CMAKE_C_FLAGS可以配置c编译器的编译选项;而设置变量CMAKE_CXX_FLAGS可配置针对c++编译器的编译选项。比如:
|
||||
|
||||
add_compile_options(-Wall -Wextra -pedantic -Werror)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pipe -std=c99")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe -std=c++11")
|
||||
4 配置编译类型
|
||||
通过设置变量CMAKE_BUILD_TYPE来配置编译类型,可设置为:Debug、Release、RelWithDebInfo、MinSizeRel等,比如:
|
||||
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
当然,更好的方式应该是在执行cmake命令的时候通过参数-D指定:
|
||||
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Debug
|
||||
如果设置编译类型为Debug,那么对于c编译器,CMake会检查是否有针对此编译类型的编译选项CMAKE_C_FLAGS_DEBUG,如果有,则将它的配置内容加到CMAKE_C_FLAGS中。
|
||||
|
||||
可以针对不同的编译类型设置不同的编译选项,比如对于Debug版本,开启调试信息,不进行代码优化:
|
||||
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g -O0")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0")
|
||||
对于Release版本,不包含调试信息,优化等级设置为2:
|
||||
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2")
|
||||
5 添加全局宏定义
|
||||
通过命令add_definitions可以添加全局的宏定义,在源码中就可以通过判断不同的宏定义实现相应的代码逻辑。用法如下:
|
||||
|
||||
add_definitions(-DDEBUG -DREAL_COOL_ENGINEER)
|
||||
6 添加include目录
|
||||
通过命令include_directories来设置头文件的搜索目录,比如:
|
||||
|
||||
include_directories(src/c)
|
||||
二 编译目标文件
|
||||
一般来说,编译目标(target)的类型一般有静态库、动态库和可执行文件。这时编写CMakeLists.txt主要包括两步:
|
||||
|
||||
编译:确定编译目标所需要的源文件
|
||||
|
||||
链接:确定链接的时候需要依赖的额外的库
|
||||
|
||||
下面以开源项目(cmake-template)来演示。项目的目录结构如下:
|
||||
|
||||
./cmake-template
|
||||
├── CMakeLists.txt
|
||||
├── src
|
||||
│ └── c
|
||||
│ ├── cmake_template_version.h
|
||||
│ ├── cmake_template_version.h.in
|
||||
│ ├── main.c
|
||||
│ └── math
|
||||
│ ├── add.c
|
||||
│ ├── add.h
|
||||
│ ├── minus.c
|
||||
│ └── minus.h
|
||||
└── test
|
||||
└── c
|
||||
├── test_add.c
|
||||
└── test_minus.c
|
||||
项目的构建任务为:
|
||||
|
||||
将math目录编译成静态库,命名为math
|
||||
|
||||
编译main.c为可执行文件demo,依赖math静态库
|
||||
|
||||
编译test目录下的测试程序,可以通过命令执行所有的测试
|
||||
|
||||
支持通过命令将编译产物安装及打包
|
||||
|
||||
1 编译静态库
|
||||
这一步需要将项目目录路径src/c/math下的源文件编译为静态库,那么需要获取编译此静态库需要的文件列表,可以使用set命令,或者file命令来进行设置。比如:
|
||||
|
||||
file(GLOB_RECURSE MATH_LIB_SRC src/c/math/*.c)
|
||||
add_library(math STATIC ${MATH_LIB_SRC})
|
||||
使用file命令获取src/c/math目录下所有的*.c文件,然后通过add_library命令编译名为math的静态库,库的类型是第二个参数STATIC指定的。
|
||||
|
||||
如果指定为SHARED则编译的就是动态链接库。
|
||||
|
||||
2 编译可执行文件
|
||||
通过add_executable命令来往构建系统中添加一个可执行构建目标,同样需要指定编译需要的源文件。但是对于可执行文件来说,有时候还会依赖其他的库,则需要使用target_link_libraries命令来声明构建此可执行文件需要链接的库。
|
||||
|
||||
在示例项目中,main.c就使用了src/c/math下实现的一些函数接口,所以依赖于前面构建的math库。所以在CMakeLists.txt中添加以下内容:
|
||||
|
||||
add_executable(demo src/c/main.c)
|
||||
target_link_libraries(demo math)
|
||||
第一行说明编译可执行文件demo需要的源文件(可以指定多个源文件,此处只是以单个文件作为示例);第二行表明对math库存在依赖。
|
||||
|
||||
此时可以在项目的根目录下执行构建和编译命令,并执行demo:
|
||||
|
||||
➜ # cmake -B cmake-build
|
||||
➜ # cmake --build cmake-build
|
||||
➜ # ./cmake-build/demo
|
||||
Hello CMake!
|
||||
10 + 24 = 34
|
||||
40 - 96 = -56
|
||||
三 安装和打包
|
||||
1 安装
|
||||
对于安装来说,其实就是要指定当前项目在执行安装时,需要安装什么内容:
|
||||
|
||||
通过install命令来说明需要安装的内容及目标路径;
|
||||
|
||||
通过设置CMAKE_INSTALL_PREFIX变量说明安装的路径;
|
||||
|
||||
3.15往后的版本可以使用cmake --install --prefix <install-path>覆盖指定安装路径。
|
||||
|
||||
比如,在示例项目中,把math和demo两个目标按文件类型安装:
|
||||
|
||||
install(TARGETS math demo
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib)
|
||||
这里通过TARGETS参数指定需要安装的目标列表;参数RUNTIME DESTINATION、LIBRARY DESTINATION、ARCHIVE DESTINATION分别指定可执行文件、库文件、归档文件分别应该安装到安装目录下个哪个子目录。
|
||||
|
||||
如果指定CMAKE_INSTALL_PREFIX为/usr/local,那么math库将会被安装到路径/usr/local/lib/目录下;而demo可执行文件则在/usr/local/bin目录下。
|
||||
|
||||
CMAKE_INSTALL_PREFIX在不同的系统上有不同的默认值,使用的时候最好显式指定路径。
|
||||
|
||||
同时,还可以使用install命令安装头文件:
|
||||
|
||||
file(GLOB_RECURSE MATH_LIB_HEADERS src/c/math/*.h)
|
||||
install(FILES ${MATH_LIB_HEADERS} DESTINATION include/math)
|
||||
假如将安装到当前项目的output文件夹下,可以执行:
|
||||
|
||||
➜ # cmake -B cmake-build -DCMAKE_INSTALL_PREFIX=./output
|
||||
➜ # cmake --build cmake-build
|
||||
➜ # cd cmake-build && make install && cd -
|
||||
Install the project...
|
||||
-- Install configuration: ""
|
||||
-- Installing: .../cmake-template/output/lib/libmath.a
|
||||
-- Installing: .../gitee/cmake-template/output/bin/demo
|
||||
-- Installing: .../gitee/cmake-template/output/include/math/add.h
|
||||
-- Installing: .../gitee/cmake-template/output/include/math/minus.h
|
||||
可以看到安装了前面install命令指定要安装的文件,并且不同类型的目标文件安装到不同子目录。
|
||||
|
||||
2 打包
|
||||
要使用打包功能,需要执行include(CPack)启用相关的功能,在执行构建编译之后使用cpack命令行工具进行打包安装;对于make工具,也可以使用命令make package。
|
||||
|
||||
打包的内容就是install命令安装的内容,关键需要设置的变量有:
|
||||
|
||||
变量 含义
|
||||
CPACK_GENERATOR 打包使用的压缩工具,比如"ZIP"
|
||||
CPACK_OUTPUT_FILE_PREFIX 打包安装的路径前缀
|
||||
CPACK_INSTALL_PREFIX 打包压缩包的内部目录前缀
|
||||
CPACK_PACKAGE_FILE_NAME 打包压缩包的名称,由CPACK_PACKAGE_NAME、CPACK_PACKAGE_VERSION、CPACK_SYSTEM_NAME三部分构成
|
||||
比如:
|
||||
|
||||
include(CPack)
|
||||
set(CPACK_GENERATOR "ZIP")
|
||||
set(CPACK_PACKAGE_NAME "CMakeTemplate")
|
||||
set(CPACK_SET_DESTDIR ON)
|
||||
set(CPACK_INSTALL_PREFIX "")
|
||||
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
|
||||
假如:CPACK_OUTPUT_FILE_PREFIX设置为/usr/local/package;CPACK_INSTALL_PREFIX设置为real/cool/engineer;CPACK_PACKAGE_FILE_NAME设置为CMakeTemplate-1.0.0;那么执行打包文件的生成路径为:
|
||||
|
||||
/usr/local/package/CMakeTemplate-1.0.0.zip
|
||||
解压这个包得到的目标文件则会位于路径下:
|
||||
|
||||
/usr/local/package/real/cool/engineer/
|
||||
此时重新执行构建,使用cpack命令执行打包:
|
||||
|
||||
➜ # cmake -B cmake-build -DCPACK_OUTPUT_FILE_PREFIX=`pwd`/output
|
||||
➜ # cmake --build cmake-build
|
||||
➜ # cd cmake-build && cpack && cd -
|
||||
CPack: Create package using ZIP
|
||||
CPack: Install projects
|
||||
CPack: - Run preinstall target for: CMakeTemplate
|
||||
CPack: - Install project: CMakeTemplate
|
||||
CPack: Create package
|
||||
CPack: - package: /Users/Farmer/gitee/cmake-template/output/CMakeTemplate-1.0.0-Darwin.zip generated.
|
||||
cpack有一些参数是可以覆盖CMakeLists.txt设置的参数的,比如这里的-G参数就会覆盖变量CPACK_GENERATOR,具体细节可使用cpack --help查看。
|
||||
|
||||
四 测试
|
||||
CMake的测试功能使用起来有几个步骤:
|
||||
|
||||
CMakeLists.txt中通过命令enable_testing()或者include(CTest)来启用测试功能;
|
||||
|
||||
使用add_test命令添加测试样例,指定测试的名称和测试命令、参数;
|
||||
|
||||
构建编译完成后使用ctest命令行工具运行测试。
|
||||
|
||||
为了控制是否开启测试,可使用option命令设置一个开关,在开关打开时才进行测试,比如:
|
||||
|
||||
option(CMAKE_TEMPLATE_ENABLE_TEST "Whether to enable unit tests" ON)
|
||||
if (CMAKE_TEMPLATE_ENABLE_TEST)
|
||||
message(STATUS "Unit tests enabled")
|
||||
enable_testing()
|
||||
endif()
|
||||
这里为了方便后续演示,暂时是默认开启的。
|
||||
|
||||
1 编写测试程序
|
||||
在此文的示例代码中,针对add.c和minus.c实现了两个测试程序,它们的功能是类似的,接受三个参数,用第一和第二个计算两个参数的和或者差,判断是否和第三个参数相等,如test_add.c的代码为:
|
||||
|
||||
// @Author: Farmer Li, 公众号: 很酷的程序员/RealCoolEngineer
|
||||
// @Date: 2021-05-10
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "math/add.h"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 4) {
|
||||
printf("Usage: test_add v1 v2 expected\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x = atoi(argv[1]);
|
||||
int y = atoi(argv[2]);
|
||||
int expected = atoi(argv[3]);
|
||||
int res = add_int(x, y);
|
||||
|
||||
if (res != expected) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
这里需要注意的是,对于测试程序来说,如果返回值非零,则表示测试失败。
|
||||
|
||||
2 添加测试
|
||||
接下来先使用add_executable命令生成测试程序,然后使用add_test命令添加单元测试:
|
||||
|
||||
add_executable(test_add test/c/test_add.c)
|
||||
add_executable(test_minus test/c/test_minus.c)
|
||||
target_link_libraries(test_add math)
|
||||
target_link_libraries(test_minus math)
|
||||
add_test(NAME test_add COMMAND test_add 10 24 34)
|
||||
add_test(NAME test_minus COMMAND test_minus 40 96 -56)
|
||||
3 执行测试
|
||||
现在重新执行cmake命令更新构建系统,执行构建,再执行测试:
|
||||
|
||||
➜ # cmake -B cmake-build
|
||||
➜ # cmake --build cmake-build
|
||||
➜ # cd cmake-build && ctest && cd -
|
||||
Test project /Users/Farmer/gitee/cmake-template/cmake-build
|
||||
Start 1: test_add
|
||||
1/2 Test #1: test_add ......................... Passed 0.00 sec
|
||||
Start 2: test_minus
|
||||
2/2 Test #2: test_minus ....................... Passed 0.01 sec
|
||||
|
||||
100% tests passed, 0 tests failed out of 2
|
||||
使用ctest -VV则可以看到更加详细的测试流程和结果。
|
||||
|
||||
在CMake 3.20往后的版本中,ctest可以使用--test-dir指定测试执行目录。
|
||||
|
||||
至此,一个较为完备的CMakeLists.txt就开发完成了。
|
86
cpp/common/box_sleep.hpp
Normal file
86
cpp/common/box_sleep.hpp
Normal file
@ -0,0 +1,86 @@
|
||||
#ifndef SLEEP_THREAD_HPP_
|
||||
#define SLEEP_THREAD_HPP_
|
||||
|
||||
/*
|
||||
* 跟 Sleep 的功能相同,其不同点是可以 随时终止正在进行的 Sleep。
|
||||
*/
|
||||
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
namespace cpppub {
|
||||
|
||||
typedef class CThreadSleep
|
||||
{
|
||||
public:
|
||||
CThreadSleep();
|
||||
~CThreadSleep() = default;
|
||||
public:
|
||||
// 进入睡眠,不传入值使用默认值,传入则使用传入值。
|
||||
void Sleep(int nMilliseconds = 0);
|
||||
// 停止所有的 Sleep 睡眠,继续向下。
|
||||
void Contiune();
|
||||
// 设置默认的睡眠时长,不填写时其默认值为 10 ms, 如果传入 <= 0 值将使用默认的 10 ms。
|
||||
void SetTimeOut(int nMilliseconds);
|
||||
|
||||
private:
|
||||
bool getStatus() const;
|
||||
|
||||
private:
|
||||
// 同步原语,能用于阻塞一个线程,或同时阻塞多个线程,直至另一线程修改共享变量(条件)并通知 condition_variable
|
||||
std::condition_variable m_Cv;
|
||||
int m_nTimeOut; // 睡眠时间
|
||||
const int m_nDefaultTimeOut = 10; // 默认睡眠时间
|
||||
std::mutex m_Mutex; // 锁
|
||||
bool m_bStopSleep; // 睡眠标志位
|
||||
}ThreadSleep;
|
||||
|
||||
CThreadSleep::CThreadSleep()
|
||||
{
|
||||
m_bStopSleep = false;
|
||||
m_nTimeOut = 10;
|
||||
}
|
||||
|
||||
inline void CThreadSleep::Sleep(int nMilliseconds)
|
||||
{
|
||||
int nSleepTime = m_nTimeOut;
|
||||
if (nMilliseconds > 0)
|
||||
nSleepTime = nMilliseconds;
|
||||
|
||||
m_bStopSleep = false;
|
||||
std::unique_lock<std::mutex> lock(m_Mutex);
|
||||
std::chrono::system_clock::time_point nowtime = std::chrono::system_clock::now();
|
||||
|
||||
// 度过 timeout 时限后 函数求值为 false 则为 false,否则为 true。
|
||||
// 若已度过时限,则求值并返回求值结果。
|
||||
if (m_Cv.wait_until(lock, nowtime + (std::chrono::milliseconds(nSleepTime)),
|
||||
[this] { return getStatus(); })) {
|
||||
// 这里触发手动关闭
|
||||
}
|
||||
else {
|
||||
// 这里触发超时
|
||||
}
|
||||
}
|
||||
|
||||
inline void CThreadSleep::Contiune()
|
||||
{
|
||||
m_bStopSleep = true;
|
||||
m_Cv.notify_all();
|
||||
}
|
||||
|
||||
inline void CThreadSleep::SetTimeOut(int nMilliseconds)
|
||||
{
|
||||
if (nMilliseconds <= 0)
|
||||
m_nTimeOut = m_nDefaultTimeOut;
|
||||
else
|
||||
m_nTimeOut = nMilliseconds;
|
||||
}
|
||||
|
||||
inline bool CThreadSleep::getStatus() const
|
||||
{
|
||||
return m_bStopSleep;
|
||||
}
|
||||
|
||||
}
|
||||
#endif // !SLEEP_THREAD_HPP_
|
||||
|
209
cpp/common/box_threadpool.hpp
Normal file
209
cpp/common/box_threadpool.hpp
Normal file
@ -0,0 +1,209 @@
|
||||
#ifndef THREAD_POOL_HEADER
|
||||
#define THREAD_POOL_HEADER
|
||||
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <future>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
namespace cppbox {
|
||||
|
||||
// 线程安全队列
|
||||
template <typename T> class CQueueMt
|
||||
{
|
||||
public:
|
||||
CQueueMt() = default;
|
||||
CQueueMt(CQueueMt&& rh) noexcept {}
|
||||
~CQueueMt() = default;
|
||||
|
||||
public:
|
||||
// 返回队列是否为空
|
||||
bool IsEmpty()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
return m_queue.empty();
|
||||
}
|
||||
// 返回队列数量
|
||||
size_t Size()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
return m_queue.size();
|
||||
}
|
||||
// 添加元素
|
||||
void Push(T& t)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
m_queue.emplace(t);
|
||||
}
|
||||
// 取出元素
|
||||
bool Pop(T& t)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
if (m_queue.empty())
|
||||
return false;
|
||||
t = std::move(m_queue.front());
|
||||
m_queue.pop();
|
||||
return true;
|
||||
}
|
||||
// 清除
|
||||
void clear()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
std::queue<T> queue;
|
||||
std::swap(m_queue, queue);
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex m_mutex;
|
||||
std::queue<T> m_queue;
|
||||
};
|
||||
|
||||
class CBoxThreadPool
|
||||
{
|
||||
private:
|
||||
class CWorker
|
||||
{
|
||||
public:
|
||||
CWorker(CBoxThreadPool* pThreadPool, const size_t nID)
|
||||
: m_nID(nID), m_pThreadPool(pThreadPool)
|
||||
{
|
||||
is_run_ = false;
|
||||
}
|
||||
// 重载操作
|
||||
void operator()()
|
||||
{
|
||||
// 1.定义基础函数类 func
|
||||
std::function<void()> func;
|
||||
// 2.是否成功取出队列中的元素
|
||||
bool have = false;
|
||||
while (m_pThreadPool->is_start_ || !is_run_ || isContinue()) {
|
||||
// 进入 while 后,标志位置成已进入。
|
||||
is_run_ = true;
|
||||
{
|
||||
// 2.1 为线程环境加锁,互斥访问线程的休眠与唤醒
|
||||
std::unique_lock<std::mutex> lock(m_pThreadPool->mutex_);
|
||||
// 2.2 如果队列为空则阻塞并等待条件变量的通知
|
||||
if (m_pThreadPool->m_queue.IsEmpty())
|
||||
m_pThreadPool->cv_.wait(lock);
|
||||
// 2.3 取出任务队列中的元素
|
||||
have = m_pThreadPool->m_queue.Pop(func);
|
||||
}
|
||||
|
||||
if (have)
|
||||
func();
|
||||
}
|
||||
}
|
||||
// 检查是否需要继续完成未完成的任务
|
||||
bool isContinue()
|
||||
{
|
||||
if (!m_pThreadPool->is_wait_)
|
||||
return false;
|
||||
if (m_pThreadPool->m_queue.IsEmpty())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t m_nID; // 工作ID
|
||||
CBoxThreadPool* m_pThreadPool; // 所属线程池
|
||||
bool is_run_; // 是否进入工作了
|
||||
};
|
||||
|
||||
public:
|
||||
explicit CBoxThreadPool(const int nThreadNum = 4)
|
||||
: th_cnt_(nThreadNum),
|
||||
is_start_(false),
|
||||
is_wait_(false),
|
||||
threads_(std::vector<std::thread>(nThreadNum))
|
||||
{
|
||||
}
|
||||
~CBoxThreadPool() { ShutDownWaitCurrent(); }
|
||||
CBoxThreadPool(const CBoxThreadPool&) = delete;
|
||||
CBoxThreadPool(CBoxThreadPool&&) = delete;
|
||||
CBoxThreadPool& operator=(const CBoxThreadPool&) = delete;
|
||||
CBoxThreadPool& operator=(CBoxThreadPool&&) = delete;
|
||||
|
||||
public:
|
||||
// 初始化线程池
|
||||
void Init()
|
||||
{
|
||||
if (!is_start_) {
|
||||
threads_.resize(th_cnt_);
|
||||
for (size_t i = 0; i < threads_.size(); ++i) {
|
||||
threads_.at(i) = std::thread(CWorker(this, i));
|
||||
}
|
||||
is_start_ = true;
|
||||
is_wait_ = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 等待各线程当前任务完成然后关闭线程池
|
||||
void ShutDownWaitCurrent()
|
||||
{
|
||||
if (!is_start_)
|
||||
return;
|
||||
is_wait_ = false;
|
||||
is_start_ = false;
|
||||
Close();
|
||||
m_queue.clear();
|
||||
}
|
||||
|
||||
// 等待所有已提交的任务完成然后关闭线程池
|
||||
void ShutDownWaitAll()
|
||||
{
|
||||
if (!is_start_)
|
||||
return;
|
||||
is_wait_ = true;
|
||||
is_start_ = false;
|
||||
Close();
|
||||
m_queue.clear();
|
||||
}
|
||||
// 向池子中提交一个待执行函数
|
||||
template <typename F, typename... Args>
|
||||
auto Submit(F&& f, Args&&... args) -> std::future<decltype(f(args...))>
|
||||
{
|
||||
// 1. 创建一个绑定参数的函数,
|
||||
// 连接函数和参数定义,特殊函数类型,避免左右值错误
|
||||
std::function<decltype(f(args...))()> func =
|
||||
std::bind(std::forward<F>(f), std::forward<Args>(args)...);
|
||||
// 2. 使用智能指针以便调用拷贝构造
|
||||
auto pTask =
|
||||
std::make_shared<std::packaged_task<decltype(f(args...))()>>(func);
|
||||
// 3. 包装进一个无参数函数
|
||||
std::function<void()> rf = [pTask]() { (*pTask)(); };
|
||||
// 4. 入队
|
||||
m_queue.Push(rf);
|
||||
// 5. 唤醒一个等待中的线程
|
||||
cv_.notify_one();
|
||||
// 6. 返回先前注册的任务指针
|
||||
return pTask->get_future();
|
||||
}
|
||||
|
||||
private:
|
||||
void Close()
|
||||
{
|
||||
cv_.notify_all();
|
||||
|
||||
for (auto& m_thread : threads_) {
|
||||
if (m_thread.joinable())
|
||||
m_thread.join();
|
||||
}
|
||||
threads_.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
int th_cnt_; // 线程数
|
||||
bool is_start_; // 线程池是否启动
|
||||
bool is_wait_; // 是否等待所有线程结束
|
||||
std::mutex mutex_; // 线程休眠锁互斥
|
||||
|
||||
CQueueMt<std::function<void()>> m_queue;
|
||||
std::vector<std::thread> threads_;
|
||||
std::condition_variable cv_; // 环境锁,用于休眠或者唤醒
|
||||
};
|
||||
|
||||
} // namespace cppbox
|
||||
#endif
|
147
cpp/common/change_net_state.hpp
Normal file
147
cpp/common/change_net_state.hpp
Normal file
@ -0,0 +1,147 @@
|
||||
#include <windows.h>
|
||||
#include <setupapi.h>
|
||||
#include <tchar.h>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#pragma comment(lib,"ws2_32.lib")
|
||||
#pragma comment(lib,"setupapi.lib")
|
||||
|
||||
//wchar_t * char2wchar(const char* cchar)
|
||||
//{
|
||||
// wchar_t *m_wchar;
|
||||
// int len = MultiByteToWideChar(CP_ACP, 0, cchar, strlen(cchar), NULL, 0);
|
||||
// m_wchar = new wchar_t[len + 1];
|
||||
// MultiByteToWideChar(CP_ACP, 0, cchar, strlen(cchar), m_wchar, len);
|
||||
// m_wchar[len] = '\0';
|
||||
// return m_wchar;
|
||||
//}
|
||||
//
|
||||
//char * wchar2char(const wchar_t* wchar)
|
||||
//{
|
||||
// char * m_char;
|
||||
// int len = WideCharToMultiByte(CP_ACP, 0, wchar, wcslen(wchar), NULL, 0, NULL, NULL);
|
||||
// m_char = new char[len + 1];
|
||||
// WideCharToMultiByte(CP_ACP, 0, wchar, wcslen(wchar), m_char, len, NULL, NULL);
|
||||
// m_char[len] = '\0';
|
||||
// return m_char;
|
||||
//}
|
||||
|
||||
BOOL DisableNetInterface(const std::string& szHardWareId, bool bStatus)
|
||||
{
|
||||
IN LPTSTR HardwareId;
|
||||
//硬件ComponentId,注册表地址:system\currentcontrolset\class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0000
|
||||
// HardwareId = L"PCI\\VEN_8086&DEV_0085&SUBSYS_13118086&REV_34";
|
||||
HardwareId = (LPTSTR)szHardWareId.c_str();
|
||||
DWORD NewState;
|
||||
if (bStatus)
|
||||
{
|
||||
NewState = DICS_DISABLE;
|
||||
//禁用
|
||||
}
|
||||
else
|
||||
{
|
||||
NewState = DICS_ENABLE;
|
||||
//启用
|
||||
}
|
||||
//调用ddk函数,来禁用网卡
|
||||
DWORD i, err;
|
||||
BOOL Found = false;
|
||||
HDEVINFO hDevInfo;
|
||||
SP_DEVINFO_DATA spDevInfoData;
|
||||
//访问系统的硬件库
|
||||
hDevInfo = SetupDiGetClassDevs(NULL, "PCI", NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);
|
||||
if (hDevInfo == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
//printf("访问系统硬件出错!");
|
||||
return false;
|
||||
}
|
||||
//枚举硬件,获得需要的接口
|
||||
spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||
for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &spDevInfoData); i++)
|
||||
{
|
||||
DWORD DataT;
|
||||
LPTSTR p, buffer = NULL;
|
||||
DWORD buffersize = 0;
|
||||
//获得硬件的属性值
|
||||
while (!SetupDiGetDeviceRegistryProperty(
|
||||
hDevInfo,
|
||||
&spDevInfoData,
|
||||
SPDRP_HARDWAREID,
|
||||
&DataT,
|
||||
(PBYTE)buffer,
|
||||
buffersize,
|
||||
&buffersize))
|
||||
{
|
||||
if (GetLastError() == ERROR_INVALID_DATA)
|
||||
{
|
||||
//不存在HardwareID. Continue.
|
||||
break;
|
||||
}
|
||||
else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
//buffer size不对.
|
||||
if (buffer)
|
||||
LocalFree(buffer);
|
||||
buffer = (LPTSTR)LocalAlloc(LPTR, buffersize);
|
||||
}
|
||||
else
|
||||
{
|
||||
//未知错误
|
||||
goto cleanup_DeviceInfo;
|
||||
}
|
||||
}
|
||||
if (GetLastError() == ERROR_INVALID_DATA)
|
||||
continue;
|
||||
//比较,找到和网卡ID相同的项
|
||||
for (p = buffer; *p && (p < &buffer[buffersize]); p += lstrlen(p) + sizeof(TCHAR))
|
||||
{
|
||||
if (!_tcscmp(HardwareId, p))
|
||||
{
|
||||
//找到网卡
|
||||
Found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (buffer)
|
||||
LocalFree(buffer);
|
||||
//如果相等
|
||||
if (Found)
|
||||
{
|
||||
//禁用该设备
|
||||
SP_PROPCHANGE_PARAMS spPropChangeParams;
|
||||
spPropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
|
||||
spPropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
|
||||
spPropChangeParams.Scope = DICS_FLAG_GLOBAL;
|
||||
spPropChangeParams.StateChange = NewState;
|
||||
//禁用:DICS_DISABLE,DICS_ENABLE启用
|
||||
//
|
||||
if (!SetupDiSetClassInstallParams(hDevInfo, &spDevInfoData, (SP_CLASSINSTALL_HEADER*)&spPropChangeParams, sizeof(spPropChangeParams)))
|
||||
{
|
||||
DWORD errorcode = GetLastError();
|
||||
}
|
||||
if (!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, &spDevInfoData))
|
||||
{
|
||||
DWORD errorcode = GetLastError();
|
||||
}
|
||||
switch (NewState)
|
||||
{
|
||||
case DICS_DISABLE:
|
||||
printf("成功禁用网络!");
|
||||
break;
|
||||
case DICS_ENABLE:
|
||||
printf("成功启用网络!");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
//delete[] HardwareId;
|
||||
//HardwareId = nullptr;
|
||||
|
||||
//退出时,清理工作环境
|
||||
cleanup_DeviceInfo:
|
||||
err = GetLastError();
|
||||
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||||
SetLastError(err);
|
||||
return true;
|
||||
}
|
64
cpp/common/closeprocess.hpp
Normal file
64
cpp/common/closeprocess.hpp
Normal file
@ -0,0 +1,64 @@
|
||||
#ifndef CLOSE_PROCESS_HPP
|
||||
#define CLOSE_PROCESS_HPP
|
||||
|
||||
/*
|
||||
* 杀掉所有名字等于指定的名称的进程。
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <tlhelp32.h>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
char* Wchar2Char(const wchar_t* wp)
|
||||
{
|
||||
int len = WideCharToMultiByte(CP_ACP, 0, wp, wcslen(wp), NULL, 0, NULL, NULL);
|
||||
char* m_char = new char[len + 1];
|
||||
WideCharToMultiByte(CP_ACP, 0, wp, wcslen(wp), m_char, len, NULL, NULL);
|
||||
m_char[len] = '\0';
|
||||
return m_char;
|
||||
}
|
||||
|
||||
BOOL KillProcessFromName(std::string strProcessName)
|
||||
{
|
||||
//创建进程快照(TH32CS_SNAPPROCESS表示创建所有进程的快照)
|
||||
HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
//PROCESSENTRY32进程快照的结构体
|
||||
PROCESSENTRY32 pe;
|
||||
//实例化后使用Process32First获取第一个快照的进程前必做的初始化操作
|
||||
pe.dwSize = sizeof(PROCESSENTRY32);
|
||||
//下面的IF效果同:
|
||||
//if(hProcessSnap == INVALID_HANDLE_VALUE) 无效的句柄
|
||||
if (!Process32First(hSnapShot, &pe))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
//将字符串转换为小写
|
||||
std::transform(strProcessName.begin(), strProcessName.end(), strProcessName.begin(), ::tolower);
|
||||
//如果句柄有效 则一直获取下一个句柄循环下去
|
||||
while (Process32Next(hSnapShot, &pe))
|
||||
{
|
||||
char* pszTem = Wchar2Char(pe.szExeFile);
|
||||
//pe.szExeFile获取当前进程的可执行文件名称
|
||||
std::string scTmp = std::string(pszTem);
|
||||
delete[] pszTem;
|
||||
//将可执行文件名称所有英文字母修改为小写
|
||||
std::transform(scTmp.begin(), scTmp.end(), scTmp.begin(), ::tolower);
|
||||
//scTmp.MakeLower();
|
||||
//比较当前进程的可执行文件名称和传递进来的文件名称是否相同
|
||||
//相同的话Compare返回0
|
||||
if (scTmp == strProcessName)
|
||||
{
|
||||
//从快照进程中获取该进程的PID(即任务管理器中的PID)
|
||||
DWORD dwProcessID = pe.th32ProcessID;
|
||||
HANDLE hProcess = ::OpenProcess(PROCESS_TERMINATE, FALSE, dwProcessID);
|
||||
::TerminateProcess(hProcess, 0);
|
||||
CloseHandle(hProcess);
|
||||
return TRUE;
|
||||
}
|
||||
//scTmp.ReleaseBuffer();
|
||||
}
|
||||
//strProcessName.ReleaseBuffer();
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
133
cpp/common/judge_ip.hpp
Normal file
133
cpp/common/judge_ip.hpp
Normal file
@ -0,0 +1,133 @@
|
||||
#ifndef W_PUBLIC_H_
|
||||
#define W_PUBLIC_H_
|
||||
|
||||
#include <WinSock2.h>
|
||||
#include <Iphlpapi.h>
|
||||
#include <iostream>
|
||||
#include <windows.h>
|
||||
#include <tlhelp32.h>
|
||||
#include <algorithm>
|
||||
|
||||
#pragma comment(lib,"Iphlpapi.lib") //需要添加Iphlpapi.lib库
|
||||
|
||||
// 工程是否是 Unicode 编码
|
||||
//#define CHARSET_UNICODE_DEFINE
|
||||
namespace cpppub {
|
||||
|
||||
bool IsLocalIPExist(const char* pszIP)
|
||||
{
|
||||
bool isHave = false;
|
||||
//PIP_ADAPTER_INFO结构体指针存储本机网卡信息
|
||||
auto pIpAdapterInfo = new IP_ADAPTER_INFO();
|
||||
//得到结构体大小,用于GetAdaptersInfo参数
|
||||
unsigned long stSize = sizeof(IP_ADAPTER_INFO);
|
||||
//调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量;其中stSize参数既是一个输入量也是一个输出量
|
||||
ULONG nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);
|
||||
delete pIpAdapterInfo;
|
||||
// 这里的操作:重新分配是为了保证有足够的空间来进行存储。
|
||||
pIpAdapterInfo = (IP_ADAPTER_INFO*)(new BYTE[stSize]);
|
||||
nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);
|
||||
//记录网卡数量
|
||||
int netCardNum = 0;
|
||||
//记录每张网卡上的IP地址数量
|
||||
int IPnumPerNetCard = 0;
|
||||
PIP_ADAPTER_INFO header = pIpAdapterInfo;
|
||||
if (ERROR_SUCCESS == nRel)
|
||||
{
|
||||
//输出网卡信息
|
||||
//可能有多网卡,因此通过循环去判断
|
||||
while (pIpAdapterInfo)
|
||||
{
|
||||
IP_ADDR_STRING *pIpAddrString = &(pIpAdapterInfo->IpAddressList);
|
||||
do
|
||||
{
|
||||
if (strcmp(pIpAddrString->IpAddress.String, pszIP) == 0)
|
||||
{
|
||||
isHave = true;
|
||||
break;
|
||||
}
|
||||
pIpAddrString = pIpAddrString->Next;
|
||||
} while (pIpAddrString);
|
||||
|
||||
if (isHave)
|
||||
break;
|
||||
|
||||
pIpAdapterInfo = pIpAdapterInfo->Next;
|
||||
}
|
||||
}
|
||||
//释放内存空间
|
||||
delete[] header;
|
||||
return isHave;
|
||||
}
|
||||
|
||||
|
||||
char* Wchar2Char(const wchar_t* wp)
|
||||
{
|
||||
int len = WideCharToMultiByte(CP_ACP, 0, wp,
|
||||
static_cast<int>(wcslen(wp)), nullptr, 0, nullptr, nullptr);
|
||||
char* m_char = new char[len + 1];
|
||||
WideCharToMultiByte(CP_ACP, 0, wp, static_cast<int>(wcslen(wp)), m_char, len, nullptr, nullptr);
|
||||
m_char[len] = '\0';
|
||||
return m_char;
|
||||
}
|
||||
|
||||
void Wchar2CharFree(const char* pszChar)
|
||||
{
|
||||
delete[] pszChar;
|
||||
}
|
||||
|
||||
BOOL KillProcessFromName(const std::string& strProcessName)
|
||||
{
|
||||
std::string szTemProcessName = strProcessName;
|
||||
//创建进程快照(TH32CS_SNAPPROCESS表示创建所有进程的快照)
|
||||
HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
//PROCESSENTRY32进程快照的结构体
|
||||
PROCESSENTRY32 pe;
|
||||
//实例化后使用Process32First获取第一个快照的进程前必做的初始化操作
|
||||
pe.dwSize = sizeof(PROCESSENTRY32);
|
||||
//下面的IF效果同:
|
||||
//if(hProcessSnap == INVALID_HANDLE_VALUE) 无效的句柄
|
||||
if (!Process32First(hSnapShot, &pe))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
//将字符串转换为小写
|
||||
std::transform(szTemProcessName.begin(), szTemProcessName.end(), szTemProcessName.begin(), ::tolower);
|
||||
//如果句柄有效 则一直获取下一个句柄循环下去
|
||||
while (Process32Next(hSnapShot, &pe))
|
||||
{
|
||||
std::string scTmp;
|
||||
|
||||
// Unicode 编码时
|
||||
// pe.szExeFile获取当前进程的可执行文件名称
|
||||
#ifdef CHARSET_UNICODE_DEFINE
|
||||
char* pszTem = Wchar2Char(pe.szExeFile);
|
||||
scTmp = std::string(pszTem);
|
||||
Wchar2CharFree(pszTem);
|
||||
pszTem = nullptr;
|
||||
#else
|
||||
scTmp = std::string(pe.szExeFile);
|
||||
#endif // CHARSET_UNICODE_DEFINE
|
||||
|
||||
//将可执行文件名称所有英文字母修改为小写
|
||||
std::transform(scTmp.begin(), scTmp.end(), scTmp.begin(), ::tolower);
|
||||
//scTmp.MakeLower();
|
||||
//比较当前进程的可执行文件名称和传递进来的文件名称是否相同
|
||||
//相同的话Compare返回0
|
||||
if (scTmp == strProcessName)
|
||||
{
|
||||
//从快照进程中获取该进程的PID(即任务管理器中的PID)
|
||||
DWORD dwProcessID = pe.th32ProcessID;
|
||||
HANDLE hProcess = ::OpenProcess(PROCESS_TERMINATE, FALSE, dwProcessID);
|
||||
::TerminateProcess(hProcess, 0);
|
||||
CloseHandle(hProcess);
|
||||
return TRUE;
|
||||
}
|
||||
//scTmp.ReleaseBuffer();
|
||||
}
|
||||
//strProcessName.ReleaseBuffer();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
86
cpp/common/msvc_complier_info.cpp
Normal file
86
cpp/common/msvc_complier_info.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
int main() {
|
||||
int mscVersion = _MSC_VER;
|
||||
|
||||
mscVersion = mscVersion - mscVersion % 10;
|
||||
std::string vcVersion;
|
||||
std::string releaseDate;
|
||||
std::string toolsetVersion;
|
||||
std::string ideInfo;
|
||||
|
||||
if (mscVersion == 1200) {
|
||||
vcVersion = "VC6.0 (Visual C++ 6.0)";
|
||||
releaseDate = "1998";
|
||||
toolsetVersion = "V60";
|
||||
ideInfo = "MSVC++ 6.0";
|
||||
} else if (mscVersion == 1300) {
|
||||
vcVersion = "VC7.0 (Visual Studio 2002)";
|
||||
releaseDate = "2002";
|
||||
toolsetVersion = "V70";
|
||||
ideInfo = "7.0";
|
||||
} else if (mscVersion == 1310) {
|
||||
vcVersion = "VC7.1 (Visual Studio 2003)";
|
||||
releaseDate = "2003";
|
||||
toolsetVersion = "V71";
|
||||
ideInfo = "7.1";
|
||||
} else if (mscVersion == 1400) {
|
||||
vcVersion = "VC8.0 (Visual Studio 2005)";
|
||||
releaseDate = "2005";
|
||||
toolsetVersion = "V80";
|
||||
ideInfo = "8.0";
|
||||
} else if (mscVersion == 1500) {
|
||||
vcVersion = "VC9.0 (Visual Studio 2008)";
|
||||
releaseDate = "2008";
|
||||
toolsetVersion = "V90";
|
||||
ideInfo = "9.0";
|
||||
} else if (mscVersion == 1600) {
|
||||
vcVersion = "VC10.0 (Visual Studio 2010)";
|
||||
releaseDate = "2010";
|
||||
toolsetVersion = "V100";
|
||||
ideInfo = "10.0";
|
||||
} else if (mscVersion == 1700) {
|
||||
vcVersion = "VC11.0 (Visual Studio 2012)";
|
||||
releaseDate = "2012";
|
||||
toolsetVersion = "V110";
|
||||
ideInfo = "11.0";
|
||||
} else if (mscVersion == 1800) {
|
||||
vcVersion = "VC12.0 (Visual Studio 2013)";
|
||||
releaseDate = "2013";
|
||||
toolsetVersion = "V120";
|
||||
ideInfo = "12.0";
|
||||
} else if (mscVersion == 1900) {
|
||||
vcVersion = "VC14.0 (Visual Studio 2015)";
|
||||
releaseDate = "2015";
|
||||
toolsetVersion = "V140";
|
||||
ideInfo = "14.0";
|
||||
} else if (mscVersion == 1910) {
|
||||
vcVersion = "VC14.1 (Visual Studio 2017)";
|
||||
releaseDate = "2017";
|
||||
toolsetVersion = "V141";
|
||||
ideInfo = "14.1";
|
||||
} else if (mscVersion == 1920) {
|
||||
vcVersion = "VC14.2 (Visual Studio 2019)";
|
||||
releaseDate = "2019";
|
||||
toolsetVersion = "V142";
|
||||
ideInfo = "14.2";
|
||||
} else if (mscVersion == 1930) {
|
||||
vcVersion = "VC14.3 (Visual Studio 2022)";
|
||||
releaseDate = "2022";
|
||||
toolsetVersion = "V143";
|
||||
ideInfo = "14.3";
|
||||
} else {
|
||||
vcVersion = "未知版本";
|
||||
releaseDate = "未知";
|
||||
toolsetVersion = "未知";
|
||||
ideInfo = "未知";
|
||||
}
|
||||
|
||||
std::cout << "VC版本: " << vcVersion << std::endl;
|
||||
std::cout << "发布时间: " << releaseDate << std::endl;
|
||||
std::cout << "工具集版本: " << toolsetVersion << std::endl;
|
||||
std::cout << "IDE信息: " << ideInfo << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
99
cpp/common/network_card.hpp
Normal file
99
cpp/common/network_card.hpp
Normal file
@ -0,0 +1,99 @@
|
||||
// 这里是其他函数实现的源Demo
|
||||
#include <winsock2.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <iostream>
|
||||
|
||||
int NetWorkInter()
|
||||
{
|
||||
//PIP_ADAPTER_INFO结构体指针存储本机网卡信息
|
||||
PIP_ADAPTER_INFO pIpAdapterInfo = new IP_ADAPTER_INFO();
|
||||
//得到结构体大小,用于GetAdaptersInfo参数
|
||||
unsigned long stSize = sizeof(IP_ADAPTER_INFO);
|
||||
//调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量;其中stSize参数既是一个输入量也是一个输出量
|
||||
int nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);
|
||||
//记录网卡数量
|
||||
int netCardNum = 0;
|
||||
//记录每张网卡上的IP地址数量
|
||||
int IPnumPerNetCard = 0;
|
||||
if (ERROR_BUFFER_OVERFLOW == nRel)
|
||||
{
|
||||
//如果函数返回的是ERROR_BUFFER_OVERFLOW
|
||||
//则说明GetAdaptersInfo参数传递的内存空间不够,同时其传出stSize,表示需要的空间大小
|
||||
//这也是说明为什么stSize既是一个输入量也是一个输出量
|
||||
//释放原来的内存空间
|
||||
delete pIpAdapterInfo;
|
||||
//重新申请内存空间用来存储所有网卡信息
|
||||
pIpAdapterInfo = (PIP_ADAPTER_INFO)new BYTE[stSize];
|
||||
//再次调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量
|
||||
nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);
|
||||
}
|
||||
if (ERROR_SUCCESS == nRel)
|
||||
{
|
||||
//输出网卡信息
|
||||
//可能有多网卡,因此通过循环去判断
|
||||
while (pIpAdapterInfo)
|
||||
{
|
||||
std::cout << "网卡数量:" << ++netCardNum << std::endl;
|
||||
std::cout << "网卡名称:" << pIpAdapterInfo->AdapterName << std::endl;
|
||||
std::cout << "网卡描述:" << pIpAdapterInfo->Description << std::endl;
|
||||
switch (pIpAdapterInfo->Type)
|
||||
{
|
||||
case MIB_IF_TYPE_OTHER:
|
||||
std::cout << "网卡类型:" << "OTHER" << std::endl;
|
||||
break;
|
||||
case MIB_IF_TYPE_ETHERNET:
|
||||
std::cout << "网卡类型:" << "ETHERNET" << std::endl;
|
||||
break;
|
||||
case MIB_IF_TYPE_TOKENRING:
|
||||
std::cout << "网卡类型:" << "TOKENRING" << std::endl;
|
||||
break;
|
||||
case MIB_IF_TYPE_FDDI:
|
||||
std::cout << "网卡类型:" << "FDDI" << std::endl;
|
||||
break;
|
||||
case MIB_IF_TYPE_PPP:
|
||||
printf("PP\n");
|
||||
std::cout << "网卡类型:" << "PPP" << std::endl;
|
||||
break;
|
||||
case MIB_IF_TYPE_LOOPBACK:
|
||||
std::cout << "网卡类型:" << "LOOPBACK" << std::endl;
|
||||
break;
|
||||
case MIB_IF_TYPE_SLIP:
|
||||
std::cout << "网卡类型:" << "SLIP" << std::endl;
|
||||
break;
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
std::cout << "网卡MAC地址:";
|
||||
for (DWORD i = 0; i < pIpAdapterInfo->AddressLength; i++)
|
||||
if (i < pIpAdapterInfo->AddressLength - 1)
|
||||
{
|
||||
printf("%02X-", pIpAdapterInfo->Address[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%02X\n", pIpAdapterInfo->Address[i]);
|
||||
}
|
||||
std::cout << "网卡IP地址如下:" << std::endl;
|
||||
//可能网卡有多IP,因此通过循环去判断
|
||||
IP_ADDR_STRING *pIpAddrString = &(pIpAdapterInfo->IpAddressList);
|
||||
do
|
||||
{
|
||||
std::cout << "该网卡上的IP数量:" << ++IPnumPerNetCard << std::endl;
|
||||
std::cout << "IP 地址:" << pIpAddrString->IpAddress.String << std::endl;
|
||||
std::cout << "子网地址:" << pIpAddrString->IpMask.String << std::endl;
|
||||
std::cout << "网关地址:" << pIpAdapterInfo->GatewayList.IpAddress.String << std::endl;
|
||||
pIpAddrString = pIpAddrString->Next;
|
||||
} while (pIpAddrString);
|
||||
pIpAdapterInfo = pIpAdapterInfo->Next;
|
||||
std::cout << "--------------------------------------------------------------------" << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
//释放内存空间
|
||||
if (pIpAdapterInfo)
|
||||
{
|
||||
delete pIpAdapterInfo;
|
||||
}
|
||||
return 0;
|
||||
}
|
93
cpp/error/cpp_err.cpp
Normal file
93
cpp/error/cpp_err.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
#include "cpp_err.h"
|
||||
#include <string>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include "windows.h"
|
||||
#include "DbgHelp.h"
|
||||
#endif
|
||||
|
||||
void stackoverflow()
|
||||
{
|
||||
// 1.线程栈空间有上限: windows 默认:1MB,Linux默认 2MB。
|
||||
// 2.当前线程占用栈空间大小:线程函数调用堆栈中各个函数占用的栈空间总和。
|
||||
// 3.哪些对象占用了栈空间:
|
||||
// (1)函数局部变量
|
||||
// (2)调用函数的参数
|
||||
// 4.常见引发栈溢出的原因:
|
||||
// (1)递归太深
|
||||
// (2)局部变量占用太大
|
||||
// (3)switch-case case分支过多。
|
||||
// (4)死循环调用
|
||||
// 5.发生线程栈溢出时,VS可能直接退出,无法看到调用堆栈,可以使用WinDBG查看。
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
int GenerateMiniDump(PEXCEPTION_POINTERS pExceptionPointers, const std::string& dump_dir)
|
||||
{
|
||||
// 定义函数指针
|
||||
typedef BOOL(WINAPI * MiniDumpWriteDumpT)(
|
||||
HANDLE,
|
||||
DWORD,
|
||||
HANDLE,
|
||||
MINIDUMP_TYPE,
|
||||
PMINIDUMP_EXCEPTION_INFORMATION,
|
||||
PMINIDUMP_USER_STREAM_INFORMATION,
|
||||
PMINIDUMP_CALLBACK_INFORMATION
|
||||
);
|
||||
// 从 "DbgHelp.dll" 库中获取 "MiniDumpWriteDump" 函数
|
||||
MiniDumpWriteDumpT pfnMiniDumpWriteDump = NULL;
|
||||
HMODULE hDbgHelp = LoadLibrary("DbgHelp.dll");
|
||||
if (NULL == hDbgHelp)
|
||||
{
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
pfnMiniDumpWriteDump = (MiniDumpWriteDumpT)GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
|
||||
|
||||
if (NULL == pfnMiniDumpWriteDump)
|
||||
{
|
||||
FreeLibrary(hDbgHelp);
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
// 创建 dmp 文件
|
||||
char path_buffer[512]{};
|
||||
char szVersion[] = "DumpDemo_v1.0";
|
||||
SYSTEMTIME stLocalTime;
|
||||
GetLocalTime(&stLocalTime);
|
||||
std::snprintf(path_buffer, sizeof(path_buffer), "%s\\%s-%04d%02d%02d-%02d%02d%02d.dmp", dump_dir.c_str(),
|
||||
szVersion, stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
|
||||
stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond);
|
||||
HANDLE hDumpFile = CreateFile(path_buffer, GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_WRITE | FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
|
||||
if (INVALID_HANDLE_VALUE == hDumpFile)
|
||||
{
|
||||
FreeLibrary(hDbgHelp);
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
// 写入 dmp 文件
|
||||
MINIDUMP_EXCEPTION_INFORMATION expParam;
|
||||
expParam.ThreadId = GetCurrentThreadId();
|
||||
expParam.ExceptionPointers = pExceptionPointers;
|
||||
expParam.ClientPointers = FALSE;
|
||||
pfnMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
|
||||
hDumpFile, MiniDumpWithDataSegs, (pExceptionPointers ? &expParam : NULL), NULL, NULL);
|
||||
// 释放文件
|
||||
CloseHandle(hDumpFile);
|
||||
FreeLibrary(hDbgHelp);
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS lpExceptionInfo)
|
||||
{
|
||||
// 这里做一些异常的过滤或提示
|
||||
if (IsDebuggerPresent())
|
||||
{
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
return GenerateMiniDump(lpExceptionInfo, "D:\\");
|
||||
}
|
||||
// windows cpp 崩溃使用 windbg 调试
|
||||
void use_windbg()
|
||||
{
|
||||
SetUnhandledExceptionFilter(ExceptionFilter);
|
||||
}
|
||||
#endif
|
9
cpp/error/cpp_err.h
Normal file
9
cpp/error/cpp_err.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
// 线程栈溢出
|
||||
void stackoverflow();
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// windows cpp 崩溃使用 windbg 调试
|
||||
void use_windbg();
|
||||
#endif
|
29
cpp/export_c/ex_lib.cpp
Normal file
29
cpp/export_c/ex_lib.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include "ex_lib.h"
|
||||
#include "my_math.h"
|
||||
#include <new>
|
||||
|
||||
struct math_struct {
|
||||
my_math impl;
|
||||
};
|
||||
|
||||
extern "C"
|
||||
math_struct* create()
|
||||
{
|
||||
return new(std::nothrow) math_struct;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
int get_sum(struct math_struct* ms, int a, int b)
|
||||
{
|
||||
if (!ms)
|
||||
return -1;
|
||||
return ms->impl.GetSum(a, b);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void free_math(struct math_struct* ms)
|
||||
{
|
||||
if (!ms)
|
||||
return;
|
||||
delete ms;
|
||||
}
|
19
cpp/export_c/ex_lib.h
Normal file
19
cpp/export_c/ex_lib.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef EX_LIB_H_
|
||||
#define EX_LIB_H_
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct math_struct;
|
||||
|
||||
math_struct* create();
|
||||
|
||||
int get_sum(struct math_struct* ms, int a, int b);
|
||||
|
||||
void free_math(struct math_struct* ms);
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // !_EX_LIB_H_
|
10
cpp/export_c/main.cpp
Normal file
10
cpp/export_c/main.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include <cstdio>
|
||||
#include "ex_lib.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
math_struct* pMath = create();
|
||||
printf("23 + 56 = %d\n", get_sum(pMath, 23, 56));
|
||||
free_math(pMath);
|
||||
return 0;
|
||||
}
|
6
cpp/export_c/my_math.cpp
Normal file
6
cpp/export_c/my_math.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include "my_math.h"
|
||||
|
||||
int my_math::GetSum(int a, int b) const
|
||||
{
|
||||
return a + b + m_nBase;
|
||||
}
|
13
cpp/export_c/my_math.h
Normal file
13
cpp/export_c/my_math.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
class my_math
|
||||
{
|
||||
private:
|
||||
int m_nBase {6};
|
||||
public:
|
||||
my_math() = default;
|
||||
~my_math() = default;
|
||||
public:
|
||||
int GetSum(int a, int b) const;
|
||||
};
|
||||
|
22
linux.txt
22
linux.txt
@ -1,22 +0,0 @@
|
||||
1.ssh配置免访问文件:authorized_keys
|
||||
2.apt设置临时代理:
|
||||
sudo apt-get -o Acquire::http::proxy="socks5h://192.168.0.102:7890/" install mariadb-server
|
||||
3.CentOS7 升级GCC
|
||||
(3.1) rpm -q gcc
|
||||
(3.2) rpm -e [第二步查到的版本号]
|
||||
如果
|
||||
error: Failed dependencies:
|
||||
gcc = 4.4.7-23.el6 is needed by (installed) gcc-c++-4.4.7-23.el6.x86_64
|
||||
gcc = 4.4.4 is needed by (installed) libtool-2.2.6-15.5.el6.x86_64
|
||||
rpm -e gcc-c++-4.4.7-23.el6.x86_64
|
||||
rpm -e libtool-2.2.6-15.5.el6.x86_64
|
||||
验证卸载:
|
||||
[root@123 /]# gcc -v
|
||||
-bash: /usr/bin/gcc: No such file or directory
|
||||
[root@123 /]# g++ -v
|
||||
-bash: /usr/bin/g++: No such file or directory
|
||||
yum install centos-release-scl
|
||||
yum install -y devtoolset-11-gcc devtoolset-11-gcc-c++
|
||||
scl enable devtoolset-11 bash
|
||||
vim /etc/profile
|
||||
PATH=$PATH::/opt/rh/devtoolset-11/root/usr/bin
|
147
linux/Linux-base.txt
Normal file
147
linux/Linux-base.txt
Normal file
@ -0,0 +1,147 @@
|
||||
1.ssh配置免访问文件:authorized_keys
|
||||
2.apt设置临时代理:
|
||||
sudo apt-get -o Acquire::http::proxy="socks5h://192.168.0.102:7890/" install mariadb-server
|
||||
3.CentOS7 升级GCC
|
||||
(3.1) rpm -q gcc
|
||||
(3.2) rpm -e [第二步查到的版本号]
|
||||
如果
|
||||
error: Failed dependencies:
|
||||
gcc = 4.4.7-23.el6 is needed by (installed) gcc-c++-4.4.7-23.el6.x86_64
|
||||
gcc = 4.4.4 is needed by (installed) libtool-2.2.6-15.5.el6.x86_64
|
||||
rpm -e gcc-c++-4.4.7-23.el6.x86_64
|
||||
rpm -e libtool-2.2.6-15.5.el6.x86_64
|
||||
验证卸载:
|
||||
[root@123 /]# gcc -v
|
||||
-bash: /usr/bin/gcc: No such file or directory
|
||||
[root@123 /]# g++ -v
|
||||
-bash: /usr/bin/g++: No such file or directory
|
||||
yum install centos-release-scl
|
||||
yum install -y devtoolset-11-gcc devtoolset-11-gcc-c++
|
||||
scl enable devtoolset-11 bash
|
||||
vim /etc/profile
|
||||
PATH=$PATH::/opt/rh/devtoolset-11/root/usr/bin
|
||||
|
||||
==>Debian系列安装后的网卡配置:
|
||||
|
||||
1.U盘安装一个无线网卡驱动包。
|
||||
2.然后需要链接有线安装两个组件:net-tools wireless-tools
|
||||
sudo apt install xxx
|
||||
3.安装完毕之后查看无线网卡的信息,例如名称为: wlan0
|
||||
4.配置netplan,(之前网上讲的是/etc/network/interface,在这里不是)
|
||||
在/etc/netplan/目录下有yaml文件,可以查看是哪个里面配置了网卡信息。
|
||||
默认内容是:
|
||||
network:
|
||||
ethernets:
|
||||
ehth0:
|
||||
dhcp4: true
|
||||
optional: true
|
||||
version 2
|
||||
在这里添加(最外层跟ethernets对齐):
|
||||
renderer: networkd
|
||||
wifis:
|
||||
wlan0:
|
||||
dhcp4: true
|
||||
access-points:
|
||||
"xxxwifiname":
|
||||
password: "xxxxwifipasswd"
|
||||
5.使用sudo netplan apply启用。
|
||||
|
||||
配置文件
|
||||
/etc/systemd/logind.conf
|
||||
|
||||
配置说明
|
||||
HandlePowerKey: 按下电源键后的行为,默认power off
|
||||
HandleSleepKey: 按下挂起键后的行为,默认suspend
|
||||
HandleHibernateKey: 按下休眠键后的行为,默认hibernate
|
||||
HandleLidSwitch: 合上笔记本盖后的行为,默认suspend
|
||||
|
||||
只监视带有 “power-switch” 标签的 输入设备的 key(按下按钮)/lid(合上盖子) 事件。
|
||||
|
||||
如果主机插入了一个扩展坞(docking station) 或者连接了多个显示器, 那么"合上盖子"将执行 HandleLidSwitchDocked= 动作;
|
||||
如果主机使用外部电源, 并且 HandleLidSwitchExternalPower= 不是默认值(“ignore”), 那么"合上盖子"将执行 HandleLidSwitchExternalPower= 动作; 否则将执行 HandleLidSwitch= 动作。
|
||||
|
||||
参数说明
|
||||
ignore(无操作),
|
||||
poweroff(关闭系统并切断电源),
|
||||
reboot(重新启动),
|
||||
halt(关闭系统但不切断电源),
|
||||
kexec(调用内核"kexec"函数),
|
||||
suspend(休眠到内存),
|
||||
hibernate(休眠到硬盘),
|
||||
hybrid-sleep(同时休眠到内存与硬盘),
|
||||
suspend-then-hibernate(先休眠到内存超时后再休眠到硬盘),
|
||||
lock(锁屏)
|
||||
|
||||
设置笔记本合并盖子不休眠
|
||||
编辑文件/etc/systemd/logind.conf
|
||||
|
||||
将
|
||||
|
||||
#HandleLidSwitch=suspend
|
||||
1
|
||||
注意前面的 # 也要去掉
|
||||
|
||||
修改为(无操作)
|
||||
|
||||
HandleLidSwitch=ignore
|
||||
1
|
||||
或(锁屏)
|
||||
|
||||
HandleLidSwitch=lock
|
||||
1
|
||||
重启服务
|
||||
|
||||
service systemd-logind restart
|
||||
1
|
||||
文章知识点与官方知识档
|
||||
————————————————
|
||||
版权声明:本文为CSDN博主「猫巳」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
|
||||
原文链接:https://blog.csdn.net/qq_31635851/article/details/124627990
|
||||
|
||||
Q1: Qt5 安装之后无法打开,那么就在cmd命令行中,设置 export QT_DEBUG_PLUGINS=1
|
||||
然后启动应用程序,会报相信的错误信息,一般是缺少各种库,比如libqxcb依赖的库有的没有,则使用
|
||||
ldd libqxcb.so
|
||||
查看具体哪些没有,然后使用 apt search xxxx 这些没有的库,最后安装。
|
||||
|
||||
Q2: 设置iBus中文输入法
|
||||
|
||||
为什么使用iBus输入法,因为fcitx有很多兼容性问题。
|
||||
|
||||
# 彻底卸载sogou和fcitx
|
||||
sudo apt purge sogoupinyin
|
||||
sudo apt purge fcitx
|
||||
sudo apt autoremove
|
||||
sudo apt remove fcitx*
|
||||
sudo apt purge fcitx*
|
||||
sudo apt autoremove
|
||||
|
||||
# 删除配置文件
|
||||
cd .config/
|
||||
rm -rf sogoupinyin/
|
||||
rm -rf ibus
|
||||
|
||||
# 安装ibus
|
||||
sudo apt install ibus ibus-sunpinyin
|
||||
|
||||
Q3: 键盘功能键设置失效问题
|
||||
echo options hid_apple fnmode=2 | sudo tee -a /etc/modprobe.d/hid_apple.conf
|
||||
sudo update-initramfs -u -k all
|
||||
sudo reboot
|
||||
|
||||
# Debian/Ubuntu/Mint
|
||||
sudo apt install initramfs-tools
|
||||
# the "-k all" part is not always needed, but it's better to do that for all kernels anyway
|
||||
sudo update-initramfs -u -k all
|
||||
|
||||
# RedHat/Fedora/CentOS
|
||||
sudo dracut --regenerate-all --force 作者:大敏鸽 https://www.bilibili.com/read/cv16950091 出处:bilibili
|
||||
|
||||
R1: 使用 plank 作为 dock 坞
|
||||
sudo apt-get install pavucontrol
|
||||
|
||||
安装远程桌面
|
||||
sudo apt-get install tightvncserver xrdp
|
||||
|
||||
秘钥
|
||||
ssh-keygen
|
||||
pub公钥>>authorized_keys
|
310
linux/Linux-knowledge.txt
Normal file
310
linux/Linux-knowledge.txt
Normal file
@ -0,0 +1,310 @@
|
||||
ctrl+p 上一个命令,ctrl+n 下一个命令
|
||||
ctrl+b 光标回移, ctrl+f 向后移动, ctrl+a 行首, ctrl+e 行尾
|
||||
ctrl+h 删除前, ctrl+d 删除后。Linux中光标盖住的是后一个字符。
|
||||
ctrl+u 删除光标前面所有。ctrl+l 清屏。
|
||||
|
||||
vim 基础操作:
|
||||
j :下移一行
|
||||
k :上移一行
|
||||
h :左移一个字符
|
||||
l :右移一个字符
|
||||
gg :跳到第一行
|
||||
G :跳到最后一行
|
||||
0 :左移到行首
|
||||
$ :右移到行尾
|
||||
ctrl + f :向下翻页
|
||||
ctrl + b :向上翻页
|
||||
ctrl + d :向下翻半页( d 代表 down )
|
||||
ctrl + u :向上翻半页( u 代表 up )
|
||||
H :移动到屏幕最上面(页面本身不动)( H 代表 high )
|
||||
L :移动到屏幕最下面(页面本身不动)( L 代表 low )
|
||||
M :移动到屏幕中间行(页面本身不动)( M 代表 middle )
|
||||
zt :把当前行移动到屏幕最上面( t 代表 top )
|
||||
zb :把当前行移动到屏幕最下面( b 代表 bottom )
|
||||
z. :把当前行移动到屏幕中间
|
||||
:<n> :跳到第 <n> 行(需要回车)
|
||||
|
||||
ls 可传一个目录参数。
|
||||
Liunx的目录结构:
|
||||
/bin: 常用命令
|
||||
/boot: 启动系统的核心文件
|
||||
/dev: Linux的外部设备,访问设备与访问文件的方式是一样的。
|
||||
/etc: 系统管理所需要的配置文件和子目录。
|
||||
/home: 用户目录。
|
||||
/lib: 库文件。
|
||||
/lost+found: 一般是空的,非法关机之后存放一些文件。
|
||||
/media: Linux会自动识别一些设备,如U盘,自动挂载到Media下面。
|
||||
/mnt: 让用户临时挂载别的文件系统时用。
|
||||
/opt: 给主机额外安装软件所摆放的目录, 默认为空。
|
||||
/proc: 虚拟的目录,内存的映射,可以直接访问这个目录来获取系统信息。
|
||||
这个目录的内容不在硬盘而是在内存中, 可以直接修改。
|
||||
/root: 超级用户目录。
|
||||
/sbin: 系统管理员的程序。
|
||||
/selinux: 是Redhat/Centos特有的一个安全机制,类似防火墙。
|
||||
/srv: 服务启动之后需要提取的数据。
|
||||
/sys: Liunx2.6内核的大变化
|
||||
/tmp: 存放临时文件。
|
||||
/usr: 很多用户程序和文件放在这里。
|
||||
/usr/bin: 系统用户程序。
|
||||
/usr/sbin: 超级用户使用的比较高级的管理程序和系统守护程序。
|
||||
/usr/src: 内核代码默认放置目录。
|
||||
/var: 存放不断扩充的东西,比如各种日志文件。
|
||||
|
||||
|
||||
cd -: 切换到临近目录。
|
||||
yun@debian:
|
||||
yun是当前登录的用户名,debian是安装系统时设置的主机名。
|
||||
$: 普通用户
|
||||
#: 超级用户
|
||||
直接cd,回家目录。
|
||||
|
||||
创建软链接:
|
||||
ln -s /home/yun/hello.c /home/yun/hello.soft
|
||||
ln -s /home/yun/download xxx.soft
|
||||
创建硬链接(并没有拷贝):
|
||||
ln /home/yun/hello.c hello.hard
|
||||
|
||||
wc: 获取文本文件的行数,单词数,字符数。
|
||||
od: 查看二进制文件,od -t 指定显示格式。
|
||||
du: 查看当前目录的大小。du -h
|
||||
|
||||
-rw-rw-r--,-文件,rw-文件所有者权限,rw-所属组权限。r--其他人权限。
|
||||
chmod:
|
||||
1.文字设定,[who]文件所有者u, 文件所属组g, 其他人o, 所有人a
|
||||
+-= (增减覆盖) [mode]读r,w写,x执行。
|
||||
2.数字设定,r->4, w->2, x->1, chmod -001 xxx
|
||||
|
||||
修改文件所属组所有者:
|
||||
chown Lisi main.cpp 所有者变了,但是所有组没有变化。
|
||||
chown Zhangsan:group2 都变了。
|
||||
chgrp 仅修改所有组。chgrp group3 xxx.cpp
|
||||
|
||||
mkfifo 创建管道
|
||||
所有的目录能查看和进入,必须有x,可执行权限。
|
||||
find [path] -name "xxx.cpp"
|
||||
?: 通配一个字符
|
||||
*: 通配所有字符。
|
||||
find [path] -size +10k[-10 k,M,]
|
||||
查找范围,多个-size即可。
|
||||
find [path] -type d
|
||||
文件类型-所有者权限-同组用户权限-其他人权限-硬链接数-所有者-所属组-占用-时间
|
||||
Linux 文件类型:
|
||||
-: 普通文件(f)
|
||||
d: 目录
|
||||
l: 链接符
|
||||
b: 块设备
|
||||
c: 字符设备
|
||||
s: socket设备
|
||||
p: 管道
|
||||
|
||||
卸载硬盘:umount /media/user/xxx-usb
|
||||
sudo fdisk -l 查看设备信息。比如U盘是/dev/sdb
|
||||
挂载硬盘:mount devicename /mnt
|
||||
sd->SCSI Device
|
||||
hd->Hard Disk
|
||||
fd->Floppy Disk
|
||||
主分区最多有4个。sda4
|
||||
|
||||
压缩相关:
|
||||
gzip 打包:g(un)zip *.txt ->xxx.gz 文件
|
||||
b(un)zip2 *.txt 都不会保留原文件,没有打包压缩。->bz2文件
|
||||
|
||||
tar: c-创建,x-解压缩, v-显示信息, f-指定名字,
|
||||
z-使用gzip的方式压缩,j-使用bzip2的方式压缩,不添加zj只能打包。
|
||||
|
||||
压缩:tar zcvf xxx -> xxx.tar.gz tar jcvf xxx -> xxx.tar.bz2
|
||||
完整示例:tar zcvf result.tar.gz *.txt
|
||||
解压到指定目录:
|
||||
tar zxvf xxx.tar.gz -C /home/yun/test/
|
||||
|
||||
终端[文字终端][图形界面终端]
|
||||
tty1->tty6 tty7
|
||||
who
|
||||
pts: 设备终端
|
||||
|
||||
PID 进程的ID
|
||||
ps [a 查看当前所有用户][u 显示用户的信息][x 查看没有终端的应用程序]
|
||||
使用管道重定向(|){输出作为另外一个命令的输入}
|
||||
ps aux | grep bash
|
||||
kill -l 查看信号
|
||||
kill -SIGKILL 2351 或者 kill -9 8311 也可以
|
||||
|
||||
env 环境变量
|
||||
|
||||
网络相关命令:
|
||||
ip addr, ping [-c 4 -i xx s], ifconfig,
|
||||
nslookup www.baidu.com 查看IP地址。
|
||||
|
||||
用户的添加:
|
||||
adduser (脚本) + Zhangsan
|
||||
useradd (命令)
|
||||
su Zhangsan 切换用户
|
||||
useradd [-s 什么解析器(/bin/bash)][-g 所属组(Robin)][-d 目录(/home/xxx)]
|
||||
[-m 如果没有xxx目录就创建Robin]
|
||||
groupadd xxxGroup 增加组
|
||||
passwd Zhangsan 修改密码
|
||||
删除用户:deluser, userdel -r
|
||||
/etc/passwd下可以查看用户
|
||||
|
||||
vsftpd: FTP服务器的一个软件。
|
||||
service xxx restart
|
||||
lftp: 可以上传和下载目录。
|
||||
|
||||
alias: 查看命令是否被封装
|
||||
ldd: 查看so文件依赖。
|
||||
Linux会优先搜索LD_LIBRARY_PATH,之后再去默认位置查找。
|
||||
也可以设置:/etc/ld.so.conf, ldconfig更新生效。
|
||||
|
||||
gdb xxx
|
||||
l 查看源码,包含main函数的文件。
|
||||
否则 l qimen.c:20 查看这块代码
|
||||
l qimen.c:run 也可以。
|
||||
继续查看后面的继续输入l或者直接回车。
|
||||
break xxx行(b 行) 普通断点。
|
||||
特殊断点:b 20 if i==15
|
||||
i b: 查看断点信息。(info break)
|
||||
start开始运行,执行一步。
|
||||
r 直接跑。[run]
|
||||
单步调试:n, 直接到断点:c (continue)
|
||||
进入函数:s (step)
|
||||
p 打印值。
|
||||
ptype 查看变量类型。
|
||||
display i 追踪变量i的值。
|
||||
undisplay 变量编号取消追踪。
|
||||
u 跳出单次循环
|
||||
finish 跳出进入的函数体。取消里面的断点才可以退出。
|
||||
d 编号删除断点。[del]
|
||||
set var i=10 设置变量的值。
|
||||
quit 退出。
|
||||
|
||||
Makefile的编写:
|
||||
三要素:目标,依赖,命令。 --> 一条规则
|
||||
result: sub.h sub.cpp
|
||||
g++ main.cpp sub.h sub.cpp -o result
|
||||
分开编译,防止每次全部编译。
|
||||
math.o: sub.cpp
|
||||
g++ -c sub.cpp
|
||||
main.o: main.cpp
|
||||
g++ -c main.cpp
|
||||
result: main.o math.o
|
||||
g++ -o result main.o math.o
|
||||
|
||||
Makefile中的变量。
|
||||
obj=main.o math.o
|
||||
result: $(obj)
|
||||
g++ -o result $(obj)
|
||||
|
||||
vim 替换:3,4s/prestr/afterstr
|
||||
makefile语法一样的情况:
|
||||
{模式规则}
|
||||
%.o:%.c
|
||||
g++ -c $< -o $@
|
||||
原理:
|
||||
1.例如依赖sub.o,那么%.o中的%就对应成了sub,
|
||||
即sub.o: sub.c
|
||||
2.$<: 自动变量, 规则中的第一个依赖。
|
||||
$@: 规则中的目标。
|
||||
$^: 规则中的所有依赖。
|
||||
以上只能在命令模式中使用。
|
||||
一般:CPPFLAGS:预处理器需要的参数,例如: -I
|
||||
CFLAGS:编译参数,例如: -Wall
|
||||
LDFLAGS:链接库参数,例如: -L
|
||||
makefile中的函数,所有的函数都有返回值。
|
||||
src=$(wildcard ./*.c)
|
||||
obj=$(patsubst ./%.c, ./%.o, $(src))
|
||||
|
||||
.PHONY:clean 声明伪目标,不检查文件。
|
||||
-rm [-]如果当前命令失败,继续执行。
|
||||
|
||||
全局变量不初始化=0,局部的未知。
|
||||
FILE* 结构体:文件描述符,读写指针,I/O缓冲区(addr)de:8KB
|
||||
Linux 启动一个进程后内存模型:{虚拟地址}
|
||||
虚拟地址作用:1.空间隔离 2.访问不连续物理空间 3.物理内存分配。
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
Linux kernel[内存管理,进程管理,设备驱动管理,文件系统]
|
||||
| 内核区32位是,3G~4G
|
||||
环境变量
|
||||
命令行参数
|
||||
栈(向下增长)
|
||||
共享库
|
||||
堆(向上增长)
|
||||
>>>>>>>>>
|
||||
.bss未初始化变量
|
||||
.data已初始化变量
|
||||
xxx 其他
|
||||
.text代码段
|
||||
>>>>>>>>> ELF段
|
||||
受保护的地址(0~4K)。
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
PCB进程控制块。文件描述符表[一个数组]。
|
||||
默认打开了三个,标准输入输出错误。
|
||||
打开一个文件占用一个描述符,最小占用原则。
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
file xxx可以查看xxx信息。
|
||||
|
||||
C库函数与系统函数之间的关系:
|
||||
例如[printf]
|
||||
->系统API(应用层write)
|
||||
->系统调用(sys_write) {用户空间到内核空间转换}
|
||||
->内核层(驱动)
|
||||
->硬件显示。
|
||||
|
||||
Linux系统IO函数:open, read, write, lseek 可使用man文档。
|
||||
man 章节号 open
|
||||
errno 全局变量
|
||||
perror(const char* s)[stdio.h]
|
||||
open系统函数中指定的权限与umask掩码取反做一个按位与的操作。
|
||||
|
||||
在vim中,可以直接使用K查看函数文档。
|
||||
|
||||
守护进程
|
||||
1.后台服务
|
||||
2.不受登录注册影响
|
||||
3.一般以d结尾。
|
||||
4.周期性执行任务
|
||||
5.独立于终端
|
||||
|
||||
简述秘钥使用方法:
|
||||
非对称加密算法:加密使用的密钥和解密使用的密钥是不同的。 公钥密码体制就是一种非对称加密算法
|
||||
私钥,公钥。服务器持有公钥,本地私钥可以登录。
|
||||
加密解密过程如下:
|
||||
加密:通过加密算法和公钥对内容(或者说明文)进行加密,得到密文。
|
||||
解密:通过解密算法和私钥对密文进行解密,得到明文。
|
||||
注意:由公钥加密的内容,只能由私钥进行解密。
|
||||
|
||||
服务:[debian]
|
||||
|
||||
/etc/systemd/system/
|
||||
xxx.service
|
||||
[Unit]
|
||||
Description=EyeblueTank
|
||||
Documentation=https://tank-doc.eyeblue.cn
|
||||
Wants=network.target
|
||||
After=network.target mariadb.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/home/yun/program/tank/tank
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
# 装载tank服务
|
||||
systemctl daemon-reload
|
||||
# 设置tank开机启动
|
||||
systemctl enable tank.service
|
||||
# 查看tank状态
|
||||
systemctl status tank.service
|
||||
# 启动tank
|
||||
systemctl start tank.service
|
||||
# 重启tank
|
||||
systemctl restart tank.service
|
||||
# 停止tank
|
||||
systemctl stop tank.service
|
||||
|
||||
1.安装mariadb 记录安装版本为10.5
|
||||
sudo apt-get install mariadb-server
|
||||
sudo mysql_secure_installation设置密码即可。
|
||||
CREATE DATABASE boys CHARACTER SET = utf8 COLLATE = utf8_general_ci;
|
||||
|
||||
neofetch
|
185
qt/QtCompilerConfigure.txt
Normal file
185
qt/QtCompilerConfigure.txt
Normal file
@ -0,0 +1,185 @@
|
||||
1.configure meta:
|
||||
-help,-h ............显示此帮助屏幕
|
||||
-verbose,-v .........在配置期间输出详细消息
|
||||
-continue............尽管有错误仍然继续配置
|
||||
-redo ................用以前使用的选项重新配置。其他选项可能会通过,但不会保存以供-redo稍后使用。
|
||||
-recheck .............放弃缓存的负配置测试结果。安装缺失的依赖关系后使用它。
|
||||
-recheck-all .........放弃所有缓存的配置测试结果。
|
||||
-feature- <特征> ...启用<特征>
|
||||
-no-feature- <feature>禁用<feature> [none]
|
||||
-list-features .......列出可用功能。请注意一些功能也有专用的命令行选项。
|
||||
-list-libraries ......列出可能的外部依赖关系。
|
||||
2.Build options:
|
||||
-opensource ..........构建Qt的开源版本
|
||||
-commercial ..........构建Qt的商业版
|
||||
-confirm-license .....自动确认许可证
|
||||
-release.............关闭调试版本的Qt [yes]
|
||||
-debug ...............打开调试生成Qt [no]
|
||||
-debug-and-release ...构建两个版本的Qt,包含和不包含打开调试[是](仅适用于Apple和Windows)
|
||||
-optimize-debug ......在调试版本中启用调试友好的优化[自动](MSVC不支持)
|
||||
-optimize-size .......优化发布版本的大小而不是速度[no]
|
||||
-optimized-tools .....甚至在调试版本中构建优化的主机工具[no]
|
||||
-force-debug-info ....为发布版本创建符号文件[no]
|
||||
-separate-debug-info。分离调试信息以分离文件[no]
|
||||
-strip ...............释放不需要的符号的二进制文件[是]
|
||||
-force-asserts .......即使在发布版本中启用Q_ASSERT [no]
|
||||
-developer-build .....编译并链接Qt以开发Qt本身(用于自动测试的出口,额外检查等)[no]
|
||||
-shared..............建立共享的Qt库[是](不适用于UIKit)
|
||||
-static ..............构建静态Qt库[no](对于UIKit是)
|
||||
-framework ...........构建Qt框架包[是](仅限Apple)
|
||||
-platform <target> ...选择主机mkspec [检测到]
|
||||
-xplatform <target> ..交叉编译时选择target mkspec [PLATFORM]
|
||||
-device <name> .......交叉编译设备<name>
|
||||
-device-option <key = value> ...为设备mkspec添加选项
|
||||
-appstore-compliant ..禁用平台应用商店中不允许使用的代码。默认情况下,默认情况下,默认情况下,平台需要通过默认应用商店进行分发,特别是Android,iOS,tvOS,watchOS和Universal Windows Platform。 [汽车]
|
||||
-qtnamespace <name> ..将所有Qt库代码封装在'namespace <name> {...}'中。
|
||||
-qtlibinfix <infix>将所有libQt5 * .so重命名为libQt5 * <infix> .so。
|
||||
-testcocoon ..........带有TestCocoon代码覆盖工具的仪器[no]
|
||||
-gcov ................具有GCov代码覆盖工具的仪器[no]
|
||||
-sanitize {address | thread | memory | undefined}仪器与指定的编译器消毒剂。
|
||||
-c ++ std <edition> ....选择C ++标准<edition> [c ++ 1z / c ++ 14 / c ++ 11](不支持MSVC)
|
||||
-sse2 ................使用SSE2指令[自动]
|
||||
-sse3 / -ssse3 / -sse4.1 / -sse4.2 / -avx / -avx2 / -avx512启用特定的x86指令[auto]启用的仍然受到运行时检测。
|
||||
-mips_dsp / -mips_dspr2使用MIPS DSP / rev2指令[auto]
|
||||
-qreal <type> ........ typedef qreal到指定的类型。 [双]注意:这会影响二进制兼容性。
|
||||
-R <string> ..........为Qt添加一个显式的运行时库路径库。支持相对于LIBDIR的路径。
|
||||
-rpath ...............使用库链接Qt库和可执行文件将路径安装为运行时库路径。如同-R LIBDIR。在苹果平台上,禁用这意味着使用绝对安装名称(基于 LIBDIR)动态库和框架。 [汽车]减少输出......减少输出符号的数量[自动]
|
||||
-reuce-relocations ..减少重定位量[auto](仅适用于Unix)
|
||||
-plugin-manifests ....将清单嵌入插件[no](仅限Windows)
|
||||
-static-runtime ......使用-static,使用静态运行时[no](仅限Windows)
|
||||
-pch .................使用预编译头文件[auto]
|
||||
-ltcg ................使用链接时间码生成[no]
|
||||
-use-gold-linker .....使用GNU gold链接器[auto]
|
||||
-incredibuild-xge ....使用IncrediBuild XGE [no](仅限Windows)
|
||||
-ccache ..............使用ccache编译器缓存[no](仅适用于Unix)
|
||||
-make-tool <tool> ....使用<tool>构建qmake [nmake](仅适用于Windows)
|
||||
-mp ..................使用多个处理器进行编译(仅限MSVC)
|
||||
-warnings-are-errors。将警告视为错误[no; yes如果-developer-build]
|
||||
-silent ..............减少构建输出以便发出警告和错误可以更容易地看到
|
||||
3.Build environment:
|
||||
-sysroot <dir> ....... 将<dir>设置为目标sysroot
|
||||
-gcc-sysroot ......... 使用-sysroot,将编译器通过--sysroot [yes]
|
||||
-pkg-config ..........使用pkg-config [auto](仅适用于Unix)
|
||||
-D <string> ..........传递附加的预处理器定义
|
||||
-I <string> ..........传递额外的包含路径
|
||||
-L <string> ..........传递额外的库路径
|
||||
-F <string> ..........传递额外的框架路径(仅适用于Apple)
|
||||
-sdk <sdk> ...........使用Apple提供的SDK <sdk>构建Qt。争论应该是以下列出的可用SDK之一'xcodebuild -showsdks'。请注意,该参数仅适用于Qt库和使用目标mkspec构建的应用程序 - 不是主机工具,如qmake,moc,rcc等。
|
||||
-android-sdk path ....设置Android SDK根路径[$ ANDROID_SDK_ROOT]
|
||||
-android-ndk路径....设置Android NDK根路径[$ ANDROID_NDK_ROOT]
|
||||
-android-ndk-platform设置Android平台
|
||||
-android-ndk-host ....设置Android NDK主机(linux-x86,linux-x86_64等)[$ ANDROID_NDK_HOST]
|
||||
-android-arch ........设置Android体系结构(armeabi,armeabi-v7a,arm64-v8a,x86,x86_64,mips,mips64)
|
||||
-android-toolchain-version ...设置Android工具链版本
|
||||
-android-style-assets自动从设备中提取样式资产运行。此选项使Android样式表现良好正确的,但也使得Android平台插件与LGPL2.1不兼容。 [是]
|
||||
4.Component selection:
|
||||
-skip <repo> .........从构建中排除整个存储库。
|
||||
-make <part> .........将<part>添加到要构建的零件列表中。指定此选项将首先清除默认列表。[库和例子,如果不是交叉构建也是工具,还测试是否 -
|
||||
开发人员构建]
|
||||
-nomake <part> .......从要构建的零件列表中排除<part>。
|
||||
-compile-examples ....未设置时,只安装示例的源代码[是]
|
||||
-gui .................构建Qt GUI模块和依赖[yes]
|
||||
-widgets .............编译Qt Widgets模块和依赖[yes]
|
||||
-no-dbus .............不要构建Qt D-Bus模块[Android和Windows默认]
|
||||
-dbus-linked .........构建Qt D-Bus并链接到libdbus-1 [auto]
|
||||
-dbus-runtime ........构建Qt D-Bus并动态加载libdbus-1 [no]
|
||||
-accessibility.......启用可访问性支持[是]注意:不建议禁用可访问性。
|
||||
-qml-debug ...........启用QML调试支持[yes]
|
||||
Qt附带一些第三方库的捆绑副本。这些被使用默认情况下,如果自动检测相应的系统库失败。
|
||||
5.Core options:
|
||||
-doubleconversion ....选择使用的双转换库[system / qt / no]没有暗示使用sscanf_l和snprintf_l(不精确)。
|
||||
-glib ................启用Glib支持[no;在Unix上自动]
|
||||
-eventfd .............启用eventfd支持
|
||||
-inotify .............启用inotify支持
|
||||
-iconv ...............启用iconv(3)支持[posix / sun / gnu / no](仅适用于Unix)
|
||||
-icu .................启用ICU支持[自动]
|
||||
-pcre ................选择使用的libpcre2 [system / qt]
|
||||
-pps .................启用PPS支持[自动](仅限QNX)
|
||||
-zlib ................选择用过的zlib [system / qt]
|
||||
6.Logging backends:
|
||||
-Journald ..........启用日志支持[no](仅限Unix)
|
||||
-syslog ............启用syslog支持[no](仅适用于Unix)
|
||||
-slog2 .............启用slog2支持[自动](仅限QNX)
|
||||
7.Network options:
|
||||
-ssl .................启用SSL支持方法[自动]
|
||||
-no-openssl ..........不要使用OpenSSL [Apple和WinRT上的默认]
|
||||
-openssl-linked ......使用OpenSSL并链接到libssl [no]
|
||||
-openssl-runtime .....使用OpenSSL并动态加载libssl [auto]
|
||||
-securetransport .....使用SecureTransport [auto](仅限Apple)
|
||||
-sctp ................启用SCTP支持[no]
|
||||
-libproxy ............启用libproxy的使用[no]
|
||||
-system-proxies ......默认使用系统网络代理[yes]
|
||||
8.Gui, printing, widget options:
|
||||
-cups ................启用CUPS支持[自动](仅适用于Unix)
|
||||
-fontconfig ..........启用Fontconfig支持[auto](仅适用于Unix)
|
||||
-freetype ............选择使用的FreeType [system / qt / no]
|
||||
-harfbuzz ............选择用过的HarfBuzz-NG [系统/ qt / no](不在Apple和Windows上自动检测)
|
||||
-gtk .................启用GTK平台主题支持[auto]
|
||||
-lgmon ...............启用lgmon支持[自动](仅限QNX)
|
||||
-no-opengl ...........禁用OpenGL支持
|
||||
-opengl <api> ........启用OpenGL支持。支持的API:es2(在Windows上默认),桌面(在Unix上默认),动态(仅限Windows)
|
||||
-opengles3 ...........启用OpenGL ES 3.x支持而不是ES 2.x [自动]
|
||||
-angle ...............使用捆绑的ANGLE支持OpenGL ES 2.0 [自动](仅限Windows)
|
||||
-combined-angle-lib ..将LibEGL和LibGLESv2合并到LibANGLE(仅限Windows)
|
||||
-qpa <name> ..........选择默认的QPA后端(例如,xcb,cocoa,windows)
|
||||
-xcb-xlib .............启用Xcb-Xlib支持[auto]
|
||||
9.Platform backends:
|
||||
-direct2d ..........启用Direct2D支持[自动](仅限Windows)
|
||||
-directfb ..........启用DirectFB支持[no](仅适用于Unix)
|
||||
-eglfs .............启用EGLFS支持[auto;没有在Android和Windows上]
|
||||
-gbm ...............为GBM [auto]启用后端(仅限Linux)
|
||||
-kms ...............启用KMS [auto]的后端(仅适用于Linux)
|
||||
-linuxfb ...........启用Linux Framebuffer支持[auto](仅限Linux)
|
||||
-mirclient .........启用Mir客户端支持[no](仅Linux)
|
||||
-xcb ...............选择使用的xcb- *库[system / qt / no](-qt-xcb仍然使用libxcb本身的系统版本)
|
||||
10.Input backends:
|
||||
-evdev .............启用evdev支持[auto]
|
||||
-imf ...............启用IMF支持[自动](仅限QNX)
|
||||
-libinput ..........启用libinput支持[auto]
|
||||
-mtdev .............启用mtdev支持[auto]
|
||||
-tslib .............启用tslib支持[自动]
|
||||
-xinput2 ...........启用XInput2支持[自动]
|
||||
-xkbcommon-x11 .....选择与xcb结合使用的xkbcommon[系统/ QT / NO]
|
||||
-xkb-config-root <dir> ...使用-qt-xkbcommon-x11,设置默认的XKB配置根目录<dir> [检测]
|
||||
-xkbcommon-evdev ...启用X-less xkbcommon与libinput结合使用[汽车]
|
||||
11.Image formats:
|
||||
-gif ...............启用对GIF的读取支持[自动]
|
||||
-ico ...............启用对ICO的支持[是]
|
||||
-libpng ............选择用过的libpng [system / qt / no]
|
||||
-libjpeg ...........选择使用的libjpeg [system / qt / no]
|
||||
12.Database options:
|
||||
-sql- <driver> ........启用SQL <驱动程序>插件。支持的驱动db2 ibase mysql oci odbc psql sqlite2 sqlite tds[全自动]
|
||||
-sqlite ..............选择用过的sqlite3 [系统/ qt]
|
||||
13.Qt3D options:
|
||||
-assimp ..............选择使用的assimp库[system / qt / no]
|
||||
-qt3d-profile-jobs ...启用作业分析[no]
|
||||
-qt3d-profile-gl .....启用OpenGL分析[no]
|
||||
-qt3d-simd ...........选择SIMD支持级别[no / sse2 / avx2]
|
||||
-qt3d-render .........启用Qt3D渲染方面[是]
|
||||
-qt3d-input ..........启用Qt3D输入方面[是]
|
||||
-qt3d-logic ..........启用Qt3D逻辑方面[是]
|
||||
-qt3d-extras .........启用Qt3D Extras方面[yes]
|
||||
-qt3d-animation .......启用Qt3D动画方面[是]
|
||||
14.Multimedia options:
|
||||
-pulseaudio ..........启用PulseAudio支持[自动](仅适用于Unix)
|
||||
-alsa ................启用ALSA支持[自动](仅适用于Unix)
|
||||
-no-gstreamer ........禁用对GStreamer的支持
|
||||
-gstreamer [版本]。启用GStreamer支持[自动]在没有参数的情况下,首先尝试1.0,然后再尝试0.10。
|
||||
-mediaplayer-backend <名称> ...选择媒体播放器后端(仅限Windows)支持的后端:directshow(默认),wmf
|
||||
15.Webengine options:
|
||||
-webengine-alsa ................启用ALSA支持[自动](仅限Linux)
|
||||
-webengine-pulseaudio ..........启用PulseAudio支持[自动](仅限Linux)
|
||||
-webengine-embedded-build ......启用Linux嵌入式构建[auto](仅限Linux)
|
||||
-webengine-icu .................使用系统ICU库[system / qt](仅限Linux)
|
||||
-webengine -ffmpeg ..............使用系统FFmpeg库[system / qt](仅限Linux)
|
||||
-webengine-opus ................使用系统Opus库[system / qt](仅限Linux)
|
||||
-webengine-webp ................使用系统WebP库[system / qt](仅限Linux)
|
||||
-webengine-pepper-plugins ......启用Pepper Flash和Widevine插件[自动]
|
||||
-webengine-printing-and-pdf ....启用打印和输出到PDF[汽车]
|
||||
-webengine-proprietary-codecs ..启用对专有编解码器的支持[no]
|
||||
-webengine-spellchecker ........启用对拼写检查程序的支持[是]
|
||||
-webengine-native-spellchecker。启用对原生拼写检查器的支持[否](仅限macOS)
|
||||
-webengine-webrtc ..............启用对WebRTC的支持[自动]
|
||||
————————————————
|
||||
版权声明:本文为CSDN博主「天空之城8020」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
|
||||
原文链接:https://blog.csdn.net/kongcheng253/article/details/129001104
|
13
qt/Qt乱码问题.txt
Normal file
13
qt/Qt乱码问题.txt
Normal file
@ -0,0 +1,13 @@
|
||||
《在windows下解决乱码问题的一个比较完美的方法(纯UTF-8环境使用下)(不影响系统其他软件的使用)》
|
||||
一、Qt设置文件编码为:
|
||||
(1) UTF-8
|
||||
(2) BOM 如果是UTF-8则添加
|
||||
二、Qt项目中运行的时候使用外部Terminal(也就是CMD)且做如下设定:
|
||||
(1) 先在启动的外部 cmd 窗口属性中勾选使用旧版控制台,然后重新启动一次(Qt运行项目的cmd,不是运行cmd)。
|
||||
(2) 步骤一完成后在注册表(regedit)中的HKEY_CURRENT_USER\Console\下会有
|
||||
一个 qt_creator_process_stub 的一个项,将此项中的 CodePage 名称的值更改为
|
||||
十进制(65001)后保存。
|
||||
(3) 此时重新运行Qt项目,发现还是有乱码,此时,将步骤一中的勾选取消就可以了。
|
||||
|
||||
《此方法未测试》
|
||||
SetConsoleOutputCP(65001);
|
Loading…
x
Reference in New Issue
Block a user