Linux I/O 系統調用完整對比分析

Linux I/O 系統調用完整對比分析

1. 概述

Linux 提供了豐富的 I/O 系統調用,每種都有其特定的用途和優勢。本文將詳細分析這些系統調用的特點、使用場景和性能特征。

2. 系統調用詳細對比

2.1 基本讀寫函數

pread/pwrite
#include <unistd.h>// 位置指定讀取/寫入
ssize_t pread(int fd, void *buf, size_t count, off_t offset);
ssize_t pwrite(int int fd, const void *buf, size_t count, off_t offset);

特點

  • 原子操作(讀取/寫入 + 位置指定)
  • 不改變文件描述符的當前位置
  • 線程安全
read/write
#include <unistd.h>// 基本讀取/寫入
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);

特點

  • 最基本的 I/O 操作
  • 會改變文件描述符的當前位置
  • 相對簡單但功能有限

2.2 分散/聚集 I/O 函數

preadv/pwritev
#include <sys/uio.h>// 位置指定的分散讀取/聚集寫入
ssize_t preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
preadv2/pwritev2
#define _GNU_SOURCE
#include <sys/uio.h>// 帶標志的增強版分散/聚集 I/O
ssize_t preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags);
ssize_t pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags);

2.3 資源限制函數

prlimit64
#include <sys/resource.h>// 獲取/設置進程資源限制
int prlimit64(pid_t pid, int resource, const struct rlimit64 *new_limit, struct rlimit64 *old_limit);

3. 功能對比表

函數位置指定分散/聚集標志控制原子性跨平臺
read/write??????
pread/pwrite?????
readv/writev??????
preadv/pwritev?????
preadv2/pwritev2?????
prlimit64?????

4. 實際示例代碼

4.1 基礎讀寫對比

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/uio.h>
#include <string.h>
#include <errno.h>
#include <time.h>// 創建測試文件
void create_test_file(const char *filename) {int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644);if (fd == -1) {perror("創建文件失敗");return;}const char *content = "Line 1: This is the first line of test data.\n""Line 2: This is the second line of test data.\n""Line 3: This is the third line of test data.\n""Line 4: This is the fourth line of test data.\n""Line 5: This is the fifth and final line.\n";write(fd, content, strlen(content));close(fd);printf("創建測試文件: %s\n", filename);
}// read/pread 性能對比
void compare_basic_io(const char *filename) {int fd = open(filename, O_RDONLY);if (fd == -1) {perror("打開文件失敗");return;}char buffer[100];ssize_t bytes_read;struct timespec start, end;printf("\n=== 基礎 I/O 對比 ===\n");// 使用 read (會改變文件位置)printf("1. read 測試:\n");clock_gettime(CLOCK_MONOTONIC, &start);bytes_read = read(fd, buffer, 50);clock_gettime(CLOCK_MONOTONIC, &end);buffer[bytes_read] = '\0';printf("   讀取 %zd 字節: %.30s...\n", bytes_read, buffer);printf("   當前文件位置: %ld\n", (long)lseek(fd, 0, SEEK_CUR));// 使用 pread (不改變文件位置)printf("2. pread 測試:\n");clock_gettime(CLOCK_MONOTONIC, &start);bytes_read = pread(fd, buffer, 50, 0);  // 從開頭讀取clock_gettime(CLOCK_MONOTONIC, &end);buffer[bytes_read] = '\0';printf("   讀取 %zd 字節: %.30s...\n", bytes_read, buffer);printf("   文件位置仍為: %ld\n", (long)lseek(fd, 0, SEEK_CUR));close(fd);
}// 分散/聚集 I/O 示例
void demonstrate_vector_io(const char *filename) {int fd = open(filename, O_RDONLY);if (fd == -1) {perror("打開文件失敗");return;}printf("\n=== 分散/聚集 I/O 示例 ===\n");// 設置分散讀取緩沖區char buffer1[20], buffer2[30], buffer3[25];struct iovec iov[3];iov[0].iov_base = buffer1;iov[0].iov_len = sizeof(buffer1) - 1;iov[1].iov_base = buffer2;iov[1].iov_len = sizeof(buffer2) - 1;iov[2].iov_base = buffer3;iov[2].iov_len = sizeof(buffer3) - 1;printf("分散讀取設置:\n");printf("  緩沖區1: %zu 字節\n", iov[0].iov_len);printf("  緩沖區2: %zu 字節\n", iov[1].iov_len);printf("  緩沖區3: %zu 字節\n", iov[2].iov_len);// 使用 preadv 一次性讀取到多個緩沖區ssize_t total_bytes = preadv(fd, iov, 3, 0);  // 從文件開頭開始讀取printf("總共讀取: %zd 字節\n", total_bytes);if (total_bytes > 0) {buffer1[iov[0].iov_len] = '\0';buffer2[iov[1].iov_len] = '\0';buffer3[iov[2].iov_len] = '\0';printf("讀取結果:\n");printf("  緩沖區1: %s\n", buffer1);printf("  緩沖區2: %s\n", buffer2);printf("  緩沖區3: %s\n", buffer3);}close(fd);
}// 資源限制示例
void demonstrate_resource_limits() {printf("\n=== 資源限制示例 ===\n");struct rlimit64 limit;// 獲取當前進程的文件大小限制if (prlimit64(0, RLIMIT_FSIZE, NULL, &limit) == 0) {printf("文件大小限制:\n");printf("  軟限制: %lld\n", (long long)limit.rlim_cur);printf("  硬限制: %lld\n", (long long)limit.rlim_max);}// 獲取內存限制if (prlimit64(0, RLIMIT_AS, NULL, &limit) == 0) {printf("虛擬內存限制:\n");if (limit.rlim_cur == RLIM64_INFINITY) {printf("  軟限制: 無限制\n");} else {printf("  軟限制: %lld 字節 (%.2f MB)\n", (long long)limit.rlim_cur,(double)limit.rlim_cur / (1024 * 1024));}if (limit.rlim_max == RLIM64_INFINITY) {printf("  硬限制: 無限制\n");} else {printf("  硬限制: %lld 字節 (%.2f MB)\n", (long long)limit.rlim_max,(double)limit.rlim_max / (1024 * 1024));}}// 獲取打開文件數限制if (prlimit64(0, RLIMIT_NOFILE, NULL, &limit) == 0) {printf("文件描述符限制:\n");printf("  軟限制: %lld\n", (long long)limit.rlim_cur);printf("  硬限制: %lld\n", (long long)limit.rlim_max);}
}int main() {const char *test_file = "io_test_file.txt";printf("=== Linux I/O 系統調用對比分析 ===\n");// 創建測試文件create_test_file(test_file);// 基礎 I/O 對比compare_basic_io(test_file);// 分散/聚集 I/O 示例demonstrate_vector_io(test_file);// 資源限制示例demonstrate_resource_limits();// 清理unlink(test_file);printf("\n=== 使用建議 ===\n");printf("選擇指南:\n");printf("1. 簡單讀寫: 使用 read/write\n");printf("2. 需要指定位置: 使用 pread/pwrite\n");printf("3. 多緩沖區操作: 使用 preadv/pwritev\n");printf("4. 需要高級控制: 使用 preadv2/pwritev2\n");printf("5. 資源限制管理: 使用 prlimit64\n");return 0;
}

4.2 性能基準測試

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/uio.h>
#include <time.h>
#include <string.h>#define ITERATIONS 10000
#define BUFFER_SIZE 1024// 性能測試結構體
struct performance_test {const char *name;double (*test_func)(int fd, const char *filename);
};// read 性能測試
double test_read_performance(int fd, const char *filename) {char buffer[BUFFER_SIZE];struct timespec start, end;clock_gettime(CLOCK_MONOTONIC, &start);for (int i = 0; i < ITERATIONS; i++) {lseek(fd, 0, SEEK_SET);  // 重置到文件開頭read(fd, buffer, sizeof(buffer));}clock_gettime(CLOCK_MONOTONIC, &end);return (end.tv_sec - start.tv_sec) * 1000000.0 + (end.tv_nsec - start.tv_nsec) / 1000.0;  // 微秒
}// pread 性能測試
double test_pread_performance(int fd, const char *filename) {char buffer[BUFFER_SIZE];struct timespec start, end;clock_gettime(CLOCK_MONOTONIC, &start);for (int i = 0; i < ITERATIONS; i++) {pread(fd, buffer, sizeof(buffer), 0);  // 始終從位置0讀取}clock_gettime(CLOCK_MONOTONIC, &end);return (end.tv_sec - start.tv_sec) * 1000000.0 + (end.tv_nsec - start.tv_nsec) / 1000.0;  // 微秒
}// readv 性能測試
double test_readv_performance(int fd, const char *filename) {char buffer1[256], buffer2[256], buffer3[256], buffer4[256];struct iovec iov[4];struct timespec start, end;// 設置分散讀取iov[0].iov_base = buffer1;iov[0].iov_len = sizeof(buffer1);iov[1].iov_base = buffer2;iov[1].iov_len = sizeof(buffer2);iov[2].iov_base = buffer3;iov[2].iov_len = sizeof(buffer3);iov[3].iov_base = buffer4;iov[3].iov_len = sizeof(buffer4);clock_gettime(CLOCK_MONOTONIC, &start);for (int i = 0; i < ITERATIONS; i++) {lseek(fd, 0, SEEK_SET);readv(fd, iov, 4);}clock_gettime(CLOCK_MONOTONIC, &end);return (end.tv_sec - start.tv_sec) * 1000000.0 + (end.tv_nsec - start.tv_nsec) / 1000.0;  // 微秒
}// preadv 性能測試
double test_preadv_performance(int fd, const char *filename) {char buffer1[256], buffer2[256], buffer3[256], buffer4[256];struct iovec iov[4];struct timespec start, end;// 設置分散讀取iov[0].iov_base = buffer1;iov[0].iov_len = sizeof(buffer1);iov[1].iov_base = buffer2;iov[1].iov_len = sizeof(buffer2);iov[2].iov_base = buffer3;iov[2].iov_len = sizeof(buffer3);iov[3].iov_base = buffer4;iov[3].iov_len = sizeof(buffer4);clock_gettime(CLOCK_MONOTONIC, &start);for (int i = 0; i < ITERATIONS; i++) {preadv(fd, iov, 4, 0);  // 始終從位置0讀取}clock_gettime(CLOCK_MONOTONIC, &end);return (end.tv_sec - start.tv_sec) * 1000000.0 + (end.tv_nsec - start.tv_nsec) / 1000.0;  // 微秒
}void run_performance_benchmark() {const char *test_file = "benchmark_test.dat";int fd;printf("=== I/O 性能基準測試 ===\n");// 創建大測試文件fd = open(test_file, O_CREAT | O_WRONLY | O_TRUNC, 0644);if (fd != -1) {char *buffer = malloc(1024 * 1024);  // 1MB 緩沖區if (buffer) {for (int i = 0; i < 10; i++) {  // 創建 10MB 文件write(fd, buffer, 1024 * 1024);}free(buffer);}close(fd);}// 打開文件進行讀取測試fd = open(test_file, O_RDONLY);if (fd == -1) {perror("打開測試文件失敗");return;}struct performance_test tests[] = {{"read", test_read_performance},{"pread", test_pread_performance},{"readv", test_readv_performance},{"preadv", test_preadv_performance},{NULL, NULL}};printf("%-10s %-15s %-15s\n", "函數", "耗時(微秒)", "平均耗時(納秒)");printf("%-10s %-15s %-15s\n", "----", "----------", "--------------");for (int i = 0; tests[i].name; i++) {double total_time = tests[i].test_func(fd, test_file);double avg_time = total_time * 1000.0 / ITERATIONS;printf("%-10s %-15.2f %-15.2f\n", tests[i].name, total_time, avg_time);}close(fd);unlink(test_file);printf("\n性能分析:\n");printf("1. pread 比 read 略慢 (位置指定開銷)\n");printf("2. readv/preadv 在多緩沖區場景下更高效\n");printf("3. preadv2/pwritev2 提供更多控制選項\n");printf("4. 選擇應基于具體使用場景\n");
}int main() {printf("=== Linux I/O 系統調用完整對比分析 ===\n\n");// 運行性能基準測試run_performance_benchmark();printf("\n=== 詳細功能對比 ===\n");printf("pread vs read:\n");printf("  ? pread: 指定位置讀取,不改變文件位置\n");printf("  ? read: 順序讀取,會改變文件位置\n");printf("\n");printf("preadv vs pread:\n");printf("  ? preadv: 分散讀取到多個緩沖區\n");printf("  ? pread: 讀取到單個緩沖區\n");printf("\n");printf("preadv2 vs preadv:\n");printf("  ? preadv2: 支持額外標志控制\n");printf("  ? preadv: 基本的分散讀取功能\n");printf("\n");printf("prlimit64:\n");printf("  ? 用于獲取和設置進程資源限制\n");printf("  ? 支持 64 位資源限制值\n");printf("  ? 可以操作其他進程的資源限制\n");printf("\n=== 實際應用建議 ===\n");printf("1. 日志文件讀寫: 使用 pread/pwrite\n");printf("2. 數據庫存儲引擎: 使用 preadv/pwritev\n");printf("3. 高性能網絡服務: 使用 preadv2/pwritev2\n");printf("4. 系統資源管理: 使用 prlimit64\n");printf("5. 簡單文件操作: 使用 read/write\n");return 0;
}

4.3 實際應用場景演示

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/uio.h>
#include <string.h>
#include <errno.h>
#include <sys/resource.h>// 日志文件讀取示例
void log_file_reader_example() {printf("=== 日志文件讀取場景 ===\n");// 創建模擬日志文件const char *log_file = "application.log";int fd = open(log_file, O_CREAT | O_WRONLY | O_TRUNC, 0644);if (fd != -1) {const char *log_entries[] = {"2023-01-01 10:00:00 INFO Application started\n","2023-01-01 10:00:01 DEBUG Loading configuration\n","2023-01-01 10:00:02 WARN Low memory warning\n","2023-01-01 10:00:03 ERROR Database connection failed\n","2023-01-01 10:00:04 INFO Recovery attempt started\n"};for (int i = 0; i < 5; i++) {write(fd, log_entries[i], strlen(log_entries[i]));}close(fd);}// 使用 pread 讀取特定時間段的日志fd = open(log_file, O_RDONLY);if (fd != -1) {char buffer[256];printf("讀取最后一條日志記錄:\n");// 從文件末尾附近讀取ssize_t bytes_read = pread(fd, buffer, sizeof(buffer) - 1, 150);if (bytes_read > 0) {buffer[bytes_read] = '\0';printf("  %s", buffer);}close(fd);}unlink(log_file);
}// 數據庫頁讀取示例
void database_page_reader_example() {printf("\n=== 數據庫頁讀取場景 ===\n");const char *db_file = "database_pages.dat";int fd = open(db_file, O_CREAT | O_WRONLY | O_TRUNC, 0644);if (fd != -1) {// 創建模擬的數據庫頁char page_data[4096];for (int page = 0; page < 10; page++) {snprintf(page_data, sizeof(page_data), "Page %d: Database page content with ID=%d and timestamp=%ld\n",page, page * 1000, time(NULL));write(fd, page_data, strlen(page_data));}close(fd);}// 使用 preadv 讀取多個數據庫頁fd = open(db_file, O_RDONLY);if (fd != -1) {char page1[1024], page2[1024], page3[1024];struct iovec iov[3];// 設置分散讀取iov[0].iov_base = page1;iov[0].iov_len = sizeof(page1) - 1;iov[1].iov_base = page2;iov[1].iov_len = sizeof(page2) - 1;iov[2].iov_base = page3;iov[2].iov_len = sizeof(page3) - 1;printf("使用 preadv 讀取多個數據庫頁:\n");ssize_t total_bytes = preadv(fd, iov, 3, 0);  // 從開頭讀取printf("  總共讀取: %zd 字節\n", total_bytes);if (total_bytes > 0) {page1[iov[0].iov_len] = '\0';page2[iov[1].iov_len] = '\0';page3[iov[2].iov_len] = '\0';printf("  頁1: %.50s...\n", page1);printf("  頁2: %.50s...\n", page2);printf("  頁3: %.50s...\n", page3);}close(fd);}unlink(db_file);
}// 網絡數據包處理示例
void network_packet_processor_example() {printf("\n=== 網絡數據包處理場景 ===\n");// 模擬網絡數據包結構struct packet_header {uint32_t magic;uint16_t version;uint16_t type;uint32_t length;uint32_t checksum;} __attribute__((packed));struct packet_payload {char data[1024];};// 創建測試數據包文件const char *packet_file = "network_packets.dat";int fd = open(packet_file, O_CREAT | O_WRONLY | O_TRUNC, 0644);if (fd != -1) {// 寫入多個數據包for (int i = 0; i < 3; i++) {struct packet_header header = {.magic = 0x12345678,.version = 1,.type = i,.length = 100,.checksum = 0xABCDEF00 + i};char payload[1024];snprintf(payload, sizeof(payload), "Packet %d payload data with timestamp %ld", i, time(NULL));write(fd, &header, sizeof(header));write(fd, payload, strlen(payload) + 1);}close(fd);}// 使用 preadv2 讀取數據包(如果支持)fd = open(packet_file, O_RDONLY);if (fd != -1) {struct packet_header headers[3];char payloads[3][256];struct iovec iov[6];  // 3個頭部 + 3個載荷// 設置分散讀取結構for (int i = 0; i < 3; i++) {iov[i*2].iov_base = &headers[i];iov[i*2].iov_len = sizeof(struct packet_header);iov[i*2+1].iov_base = payloads[i];iov[i*2+1].iov_len = sizeof(payloads[i]) - 1;}printf("使用分散讀取處理網絡數據包:\n");ssize_t bytes_read = preadv(fd, iov, 6, 0);printf("  讀取字節數: %zd\n", bytes_read);if (bytes_read > 0) {for (int i = 0; i < 3; i++) {printf("  數據包 %d:\n", i);printf("    魔數: 0x%08X\n", headers[i].magic);printf("    版本: %d\n", headers[i].version);printf("    類型: %d\n", headers[i].type);printf("    長度: %d\n", headers[i].length);printf("    校驗: 0x%08X\n", headers[i].checksum);payloads[i][iov[i*2+1].iov_len] = '\0';printf("    載荷: %.50s...\n", payloads[i]);printf("\n");}}close(fd);}unlink(packet_file);
}// 資源限制管理示例
void resource_limit_management_example() {printf("\n=== 資源限制管理場景 ===\n");struct rlimit64 old_limit, new_limit;// 獲取當前文件大小限制if (prlimit64(0, RLIMIT_FSIZE, NULL, &old_limit) == 0) {printf("當前文件大小限制:\n");if (old_limit.rlim_cur == RLIM64_INFINITY) {printf("  軟限制: 無限制\n");} else {printf("  軟限制: %lld 字節 (%.2f GB)\n", (long long)old_limit.rlim_cur,(double)old_limit.rlim_cur / (1024 * 1024 * 1024));}}// 獲取打開文件數限制if (prlimit64(0, RLIMIT_NOFILE, NULL, &old_limit) == 0) {printf("當前文件描述符限制:\n");printf("  軟限制: %lld\n", (long long)old_limit.rlim_cur);printf("  硬限制: %lld\n", (long long)old_limit.rlim_max);}// 獲取內存限制if (prlimit64(0, RLIMIT_AS, NULL, &old_limit) == 0) {printf("當前虛擬內存限制:\n");if (old_limit.rlim_cur == RLIM64_INFINITY) {printf("  軟限制: 無限制\n");} else {printf("  軟限制: %lld 字節 (%.2f GB)\n", (long long)old_limit.rlim_cur,(double)old_limit.rlim_cur / (1024 * 1024 * 1024));}}printf("\n資源限制管理最佳實踐:\n");printf("1. 合理設置文件大小限制防止磁盤填滿\n");printf("2. 適當增加文件描述符限制支持高并發\n");printf("3. 監控內存使用防止內存泄漏\n");printf("4. 使用 prlimit64 動態調整資源限制\n");
}int main() {printf("=== Linux I/O 系統調用應用場景演示 ===\n\n");// 日志文件讀取場景log_file_reader_example();// 數據庫頁讀取場景database_page_reader_example();// 網絡數據包處理場景network_packet_processor_example();// 資源限制管理場景resource_limit_management_example();printf("\n=== 總結 ===\n");printf("I/O 系統調用選擇指南:\n");printf("\n");printf("┌─────────────┬────────────────────────────────────┐\n");printf("│ 場景        │ 推薦函數                              │\n");printf("├─────────────┼────────────────────────────────────┤\n");printf("│ 簡單讀寫    │ read/write                            │\n");printf("│ 位置指定    │ pread/pwrite                          │\n");printf("│ 多緩沖區    │ readv/writev                          │\n");printf("│ 位置+多緩沖 │ preadv/pwritev                        │\n");printf("│ 高級控制    │ preadv2/pwritev2                      │\n");printf("│ 資源限制    │ prlimit64                             │\n");printf("└─────────────┴────────────────────────────────────┘\n");printf("\n");printf("性能優化建議:\n");printf("1. 批量操作減少系統調用次數\n");printf("2. 合理選擇緩沖區大小\n");printf("3. 使用位置指定避免文件位置移動\n");printf("4. 分散/聚集 I/O 減少內存拷貝\n");printf("5. 合理設置資源限制防止系統過載\n");return 0;
}

5. 編譯和運行說明

# 編譯示例程序
gcc -o io_comparison_example1 example1.c
gcc -o io_comparison_example2 example2.c
gcc -o io_comparison_example3 example3.c# 運行示例
./io_comparison_example1
./io_comparison_example2
./io_comparison_example3

6. 系統要求檢查

# 檢查內核版本
uname -r# 檢查 glibc 版本
ldd --version# 檢查系統調用支持
grep -E "(pread|pwrite|prlimit)" /usr/include/asm/unistd_64.h# 查看文件系統性能
hdparm -Tt /dev/sda  # 硬盤性能測試

7. 重要注意事項

  1. 原子性: pread/pwrite 操作是原子的
  2. 位置獨立: 不改變文件描述符的當前位置
  3. 錯誤處理: 始終檢查返回值和 errno
  4. 內存對齊: 在某些架構上有對齊要求
  5. 權限檢查: 確保有足夠的權限進行操作
  6. 資源清理: 及時關閉文件描述符

8. 最佳實踐總結

// 安全的 I/O 操作封裝
ssize_t safe_pread(int fd, void *buf, size_t count, off_t offset) {if (fd < 0 || !buf || count == 0) {errno = EINVAL;return -1;}ssize_t result;do {result = pread(fd, buf, count, offset);} while (result == -1 && errno == EINTR);return result;
}// 安全的分散讀取封裝
ssize_t safe_preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset) {if (fd < 0 || !iov || iovcnt <= 0 || iovcnt > IOV_MAX) {errno = EINVAL;return -1;}ssize_t result;do {result = preadv(fd, iov, iovcnt, offset);} while (result == -1 && errno == EINTR);return result;
}// 資源限制檢查
int check_resource_limits() {struct rlimit64 limit;// 檢查文件大小限制if (prlimit64(0, RLIMIT_FSIZE, NULL, &limit) == 0) {if (limit.rlim_cur != RLIM64_INFINITY && limit.rlim_cur < 1024 * 1024) {printf("警告: 文件大小限制過小 (%lld 字節)\n", (long long)limit.rlim_cur);}}// 檢查文件描述符限制if (prlimit64(0, RLIMIT_NOFILE, NULL, &limit) == 0) {if (limit.rlim_cur < 1024) {printf("警告: 文件描述符限制過小 (%lld)\n", (long long)limit.rlim_cur);}}return 0;
}

這些示例全面展示了 Linux I/O 系統調用的功能特點、使用方法和實際應用場景,幫助開發者根據具體需求選擇合適的 I/O 操作方式

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/91643.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/91643.shtml
英文地址,請注明出處:http://en.pswp.cn/web/91643.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

TiDB集群部署

架構&#xff1a; tidb–3臺&#xff0c;pd–3臺&#xff0c;tikv–3臺 8c16g200g 1x2.2x.2x7.124 1x2.2x.2x7.148 1x2.2x.2x7.87 1x2.2x.2x7.93 1x2.2x.2x7.127 1x2.2x.2x7.104 pd-3臺 4c8g100g 1x2.2x.2x7.143 1x2.2x.2x7.132 1x2.2x.2x7.91 1、下載安裝包 #注&#xff1a;我…

C#中對于List的多種排序方式

在 C# 中給 List<AI> 排序&#xff0c;只要 明確排序規則&#xff08;比如按某個字段、某幾個字段、或外部規則&#xff09;&#xff0c;就能用下面幾種常見寫法。下面全部基于這個示例類&#xff1a;public class AI {public int country; // 國家編號public int pr…

Spring框架中Bean的生命周期:源碼解析與最佳實踐

第1章&#xff1a;Spring Bean生命周期概述1.1 什么是Spring Bean生命周期&#xff1f;定義&#xff1a;Spring Bean生命周期是指從Bean的創建、初始化、使用到銷毀的完整過程&#xff0c;由Spring容器嚴格管理 。核心思想是Spring容器通過IoC&#xff08;控制反轉&#xff09;…

【51單片機6位數碼管密碼鎖】2022-10-15

緣由六位密碼器設計連接LED-嵌入式-CSDN問答 矩陣51單片機密碼鎖,回復:https://bbs.csdn.net/topics/392713242_智者知已應修善業的博客-CSDN博客 #include "REG52.h" unsigned char code smgduan[]{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x…

?我的第一個開源項目:躍動的心

還是一個編程初學者時&#xff0c;我懷著激動的心情完成了人生第一個開源項目——一個用HTML5 Canvas制作的動態跳動愛心效果。這個項目雖然簡單&#xff0c;卻讓我深刻體會到了開源分享的快樂和技術創造的魅力。 壹、項目靈感 這個項目的靈感來源于瀏覽網頁時&#xff0c;被各…

技術演進中的開發沉思-53 DELPHI VCL系列:windows的消息(下):TApplication窗體

今天我們梳理下關于TApplication的窗體消息下半部分的內容。前面也說過&#xff0c;在 Delphi 的世界里&#xff0c;TApplication 就像一位經驗豐富的總工程師&#xff0c;而主窗體則是它傾注心血打造的核心建筑。如果你第一次在實驗室里敲出 Delphi 代碼時&#xff0c;屏幕上彈…

cesium FBO(四)自定義相機渲染到Canvas(離屏渲染)

前面幾節的例子是將Cesium默認的相機渲染到紋理&#xff08;RTT&#xff09;或Canvas&#xff0c;這片文章講解如何將自定義的一個camera的畫面渲染到Canvas上&#xff0c;有了前面幾篇的基礎了&#xff0c;也能將自定義的畫面渲染紋理、也可以灰度處理&#xff0c;原理是一樣的…

雙機并聯無功環流抑制虛擬阻抗VSG控制【simulink仿真模型實現】

雙機并聯虛擬同步發電機&#xff08;VSG&#xff09;系統中&#xff0c;因線路阻抗不匹配及參數差異&#xff0c;易引發無功環流。本方案在傳統VSG控制基礎上&#xff0c;引入自適應虛擬阻抗環節。其核心在于&#xff1a;實時檢測兩機間無功環流分量&#xff0c;據此動態調節各…

python測試總結

測試題的基礎知識點總結 1.循環求和 for循環步長&#xff08;range(2,101,2)&#xff09; while循環條件判斷&#xff08;i%20&#xff09; 生成器表達式&#xff08;sum(i for i in range )&#xff09; 所以&#xff1a;sum(range(1,101,2))&#xff08;奇數和&#xff09;和…

識別和分類惡意軟件樣本的工具YARA

YARA 是一個用于識別和分類惡意軟件樣本的工具,廣泛應用于惡意軟件分析、威脅情報、入侵檢測等領域。它通過編寫規則(YARA Rules)來匹配文件中的特定字符串、十六進制模式、正則表達式等特征。 一、YARA 的基本使用方法 1. 安裝 YARA Linux(Ubuntu/Debian) sudo apt-ge…

GaussDB 約束的語法

1 約束的作用約束是作用于數據表中列上的規則&#xff0c;用于限制表中數據的類型。約束的存在保證了數據庫中數據的精確性和可靠性。約束有列級和表級之分&#xff0c;列級約束作用于單一的列&#xff0c;而表級約束作用于整張數據表。下面是 GaussDB SQL 中常用的約束。NOT …

SecurityContextHolder 管理安全上下文的核心組件詳解

SecurityContextHolder 管理安全上下文的核心組件詳解在 Spring Security 中&#xff0c;SecurityContextHolder 是??安全上下文&#xff08;Security Context&#xff09;的核心存儲容器??&#xff0c;其核心作用是??在當前線程中保存當前用戶的認證信息&#xff08;如用…

c++詳解系列(引用指針)

目錄 1.什么是引用 2.引用的定義 3.引用的特性 4.引用的使用 4.1引用傳參 4.2傳引用返回 5.const引用&#xff08;在引用的定義前用const修飾&#xff09; 5.1對于引用 5.2對于指針 6.引用&指針 總結 1.什么是引用 引用就是給變量起別名&#xff0c;一個變量可以…

深度學習loss總結(二)

對于目前深度學習主流任務學習,loss的設置至關重要。下面就不同任務的loss設置進行如下總結: (1)目標檢測 2D/3D目標檢測中的 Loss(損失函數)是訓練模型時優化目標的核心,通常包括位置、類別、尺寸、方向等多個方面。以下是目前 常見的 2D 和 3D 目標檢測 Loss 分類與…

【Linux網絡】netstat 的 -anptu 各個參數各自表示什么意思?

netstat 是一個網絡統計工具&#xff0c;它可以顯示網絡連接、路由表、接口統計、偽裝連接和多播成員資格。在 netstat 命令中&#xff0c;不同的參數可以用來定制輸出的內容。 你提到的 -anptu 參數組合各自的功能如下&#xff1a; -a (all): 顯示所有活動的連接和監聽端口。它…

[硬件電路-115]:模擬電路 - 信號處理電路 - 功能放大器工作分類、工作原理、常見芯片

功能放大器是以特定功能為核心的集成化放大電路&#xff0c;通過將運算放大器與外圍電阻、電容等元件集成在單一芯片中&#xff0c;實現標準化、高性能的信號放大功能。其核心優勢在于簡化設計流程、提升系統穩定性&#xff0c;并針對特定應用場景優化性能參數。以下從定義、分…

雙網卡UDP廣播通信機制詳解

UDP廣播通信機制詳解 一、通信流程分析 發送階段 通過Client.Bind(192.168.0.3, 60000)將UDP套接字綁定到指定網卡和端口設置RemoteHost "255.255.255.255"實現全網段廣播數據流向&#xff1a;192.168.0.3:60000 → 255.255.255.255:50000 接收階段 設備響應數據應返…

從遮擋難題到精準測量:激光頻率梳技術如何實現深孔 3D 輪廓的 2um 級重復精度?

一、深孔 3D 輪廓測量的遮擋困境深孔結構&#xff08;如航空發動機燃油噴嘴孔、模具冷卻孔&#xff09;因孔深大&#xff08;常超 100mm&#xff09;、深徑比高&#xff08;&#xff1e;10:1&#xff09;&#xff0c;其 3D 輪廓測量長期受限于光學遮擋難題。傳統光學測量技術&a…

.NET 依賴注入(DI)全面解析

文章目錄一、依賴注入核心原理1. 控制反轉(IoC)與DI關系2. .NET DI核心組件二、服務生命周期1. 三種生命周期類型三、DI容器實現原理1. 服務注冊流程2. 服務解析流程四、高級實現方法1. 工廠模式注冊2. 泛型服務注冊3. 多實現解決方案五、ASP.NET Core中的DI集成1. 控制器注入2…

K8S部署ELK(二):部署Kafka消息隊列

目錄 1. Kafka 簡介 1.1 Kafka 核心概念 &#xff08;1&#xff09;消息系統 vs. 流處理平臺 &#xff08;2&#xff09;核心組件 1.2 Kafka 核心特性 &#xff08;1&#xff09;高吞吐 & 低延遲 &#xff08;2&#xff09;持久化存儲 &#xff08;3&#xff09;分…