- 浏览: 93453 次
- 性别:
- 来自: 天津
最新评论
-
ming1259:
谢谢你了,我快被这个问题这么死了!终于知道为什么bash命令提 ...
linux 输入长命令行 会无缘无故的回到行开始,本来应该在下一行继续的! -
duolaimifa:
我也遇到了同样的问题,之前以为是中文putty的问题,后来换了 ...
linux 输入长命令行 会无缘无故的回到行开始,本来应该在下一行继续的! -
hxlzpnyist:
邓哥 叼爆啦
GtkShot -- Linux下的截图软件 -
flytreeleft:
__floyd__ 写道Cool!* 关于中间颜色的设置
se ...
使用Terminator和Tmux打造完美终端 -
__floyd__:
Cool!* 关于中间颜色的设置
set -g status- ...
使用Terminator和Tmux打造完美终端
本文所说的缓冲池的构建与一般的开辟一个大的内存,需要申请内存时就直接在该大内存中再划分出小内存出来使用不同,CBufferPool使用的是队列链表,程序按出队/入队的方式对内存进行读写.
设计该类的目的是因为在需求中,我有一个写入线程和一个读取线程,读取线程会挨个读取写入线程写入的数据,于是想到使用队列,按先入先出的方式可以顺序读取已写入的数据,由于考虑到可能需要动态增加队列的大小,故采用了环形链表形式的队列.第一个问题解决,即决定了所要使用的数据结构--环形队列链表.
第二个考虑的问题是,在使用时不使用什么GetReadBuffer/PutWriteBuffer之类的显式调用读写队列的方法,我只需要通过相同的方法如本设计所使用的GetOut/PutBack方法就可以取到读或写缓冲,仅需在参数中指定我需要获取到的是读还是写缓冲就行了,这样可以很好地屏蔽二者在调用上的差异.所以,我设计了UserBuffer结构体,并在其中添加属性type,用于标识该buffer是用于读的还是用于写的.同时,在使用GetOut方法获取到要使用的buffer后,UserBuffer中的id将被赋值为与缓冲池中对应的PoolBuffer的id相同的值,这样在使用PutBack放回该buffer时就能区分该buffer是否是CBufferPool所返回的缓冲,防止可能出现的非法操作,如放回不属于CBufferPool所返回的缓冲等.
第三个问题是考虑到缓冲池中使用的数据结构应该和用户使用的数据结构是类似的,只是在缓冲池中需要有指向下一个缓冲的指针,并且缓冲池内部的数据结构对使用者是不开放的,使用者不能看到或直接使用该数据,故而,最终设计了用户使用类UserBuffer和缓冲池内部类PoolBuffer.从代码中可以看到两个数据结构基本上是相同的,不同的除了PoolBuffer中的next指针以外,就是UserBuffer中用于标识该缓冲的使用或请求类型的type和PoolBuffer中标识该缓冲处于读还是写状态的status.也就是,当用户标识UserBuffer的type为POOL_BUFFER_TYPE_READ时,通过方法GetOut方法缓冲池就会返回队列首部的可读的缓冲,同时该缓冲将被标记状态为POOL_BUFFER_STATUS_READING,防止该缓冲被写入线程使用;当UserBuffer的type为POOL_BUFFER_TYPE_WRITE时,通过GetOut方法可以得到缓冲池中可写的缓冲,同样地该缓冲的状态将被标记为POOL_BUFFER_STATUS_WRITING,防止读线程使用.
第四个问题是,本设计在获取写缓冲时会根据请求的缓冲大小动态地开辟合适的内存空间,当所请求的大小和已经存在的缓冲大小不相同时便会重新开辟新的内存空间,但是出现的问题是当请求的缓冲大小和已经存在的缓冲大小相差不是很大,比如就在1KB以内,那如果是比较两者大小不相等就开辟的话,这个效率上就会很差了,所以,在设计中,采用了按片(Slice)开辟缓冲的方法,在比较时采用了比较两者所占用的片的个数是否相等来判断是否要重新开辟内存的方法,这在一定程度上减少了重复开辟新内存的消耗.不过本版本还未提供修改片大小的方法,加上也不麻烦,所以就不加了.^_^
于是,经过一段时间的思考和实验,最终完成了该设计,并贴出源代码,供有需要的盆友参考
本设计还存在许多不足,比如该版本只考虑了单写入线程/单读取线程,没有考虑多个写入线程/多读取线程的情况,只能说是满足了基本的要求,待改进部分还是很多的,有机会和需求时再做改进吧.
buffer.h:
/** * buffer.h * * Copyright (C) 2011 flytreeleft(flytreeleft@126.com). * * This file is placed under the LGPL. * * If you have some questions or advises, please email me! * Thank you! */ #ifndef __BUFFER_H_ #define __BUFFER_H_ typedef unsigned int uint32_t; typedef struct UserBuffer { // the buffer pool will use the id to decide // whether this buffer belongs to it or not uint32_t id; // using type -- to read or to write int type; // the size of buffer which is got // or needed to set uint32_t size; void *start; // address of buffer } Buffer; #endif
bufferpool.h:
/** * bufferpool.h * * Copyright (C) 2011 flytreeleft(flytreeleft@126.com). * * This file is placed under the LGPL. * * If you have some questions or advises, please email me! * Thank you! */ #ifndef __BUFFER_POOL_H_ #define __BUFFER_POOL_H_ #include <pthread.h> #include "buffer.h" #define MIN_POOL_BUFFER_COUNT (1) #define POOL_BUFFER_INVALID_ID (0) enum { POOL_BUFFER_TYPE_UNKNOWN, POOL_BUFFER_TYPE_READ, POOL_BUFFER_TYPE_WRITE }; enum { POOL_BUFFER_STATUS_UNUSED = 0, POOL_BUFFER_STATUS_READING, POOL_BUFFER_STATUS_WRITING }; class CBufferPool { private: typedef struct _PoolBuffer { // every buffer has a different id in pool uint32_t id; // using status of buffer int status; // address of buffer void *start; uint32_t size; struct _PoolBuffer *next; } PoolBuffer; uint32_t id_seed; PoolBuffer *input; PoolBuffer *output; PoolBuffer *head; uint32_t slice_size; // size per slice pthread_mutex_t rw_mutex; int size; public: CBufferPool(void); CBufferPool(int count); void SetSliceSize(uint32_t size); int GetSize(void) { return size; } bool Increase(int increase); bool Decrease(int decrease); void Create(int count); void Clear(void); bool GetOut(Buffer *buffer); bool PutBack(Buffer *buffer); bool IsFull(void); bool IsEmpty(void); void Print(void); ~CBufferPool(void); private: void InitData(void); bool IsClear(void); bool GetReadBuffer(Buffer *reader); bool GetWriteBuffer(Buffer *writer); bool PutReadBuffer(Buffer *reader); bool PutWriteBuffer(Buffer *writer); uint32_t GenerateId(void) { return ++id_seed; } }; #endif
bufferpool.cpp:
/** * bufferpool.cpp * * Copyright (C) 2011 flytreeleft(flytreeleft@126.com). * * This file is placed under the LGPL. * * If you have some questions or advises, please email me! * Thank you! */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include "bufferpool.h" #include "zero.h" CBufferPool::CBufferPool(void) { InitData(); } CBufferPool::CBufferPool(int count) { InitData(); Create(count); } void CBufferPool::InitData(void) { head = NULL; input = output = head; size = 0; slice_size = 1024; // 1KB pthread_mutex_init(&rw_mutex, NULL); } void CBufferPool::SetSliceSize(uint32_t size) { slice_size = (size > 0 ? size : 1); } /** * create additional buffers */ bool CBufferPool::Increase(int increase) { PoolBuffer *tmp = NULL; bool succ = true; pthread_mutex_lock(&rw_mutex); if (!IsClear()) { while (increase > 0) { tmp = SAFE_MALLOC(PoolBuffer, sizeof(PoolBuffer)); if (tmp != NULL) { ZERO(tmp); tmp->id = GenerateId(); size++; increase--; tmp->next = input->next; input->next = tmp; } else { printf("no enough space,"\ "when increasing pool:"\ "last size is %d\n", size); break; } } } else { printf("Please create pool first!\n"); } pthread_mutex_unlock(&rw_mutex); return succ; } bool CBufferPool::Decrease(int decrease) { PoolBuffer *next = NULL; PoolBuffer *tmp = NULL; bool succ = true; pthread_mutex_lock(&rw_mutex); if (!IsClear()) { next = input->next; while (next != output && decrease > 0 && size > MIN_POOL_BUFFER_COUNT) { tmp = next->next; SAFE_FREE(next->start); SAFE_FREE(next); next = tmp; size--; decrease--; } input->next = next; } else { printf("There is no buffer in pool!\n"); } pthread_mutex_unlock(&rw_mutex); return succ; } /** * get out buffer to read or write, according to buffer's type */ bool CBufferPool::GetOut(Buffer *buffer) { bool succ = false; pthread_mutex_lock(&rw_mutex); if (buffer != NULL) { switch (buffer->type) { case POOL_BUFFER_TYPE_READ: succ = GetReadBuffer(buffer); break; case POOL_BUFFER_TYPE_WRITE: succ = GetWriteBuffer(buffer); break; } } pthread_mutex_unlock(&rw_mutex); return succ; } bool CBufferPool::PutBack(Buffer *buffer) { bool succ = false; pthread_mutex_lock(&rw_mutex); if (buffer != NULL) { switch (buffer->type) { case POOL_BUFFER_TYPE_READ: succ = PutReadBuffer(buffer); break; case POOL_BUFFER_TYPE_WRITE: succ = PutWriteBuffer(buffer); break; } } buffer->id = POOL_BUFFER_INVALID_ID; buffer->size = 0; buffer->start = NULL; pthread_mutex_unlock(&rw_mutex); return succ; } bool CBufferPool::GetReadBuffer(Buffer *reader) { bool succ = false; if (!IsClear() && !IsEmpty() && output->status != POOL_BUFFER_STATUS_WRITING) { reader->id = output->id; reader->size = output->size; reader->start = output->start; output->status = POOL_BUFFER_STATUS_READING; succ = true; } return succ; } bool CBufferPool::GetWriteBuffer(Buffer *writer) { bool succ = false; uint32_t o, n; if (!IsClear() && !IsFull() && input->status != POOL_BUFFER_STATUS_READING && writer->size > 0) { o = (input->size / slice_size) + (input->size % slice_size > 0 ? 1 : 0); n = (writer->size / slice_size) + (writer->size % slice_size > 0 ? 1 : 0); if (o != n) { SAFE_FREE(input->start); input->start = SAFE_MALLOC(void, n * slice_size); } input->size = writer->size; writer->start = input->start; writer->id = input->id; input->status = POOL_BUFFER_STATUS_WRITING; succ = true; } return succ; } bool CBufferPool::PutReadBuffer(Buffer *reader) { bool succ = false; if (!IsClear() && reader->id == output->id && output->status == POOL_BUFFER_STATUS_READING) { output->status = POOL_BUFFER_STATUS_UNUSED; output = output->next; succ = true; } return succ; } bool CBufferPool::PutWriteBuffer(Buffer *writer) { bool succ = false; if (!IsClear() && writer->id == input->id && input->status == POOL_BUFFER_STATUS_WRITING) { input->status = POOL_BUFFER_STATUS_UNUSED; input = input->next; succ = true; } return succ; } /** * when input pointer's next and output are equal, * the pool is full */ bool CBufferPool::IsFull(void) { return (input != NULL ? input->next == output : false); } /** * when output pointer and input pointer are equal, * the pool is empty */ bool CBufferPool::IsEmpty(void) { return (output == input); } /** * create buffers in pool. */ void CBufferPool::Create(int count) { PoolBuffer *tmp = NULL; pthread_mutex_lock(&rw_mutex); if (count < MIN_POOL_BUFFER_COUNT) { count = MIN_POOL_BUFFER_COUNT; } if (!IsClear()) { printf("Please clear the pool first!\n"); return; } while (count >= 0) { // i need to create one more buffer tmp = SAFE_MALLOC(PoolBuffer, sizeof(PoolBuffer)); if (tmp != NULL) { ZERO(tmp); tmp->id = GenerateId(); size++; count--; if (head != NULL) { tmp->next = head->next; head->next = tmp; } else { head = tmp; head->next = tmp; } } else { printf("no enough space,"\ "when creating buffer pool:"\ "last size is %d\n", size); break; } } // hide one buffer size = (size > 0 ? size - 1 : 0); input = output = head; pthread_mutex_unlock(&rw_mutex); } /** * free buffer from head to tail, one by one */ void CBufferPool::Clear(void) { PoolBuffer *next = head; PoolBuffer *tmp = NULL; pthread_mutex_lock(&rw_mutex); if (!IsClear()) { do { tmp = next->next; SAFE_FREE(next->start); SAFE_FREE(next); next = tmp; } while(next != head); } size = 0; head = NULL; input = output = head; pthread_mutex_unlock(&rw_mutex); } /** * print all buffers' information */ void CBufferPool::Print(void) { PoolBuffer *h = head; if (!IsClear()) { do { printf("----------------------\n"); printf("| id = %3d,size = %3d|\n", h->id, h->size); printf("----------------------\n"); h = h->next; } while(h != head); } else { printf("there is no buffer in pool...\n"); } } /** * is there no buffer in pool? */ bool CBufferPool::IsClear(void) { bool clear = true; if (size >= MIN_POOL_BUFFER_COUNT && head != NULL && input != NULL && output != NULL) { clear = false; } return clear; } CBufferPool::~CBufferPool(void) { Clear(); }
zero.h:
/** * zero.h * * Copyright (C) 2011 flytreeleft(flytreeleft@126.com). * * This file is placed under the LGPL. * * If you have some questions or advises, please email me! * Thank you! */ #ifndef __ZERO_H_ #define __ZERO_H_ #include <stdlib.h> #include <string.h> #define ZERO(obj) memset(obj, 0, sizeof(*obj)) #define ZERO_ARRAY(array,count) memset(array, 0, (count) * sizeof(array[0])) #define SAFE_MALLOC(type,size) (type *)safe_malloc(size) #define SAFE_FREE(p) safe_free(p) static inline void *safe_malloc(int size) { return size > 0 ? malloc(size) : NULL; } static inline void safe_free(void *p) { if (p != NULL) { free(p); } } #endif
加上测试代码:
pooltest.cpp:
/** * pooltest.cpp * * Copyright (C) 2011 flytreeleft(flytreeleft@126.com). * * This file is placed under the LGPL. * * If you have some questions or advises, please email me! * Thank you! */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "bufferpool.h" #define POOL_SIZE (1) #define TEXT_SIZE (10) int main(void) { Buffer buffer; CBufferPool pool; int i; char text[TEXT_SIZE]; // increase of decrease befor create pool.Increase(2); pool.Decrease(2); // create new pool.Create(POOL_SIZE); pool.Print(); // create befor clear pool.Create(POOL_SIZE); printf("writing...\n"); // write buffer in pool for (i = 0; i < pool.GetSize(); i++) { // initialize buffer.type = POOL_BUFFER_TYPE_WRITE; buffer.size = TEXT_SIZE; // get input buffer from pool if (pool.GetOut(&buffer)) { printf("input : id %d\n", buffer.id); // write buffer snprintf(text, TEXT_SIZE, "test %d", i); memcpy(buffer.start, text, TEXT_SIZE); printf("\ttext : %s\n", text); // put buffer to pool pool.PutBack(&buffer); } } pool.Print(); printf("reading...\n"); // read buffer in pool for (i = 0; i < pool.GetSize(); i++) { // initialize buffer.type = POOL_BUFFER_TYPE_READ; // get output buffer from pool if (pool.GetOut(&buffer)) { printf("output : id %d, size %d\n", buffer.id, buffer.size); // read buffer printf("\ttext : %s\n", (char *)buffer.start); // put buffer to pool pool.PutBack(&buffer); } } printf("increase buffer...\n"); pool.Increase(2); pool.Print(); printf("decrease buffer...\n"); pool.Decrease(2); pool.Print(); return 0; }
编译代码:
$ gcc -o pooltest pooltest.cpp bufferpool.cpp
相关推荐
内存缓冲池是一种优化内存分配和释放的技术,它通过预先分配一大块内存并将其划分为多个固定大小的小块来提供高效的服务。在本文中,我们将详细探讨如何实现内存缓冲池,特别是采用多级链表的方式。 1. **多级链表...
2. **缓冲池管理**:创建一个管理类来维护整个缓冲池,包括初始化缓冲池(分配内存并初始化缓冲区对象)、获取空闲缓冲区(从池中取出未被使用的缓冲区)、归还缓冲区(将使用完的缓冲区放回池中)和释放缓冲池...
缓冲池的设计目的是为了在多个进程或线程之间共享数据,通过缓存数据来优化数据传输,降低磁盘和内存之间的数据交换频率。在这个"缓冲池的简单模拟-操作系统课程设计"中,开发者使用了VC++作为编程环境,创建了一个...
6. **扩展性**:优秀的缓冲池设计应具备良好的扩展性,能够根据程序运行情况动态调整缓冲池的大小,以应对内存需求的变化。 7. **内存池**:缓冲池常常是内存池策略的一部分,内存池包括了缓冲池和其他内存管理策略...
缓冲池是内存中的一块区域,DB2 会将用到数据放到缓冲池中提高性能。缓冲池太小,每次查询仍然要到磁盘中操作,达不到缓冲的效果。缓冲池太大,超出操作系统管理的限制,会导致数据库无法连接的错误。缓冲池是通过表...
本程序是一个在Windows环境下使用C++实现的I/O缓冲池演示,旨在帮助开发者理解和应用这一概念。 I/O缓冲池的核心思想是预先在内存中分配一组缓冲区,当进行I/O操作时,数据会被先存入缓冲区,而不是直接写入或读出...
缓冲池是一种内存管理策略,它为多个并发进程提供共享的缓存区域,用于存储数据,以提高系统效率和性能。在本项目中,我们用Java编程语言实现了缓冲池的模拟,旨在理解和学习操作系统的相关机制。 缓冲池的主要目标...
7. **内存泄漏检测**:虽然Linux内核本身有防止内存泄漏的设计,但开发者仍然需要关注应用程序的内存泄漏问题。Linux提供了一些工具,如`pmap`、`top`和`valgrind`,帮助检测和定位内存泄漏。 以上只是x86架构下...
在 Unix 下,可以使用以下命令来查看缓冲池相关信息: * 切换到 db2inst1 账号:su – db2inst1 * 连接到 pzbdw 数据库:db2 connect to pzbdw * 查看缓冲池定义:db2 "select BPNAME,NPAGES,PAGESIZE from syscat....
在Windows操作系统中,缓冲池是一种内存管理机制,用于优化系统对内存资源的分配和使用,尤其是在处理并发和多线程环境时。缓冲池的核心概念是将内存分配过程集中化,减少碎片并提高效率。本代码实现了一个特定的...
标题“缓冲池实现”指的是一种设计策略,它利用内存中的固定大小的数据结构来存储待处理的数据,以便多个线程可以高效地共享和访问这些资源。这种技术的核心在于减少等待时间,提高并发性能,并最小化系统资源的消耗...
为了模拟缓冲池的使用,实验设计了三个线程:输入线程、输出线程和计算线程。每个线程都有特定的任务: - **输入线程**:负责从外部设备读取数据,并将数据放入输入缓冲队列中。 - **计算线程**:从输入缓冲队列中...
4. **优先级**:可以为不同的缓冲池设置不同的优先级,高优先级的缓冲池更可能获得更多的内存资源。 #### 六、总结 在DB2中合理设计和优化表空间与缓冲池对于提高数据库性能至关重要。通过理解不同类型的表空间...
本教程全面涵盖了Linux内存管理和缓冲区操作,特别关注内存泄漏检测和缓冲区溢出攻击的防范。 首先,让我们探讨C语言中的内存管理。在C语言中,程序员需要手动进行内存分配和释放,这包括使用`malloc()`、`calloc()...
Linux内核的Slab内存缓冲区管理器是用于高效管理内核对象的一种机制,它针对的是内核在运行过程中频繁创建、使用和回收的小对象内存分配。Slab管理器的引入解决了传统内存分配方法中可能导致的浪费和低效问题。 在...
Linux内核中的内存管理是操作系统设计的关键组成部分,它涉及到如何高效地分配、使用和回收内存资源。内存池是Linux 2.6版本引入的一种优化内存分配策略,特别针对小内存块的频繁分配和释放,以减少内存碎片和提高...
Linux内核是操作系统的核心部分,负责管理系统的硬件资源,其中包括至关重要的内存管理和缓冲机制。内存管理确保了系统中多个进程的高效、安全运行,而缓冲机制则优化了数据的读写速度,提高了整体性能。 一、Linux...
Linux 上的 DB2 内存和文件缓存性能调优 本文总结了 Linux 上 DB2 内存和文件缓存的性能调优,讨论了内存使用和文件缓存对性能的影响,以及 Linux 上 DB2 特有的特性。通过本文,可以了解特定的 DB2 特性的优点,...
在VC++环境中,双列队缓冲池是一种常见的数据结构,用于高效管理内存资源,提高程序运行效率。双列队缓冲池通常由两个队列组成,一个用于分配内存块,另一个用于回收内存块,实现了内存的快速申请和释放。这种设计在...