Linux系统篇——文件描述符FD

🧠 Linux 文件描述符(File Descriptor)详解与学习指南


一、什么是文件描述符(fd)

在 Linux 中,一切皆文件(everything is a file),包括普通文件、目录、套接字(socket)、管道(pipe)、设备文件等。

文件描述符(File Descriptor, fd) 是一个非负整数,是 Linux 为每个打开的文件或资源分配的索引号,用于在内核中标识和操作打开的文件对象。


二、标准文件描述符

Linux 启动一个进程时,会默认打开三个文件描述符:

文件描述符名称作用
0stdin标准输入(键盘)
1stdout标准输出(终端)
2stderr标准错误输出(终端)

三、文件描述符的分配机制

  1. 文件描述符是按顺序从最小的可用整数分配的。
  2. 每个进程都有自己的文件描述符表,是进程私有的。
  3. 文件描述符表中的每个项指向一个文件表项(File Table Entry),其中包含文件偏移量、访问模式等。
  4. 文件表项再指向VFS I节点(与具体文件绑定)。

✅ 这三层结构:文件描述符表文件表项inode(VFS)


四、相关系统调用

1. 打开/关闭文件

int open(const char *pathname, int flags);       // 返回 fd
int open(const char *pathname, int flags, mode_t mode);
int close(int fd);                               // 关闭文件描述符

2. 读写文件

ssize_t read(int fd, void *buf, size_t count);   // 从fd读取数据
ssize_t write(int fd, const void *buf, size_t count); // 向fd写数据

3. 文件描述符复制

int dup(int oldfd);          // 复制fd,返回新的最小可用fd
int dup2(int oldfd, int newfd); // 精确复制fd到newfd上
int dup3(int oldfd, int newfd, int flags); // 带flag控制

五、文件描述符的高级操作

1. 重定向

command > file.txt     # stdout 重定向
command < input.txt    # stdin 重定向
command 2> err.txt     # stderr 重定向
command &> all.txt     # stdout 和 stderr 同时重定向

也可以在 C 中重定向:

int fd = open("output.txt", O_WRONLY | O_CREAT, 0644);
dup2(fd, 1); // 将stdout重定向到fd

2. 非阻塞 IO 设置

int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);  // 设置非阻塞

六、查看进程打开的文件描述符

ls /proc/<pid>/fd/

也可以用 lsof -p <pid> 查看详细信息。


七、文件描述符泄漏与管理

常见问题:

  • 打开文件未及时 close,导致资源泄漏。
  • 子进程继承父进程的 fd,造成 文件句柄泄漏
  • 文件描述符耗尽:系统或进程达到 fd 打开数量上限(默认 1024)

设置进程最大文件描述符数

ulimit -n 65535

八、实际应用场景

  • 网络编程中 socket 使用 fd
  • 多路复用(select, poll, epoll)基于 fd
  • 管道、重定向、子进程通信均依赖 fd
  • 内核态-用户态资源管理

九、调试和监控工具

工具用途
lsof查看进程打开的文件
strace跟踪系统调用,观察 fd 使用
/proc/<pid>/fd查看指定进程文件描述符

🔚 总结

特性内容
定义fd 是对打开文件的标识索引
范围一般为非负整数,进程私有
用途文件、网络、设备、IPC 等操作
管理合理使用 close/dup/ulimit 等机制

嵌入式设备(尤其是运行 Linux 的嵌入式系统)中,文件描述符(fd)管理 是资源管理中的核心内容之一。因为资源有限(内存小、文件系统简化、线程少等),fd 使用必须更加谨慎、合理。

📟 嵌入式设备上的 fd 管理详解


一、嵌入式环境下的 fd 特点

特点描述
资源有限文件描述符数量小(常见为 ulimit -n 64 或更低)
文件类型多样普通文件、设备文件、socket、管道等都依赖 fd
常驻服务进程多比如 watchdog、通信服务、日志服务,fd 泄漏易积累
稳定性要求高fd 泄漏可能引起系统死锁或重启,不能容忍崩溃

二、常见 fd 使用场景(嵌入式)

场景描述
UART/串口通信打开 /dev/ttyS* 获取 fd,收发数据
网络通信使用 socket 返回的 fd 读写数据
IO 控制设备open("/dev/xxx") + ioctl() 控制硬件
日志输出写文件或通过网络/串口输出日志
管道通信父子进程或线程间通信依赖 fd 管道
epoll/select/poll多路复用高效管理多个 IO 设备

三、fd 使用示例(嵌入式通信)

示例:串口通信(串口为 /dev/ttyS1

int fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NONBLOCK);
if (fd < 0) {perror("open");return -1;
}
// 配置串口参数略
write(fd, "hello", 5);   // 发送数据
read(fd, buf, 100);       // 接收数据
close(fd);                // 必须释放

四、fd 泄漏问题与监控手段

1. 常见原因

  • 打开文件/设备后忘记 close
  • 多线程重复打开但未共享/回收 fd
  • 子进程未清理继承的 fd
  • 线程/进程异常退出未清理 fd

2. 检查方法

  • 查看 /proc/<pid>/fd/
  • 使用 lsof -p <pid>
  • 增加代码层日志打印:打开/关闭 fd 时打印日志
  • 使用 valgrind 检查资源泄露(如适用于开发阶段)

五、fd 复用与最大限制优化

1. 降低 fd 数量开销的方式

  • 长连接共享 fd(例如:UART 只初始化一次,线程共享)
  • fd 池化:维护打开的 fd 池,避免重复打开
  • epoll/select 合理使用 IO 多路复用,避免线程 per fd 模式

2. 增加 fd 限制(需内核支持)

临时提升限制:

ulimit -n 512

程序内:

#include <sys/resource.h>
struct rlimit rl;
rl.rlim_cur = 512;
rl.rlim_max = 512;
setrlimit(RLIMIT_NOFILE, &rl);

注意:嵌入式系统需要 root 权限且内核配置允许


六、fd 管理最佳实践(嵌入式专属)

建议描述
封装 open/close 接口统一记录日志、错误码处理,便于排查问题
加入 fd 泄漏检测机制启动时检测打开文件数量,定期检查 fd 使用量
定期巡检 fd 表定时读取 /proc/self/fd 判断是否异常增长
所有打开动作均加错误判断包括 open/socket/accept 等,避免异常触发崩溃
使用 epoll/poll 管理高并发 fd尤其适合小资源高效率处理设备数据
子进程创建前清理 fd使用 FD_CLOEXEC 或手动关闭无用 fd
异常退出时做清理信号处理器中注册清理动作,确保 fd 不悬挂

七、常见陷阱

场景错误现象
没有设置 O_NONBLOCK串口或 socket 阻塞,线程卡死
多线程使用同一 fd 无锁保护串口数据错乱或丢失
accept 后未 closefd 泄漏,连接数逐渐耗尽
子进程继承父 fd意外重用已关闭 fd,产生不可预期行为
fd 重复打开造成重复资源消耗且无警告

八、可选工具与方案

工具/技术功能
valgrind --leak-check=full检查内存/资源泄漏
lsof / fuser检查 fd 占用
strace跟踪 open/read/write/close 系统调用
procfs(如 /proc/self/fd/动态查看当前进程 fd

🧠 总结

类别要点
管理方式合理打开、及时关闭、使用 fd 池化
泄漏检查周期性监控 /proc,记录每次 fd 分配
性能优化使用 epoll,避免创建多线程 per fd
系统设置合理设定 ulimit,避免 fd 耗尽问题
稳定性保障异常退出、信号退出前清理 fd,防止死锁或资源不释放

对嵌入式系统的 文件描述符(fd)管理封装代码fd 泄漏检测模块实现,目标是提高资源使用可控性、稳定性和排错效率。


🛠️ 一、fd 管理封装模块(fd_manager.c/.h)

✅ 设计目标:

  • 封装 open/close/dup 等系统调用
  • 自动记录和追踪 fd 状态
  • 支持日志输出和自动清理

📄 fd_manager.h

#ifndef FD_MANAGER_H
#define FD_MANAGER_H#include <stdio.h>#define MAX_TRACKED_FD 1024typedef struct {int fd;char tag[64];   // 用于标识fd用途,比如"log", "uart0"char file[128]; // 打开时的文件名
} FDTrack;int tracked_open(const char *pathname, int flags, const char *tag);
int tracked_open_mode(const char *pathname, int flags, mode_t mode, const char *tag);
int tracked_close(int fd);
void fd_manager_dump(void);              // 打印当前已打开的 fd
void fd_manager_cleanup_all(void);      // 程序退出时自动关闭所有 fd#endif

📄 fd_manager.c

#include "fd_manager.h"
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>static FDTrack fd_table[MAX_TRACKED_FD];static void track_fd(int fd, const char *pathname, const char *tag) {if (fd < 0 || fd >= MAX_TRACKED_FD) return;fd_table[fd].fd = fd;snprintf(fd_table[fd].file, sizeof(fd_table[fd].file), "%s", pathname);snprintf(fd_table[fd].tag, sizeof(fd_table[fd].tag), "%s", tag);
}static void untrack_fd(int fd) {if (fd < 0 || fd >= MAX_TRACKED_FD) return;fd_table[fd].fd = -1;fd_table[fd].file[0] = '\0';fd_table[fd].tag[0] = '\0';
}int tracked_open(const char *pathname, int flags, const char *tag) {int fd = open(pathname, flags);if (fd >= 0) track_fd(fd, pathname, tag);return fd;
}int tracked_open_mode(const char *pathname, int flags, mode_t mode, const char *tag) {int fd = open(pathname, flags, mode);if (fd >= 0) track_fd(fd, pathname, tag);return fd;
}int tracked_close(int fd) {int ret = close(fd);if (ret == 0) untrack_fd(fd);return ret;
}void fd_manager_dump(void) {printf(">> Opened FD List:\n");for (int i = 0; i < MAX_TRACKED_FD; i++) {if (fd_table[i].fd >= 0) {printf("  [fd=%d] tag=%s file=%s\n", fd_table[i].fd, fd_table[i].tag, fd_table[i].file);}}
}void fd_manager_cleanup_all(void) {for (int i = 0; i < MAX_TRACKED_FD; i++) {if (fd_table[i].fd >= 0) {close(fd_table[i].fd);untrack_fd(i);}}
}

🔧 使用示例:

#include "fd_manager.h"int main() {int uart_fd = tracked_open("/dev/ttyS1", O_RDWR, "uart0");if (uart_fd < 0) {perror("UART open failed");return 1;}int log_fd = tracked_open_mode("log.txt", O_CREAT | O_WRONLY, 0644, "log");write(log_fd, "hello fd\n", 9);fd_manager_dump();  // 打印当前打开的 fdtracked_close(log_fd);tracked_close(uart_fd);return 0;
}

🕵️‍♂️ 二、fd 泄漏检测模块实现

🧩 方法一:通过 /proc/self/fd 定期检查 fd 增长

#include <stdio.h>
#include <dirent.h>
#include <unistd.h>int count_open_fds() {DIR *dir = opendir("/proc/self/fd");if (!dir) return -1;int count = 0;struct dirent *entry;while ((entry = readdir(dir))) {// 排除 . 和 ..if (entry->d_name[0] == '.') continue;count++;}closedir(dir);return count;
}void monitor_fd_leaks() {static int prev_count = -1;int current = count_open_fds();if (current >= 0) {if (prev_count >= 0 && current > prev_count) {printf("⚠️ Warning: FD count increased from %d to %d\n", prev_count, current);}prev_count = current;}
}

🔁 建议定期调用:

while (1) {monitor_fd_leaks();   // 每隔5秒检测一次sleep(5);
}

✅ 总结

组件作用
fd_manager 模块封装 open/close,自动记录 fd 来源、状态
fd 泄漏检测动态比较 /proc/self/fd,发现异常增长
实用价值对嵌入式通信程序、守护进程、串口调试程序特别有用

线程安全版本的 fd 管理封装模块,适用于嵌入式 Linux 多线程环境(如 POSIX 线程)。它在原有的 fd_manager 基础上加入了互斥锁保护,确保多个线程同时操作文件描述符时不会引发数据竞态或管理混乱。


🧵 线程安全 fd 管理模块(fd_manager_threadsafe.c/.h)

🔐 使用 pthread_mutex_t 加锁保护 fd_table 的读写

📄 fd_manager_threadsafe.h

#ifndef FD_MANAGER_THREADSAFE_H
#define FD_MANAGER_THREADSAFE_H#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>#define MAX_TRACKED_FD 1024typedef struct {int fd;char tag[64];   // 用于标记用途char file[128]; // 打开路径
} FDTrack;int tracked_open(const char *pathname, int flags, const char *tag);
int tracked_open_mode(const char *pathname, int flags, mode_t mode, const char *tag);
int tracked_close(int fd);
void fd_manager_dump(void);              // 打印当前 fd 状态
void fd_manager_cleanup_all(void);      // 程序退出时清理所有 fd
void fd_manager_init(void);             // 初始化(必须调用一次)
void fd_manager_deinit(void);           // 销毁(程序退出前调用)#endif

📄 fd_manager_threadsafe.c

#include "fd_manager_threadsafe.h"
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>static FDTrack fd_table[MAX_TRACKED_FD];
static pthread_mutex_t fd_table_lock;void fd_manager_init(void) {pthread_mutex_init(&fd_table_lock, NULL);for (int i = 0; i < MAX_TRACKED_FD; i++) {fd_table[i].fd = -1;}
}void fd_manager_deinit(void) {fd_manager_cleanup_all();pthread_mutex_destroy(&fd_table_lock);
}static void track_fd(int fd, const char *pathname, const char *tag) {if (fd < 0 || fd >= MAX_TRACKED_FD) return;pthread_mutex_lock(&fd_table_lock);fd_table[fd].fd = fd;snprintf(fd_table[fd].file, sizeof(fd_table[fd].file), "%s", pathname);snprintf(fd_table[fd].tag, sizeof(fd_table[fd].tag), "%s", tag);pthread_mutex_unlock(&fd_table_lock);
}static void untrack_fd(int fd) {if (fd < 0 || fd >= MAX_TRACKED_FD) return;pthread_mutex_lock(&fd_table_lock);fd_table[fd].fd = -1;fd_table[fd].file[0] = '\0';fd_table[fd].tag[0] = '\0';pthread_mutex_unlock(&fd_table_lock);
}int tracked_open(const char *pathname, int flags, const char *tag) {int fd = open(pathname, flags);if (fd >= 0) track_fd(fd, pathname, tag);return fd;
}int tracked_open_mode(const char *pathname, int flags, mode_t mode, const char *tag) {int fd = open(pathname, flags, mode);if (fd >= 0) track_fd(fd, pathname, tag);return fd;
}int tracked_close(int fd) {int ret = close(fd);if (ret == 0) untrack_fd(fd);return ret;
}void fd_manager_dump(void) {pthread_mutex_lock(&fd_table_lock);printf(">> Opened FD List (thread-safe):\n");for (int i = 0; i < MAX_TRACKED_FD; i++) {if (fd_table[i].fd >= 0) {printf("  [fd=%d] tag=%s file=%s\n", fd_table[i].fd, fd_table[i].tag, fd_table[i].file);}}pthread_mutex_unlock(&fd_table_lock);
}void fd_manager_cleanup_all(void) {pthread_mutex_lock(&fd_table_lock);for (int i = 0; i < MAX_TRACKED_FD; i++) {if (fd_table[i].fd >= 0) {close(fd_table[i].fd);fd_table[i].fd = -1;fd_table[i].file[0] = '\0';fd_table[i].tag[0] = '\0';}}pthread_mutex_unlock(&fd_table_lock);
}

✅ 使用方式示例(多线程)

#include <pthread.h>
#include "fd_manager_threadsafe.h"void* thread_func(void* arg) {int fd = tracked_open("/dev/ttyS1", O_RDWR, "uart");if (fd >= 0) {// 模拟使用write(fd, "data", 4);tracked_close(fd);}return NULL;
}int main() {fd_manager_init();  // 初始化模块pthread_t t1, t2;pthread_create(&t1, NULL, thread_func, NULL);pthread_create(&t2, NULL, thread_func, NULL);pthread_join(t1, NULL);pthread_join(t2, NULL);fd_manager_dump();fd_manager_deinit();  // 清理资源return 0;
}

🧠 总结

特性说明
🔐 线程安全使用 pthread_mutex 对共享 fd 表加锁
📋 可追踪每个 fd 都记录来源、用途、路径
🧹 自动清理支持批量关闭所有打开的 fd
🧪 便于调试可随时打印当前所有活跃 fd 状态

Linux 文件描述符 (File Descriptor, FD)

一、文件描述符概念

在 Linux 中,文件描述符是操作系统为每个进程分配的整数,用于标识打开的文件或其他输入输出资源(如管道、套接字等)。文件描述符是 Linux 内核与用户空间交互的重要桥梁,是 I/O 操作的核心。

二、文件描述符的类型

文件描述符可以用于表示以下几种资源:

  1. 普通文件:例如文本文件、二进制文件。
  2. 设备文件:如 /dev/null 或终端设备 /dev/tty
  3. 管道:如命名管道或匿名管道。
  4. 套接字:网络通信的端点。
  5. 标准输入输出:默认分配的三个描述符:
    • 0:标准输入(stdin
    • 1:标准输出(stdout
    • 2:标准错误(stderr
三、文件描述符的分配
  • 当一个进程打开一个文件时,内核会分配一个最小可用的非负整数作为文件描述符。
  • 每个进程有自己独立的文件描述符表。
四、文件描述符的工作原理

文件描述符与文件系统的交互包括以下关键数据结构:

  1. 进程的文件描述符表
    • 每个进程都有一个文件描述符表(数组),其中的每个条目指向一个打开文件的记录。
  2. 系统打开文件表
    • 每个条目保存打开文件的状态,包括文件偏移量、访问模式等。
  3. 文件系统 inode 表
    • 包含文件的元数据,如权限、大小等。

工作流程

  • 当使用 open 打开文件时,内核分配一个文件描述符并关联到系统打开文件表。
  • 文件描述符指向打开文件表的一个条目,该条目再指向文件的具体 inode。
五、常用操作与开发示例
1. 打开文件

使用 open 打开文件,返回一个文件描述符。

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>int main() {int fd = open("example.txt", O_RDONLY);if (fd < 0) {perror("open");return 1;}printf("File descriptor: %d\n", fd);close(fd);return 0;
}
2. 读写文件

通过 readwrite 使用文件描述符进行 I/O 操作。

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>int main() {int fd = open("example.txt", O_RDWR | O_CREAT, 0644);if (fd < 0) {perror("open");return 1;}const char *content = "Hello, File Descriptor!";write(fd, content, 25);// Reset file offset and readlseek(fd, 0, SEEK_SET); char buffer[256];ssize_t nbytes = read(fd, buffer, sizeof(buffer) - 1);buffer[nbytes] = '\0';printf("Read content: %s\n", buffer);close(fd);return 0;
}
3. 复制文件描述符

使用 dupdup2 复制文件描述符。

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>int main() {int fd = open("example.txt", O_RDWR | O_CREAT, 0644);if (fd < 0) {perror("open");return 1;}int new_fd = dup(fd);write(new_fd, "Duplicated FD content\n", 23);close(fd);close(new_fd);return 0;
}
4. 关闭文件描述符

使用 close 释放文件描述符。

close(fd);
5. 设置非阻塞模式

通过 fcntl 修改文件描述符的标志。

#include <fcntl.h>
#include <unistd.h>int set_nonblocking(int fd) {int flags = fcntl(fd, F_GETFL, 0);if (flags == -1) return -1;return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
六、开发中的常见用法
  1. 文件读写:通过 openreadwrite 操作文件。
  2. 进程通信:使用管道或套接字的文件描述符。
  3. 重定向 I/O:通过 dup2 实现标准输入输出重定向。
  4. 事件驱动开发:结合 selectepoll 使用文件描述符实现异步 I/O。
七、注意事项
  1. 资源泄漏:文件描述符需要及时关闭,否则可能耗尽。
  2. 错误检查:每次调用 openread 等函数后,检查返回值。
  3. 线程安全:多个线程共享文件描述符时需要同步。
  4. 最大限制:使用 ulimit -n 查看当前系统允许的最大文件描述符数量。
八、总结

文件描述符是 Linux I/O 的基础,开发者可以通过对其操作实现高效的资源管理、通信和文件操作。掌握文件描述符的用法和底层原理,可以为开发高性能 Linux 程序提供强大的工具。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/49404.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS- 2.1 实战之图文混排、表格、表单、学校官网一级导航栏

本系列可作为前端学习系列的笔记&#xff0c;代码的运行环境是在HBuilder中&#xff0c;小编会将代码复制下来&#xff0c;大家复制下来就可以练习了&#xff0c;方便大家学习。 HTML系列文章 已经收录在前端专栏&#xff0c;有需要的宝宝们可以点击前端专栏查看&#xff01; 系…

文件同步2

请大家思考如何使用scp命令去解决这个问题。 有两种思路&#xff1a; 第一种&#xff1a;三个文件一个一个去拷贝。缺点是操作麻烦&#xff0c;要逐一操作。 第二种&#xff1a;重新把A上的conf拷贝到B上。缺点是会重复拷贝文件1&#xff0c;2&#xff0c;3&#xff0c;4。 …

Maven使用详解:Maven的概述(二)

一、核心定义与功能 Maven是由Apache软件基金会开发的开源项目管理工具&#xff0c;专为Java项目设计&#xff0c;主要用于自动化构建、依赖管理和项目标准化。其核心功能包括&#xff1a; 依赖管理&#xff1a;通过pom.xml文件声明依赖库&#xff0c;自动从中央仓库下载并管…

大疆无人机自主飞行解决方案局限性及增强解决方案-AIBOX:特色行业无人机巡检解决方案

大疆无人机自主飞行解决方案局限性及增强解决方案-AIBOX&#xff1a;特色行业无人机巡检解决方案 大疆无人机是低空行业无人机最具性价比的产品&#xff0c;尤其是大疆机场3的推出&#xff0c;以及持续自身产品升级迭代&#xff0c;包括司空2、大疆智图以及大疆智运等专业软件和…

leetcode:58. 最后一个单词的长度(python3解法)

难度&#xff1a;简单 给你一个字符串 s&#xff0c;由若干单词组成&#xff0c;单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。 单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。 示例 1&#xff1a; 输入&#xff1a;s "Hello World"…

Ubuntu24.04 安装 5080显卡驱动以及cuda

前言 之前使用Ubuntu22.04版本一直报错,然后换了24.04版本才能正常安装 一. 配置基础环境 Linux系统进行环境开发环境配置-CSDN博客 二. 安装显卡驱动 1.安装驱动 按以下步骤来&#xff1a; sudo apt update && sudo apt upgrade -y#下载最新内核并安装 sudo add…

Github 2025-05-15 Go开源项目日报 Top10

根据Github Trendings的统计,今日(2025-05-15统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Go项目10Python项目1Ollama: 本地大型语言模型设置与运行 创建周期:248 天开发语言:Go协议类型:MIT LicenseStar数量:42421 个Fork数量:27…

操作系统-锁/内存/中断/IO

文章目录 锁自旋锁互斥锁悲观锁和乐观锁 内存管理物理/虚拟内存页表段表虚拟内存布局写时复制copy on writebrk&#xff0c;mmap页面置换算法 中断中断分类中断流程 网络I/OI/O模型服务器处理并发请求 锁 自旋锁 自旋锁是一种基于忙等待&#xff08;Busy-Waiting&#xff09;…

校园一卡通安全策略研究调研报告

目录 一、研究背景 二、问题分析 三、解决方案 1.系统功能整合 2.用户体验优化 3.安全性能提升 4.代码说明 ①ConfigController.java ②FileController.java ③SushedianfeiController.java ④UserService.java ⑤XiaoyuankachongzhiController.java ⑥其他代码 …

EWOMAIL

1、错误 Problem: problem with installed package selinux-policy-targeted-3.14.3-41.el8.noarch package fail2ban-server-1.0.2-3.el8.noarch requires (fail2ban-selinux if selinux-policy-targeted), but none of the providers can be installed - package fail2ban-…

强化学习算法实战:一个例子实现sarsa、dqn、ddqn、qac、a2c、trpo、ppo

简介 在学习强化学习算法&#xff1a;sarsa、dqn、ddqn、qac、a2c、trpo、ppo时&#xff0c;由于有大量数据公式的推导&#xff0c;觉得十分晦涩&#xff0c;且听过就忘记了。 但是当把算法应用于实战时&#xff0c;代码的实现要比数据推导要直观很多。 接下来通过不同的算法实…

《数据库原理》部分习题解析1

《数据库原理》部分习题解析1 1. 名词解释 &#xff08;1&#xff09;关系&#xff08;2&#xff09;属性&#xff08;3&#xff09;域&#xff08;4&#xff09;元组&#xff08;5&#xff09;码&#xff08;6&#xff09;分量&#xff08;7&#xff09;关系模式 &#xff0…

20250515通过以太网让VLC拉取视熙科技的机芯的rtsp视频流的步骤

20250515通过以太网让VLC拉取视熙科技的机芯的rtsp视频流的步骤 2025/5/15 20:26 缘起&#xff1a;荣品的PRO-RK3566适配视熙科技 的4800W的机芯。 1080p出图预览的时候没图了。 通过105的机芯出图确认 荣品的PRO-RK3566 的硬件正常。 然后要确认 视熙科技 的4800W的机芯是否出…

AI 赋能防艾宣传:从创意到实践,我的 IP 形象设计之旅

在数字技术飞速发展的今天&#xff0c;如何让严肃的健康传播变得更有温度、更具吸引力&#xff1f;作为一名参与防艾宣传实践的学生&#xff0c;我尝试通过 AI 工具构建专属 IP 形象&#xff0c;让防艾知识从 "被动接受" 转化为 "主动探索"。这篇文章将分享…

机器学习笔记2

5 TfidfVectorizer TF-IDF文本特征词的重要程度特征提取 (1) 算法 词频(Term Frequency, TF), 表示一个词在当前篇文章中的重要性 逆文档频率(Inverse Document Frequency, IDF), 反映了词在整个文档集合中的稀有程度 (2) API sklearn.feature_extraction.text.TfidfVector…

MYSQL 子查询

标量子查询 #标量子查询 #1.查询“研发部”的所有员工信息 # a.查询“研发部”部门id select id from dept where name研发部;#b.根据销售部部门id&#xff0c;查询员工信息 select * from emp where dept_id(select id from dept where name研发部);#2.查询在王金彪入职之后…

EasyRTC嵌入式音视频通话SDK驱动智能硬件音视频应用新发展

一、引言 在数字化浪潮下&#xff0c;智能硬件蓬勃发展&#xff0c;从智能家居到工业物联网&#xff0c;深刻改变人们的生活与工作。音视频通讯作为智能硬件交互与协同的核心&#xff0c;重要性不言而喻。但嵌入式设备硬件资源受限&#xff0c;传统音视频方案集成困难。EasyRT…

c/c++中程序内存区域的划分

c/c程序内存分配的几个区域&#xff1a; 1.栈区&#xff1a;在执行函数时&#xff0c;函数内局部变量的存储单元都可以在栈上创建&#xff0c;函数执行结束时这些存储单元自动被释放&#xff0c;栈内存分配运算内置于处理器的指令集中&#xff0c;效率很高但是分配的内存容量有…

微信小程序 自定义图片分享-绘制数据图片以及信息文字

一 、需求 从数据库中读取头像&#xff0c;姓名电话等信息&#xff0c;当分享给女朋友时&#xff0c;每个信息不一样 二、实现方案 1、先将数据库中需要的头像姓名信息读取出来加载到data 数据项中 data:{firstName:, // 姓名img:, // 头像shareImage:,// 存储临时图片 } 2…

IPLOOK超轻量核心网,助力5G专网和MEC边缘快速落地

随着5G深入千行百业&#xff0c;行业客户对核心网的灵活性、可控性和部署效率提出了更高要求。IPLOOK面向数字化转型需求&#xff0c;推出了超轻量级核心网解决方案&#xff0c;具备体积小、资源占用少、部署灵活、易于维护等特性&#xff0c;广泛适用于专网、实验室、MEC边缘云…