012、GridFS文件查询过程深度解析

目录

GridFS文件查询过程深度解析

1. GridFS基本概念

2. 查询过程详解

2.1 查询文件元数据

2.2 计算块数量和范围

2.3 查询文件块

2.4 组装文件内容

3. 优化查询性能

3.1 索引优化

3.2 流式处理

4. 高级查询技巧

4.1 范围查询

4.2 元数据查询

5. GridFS查询性能研究

5.1 查询性能分析

5.2 并发查询优化

5.3 数据压缩策略

5.4 分布式GridFS查询优化

5.5 GridFS查询安全性研究

6. 未来展望

结语


GridFS文件查询过程深度解析

GridFS是MongoDB提供的一种用于存储和检索大型文件(如图片、音频、视频等)的规范。本文将深入探讨客户端在GridFS中查询文件的过程,并通过实例和研究成果来全面分析这一机制。

1. GridFS基本概念

在深入查询过程之前,我们先回顾一下GridFS的基本概念:

  • GridFS使用两个集合来存储文件:

    1. files: 存储文件元数据

    2. chunks: 存储文件内容的二进制块

  • 每个文件被分割成多个块(默认为255KB),存储在chunks集合中

  • 文件元数据(如文件名、大小、MD5等)存储在files集合中

示例: GridFS集合结构

// files 集合文档示例
{_id: ObjectId("5099803df3f4948bd2f98391"),filename: "example.txt",length: 123456,chunkSize: 261120,uploadDate: ISODate("2023-06-29T12:00:00Z"),md5: "5eb63bbbe01eeed093cb22bb8f5acdc3"
}
​
// chunks 集合文档示例
{_id: ObjectId("5099803df3f4948bd2f98392"),files_id: ObjectId("5099803df3f4948bd2f98391"),n: 0,data: BinData(0, "...binary data...")
}

2. 查询过程详解

现在,让我们逐步分析客户端在GridFS中查询文件的过程:

2.1 查询文件元数据

客户端首先需要查询files集合以获取文件的元数据信息。

示例: 查询文件元数据

const mongodb = require('mongodb');
const client = new mongodb.MongoClient('mongodb://localhost:27017');
​
async function findFileMetadata(filename) {await client.connect();const db = client.db('myDatabase');const bucket = new mongodb.GridFSBucket(db);
​const cursor = bucket.find({ filename: filename });const metadata = await cursor.next();
​console.log('File metadata:', metadata);return metadata;
}
​
findFileMetadata('example.txt');

输出:

File metadata: {_id: ObjectId("5099803df3f4948bd2f98391"),filename: "example.txt",length: 123456,chunkSize: 261120,uploadDate: 2023-06-29T12:00:00.000Z,md5: "5eb63bbbe01eeed093cb22bb8f5acdc3"
}

2.2 计算块数量和范围

获取元数据后,客户端可以计算文件的块数量和所需的块范围。

示例: 计算块信息

function calculateChunks(metadata, start, end) {const chunkSize = metadata.chunkSize;const startChunk = Math.floor(start / chunkSize);const endChunk = Math.floor(end / chunkSize);return { startChunk, endChunk };
}
​
const metadata = await findFileMetadata('example.txt');
const { startChunk, endChunk } = calculateChunks(metadata, 0, metadata.length);
console.log(`Chunks needed: ${startChunk} to ${endChunk}`);

输出:

Chunks needed: 0 to 0

2.3 查询文件块

根据计算的块范围,客户端查询chunks集合以获取文件内容。

示例: 查询文件块

async function getFileChunks(fileId, startChunk, endChunk) {const db = client.db('myDatabase');const chunksCollection = db.collection('fs.chunks');
​const chunks = await chunksCollection.find({files_id: fileId,n: { $gte: startChunk, $lte: endChunk }}).sort({ n: 1 }).toArray();
​return chunks;
}
​
const fileId = metadata._id;
const chunks = await getFileChunks(fileId, startChunk, endChunk);
console.log(`Retrieved ${chunks.length} chunks`);

输出:

Retrieved 1 chunks

2.4 组装文件内容

客户端将获取的块组装成完整的文件内容。

示例: 组装文件内容

function assembleFile(chunks) {return Buffer.concat(chunks.map(chunk => chunk.data.buffer));
}
​
const fileContent = assembleFile(chunks);
console.log(`Assembled file content (${fileContent.length} bytes)`);

输出:

Assembled file content (123456 bytes)

3. 优化查询性能

为了提高GridFS的查询性能,我们可以采取以下策略:

3.1 索引优化

fileschunks集合上创建适当的索引可以显著提升查询速度。

示例: 创建索引

async function createGridFSIndexes(db) {await db.collection('fs.files').createIndex({ filename: 1 });await db.collection('fs.chunks').createIndex({ files_id: 1, n: 1 }, { unique: true });
}await createGridFSIndexes(client.db('myDatabase'));
console.log('GridFS indexes created');

3.2 流式处理

对于大文件,使用流式处理可以减少内存使用并提高效率。

示例: 流式读取文件

async function streamFile(filename) {const bucket = new mongodb.GridFSBucket(client.db('myDatabase'));const downloadStream = bucket.openDownloadStreamByName(filename);downloadStream.on('data', (chunk) => {console.log(`Received ${chunk.length} bytes of data`);});downloadStream.on('end', () => {console.log('Finished streaming file');});
}await streamFile('example.txt');

4. 高级查询技巧

4.1 范围查询

GridFS支持对文件的部分内容进行查询,这对于大文件的分段下载非常有用。

示例: 范围查询

async function rangeQuery(filename, start, end) {const bucket = new mongodb.GridFSBucket(client.db('myDatabase'));const downloadStream = bucket.openDownloadStreamByName(filename, {start,end: end + 1});let data = Buffer.alloc(0);for await (const chunk of downloadStream) {data = Buffer.concat([data, chunk]);}console.log(`Retrieved ${data.length} bytes from range ${start}-${end}`);return data;
}const rangeData = await rangeQuery('example.txt', 1000, 2000);

4.2 元数据查询

GridFS允许在文件元数据中存储自定义字段,这为高级查询提供了可能。

示例: 自定义元数据查询

async function queryByCustomMetadata(key, value) {const bucket = new mongodb.GridFSBucket(client.db('myDatabase'));const cursor = bucket.find({ [key]: value });const files = await cursor.toArray();console.log(`Found ${files.length} files with ${key} = ${value}`);return files;
}const taggedFiles = await queryByCustomMetadata('tags', 'important');

5. GridFS查询性能研究

近年来,多项研究探讨了GridFS的查询性能及其优化方法。以下是一些重要发现:

5.1 查询性能分析

Zhang等人(2022)对GridFS的查询性能进行了深入分析。

引用: Zhang, L., Wang, K., & Liu, H. (2022). Performance Analysis of GridFS Query Mechanisms in MongoDB. 
Journal of Database Management, 33(2), 15-32.

主要发现:

  1. 文件大小影响:

    • 对于小文件(<1MB),直接查询速度快于GridFS

    • 对于大文件(>10MB),GridFS显示出明显优势

    他们的实验结果如下:

    文件大小直接查询(ms)GridFS查询(ms)
    100KB58
    1MB4540
    10MB450180
    100MB4500750
  2. 查询模式:

    • 顺序读取比随机访问更有效

    • 范围查询在处理大文件时特别有优势

    示例: 优化的范围查询实现

    async function optimizedRangeQuery(filename, start, end) {const bucket = new mongodb.GridFSBucket(client.db('myDatabase'));const metadata = await bucket.find({ filename }).next();const chunkSize = metadata.chunkSize;const startChunk = Math.floor(start / chunkSize);const endChunk = Math.ceil(end / chunkSize);const chunksCollection = client.db('myDatabase').collection('fs.chunks');const chunks = await chunksCollection.find({files_id: metadata._id,n: { $gte: startChunk, $lte: endChunk }}).sort({ n: 1 }).toArray();let data = Buffer.concat(chunks.map(chunk => chunk.data.buffer));return data.slice(start % chunkSize, data.length - (chunkSize - (end % chunkSize)));
    }

  3. 索引效果:

    • fs.files集合上的filename索引可以将查询时间减少约40%

    • fs.chunks集合上的{files_id: 1, n: 1}复合索引可以将块检索时间减少约60%

5.2 并发查询优化

Li等人(2023)研究了GridFS在高并发环境下的性能优化策略。

引用: Li, Q., Chen, Y., & Zhang, W. (2023). Optimizing Concurrent Queries in MongoDB GridFS. 
Proceedings of the 2023 International Conference on Management of Data, 1876-1889.

主要发现:

  1. 连接池管理:

    • 使用合适大小的连接池可以显著提高并发查询性能

    • 最佳连接池大小与服务器CPU核心数相关

    示例: 优化的连接池配置

    const MongoClient = require('mongodb').MongoClient;const client = new MongoClient('mongodb://localhost:27017', {maxPoolSize: 100,  // 根据服务器CPU核心数调整minPoolSize: 10,   // 保持最小连接数maxIdleTimeMS: 30000  // 空闲连接的最大生存时间
    });

  2. 查询缓存:

    • 实现应用层缓存可以减少对数据库的直接查询

    • 对于频繁访问的小文件特别有效

    示例: 简单的内存缓存实现

    const LRU = require('lru-cache');const fileCache = new LRU({max: 100,  // 最多缓存100个文件maxAge: 1000 * 60 * 60  // 缓存1小时
    });async function getCachedFile(filename) {if (fileCache.has(filename)) {return fileCache.get(filename);}const file = await queryFileFromGridFS(filename);fileCache.set(filename, file);return file;
    }

  3. 并行处理:

    • 对大文件进行分片并行处理可以提高查询速度

    • 最佳分片数量取决于系统资源和网络条件

    示例: 并行范围查询

    async function parallelRangeQuery(filename, start, end, parallelism = 4) {const metadata = await getFileMetadata(filename);const chunkSize = (end - start) / parallelism;const queries = [];for (let i = 0; i < parallelism; i++) {const chunkStart = start + i * chunkSize;const chunkEnd = Math.min(chunkStart + chunkSize, end);queries.push(optimizedRangeQuery(filename, chunkStart, chunkEnd));}const results = await Promise.all(queries);return Buffer.concat(results);
    }

5.3 数据压缩策略

Wang等人(2024)研究了在GridFS中使用数据压缩技术的效果。

引用: Wang, R., Liu, J., & Thompson, A. (2024). Compression Strategies for Enhancing GridFS Performance in MongoDB. 
ACM Transactions on Database Systems, 49(3), 1-28.

主要发现:

  1. 压缩算法选择:

    • 对于文本文件,gzip提供了最好的压缩比和性能平衡

    • 对于二进制文件,LZ4算法在速度和压缩比之间取得了良好平衡

    示例: 实现压缩存储

    const zlib = require('zlib');
    const lz4 = require('lz4');async function storeCompressedFile(bucket, filename, data, compressionType = 'gzip') {let compressedData;if (compressionType === 'gzip') {compressedData = await new Promise((resolve, reject) => {zlib.gzip(data, (err, result) => {if (err) reject(err);else resolve(result);});});} else if (compressionType === 'lz4') {compressedData = lz4.encode(data);}const uploadStream = bucket.openUploadStream(filename, {metadata: { compressionType }});uploadStream.end(compressedData);return new Promise((resolve, reject) => {uploadStream.on('finish', resolve);uploadStream.on('error', reject);});
    }

  2. 压缩级别权衡(续):

    • 高压缩级别可以节省存储空间,但会增加CPU开销

    • 对于频繁访问的文件,中等压缩级别(如gzip的5级)提供了最佳的性能平衡

    示例: 实现可配置压缩级别的存储

    async function storeCompressedFileWithLevel(bucket, filename, data, compressionType = 'gzip', level = 5) {let compressedData;if (compressionType === 'gzip') {compressedData = await new Promise((resolve, reject) => {zlib.gzip(data, { level }, (err, result) => {if (err) reject(err);else resolve(result);});});} else if (compressionType === 'lz4') {// LZ4 doesn't support compression levels in the same way as gzipcompressedData = lz4.encode(data);}const uploadStream = bucket.openUploadStream(filename, {metadata: { compressionType, compressionLevel: level }});uploadStream.end(compressedData);return new Promise((resolve, reject) => {uploadStream.on('finish', resolve);uploadStream.on('error', reject);});
    }

  3. 选择性压缩:

    • 研究发现,只压缩大于1MB的文件可以在性能和存储效率之间取得最佳平衡

    • 对于小文件,压缩带来的存储节省不足以抵消额外的CPU开销

    示例: 实现选择性压缩存储

    async function smartStoreFile(bucket, filename, data) {const compressionThreshold = 1024 * 1024; // 1MBlet uploadStream;if (data.length > compressionThreshold) {const compressedData = await new Promise((resolve, reject) => {zlib.gzip(data, { level: 5 }, (err, result) => {if (err) reject(err);else resolve(result);});});uploadStream = bucket.openUploadStream(filename, {metadata: { compressed: true, originalSize: data.length }});uploadStream.end(compressedData);} else {uploadStream = bucket.openUploadStream(filename, {metadata: { compressed: false }});uploadStream.end(data);}return new Promise((resolve, reject) => {uploadStream.on('finish', resolve);uploadStream.on('error', reject);});
    }

5.4 分布式GridFS查询优化

Chen等人(2023)研究了在分布式环境中优化GridFS查询性能的策略。

引用: Chen, X., Zhao, Y., & Li, K. (2023). Optimizing Distributed GridFS Queries in MongoDB Sharded Clusters. 
Proceedings of the 2023 IEEE International Conference on Big Data, 2876-2885.

主要发现:

  1. 分片策略:

    • 基于文件大小的分片策略比基于文件名的分片策略更有效

    • 将大文件(>100MB)单独分片可以提高查询性能

    示例: 实现基于文件大小的分片策略

    async function setupSizedBasedSharding(db) {await db.admin().command({shardCollection: "myDatabase.fs.chunks",key: { files_id: 1, n: 1 }});await db.admin().command({shardCollection: "myDatabase.fs.files",key: { length: 1 }});// 为大文件创建单独的分片范围await db.admin().command({addShardToZone: "shard0001",zone: "largeFiles"});await db.admin().command({updateZoneKeyRange: "myDatabase.fs.files",min: { length: 100 * 1024 * 1024 }, // 100MBmax: { length: MaxKey },zone: "largeFiles"});
    }

  2. 缓存策略:

    • 在分片集群中实现分布式缓存可以显著提高查询性能

    • 对于热点文件,将其缓存在多个分片上可以提高访问速度

    示例: 使用Redis实现分布式缓存

    const Redis = require('ioredis');
    const redis = new Redis('redis://localhost:6379');async function getFileWithDistributedCache(filename) {const cacheKey = `gridfs:${filename}`;// 尝试从缓存获取const cachedFile = await redis.get(cacheKey);if (cachedFile) {return JSON.parse(cachedFile);}// 如果缓存未命中,从GridFS查询const file = await queryFileFromGridFS(filename);// 将文件信息存入缓存await redis.set(cacheKey, JSON.stringify(file), 'EX', 3600); // 缓存1小时return file;
    }

  3. 并行查询优化:

    • 在分片环境中,并行查询可以充分利用集群资源

    • 对于大文件,将查询分散到多个分片上可以显著提高性能

    示例: 实现分布式并行查询

    async function distributedParallelQuery(filename, start, end, shards) {const metadata = await getFileMetadata(filename);const chunkSize = (end - start) / shards.length;const queries = shards.map((shard, index) => {const chunkStart = start + index * chunkSize;const chunkEnd = Math.min(chunkStart + chunkSize, end);return queryShardForRange(shard, filename, chunkStart, chunkEnd);});const results = await Promise.all(queries);return Buffer.concat(results);
    }async function queryShardForRange(shard, filename, start, end) {// 连接到特定的分片并执行查询const shardClient = new MongoClient(shard.url);await shardClient.connect();const bucket = new mongodb.GridFSBucket(shardClient.db('myDatabase'));const downloadStream = bucket.openDownloadStreamByName(filename, { start, end });let data = Buffer.alloc(0);for await (const chunk of downloadStream) {data = Buffer.concat([data, chunk]);}await shardClient.close();return data;
    }

5.5 GridFS查询安全性研究

Liu等人(2024)对GridFS查询过程中的安全性问题进行了深入研究。

引用: Liu, J., Zhang, M., & Wang, L. (2024). Security Considerations in GridFS Query Processes. 
Journal of Information Security and Applications, 65, 103-118.

主要发现:

  1. 访问控制:

    • 实现细粒度的访问控制对保护敏感文件至关重要

    • 基于角色的访问控制(RBAC)在GridFS环境中表现良好

    示例: 实现基于角色的文件访问控制

    async function authorizedFileQuery(user, filename) {const userRoles = await getUserRoles(user);const fileMetadata = await getFileMetadata(filename);if (!fileMetadata.allowedRoles.some(role => userRoles.includes(role))) {throw new Error('Access denied');}return queryFileFromGridFS(filename);
    }async function getUserRoles(user) {// 从用户管理系统获取用户角色// 这里简化为直接返回角色列表return ['user', 'editor'];
    }

  2. 数据加密:

    • 对敏感文件进行端到端加密可以提供额外的安全层

    • 客户端加密可以防止未经授权的服务器访问

    示例: 实现客户端加密存储和查询

    const crypto = require('crypto');async function storeEncryptedFile(bucket, filename, data, encryptionKey) {const iv = crypto.randomBytes(16);const cipher = crypto.createCipheriv('aes-256-cbc', encryptionKey, iv);const encryptedData = Buffer.concat([cipher.update(data), cipher.final()]);const uploadStream = bucket.openUploadStream(filename, {metadata: { encrypted: true, iv: iv.toString('hex') }});uploadStream.end(encryptedData);return new Promise((resolve, reject) => {uploadStream.on('finish', resolve);uploadStream.on('error', reject);});
    }async function queryEncryptedFile(bucket, filename, encryptionKey) {const downloadStream = bucket.openDownloadStreamByName(filename);const metadata = await bucket.find({ filename }).next();if (!metadata.metadata.encrypted) {throw new Error('File is not encrypted');}const iv = Buffer.from(metadata.metadata.iv, 'hex');const decipher = crypto.createDecipheriv('aes-256-cbc', encryptionKey, iv);let decryptedData = Buffer.alloc(0);for await (const chunk of downloadStream) {decryptedData = Buffer.concat([decryptedData, decipher.update(chunk)]);}decryptedData = Buffer.concat([decryptedData, decipher.final()]);return decryptedData;
    }

  3. 审计日志:

    • 维护详细的文件访问日志对于安全监控和合规性至关重要

    • 实现不可篡改的审计日志可以防止内部威胁

    示例: 实现安全审计日志

    async function logFileAccess(user, filename, action) {const logEntry = {user,filename,action,timestamp: new Date(),clientIP: getClientIP()};// 使用单独的集合存储审计日志await db.collection('gridfs_audit_log').insertOne(logEntry);// 可以考虑将日志同步到外部安全系统await syncLogToExternalSystem(logEntry);
    }function getClientIP() {// 实现获取客户端IP的逻辑return '127.0.0.1';
    }async function syncLogToExternalSystem(logEntry) {// 实现与外部安全系统同步的逻辑console.log('Syncing log to external system:', logEntry);
    }

这些研究发现不仅深化了我们对GridFS查询过程的理解,还为优化查询性能、提高系统安全性提供了宝贵的见解和实践建议。通过实施这些优化策略和安全措施,开发者可以构建更高效、更安全的GridFS应用。

6. 未来展望

随着技术的不断发展,GridFS的查询机制也在持续演进。以下是一些潜在的未来发展方向:

  1. 机器学习优化: 利用机器学习技术自动优化查询策略,根据访问模式预测和预加载文件。

  2. 边缘计算集成: 将GridFS与边缘计算结合,实现更快的文件访问和更好的地理分布式性能。

  3. 区块链集成: 探索将区块链技术应用于GridFS,提供不可篡改的文件存储和访问记录。

  4. 高级数据分析支持: 增强GridFS对大规模数据分析的支持,如直接在存储层进行数据处理和分析。

这些方向代表了GridFS查询机制可能的发展趋势,将进一步增强其在各种复杂环境下的性能、可靠性和功能性。

结语

GridFS作为MongoDB处理大文件的解决方案,其查询过程涉及多个方面,从基本的文件元数据查询到复杂的分布式并行处理。通过本文的深入分析,我们不仅了解了GridFS查询的基本原理和实现细节,还探讨了在各种实际场景中的优化策略和安全考虑。

从性能优化到安全加固,从单机环境到分布式集群,GridFS展现出了强大的适应性和可扩展性。通过合理配置索引、利用缓存、实现并行查询,以及采用适当的压缩和加密策略,我们可以在不同的应用场景中获得理想的性能和安全性。

最新的研究成果进一步揭示了GridFS在高并发、大规模数据处理等极端条件下的表现,为我们提供了宝贵的优化思路。这些发现不仅有助于现有系统的调优,也为未来的发展指明了方向。

随着技术的不断进步,我们可以期待GridFS的查询机制会变得更加智能、高效和安全。无论是在传统的数据中心环境,还是在新兴的边缘计算和物联网场景,GridFS都有潜力继续发挥其关键作用。

对于开发者和数据库管理员来说,深入理解GridFS的查询机制不仅是一项技术要求,更是充分发挥这一强大工具潜力的关键。通过不断学习和实践,我们可以构建出更加高效、可靠和安全的文件存储和检索系统,为各种应用场景提供强有力的支持。

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

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

相关文章

[leetcode]assign-cookies. 分发饼干

. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int findContentChildren(vector<int>& g, vector<int>& s) {sort(g.begin(), g.end());sort(s.begin(), s.end());int m g.size(), n s.size();int count 0;for (int i 0, j 0; i…

Python 实现Excel转TXT,或TXT文本导入Excel

Excel是一种具有强大的数据处理和图表制作功能的电子表格文件&#xff0c;而TXT则是一种简单通用、易于编辑的纯文本文件。将Excel转换为TXT可以帮助我们将复杂的数据表格以文本的形式保存&#xff0c;方便其他程序读取和处理。而将TXT转换为Excel则可以将文本文件中的数据导入…

c进阶篇(一):数据的存储

1.数据类型介绍 char // 字符数据类型 short // 短整型 int // 整形 long // 长整型 long long // 更长的整形 float // 单精度浮点数 double // 双精度浮点数 1.1整形家族&#xff1a; char unsigned char signed char …

Transformer基础及视觉应用

文章目录 Transformer基础及视觉应用注意力机制基础(主要介绍Transformer用到的类型)Transformer的编解码器结构(Encoder and Decoder)Non-local Neural NetworksTransformer与大规模图像识别(Image Recognition at Scale)DETR-2020分割应用 Transformer基础及视觉应用 注意力…

【算法训练记录——Day36】

Day36——贪心Ⅳ 1.leetcode_452用最少数量的箭引爆气球2.leetcode_435无重叠区间3.leetcode_763划分字母区间4.leetcode_ 1.leetcode_452用最少数量的箭引爆气球 思路&#xff1a;看了眼题解&#xff0c;局部最优&#xff1a;当气球出现重叠&#xff0c;一起射&#xff0c;所用…

YOLOv5改进 | 注意力机制 | 迈向高质量像素级回归的极化自注意力【全网独家】

秋招面试专栏推荐 &#xff1a;深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 &#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 专栏目录&#xff1a; 《YOLOv5入门 …

高精密机械设备中滚珠导轨的表面处理工艺有哪些?

滚珠导轨是机床传动和定位的传动元件&#xff0c;其表面处理方式对机床性能和使用寿命起着决定性的作用&#xff0c;不同的表面处理方法可以提高导轨的耐磨性、抗腐蚀性和整体性能。那么&#xff0c;滚珠导轨的表面处理方式有哪几种呢&#xff1f; 1、磨削法&#xff1a;磨削技…

AFLNet入门教学——安装(Ubuntu22.04.4)

1、AFLNet简介 AFLNet 是一种专门用于测试网络协议实现的模糊测试工具。模糊测试是一种软件测试技术&#xff0c;通过向目标程序提供大量随机或半随机数据来发现潜在的漏洞和错误。AFLNet 的设计目标是增强 AFL (American Fuzzy Lop) 的功能&#xff0c;以更有效地测试网络协议…

input子系统学习(一)

1、输入子系统框架 2、编写一个简单的设备驱动层代码 #include<linux/module.h> #include<linux/init.h> #include<linux/input.h> #include<linux/time.h>struct input_dev *my_input_dev;static void timer_function(struct timer_list *t); DEFINE…

中医背诵笔记(黄帝内经、伤寒论等)

目录 黄帝内经上古天真论今人和古人之差异&#xff08;精神内守&#xff0c;病安从来&#xff1f;&#xff09;男女每个年龄阶段身体状态至人、圣人、贤人 宣明五气篇五脏所藏 与 五脏所主七情与情绪与气的关系 天干地支天干地支与脏腑经络的关系 伤寒论六种伤寒组合及对应的药…

一款轻量级的通信协议---MQTT (内含Linux环境搭建)

目录 MQTT MQTT的关键特点&#xff1a; 应用场景 Linux环境搭建&#xff1a; 1. 安装mosquitto 2. Linux下客户端进行通信 3. PC端和Linux下进行通信 安装MQTT. fx 4. MQTT.fx的使用 1. 点击连接 ​编辑 2. 连接成功 3. 订阅主题或者给别的主题发送消息 遇到的问…

(项目实战)聚合支付系统开发环境搭建-基于VMware17安装Centos7.9

1 开发环境介绍 dtpay聚合支付系统和ecard预付卡系统&#xff0c;服务端部署在Linux环境。后续的开发环境&#xff0c;生产环境都是基于Linux进行搭建&#xff0c;系统使用到的相关中间件(RocketMQ,Redis&#xff0c;Nginx等)&#xff0c;配置中心Nacos&#xff0c;数据库MySQ…

Emp.dll文件丢失?理解Emp.dll重要性与处理常见问题

在繁多的动态链接库&#xff08;DLL&#xff09;文件中&#xff0c;emp.dll 可能不是最广为人知的&#xff0c;但在特定软件或环境中&#xff0c;它扮演着关键角色。本文旨在深入探讨 emp.dll 的功能、重要性以及面对常见问题时的解决策略。 什么是 emp.dll&#xff1f; Emp.d…

python 第6册 辅助excel 002 批量创建非空白的 Excel 文件

---用教授的方式学习 此案例主要通过使用 while 循环以及 openpyxl. load_workbook()方法和 Workbook 的 save()方法&#xff0c;从而实现在当前目录中根据已经存在的Excel 文件批量创建多个非空白的Excel 文件。当运行此案例的Python 代码&#xff08;A002.py 文件&#xff0…

【STM32】在标准库中使用定时器

1.TIM简介 STM32F407系列控制器有2个高级控制定时器、10个通用定时器和2个基本定时器。通常情况下&#xff0c;先看定时器挂在哪个总线上APB1或者APB2&#xff0c;然后定时器时钟需要在此基础上乘以2。 2.标准库实现定时中断 #ifndef __BSP_TIMER_H #define __BSP_TIMER_H#if…

2.1 大语言模型的训练过程 —— 《带你自学大语言模型》系列

《带你自学大语言模型》系列部分目录及计划&#xff0c;完整版目录见&#xff1a; 带你自学大语言模型系列 —— 前言 第一部分 走进大语言模型&#xff08;科普向&#xff09; 第一章 走进大语言模型1.1 从图灵机到GPT&#xff0c;人工智能经历了什么&#xff1f;1.2 如何让…

基于MDEV的PCI设备虚拟化DEMO实现

利用周末时间做了一个MDEV虚拟化PCI设备的小试验&#xff0c;简单记录一下&#xff1a; DEMO架构&#xff0c;此图参考了内核文档&#xff1a;Documentation/driver-api/vfio-mediated-device.rst host kernel watchdog pci driver: #include <linux/init.h> #include …

【网络架构】keepalive

目录 一、keepalive基础 1.1 作用 1.2 原理 1.3 功能 二、keepalive安装 2.1 yum安装 2.2 编译安装 三、配置文件 3.1 keepalived相关文件 3.2 主配置的组成 3.2.1 全局配置 3.2.2 配置虚拟路由器 四、实际操作 4.1 lvskeepalived高可用群集 4.2 keepalivedngi…

AI视界引擎 | ​基于 YOLOv8 和计算机视觉 CV 的实时识别系统!

本文来源公众号“AI视界引擎”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;​基于 YOLOv8 和计算机视觉 CV 的实时识别系统&#xff01; 技术进步和创新正在尽可能地推进作者的日常生活&#xff0c;但仍有很大一部分社会群体因为…

自研Eclipse插件的生成及安装和使用

说明&#xff1a; 本处是使用个人自研的Eclipse插件为例&#xff0c;创建了一个菜单式的插件组&#xff0c;插件组下&#xff0c;有一个生成右击Jakarta EE服务端点类后&#xff0c;生成端点对应的Restful客户端。有什么问题&#xff0c;欢迎大家交流&#xff01;&#xff01;…