当前位置: 首页 > news >正文

fchown/fchownat系统调用及示例

55. fchmod - 通过文件描述符改变文件权限

函数介绍

fchmod是一个Linux系统调用,用于通过文件描述符来改变文件的访问权限。它是chmod函数的文件描述符版本,避免了路径名解析。

函数原型

#include <sys/stat.h>
#include <unistd.h>int fchmod(int fd, mode_t mode);

功能

通过文件描述符改变文件的访问权限(读、写、执行权限)。

参数

  • int fd: 已打开文件的文件描述符
  • mode_t mode: 新的文件权限模式
    • 八进制表示:如0644, 0755, 0600
    • 符号常量组合:如S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH

返回值

  • 成功时返回0
  • 失败时返回-1,并设置errno

特殊限制

  • 需要对文件有适当的权限
  • 某些文件系统可能不支持
  • 只能修改调用者拥有的文件(除非是root)

相似函数

  • chmod(): 通过路径名改变文件权限
  • fchmodat(): 相对路径版本
  • chmodat(): 已废弃的相对路径版本

示例代码

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>// 将权限模式转换为可读字符串
void print_permissions(mode_t mode) {char perms[11];strcpy(perms, "----------");// 用户权限if (mode & S_IRUSR) perms[1] = 'r';if (mode & S_IWUSR) perms[2] = 'w';if (mode & S_IXUSR) perms[3] = 'x';// 组权限if (mode & S_IRGRP) perms[4] = 'r';if (mode & S_IWGRP) perms[5] = 'w';if (mode & S_IXGRP) perms[6] = 'x';// 其他用户权限if (mode & S_IROTH) perms[7] = 'r';if (mode & S_IWOTH) perms[8] = 'w';if (mode & S_IXOTH) perms[9] = 'x';// 特殊位if (mode & S_ISUID) perms[3] = (perms[3] == 'x') ? 's' : 'S';if (mode & S_ISGID) perms[6] = (perms[6] == 'x') ? 's' : 'S';if (mode & S_ISVTX) perms[9] = (perms[9] == 'x') ? 't' : 'T';printf("%s", perms);
}// 获取文件详细信息
void print_file_info(const char* filename, int fd) {struct stat sb;if (fstat(fd, &sb) == -1) {perror("fstat失败");return;}printf("文件 '%s' 的信息:\n", filename);printf("  inode: %ld\n", sb.st_ino);printf("  权限: ");print_permissions(sb.st_mode);printf(" (八进制: %o)\n", sb.st_mode & 0777);printf("  大小: %ld 字节\n", sb.st_size);printf("  所有者: %d", sb.st_uid);struct passwd *pw = getpwuid(sb.st_uid);if (pw) {printf(" (%s)", pw->pw_name);}printf("\n");printf("  所属组: %d", sb.st_gid);struct group *gr = getgrgid(sb.st_gid);if (gr) {printf(" (%s)", gr->gr_name);}printf("\n\n");
}int main() {int fd;int result;printf("=== Fchmod 函数示例 ===\n");printf("当前用户 UID: %d\n", getuid());printf("当前有效 UID: %d\n", geteuid());// 示例1: 基本使用printf("\n示例1: 基本使用\n");// 创建测试文件fd = open("test_fchmod.txt", O_CREAT | O_RDWR | O_TRUNC, 0666);if (fd == -1) {perror("创建测试文件失败");exit(EXIT_FAILURE);}printf("创建测试文件: test_fchmod.txt\n");// 写入测试数据const char* test_data = "This is test data for fchmod demonstration.\n";write(fd, test_data, strlen(test_data));// 显示初始权限print_file_info("test_fchmod.txt", fd);// 示例2: 改变文件权限printf("示例2: 改变文件权限\n");// 设置为只读模式 (0444)result = fchmod(fd, 0444);if (result == -1) {perror("设置只读权限失败");} else {printf("成功设置只读权限 (0444)\n");print_file_info("test_fchmod.txt", fd);}// 尝试写入(应该失败)const char* more_data = "More data";ssize_t bytes_written = write(fd, more_data, strlen(more_data));if (bytes_written == -1) {printf("写入失败(预期): %s\n", strerror(errno));}// 设置为读写模式 (0644)result = fchmod(fd, 0644);if (result == -1) {perror("设置读写权限失败");} else {printf("成功设置读写权限 (0644)\n");print_file_info("test_fchmod.txt", fd);}// 现在应该可以写入bytes_written = write(fd, more_data, strlen(more_data));if (bytes_written != -1) {printf("写入成功,写入 %ld 字节\n", bytes_written);}// 设置为可执行模式 (0755)result = fchmod(fd, 0755);if (result == -1) {perror("设置可执行权限失败");} else {printf("成功设置可执行权限 (0755)\n");print_file_info("test_fchmod.txt", fd);}// 示例3: 使用符号常量printf("\n示例3: 使用符号常量\n");// 设置为用户读写,组和其他用户只读mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;result = fchmod(fd, mode);if (result == -1) {perror("使用符号常量设置权限失败");} else {printf("使用符号常量设置权限成功\n");printf("  模式: S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH\n");print_file_info("test_fchmod.txt", fd);}// 设置特殊位mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH | S_ISUID;result = fchmod(fd, mode);if (result == -1) {perror("设置特殊位失败");} else {printf("设置setuid位成功\n");print_file_info("test_fchmod.txt", fd);}// 示例4: 错误处理演示printf("\n示例4: 错误处理演示\n");// 使用无效的文件描述符result = fchmod(999, 0644);if (result == -1) {if (errno == EBADF) {printf("无效文件描述符错误处理正确: %s\n", strerror(errno));}}// 权限不足的情况(需要非root用户测试)if (geteuid() != 0) {printf("非root用户权限测试:\n");// 创建一个文件并关闭它,然后尝试修改(应该失败)int temp_fd = open("temp_file.txt", O_CREAT | O_WRONLY, 0644);if (temp_fd != -1) {close(temp_fd);// 重新以只读方式打开temp_fd = open("temp_file.txt", O_RDONLY);if (temp_fd != -1) {result = fchmod(temp_fd, 0777);if (result == -1) {if (errno == EPERM || errno == EACCES) {printf("权限不足错误处理正确: %s\n", strerror(errno));}}close(temp_fd);}unlink("temp_file.txt");}}// 示例5: 与chmod的对比printf("\n示例5: 与chmod的对比\n");printf("fchmod vs chmod 对比:\n");printf("chmod(\"file.txt\", 0644):\n");printf("  - 通过路径名指定文件\n");printf("  - 需要路径解析\n");printf("  - 可能受符号链接影响\n\n");printf("fchmod(fd, 0644):\n");printf("  - 通过文件描述符指定文件\n");printf("  - 直接操作已打开的文件\n");printf("  - 不受路径变化影响\n");printf("  - 更高效,避免路径解析\n\n");// 示例6: 实际应用场景printf("示例6: 实际应用场景\n");printf("安全文件创建模式:\n");printf("int create_secure_file(const char* filename) {\n");printf("    int fd = open(filename, O_CREAT | O_WRONLY, 0600);\n");printf("    if (fd == -1) return -1;\n");printf("    \n");printf("    // 确保权限正确设置\n");printf("    if (fchmod(fd, 0600) == -1) {\n");printf("        close(fd);\n");printf("        return -1;\n");printf("    }\n");printf("    \n");printf("    return fd;\n");printf("}\n\n");printf("临时文件权限管理:\n");printf("int create_temp_file() {\n");printf("    int fd = open(\"temp.dat\", O_CREAT | O_RDWR, 0600);\n");printf("    if (fd == -1) return -1;\n");printf("    \n");printf("    // 使用过程中保持私密权限\n");printf("    // ... 处理敏感数据 ...\n");printf("    \n");printf("    // 完成后调整权限\n");printf("    fchmod(fd, 0444);  // 只读\n");printf("    \n");printf("    return fd;\n");printf("}\n\n");// 示例7: 原子性优势printf("示例7: 原子性优势\n");printf("fchmod的原子性优势:\n");printf("1. 直接通过文件描述符操作\n");printf("2. 避免路径解析过程中的竞态条件\n");printf("3. 不受文件重命名影响\n");printf("4. 在文件移动后仍然有效\n\n");// 演示原子性优势printf("原子性演示:\n");int atomic_fd = open("atomic_test.txt", O_CREAT | O_RDWR, 0666);if (atomic_fd != -1) {write(atomic_fd, "atomic test", 11);printf("创建文件并获取文件描述符: %d\n", atomic_fd);// 重命名文件if (rename("atomic_test.txt", "atomic_test_renamed.txt") == 0) {printf("文件已重命名为: atomic_test_renamed.txt\n");// 仍然可以通过原来的文件描述符修改权限if (fchmod(atomic_fd, 0400) == 0) {printf("通过原文件描述符成功修改权限\n");print_file_info("atomic_test_renamed.txt", atomic_fd);}}close(atomic_fd);unlink("atomic_test_renamed.txt");}// 示例8: 权限安全最佳实践printf("示例8: 权限安全最佳实践\n");printf("文件权限安全建议:\n");printf("1. 私密文件使用 0600 (rw-------)\n");printf("2. 日志文件使用 0640 (rw-r-----)\n");printf("3. 配置文件使用 0644 (rw-r--r--)\n");printf("4. 可执行文件使用 0755 (rwxr-xr-x)\n");printf("5. 目录使用 0755 (rwxr-xr-x)\n");printf("6. 临时文件使用 0600 (rw-------)\n\n");printf("使用fchmod的安全模式:\n");printf("1. 创建时设置保守权限\n");printf("2. 根据需要调整权限\n");printf("3. 完成后收紧权限\n");printf("4. 验证权限更改结果\n");printf("5. 及时处理错误情况\n\n");// 示例9: 性能考虑printf("示例9: 性能考虑\n");printf("fchmod性能优势:\n");printf("1. 避免路径解析开销\n");printf("2. 直接操作内核文件结构\n");printf("3. 减少系统调用次数\n");printf("4. 在循环中修改多个文件时更高效\n\n");// 示例10: 错误恢复printf("示例10: 错误恢复\n");printf("健壮的权限管理:\n");printf("int safe_chmod(int fd, mode_t new_mode) {\n");printf("    struct stat old_stat;\n");printf("    if (fstat(fd, &old_stat) == -1) {\n");printf("        return -1;\n");printf("    }\n");printf("    \n");printf("    mode_t old_mode = old_stat.st_mode;\n");printf("    if (fchmod(fd, new_mode) == -1) {\n");printf("        // 可以选择恢复原权限\n");printf("        // fchmod(fd, old_mode);\n");printf("        return -1;\n");printf("    }\n");printf("    \n");printf("    return 0;\n");printf("}\n\n");// 清理资源close(fd);unlink("test_fchmod.txt");printf("总结:\n");printf("fchmod是通过文件描述符修改文件权限的函数\n");printf("相比chmod具有更好的性能和原子性\n");printf("避免了路径解析和符号链接问题\n");printf("适用于需要频繁权限管理的场景\n");printf("是安全文件操作的重要工具\n");return 0;
}

56. fchmodat - 相对路径改变文件权限

函数介绍

fchmodat是一个Linux系统调用,用于相对于指定目录文件描述符改变文件的访问权限。它是chmodfchmod的扩展版本。

函数原型

#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags);

功能

相对于目录文件描述符改变文件的访问权限,支持相对路径和额外标志。

参数

  • int dirfd: 目录文件描述符
    • AT_FDCWD: 使用当前工作目录
  • const char *pathname: 文件路径名(相对或绝对)
  • mode_t mode: 新的文件权限模式
  • int flags: 控制标志
    • 0: 基本行为
    • AT_SYMLINK_NOFOLLOW: 不跟随符号链接

返回值

  • 成功时返回0
  • 失败时返回-1,并设置errno

特殊限制

  • 需要Linux 2.6.16以上内核支持
  • 某些标志需要特定内核版本
  • 需要适当的文件权限

相似函数

  • chmod(): 基础版本(通过路径名)
  • fchmod(): 文件描述符版本
  • chmodat(): 已废弃的版本

示例代码

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <dirent.h>// 创建测试环境
int setup_test_environment() {// 创建测试目录if (mkdir("fchmodat_test", 0755) == -1 && errno != EEXIST) {perror("创建测试目录失败");return -1;}printf("创建测试目录: fchmodat_test\n");// 在目录中创建测试文件int fd = open("fchmodat_test/file1.txt", O_CREAT | O_WRONLY, 0666);if (fd != -1) {write(fd, "test file 1", 11);close(fd);printf("创建测试文件: fchmodat_test/file1.txt\n");}fd = open("fchmodat_test/file2.txt", O_CREAT | O_WRONLY, 0666);if (fd != -1) {write(fd, "test file 2", 11);close(fd);printf("创建测试文件: fchmodat_test/file2.txt\n");}// 创建子目录if (mkdir("fchmodat_test/subdir", 0755) == -1 && errno != EEXIST) {perror("创建子目录失败");} else {printf("创建子目录: fchmodat_test/subdir\n");fd = open("fchmodat_test/subdir/file3.txt", O_CREAT | O_WRONLY, 0666);if (fd != -1) {write(fd, "test file 3", 11);close(fd);printf("创建测试文件: fchmodat_test/subdir/file3.txt\n");}}return 0;
}// 显示文件权限
void show_file_permissions(const char* filepath) {struct stat sb;if (stat(filepath, &sb) == 0) {printf("  %s: ", filepath);printf("%o (", sb.st_mode & 0777);// 简单权限显示if (sb.st_mode & S_IRUSR) printf("r"); else printf("-");if (sb.st_mode & S_IWUSR) printf("w"); else printf("-");if (sb.st_mode & S_IXUSR) printf("x"); else printf("-");if (sb.st_mode & S_IRGRP) printf("r"); else printf("-");if (sb.st_mode & S_IWGRP) printf("w"); else printf("-");if (sb.st_mode & S_IXGRP) printf("x"); else printf("-");if (sb.st_mode & S_IROTH) printf("r"); else printf("-");if (sb.st_mode & S_IWOTH) printf("w"); else printf("-");if (sb.st_mode & S_IXOTH) printf("x"); else printf("-");printf(")\n");}
}int main() {int dirfd, result;printf("=== Fchmodat 函数示例 ===\n");// 示例1: 基本使用printf("\n示例1: 基本使用\n");// 设置测试环境if (setup_test_environment() == -1) {exit(EXIT_FAILURE);}// 显示初始权限printf("初始文件权限:\n");show_file_permissions("fchmodat_test/file1.txt");show_file_permissions("fchmodat_test/file2.txt");show_file_permissions("fchmodat_test/subdir/file3.txt");// 示例2: 相对于当前目录printf("\n示例2: 相对于当前目录\n");// 使用AT_FDCWD表示当前目录result = fchmodat(AT_FDCWD, "fchmodat_test/file1.txt", 0400, 0);if (result == 0) {printf("成功修改文件权限为只读 (0400)\n");show_file_permissions("fchmodat_test/file1.txt");} else {printf("修改权限失败: %s\n", strerror(errno));}// 示例3: 相对于指定目录printf("\n示例3: 相对于指定目录\n");// 打开测试目录获取文件描述符dirfd = open("fchmodat_test", O_RDONLY);if (dirfd == -1) {perror("打开测试目录失败");goto cleanup;}printf("获取目录文件描述符: %d\n", dirfd);// 相对于目录文件描述符修改文件权限result = fchmodat(dirfd, "file2.txt", 0600, 0);if (result == 0) {printf("相对于目录描述符修改文件权限成功\n");show_file_permissions("fchmodat_test/file2.txt");} else {printf("相对路径修改权限失败: %s\n", strerror(errno));}// 修改子目录中的文件result = fchmodat(dirfd, "subdir/file3.txt", 0755, 0);if (result == 0) {printf("修改子目录中文件权限成功\n");show_file_permissions("fchmodat_test/subdir/file3.txt");} else {printf("修改子目录文件权限失败: %s\n", strerror(errno));}close(dirfd);// 示例4: 使用标志位printf("\n示例4: 使用标志位\n");// 创建符号链接进行测试if (symlink("fchmodat_test/file1.txt", "symlink_to_file1") == -1 && errno != EEXIST) {perror("创建符号链接失败");} else {printf("创建符号链接: symlink_to_file1 -> fchmodat_test/file1.txt\n");// 默认行为(跟随符号链接)result = fchmodat(AT_FDCWD, "symlink_to_file1", 0644, 0);if (result == 0) {printf("默认行为(跟随符号链接)修改成功\n");} else {printf("默认行为修改失败: %s\n", strerror(errno));}#ifdef AT_SYMLINK_NOFOLLOW// 不跟随符号链接(这个标志在fchmodat中可能不被支持)printf("注意: AT_SYMLINK_NOFOLLOW在fchmodat中可能不被支持\n");printf("因为fchmodat主要用于修改权限,而不是链接本身\n");
#endifunlink("symlink_to_file1");}// 示例5: 错误处理演示printf("\n示例5: 错误处理演示\n");// 使用无效的目录文件描述符result = fchmodat(999, "file.txt", 0644, 0);if (result == -1) {if (errno == EBADF) {printf("无效目录文件描述符错误处理正确: %s\n", strerror(errno));}}// 修改不存在的文件result = fchmodat(AT_FDCWD, "fchmodat_test/nonexistent.txt", 0644, 0);if (result == -1) {if (errno == ENOENT) {printf("修改不存在文件错误处理正确: %s\n", strerror(errno));}}// 使用无效的权限模式(虽然不会报错,但可能被截断)result = fchmodat(AT_FDCWD, "fchmodat_test/file1.txt", 07777, 0);if (result == 0) {printf("使用大权限值可能被截断\n");show_file_permissions("fchmodat_test/file1.txt");}// 使用无效的标志result = fchmodat(AT_FDCWD, "fchmodat_test/file1.txt", 0644, 0x1000);if (result == -1) {printf("无效标志处理: %s\n", strerror(errno));}// 示例6: 与相关函数对比printf("\n示例6: 与相关函数对比\n");printf("chmod() vs fchmod() vs fchmodat() 对比:\n");printf("chmod(\"path/file.txt\", 0644):\n");printf("  - 通过路径名指定文件\n");printf("  - 需要完整的路径解析\n");printf("  - 可能受符号链接影响\n\n");printf("fchmod(fd, 0644):\n");printf("  - 通过文件描述符指定文件\n");printf("  - 直接操作已打开的文件\n");printf("  - 最高效,但需要先打开文件\n\n");printf("fchmodat(dirfd, \"file.txt\", 0644, 0):\n");printf("  - 相对于目录文件描述符\n");printf("  - 支持相对路径\n");printf("  - 更灵活的路径处理\n");printf("  - 支持额外标志\n\n");printf("fchmodat(AT_FDCWD, \"path/file.txt\", 0644, 0):\n");printf("  - 等同于chmod()但支持标志\n");printf("  - 更现代的接口\n\n");// 示例7: 实际应用场景printf("示例7: 实际应用场景\n");printf("批量文件权限修改:\n");printf("int batch_chmod_in_directory(const char* dirname, mode_t mode) {\n");printf("    int dirfd = open(dirname, O_RDONLY);\n");printf("    if (dirfd == -1) return -1;\n");printf("    \n");printf("    DIR* dir = fdopendir(dirfd);\n");printf("    if (!dir) {\n");printf("        close(dirfd);\n");printf("        return -1;\n");printf("    }\n");printf("    \n");printf("    struct dirent* entry;\n");printf("    while ((entry = readdir(dir)) != NULL) {\n");printf("        if (entry->d_name[0] != '.') {  // 跳过隐藏文件\n");printf("            fchmodat(dirfd, entry->d_name, mode, 0);\n");printf("        }\n");printf("    }\n");printf("    \n");printf("    closedir(dir);\n");printf("    return 0;\n");printf("}\n\n");printf("安全的相对路径操作:\n");printf("int secure_chmod_in_sandbox(int sandbox_dirfd, \n");printf("                           const char* filename, mode_t mode) {\n");printf("    // 避免路径遍历攻击\n");printf("    if (strstr(filename, \"../\") != NULL) {\n");printf("        return -1; // 拒绝不安全路径\n");printf("    }\n");printf("    \n");printf("    return fchmodat(sandbox_dirfd, filename, mode, 0);\n");printf("}\n\n");// 示例8: 相对路径优势printf("示例8: 相对路径优势\n");printf("fchmodat相对路径的优势:\n");printf("1. 避免重复路径解析\n");printf("2. 在chroot环境中更安全\n");printf("3. 支持原子性目录操作\n");printf("4. 减少字符串操作\n");printf("5. 更好的错误隔离\n\n");// 演示相对路径优势printf("相对路径优势演示:\n");dirfd = open("fchmodat_test", O_RDONLY);if (dirfd != -1) {printf("使用目录文件描述符进行批量操作:\n");// 修改多个文件权限const char* files[] = {"file1.txt", "file2.txt", "subdir/file3.txt"};mode_t modes[] = {0644, 0600, 0755};for (int i = 0; i < 3; i++) {result = fchmodat(dirfd, files[i], modes[i], 0);if (result == 0) {printf("  修改 %s 权限为 %o 成功\n", files[i], modes[i]);} else {printf("  修改 %s 权限失败: %s\n", files[i], strerror(errno));}}close(dirfd);}// 示例9: 权限管理最佳实践printf("示例9: 权限管理最佳实践\n");printf("使用fchmodat的最佳实践:\n");printf("1. 优先使用AT_FDCWD进行简单操作\n");printf("2. 复杂目录操作使用目录文件描述符\n");printf("3. 合理验证路径安全性\n");printf("4. 及时处理错误情况\n");printf("5. 避免硬编码绝对路径\n");printf("6. 使用适当的权限模式\n\n");printf("权限设置建议:\n");printf("私密文件: 0600 (rw-------)\n");printf("用户文件: 0644 (rw-r--r--)\n");printf("可执行文件: 0755 (rwxr-xr-x)\n");printf("目录: 0755 (rwxr-xr-x)\n");printf("临时文件: 0600 (rw-------)\n\n");// 示例10: 性能考虑printf("示例10: 性能考虑\n");printf("fchmodat性能特点:\n");printf("1. 相对于chmod减少路径解析\n");printf("2. 相对于fchmod避免文件打开/关闭\n");printf("3. 目录文件描述符可重复使用\n");printf("4. 批量操作效率更高\n");printf("5. 减少系统调用开销\n\n");// 清理测试环境cleanup:printf("清理测试环境...\n");unlink("fchmodat_test/subdir/file3.txt");rmdir("fchmodat_test/subdir");unlink("fchmodat_test/file1.txt");unlink("fchmodat_test/file2.txt");rmdir("fchmodat_test");printf("\n总结:\n");printf("fchmodat是chmod的现代扩展版本\n");printf("支持相对目录文件描述符\n");printf("提供额外的控制标志\n");printf("更安全的路径处理\n");printf("适用于复杂的文件权限管理场景\n");printf("是现代Linux应用开发的重要工具\n");return 0;
}
http://www.lryc.cn/news/602671.html

相关文章:

  • 技术总结|如何使用提升 strlen 的性能?
  • lesson26-2:使用Tkinter打造简易画图软件优化版
  • 数据链路层 和 ARP协议
  • MQTT的原理
  • 华为Huawei 6730交换机查看接口收发光命令 transceiver
  • 9.c语言常用算法
  • Anaconda创建环境报错:CondaHTTPEFTOT: HTTP 403 FORBIDDEN for url
  • Linux中配置haproxy
  • gitlab 在线合并分支a-分支b,解决冲突后,反向合并分支b-分支a
  • 数据结构——图(二、图的存储和基本操作)
  • 人机交互打字游戏
  • Leetcode——11. 盛最多水的容器
  • 力扣-39.组合总和
  • PhpStorm + PHP8.1 + XDebug3 实现断点调试(亲测可用)
  • 面试问题收集——卷积神经网络
  • 从 “看天吃饭” 到 “精准可控”:边缘计算网关如何引爆智慧农业种植变革?
  • 计算机毕设分享-基于SpringBoot的健身房管理系统(开题报告+前后端源码+Lun文+开发文档+数据库设计文档)
  • 服务器多线主要是指什么?
  • 服务器查日志太慢,试试grep组合拳
  • 数据中心入门学习(四):服务器概述与PCIe总线
  • 数据结构面经
  • 坚鹏:AI智能体培训是知行学成为AI智能体创新应用引领者的基础
  • 【Spring Boot 快速开发】一、入门
  • AI技术落地的综合实战经验报告,结合最新行业案例、代码示例及可视化图表,系统阐述AI在开发提效、算法优化与行业应用中的实践路径。
  • Python将Word转换为Excel
  • EXCEL 怎么把汉字转换成拼音首字母
  • 根据发热量确定选择TEC制冷片测评分析学习
  • Open CV图像基本操作可莉版
  • IP协议解析:从寻址到路由
  • Vue3判断对象是否为空方法