diff --git a/linux/command.md b/linux/command.md index 04f3e92..4a524a8 100644 --- a/linux/command.md +++ b/linux/command.md @@ -124,6 +124,7 @@ - [wget](#wget) - [NetworkManager](#networkmanager) - [nmap](#nmap) +- [iperf3](#iperf) : 网络性能测试工具 - [index](#index) @@ -777,3 +778,25 @@ exit # 退出 chroot umount -R /mnt # 卸载所有分区 reboot ``` + +--- + +### **iperf** + +- 通用参数 + - `-p` : 指定端口 + - `-i` : 报告间隔时间(s) + - `-V` : 详细日志 + +- 客户端参数 + - `-c` : 指定服务端IP + - `-u` : UDP + - `-R` : 反向传输(服务器发,客户端收) + - `-P` : 并发连接数 + - `-b` : UDP目标带宽 + +- 服务端参数 + - `-s` : 启动服务器 + - `-B` : 绑定指定IP + +--- diff --git a/program/c_cpp/libs/dbtools.h b/program/c_cpp/libs/dbtools.h deleted file mode 100644 index 52fc8d9..0000000 --- a/program/c_cpp/libs/dbtools.h +++ /dev/null @@ -1,25 +0,0 @@ -/* -Copyright(c) 2025 Rangersly All rights reserved. - -DEBUG 工具封包 - -Version: v0.1-Alpha -*/ - -#include -#include - -#ifdef DEBUG - /* 字符串检查宏,输出字符串的每一位数据*/ - #define POINT_STR(str, len) size_t _len = (size_t)len; \ - printf("%s\033[0m\n", str); \ - for(int i = 0; i < _len; i++) { \ - printf("%d --- %2x \n", i, (char)str[i], (unsigned char)str[i]);} - - /*输出调试错误报错信息,辅助定位错误地点*/ - #define PERROR(str) printf("%s:%d:%s:\n%s\n", __FILE__, __LINE__, __func__, str); exit(0) -#else - #define POINT_STR(str, len) - #define PERROR(str) -#endif - diff --git a/program/c_cpp/libs/log/log.c b/program/c_cpp/libs/log/log.c deleted file mode 100644 index de43d04..0000000 --- a/program/c_cpp/libs/log/log.c +++ /dev/null @@ -1,167 +0,0 @@ -#include "log.h" - -#ifdef NDEBUG - #define POINT_STR(str) - #define PERROR(str) -#else - #define POINT_STR(str) for(int i = 0; i < strlen(str); i++) { \ - printf("%c --- %d\n", (char)str[i], (int)str[i]);} - #define PERROR(str) printf(str);return -#endif - -static int low_show_level = LOG_INFO; -static int log_number = 1; -static FILE *log_out_fp = NULL; -static char log_head_format[LOG_HEAD_MAX_FORMAT] = "[%y-%m-%d-%n]"; -static char log_head[LOG_HEAD_MAX_FORMAT << 3]; - - -static int -get_loghead(void); -// 根据 log_head_format 生成日志头 log_head -// 有无法识别的符号返回 -1 成功返回0 - -static void -int_to_str(int num, char *restrict str); -// 将int 型数据转换成str -// 需要注意 str 要大于 int 的位数,否则将溢出 - - -void -log_setoutfile(const char *restrict filename) { - if((log_out_fp = fopen(filename, "w")) == NULL) - PERROR("LOG: log_setoutfile open file fail !\n"); - return; -} - -void -log_setlevel(int level) { - if(level < LOG_INFO || level > LOG_FATAL) { // 检测最低日志等级 - low_show_level = LOG_INFO; - PERROR("LOG: log_setlevel level is > LOG_FATAL or < LOG_INFO\n"); - } - low_show_level = level; - return; -} - -void -log_sethead(const char *restrict head) { - if(strlen(head) >= LOG_HEAD_MAX_FORMAT) - PERROR("LOG: log_sethead head so long!\n"); - strncpy(log_head_format, head, LOG_HEAD_MAX_FORMAT); - if(get_loghead()) - PERROR("LOG: log_sethead have fail char !\n"); - return; -} - -void -log_print(int level, const char *restrict message) { - if(log_out_fp == NULL) // 未设置输出文件 - log_out_fp = stdout; - if(level < LOG_INFO || level > LOG_FATAL) // 日志等级不在范围内 - PERROR("LOG: log_print level out of range !\n"); - if(level < low_show_level) // 低于最低等级的log不进行打印 - return; - - if(get_loghead() != 0) // 生成日志头 - PERROR("LOG: log_print get_loghead error\n"); - if(!fputs(log_head, log_out_fp)) // 打印日志头 - PERROR("LOG: log_print fputs_head error\n"); - - switch(level) { // 打印错误等级 - case LOG_INFO: - if(fputs("INFO:", log_out_fp)) - break; - case LOG_WARNING: - if(fputs("WARNING:", log_out_fp)) - break; - case LOG_ERROR: - if(fputs("ERROR:", log_out_fp)) - break; - case LOG_FATAL: - if(fputs("FATAL:", log_out_fp)) - break; - default: - PERROR("LOG: log_print out level is untrue !\n"); - } - - if(!fputs(message, log_out_fp)) // 打印message - PERROR("LOG: log_head fputs fail !\n"); - fputc('\n', log_out_fp); - log_number++; // 日志计数++ - return; -} - -int -get_loghead(void) { - char buf[64]; - time_t now_time = time(NULL); - clock_t core_time = clock() / CLOCKS_PER_SEC; // 以 s 为单位的 cpu 时间 - struct tm *tm_time = localtime(&now_time); - int temp; - - memset(log_head, '\0', sizeof(log_head)); // 重置日志头 - - for(int i = 0; i < strlen(log_head_format); i++) { - if(log_head_format[i] != '%') { // 非特殊字符则按正常复制 - log_head[strlen(log_head)] = log_head_format[i]; - continue; - } - - i++; - switch(log_head_format[i]) { // 特殊字符转换 - case 'y' : - strftime(buf, 64, "%Y", tm_time); - break; - case 'm' : - strftime(buf, 64, "%m", tm_time); - break; - case 'd' : - strftime(buf, 64, "%d", tm_time); - break; - case 'h' : - strftime(buf, 64, "%H", tm_time); - break; - case 'M' : - strftime(buf, 64, "%M", tm_time); - break; - case 's' : - strftime(buf, 64, "%S", tm_time); - break; - case 'n' : - int_to_str(log_number, buf); - break; - case 'c' : - int_to_str(core_time, buf); - break; - default: - return -1; - } - strcat(log_head, buf); - } - return 0; -} - -void -int_to_str(int num, char *restrict str) { - if(num < 0) - return; // 日志编号不可能小于 0 - - // 逐位提取数字(反向存储) - int start = 0; - do { - str[start++] = num % 10 + '0'; - num /= 10; - } while (num > 0); - str[start] = '\0'; - - // 反转数字部分 - char buf[16]; - strncpy(buf, str, 16); - for(int i = 0; i < strlen(buf); i++) - str[--start] = buf[i]; - return; -} - -#undef POINT_STR -#undef PERROR diff --git a/program/c_cpp/libs/log/log.h b/program/c_cpp/libs/log/log.h deleted file mode 100644 index ad7aef4..0000000 --- a/program/c_cpp/libs/log/log.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright(c) 2025 Rangersly All rights reserved. -// -// function : -// Output log -// -// Author: -// Rangersly -// -// Versions: -// - 1.0 base function - -#pragma once - -#include -#include -#include - -#define LOG_INFO 0 -#define LOG_WARNING 1 -#define LOG_ERROR 2 -#define LOG_FATAL 3 - -#define LOG_HEAD_MAX_FORMAT 32 - -// 如果未定义 NDEBUG 宏,错误发生时将打印错误信息 - -extern void -log_setoutfile(const char *restrict filename); -// 设置输出文件 -// 默认输出为 stdout - -extern void -log_setlevel(int level); -// 设置最低输出日志等级,低于最低等级的日志将忽略 - -extern void -log_sethead(const char *restrict head); -// 设置日志头,最大不可超过15个字符 -// 符号表 -// %y year -// %m month -// %d day -// %h hour -// %M minute -// %s second -// %n number -// %c core time .3f - -extern void -log_print(int level, const char *restrict message); -// 输出日志 ^---等级 ^---输出信息 - - - -// EXAMPLE -/* -#include -#include "log.h" - -int main(void) { - log_setoutfile("log.out"); - log_setlevel(LOG_ERROR); - log_sethead("#%d-%h-%M-%s-%n-%c#"); - - log_print(LOG_INFO, " hello"); - log_print(LOG_WARNING, " hello"); - log_print(LOG_ERROR, " hello"); - log_print(LOG_FATAL, " hello"); - return 0; -} -*/ diff --git a/program/c_cpp/universal/io.md b/program/c_cpp/universal/io.md index 149470a..805eeb3 100644 --- a/program/c_cpp/universal/io.md +++ b/program/c_cpp/universal/io.md @@ -15,6 +15,7 @@ - [cpp fio](#cpp-fio) - [关闭缓冲区读取](#../linux/ncurses.c) - [ANSI](#./ansi.md) +- [宏](#macro) --- @@ -215,3 +216,8 @@ ________________________________________________ ios::end */ ``` + +--- + +### **macro** +- `BUFSIZ` : 系统级缓冲区大小 diff --git a/program/c_cpp/universal/libs.md b/program/c_cpp/universal/libs.md index dec6d82..0c03d99 100644 --- a/program/c_cpp/universal/libs.md +++ b/program/c_cpp/universal/libs.md @@ -35,8 +35,6 @@ - [string hash](../libs/string_hash.c) - [thread pool](../libs/thread-pool.cpp) : 简易线程池 - [BIT](../libs/bit.h) : 有关位运算的函数封装 - - [LOG](../libs/log/log.h) : 简单日志系统 - - [dbtools](../libs/dbtools.h) : DEBUG工具集 --- @@ -319,7 +317,6 @@ struct tm { ## **errno** ### **1. `errno` 全局变量** `extern int errno; // 声明全局错误变量` -- 当标准库函数执行失败时,会设置 `errno` 为特定的错误码. - **特点** - 由系统或库函数自动设置,**程序启动时初始化为 0**(表示无错误). - **每个线程有独立的 `errno`**(多线程安全). @@ -355,21 +352,6 @@ struct tm { - `char *strerror(int errnum);` - 返回错误码对应的字符串描述. -### **4. 使用场景** -- **(1) 文件操作错误处理** -- **(2) 数学函数错误处理** -- **(3) 动态内存分配错误** - -### **5. 注意事项** -1. **`errno` 的线程安全性**: - - 在多线程环境中,`errno` 是线程局部的(每个线程独立维护). -2. **`errno` 的初始化**: - - 程序启动时 `errno` 为 0,调用成功**不会清零**(需手动重置). -3. **`errno` 的检查时机**: - - 必须在函数返回后**立即检查**,否则可能被后续操作覆盖. -4. **不可直接修改 `errno`**: - - 除非明确需要设置错误码,否则不应手动修改 `errno`. - --- ## **assert** diff --git a/program/tool/gcc_g++.md b/program/tool/gcc_g++.md index 72d65c1..7b57baf 100644 --- a/program/tool/gcc_g++.md +++ b/program/tool/gcc_g++.md @@ -6,48 +6,56 @@ - [制作库文件](#make-lib) ## **option** -- `g++ -S test.s test.cpp` 编译成汇编文件 -- `g++ -c test.o test.s` 目标文件 -- `g++ -o test test.o` 链接 -- `g++ -S -o - -fverbose-asm xxx.cpp > xxx.s` // 输出带注释的汇编 +- `-S` : 编译成汇编文件 +- `-c` : 目标文件 +- `-o` : 链接 +- `-g` : 调试 - `-D ` 定义一个宏,默认值为1 - `-U ` 取消定义 +- `-l` : 链接库名称 +- `-L` : 链接库位置 +- `-I` : 头文件位置 +- `-Wall` : 启动所有常见警告 +- `-fPIC` : 生成位置无关代码 +- `-MMD` : 自动生成`.d`文件,记录源文件与头文件的依赖关系,头文件修改后自动触发相关源文件重编译 -- `gcc -s` 选项用于剥除可执行文件中的符号表和重定位信息,减小可执行文件的大小 +- `gcc -s` 剥除可执行文件中的符号表和重定位信息 - **正常功能保持** - **性能无显著差异** - - **调试困难**:符号表中包含了函数名、变量名等调试信息。使用 `-s` 选项后,这些信息会被移除,使得调试变得非常困难 - - **反汇编和分析不便**:没有符号表,反汇编工具(如 `objdump`)无法显示函数名和变量名等信息,只能显示汇编指令和地址。这会增加对程序进行反汇编分析的难度。 + - **调试困难和反汇编不便** : 使用 `-s` 选项后,符号表信息会被移除,使得调试变得非常困难,反汇编工具无法显示函数名和变量名等信息,只能显示汇编指令和地址 +- `g++ -S -o - -fverbose-asm xxx.cpp > xxx.s` // 输出带注释的汇编 --- ### **level** - - **O0** 不进行任何优化 - - **O1** 基础优化 - - 删除未使用的变量和函数 - - 简化控制流(如合并重复代码) - - 常量折叠(如 2+3 替换为 5) - - 简单的寄存器分配 - - **O2** 中等优化,推荐级别 - - 指令调度(提高指令级并行性) - - 循环优化(如循环展开、循环不变代码外提) - - 函数内联(简单函数直接展开) - - 分支预测优化 - - 数据流分析优化 - - **O3** 激进优化 - - 更激进的循环优化(如自动向量化,利用 SIMD 指令如 SSE/AVX) - - 函数内联更积极(可能导致代码膨胀) - - 删除冗余内存访问 - - 数学表达式重构(可能影响浮点精度) - - **优化易导致的问题** - - 暴露未定义行为(Undefined Behavior, UB) - - 调试信息不匹配 - - 重新排列或合并浮点运算,导致精度损失 - - 代码体积膨胀 - - 重排内存访问顺序,影响多线程程序或硬件寄存器操作 - - 依赖时序的代码失效 - - 向量化(SIMD)导致的兼容性问题 - - 内联汇编的意外行为 +- **O0** 不进行任何优化 +- **O1** 基础优化 + - 删除未使用的变量和函数 + - 简化控制流(如合并重复代码) + - 常量折叠(如 2+3 替换为 5) + - 简单的寄存器分配 +- **O2** 中等优化,推荐级别 + - 指令调度(提高指令级并行性) + - 循环优化(如循环展开、循环不变代码外提) + - 函数内联(简单函数直接展开) + - 分支预测优化 + - 数据流分析优化 +- **O3** 激进优化 + - 更激进的循环优化(如自动向量化,利用 SIMD 指令如 SSE/AVX) + - 函数内联更积极(可能导致代码膨胀) + - 删除冗余内存访问 + - 数学表达式重构(可能影响浮点精度) +- **优化易导致的问题** + - 暴露未定义行为(Undefined Behavior, UB) + - 调试信息不匹配 + - 重新排列或合并浮点运算,导致精度损失 + - 代码体积膨胀 + - 重排内存访问顺序,影响多线程程序或硬件寄存器操作 + - 依赖时序的代码失效 + - 向量化(SIMD)导致的兼容性问题 + - 内联汇编的意外行为 +- **Os** + - 减小体积 --- @@ -56,25 +64,18 @@ --- ### 静态库制作: - g++ -c -o libtest.a {test.cpp 源代码文件清单} -// g++ -c test.cpp -// ar -crv libtest.a test.o +1. `g++ -c test.cpp` +2. `ar rcs libtest.a test.o` --- ### 动态库制作 - g++ -fPIC -shared -o libtest.so {test.cpp 源代码文件清单} -// g++ -fPIC -c test.cpp -// g++ -shared -o libtest.so tset.o - 两种方法 - 1 + .so 放到 /usr/lib 或 /lib - 2 + 路径放到/etc/ld.so.conf 运行ldconfd 重建/etc/ld.so.cache +`g++ -fPIC -shared -o libtest.so {test.cpp 源代码文件清单}` --- ### 库使用 - g++ -o main -l库名 -L库路径 -I头文件路径 - // g++ -o main -ltest -L/home/e0x1a/test + g++ -o main -l库名 -L库路径 -I头文件路径 #### 编译主程序时链接动态库 - `gcc -o myprogram main.c -L. -lmylib -Wl,-rpath=.`