三九宝宝网宝宝教育教学论文

C语言里如何设置缓冲区

03月11日 编辑 39baobao.com

[C语言指针搜索数组里的数]1 2 3 4 5 6 7 8 9 10 11 12 13 intmy_max = -INT_MAX; intrnd = 0; //第一步取得2113数组5261里最大数 for(i = 0; i < sizeof(arr), ++i) { if(arr[i] > my_max) my_max =...+阅读

将数据以链表形式顺序存放,新数据总是放在表尾,待处理的数据总是在头结点下的第一个结点,处理完毕则释放空间。

#define BufferSize 1024 // 合适的大小你知道的

typedef struct node {

char *buffer;

struct node *next;

}*linkList;

LinkList *InitList() {

LinkList *head;

head = (char *)malloc(size(node));

head->next = NULL:

return head;

}

void AddData(LinkList *head, char *data) { // 将新数据添加到表尾

LinkList *p = head;

LinkList *anode = (char *)malloc(size(node));

anode->buffer = (char *)malloc(size(BufferSize));

strncpy(anode->buffer,data,BufferSize);

anode->next = NULL:

while(p->next) p = p->next;

p->next = anode;

}

void DealData(LinkList *head) {

LinkList *p = head->next;

if(p) {

head->next = p->next;

// p->buffer指向的数据待处理

free(p->buffer); // 处理完毕,释放空间

free(p);

}

}

教你Oracle的数据缓冲区是如何工作

但是,这种行为从Oracle 8i开始就变了:新数据缓冲区被放置在缓冲区链的中部。在调节数据库的时候,你的目标就是为数据缓冲区分配尽量多的内存,而不会导致数据库服务器在内存里分页。数据缓冲区每小时的命中率一旦低于90%,你就应该为数据块缓冲区增加缓冲区。

数据块的存活时间

在调入数据块之后,Oracle会不停地跟踪数据块的使用计数(touch count,也就是说,这个数据块被用户线程所访问的次数)。如果一个数据块被多次使用,它就被移动到最近使用过的数据列表的最前面,这样就能确保它会在内存里保存一段较长的时间。这种新的中点插入技术会确保最常使用的数据块被保留在最近使用过的数据列表的最前面,因为新的数据块只有在它们被重复使用的时候才会被移动到缓冲区链的最前面。

总而言之,Oracle 8i数据缓冲池的管理要比先前的版本更加有效。通过将新的数据块插入缓冲区的中部,并根据访问活动(频率)调整缓冲区链,每个数据缓冲区就被分割成两个部分:热区(hot section),代表数据缓冲区的最近使用的一半;冷区(cold section),代表数据缓冲区的最早使用的一半。只有那些被反复请求的数据块才会被移进每个缓冲池的热区,这就让每个数据缓冲区在缓冲常用数据块的时候效率更高。

热区的大小要用下面的隐藏参数来配置:

_db_percent_hot_default _db_percent_hot_keep _db_percent_hot_recycle

Oracle公司作为官方没有推荐更改这些隐藏参数。只有懂得内部机制和希望调节其数据缓冲区行为的有经验人员才应该使用这些参数。

找到热数据块

Oracle 8i保留着一个X$BH内部查看表,用来显示数据缓冲池的相对性能。X$BH查看表有下列数据列:

Tim:两次使用之间的时间差,和_db_aging_touch_time参数相关。

Tch:使用计数,它和被使用过_db_aging_hot_criteria次之后从冷区移入热区直接相关。

由于Tch数据列用来追踪特定数据块的使用次数,所以你就能够编写一个字典查询来显示缓冲区里的热数据块——使用计数大于10的数据块,就像下面这样:

SELECT obj object, dbarfil file#, dbablk block#, tch touchesFROM x$bhWHERE tch 10ORDER BY tch desc;

这项高级查询技术在用于追踪DEFAULT缓冲池里的对象时尤其有用。一旦定位了热数据块,你就能够把它们从DEFAULT缓冲池移动到KEEP缓冲池。[next]完全缓冲数据库

从Oracle 8i开始,随着64位寻址的出现,你就能够创建一个完全在数据缓冲区里缓冲的数据库。现今,任何数据库通常只用不到20G的内存就能够被完全缓冲,而更大的数据库仍然需要部分数据缓冲区。

要利用完全数据缓冲的优势,就要记住从内存取回数据块和从磁盘取回数据块的时间差。对磁盘的访问时间是以毫秒或者说千分之一秒来计算的,而内存的速度是以纳秒或者说十亿分之一秒来计算的。因此内存的访问速度要快三个数量级,即通常要比磁盘的访问速度块将近14,000倍。

在完全缓冲Oracle数据库的时候,你需要仔细制定缓冲的规划,并在需要的时候增加db_block_ buffers参数的值。在缓冲整个数据库的时候,多数据缓冲池就不再需要了,所以你可以在DEFAULT数据池里缓冲所有的数据块。

数据缓冲区的解决数据缓冲区内存的方案

从概念上讲,数据缓冲区在传统方案下是由两个操作创建的:数据缓冲区实体的创建和实际内存的分配。然而事实上,在实际数据变得可用之前,您不需要分配实际的内存 —— 即可以将两个操作分离开来。最初可以使用内存块的一个空链表来创建一个抽象缓冲区。抽象数据缓冲区仅在实际数据变得可用时才分配内存。释放内存也变成了抽象数据缓冲的责任。考虑到所有这些,集中内存管理和数据复制操作就会带来以下优点:各方都能通过调用预定义的 API 函数来构造和/或销毁数据缓冲区。 内存使用将保持接近最优状态,因为缓冲区内存仅在必要时才分配,并且会尽快释放,从而最小化内存泄露。 任何一方都不需要知道底层的内存管理方案,使得软件高度可移植,同时保证了交互双方之间的兼容性。

由于没有哪一方需要管理内存,确定缓冲区的大小就变得不必要了(因而也不可能存在前面指出的多次执行问题)。 事实证明缓冲区溢出也不可能会发生,因为仅当存在额外数据空间时才会复制数据。一种简单的实现 为了表示一个抽象数据缓冲区,需要声明两个结构化的数据类型:清单 1. 声明两个结构化的数据类型来表示一个抽象数据缓冲区 typedef struct BufferBlockHeader_st BufferBlockHeader; struct BufferBlockHeader_st { BufferBlockHeader * pNextBlock;}; struct Buffer_st { long int totalLength; BufferBlockHeader * pFirstBlock; short int startPoint; BufferBlockHeader * pLastBlock; short int endPoint;}; typedef struct Buffer_st Buffer; Buffer 包含关于已创建的抽象缓冲区的信息,它还管理内存块的一个链表:totalLoength 记录当前存储在缓冲区中的字节数。

pFirstBlock 指向该链表中的第一个内存块。 startPoint 记录第一个内存块中第一个字节的偏移位置。 pLostBlock 指向该链表的最后一个内存块。 endPoint 记录最后一个内存块中第一个空闲字节的偏移位置。您可以向 Buffer 引入一个附加参数,用以指定每个内存块的大小,并且可以在抽象缓冲区的初始化期间,将该参数设置为一个可取的值。这里假设使用默认块大小。如果分配了的话, BufferBlockHeader 结构中的 pNextBlock 总是指向该链表中的下一个内存块。每个内存块在分配时都包含一个 BufferBlockHeader 头,后面跟着一个用于存储实际数据的缓冲区块。图 1 描述了一个存储了一些数据的抽象缓冲区。图 1. 抽象缓冲区的数据结构 M 表示 Buffer 的大小(它通常为 20 字节), B 表示所选择的内存块大小。

内存开销大约为 (M+B) 个字节(每个内存块开头的指针忽略不计)。 (M+B) 中的 B 平均起来仅有所使用的第一和最后一个内存块的一半。这个开销几乎保持不变。在能够缓冲数据之前,必须通过调用下面的 newBuffer() 函数来显式地创建抽象缓冲区:清单 2 使用 newBuffer() 函数创建抽象缓冲区 Buffer * newBuffer() { allocate a Buffer structure; initialize the structure;} 在 清单 2中,该函数分配了包含一个 Buffer 的内存块,并初始化它的条目以指明它是一个空抽象缓冲区。相应地,必须在使用抽象缓冲区之后通过调用下面的 freeBuffer() 函数来销毁它:清单 3 使用 freeBuffer() 函数来销毁抽象缓冲区 void freeBuffer(Buffer * pBuffer /* pointer to the buffer to be freed */ ) { while (there is more memory block in the linked list) { free the next memory block; } free the Buffer structure;} 清单 3中的函数释放链表中的所有内存块,然后释放由 newBuffer() 分配的 Buffer 。

要逐步向抽象缓冲区追加数据段,可使用以下函数:清单 4. 逐步向抽象缓冲区追加数据段 long int appendData(Buffer * pBuffer, /* pointer to the abstract buffer */ byte * pInput, /* pointer to the data source */ long int offset, /* offset of the input data */ long int dataLength /* number of bytes of the input data */ ) { while (there is more input data) { fill the current memory block; if (there is more input data) { allocate a new memory block and add it into the linked list; } } } 清单 4中的函数把存储在 pInput[offset..offset+dataLength] 中的字节复制到 pBuffer 所指向的抽象缓冲区中,并在必要时在链表中插入新的内存块,然后返回成功复制到抽象缓冲区中的字节数目。采用类似的方式,您可以使用以下函数,逐段地从抽象缓冲区读取数据段:清单 5. 从抽象缓冲区读取数据段 long int readData(Buffer * pBuffer, /* pointer to the abstract buffer */ byte * pOutput, /* pointer to the output byte array */ long int offset, /* offset of the output byte array */ long int arrayLength /* size of available output byte array */ ) { while (there is something more to read and there is room for output) { read from the first memory block; if (the first memory block is empty) { delete the first memory block from the linked list and free its memory; } }} 在 清单 5 中,该函数销毁性地从 pBuffer 所指向的抽象缓冲区最多读取 arrayLength 个前导字节,并在内存块变为空时从链表中删除它们,然后返回成功读取的字节数目。

如果需要,您可以实现一个类似 readData() 的函数来允许非销毁性的读取。实现一个函数来返回当前存储在抽象缓冲区...

以下为关联文档:

C语言里如何求余数#include<stdio.h> #include<math.h> void main() { int m,n,r; printf("输入m,n\n"); scanf("%d,%d",&m,&n); if (m>n) r=m%n; else { r=m; m=n; n=r; r=m%n; } while(r!=0) { m=...

C语言里的乘方怎么写#include "math.h" main() { int a,b,c,d; printf("dishu:"); scanf("%d",&a); printf("cishu:"); scanf("%d",&b); printf("beichu:"); scanf("%d",&c); d=(int)(pow((double)(a),(double...

有关C语言的问题:刚刚用TurboC2 0如何设置目录设置Directories首先运行TC目录下的TC.exe,这是TC2.0编译环境的主程序,按F10键打开主菜单,选取其中的"Options->Directories",所要设定各选项对应意义如下: Include directories: Include头文件所...

c语言里:sizeof怎样用法判断数据类型长度符的关键字 用法: sizeof(类型说明符,数组名或表达式); 或sizeof 变量名 定义: sizeof是C/C++中的一个操作符(operator),简单的说其作用就是返回一个对象或者类型所...

c语言里结构体定义1、struct REC{int n; char c;};REC t1,t2;//修改 struct REC t1,t2;因为不是所有编译器都支持你那种写法 2、typedef struct REC{int n=0;char;}t1,t2;REC t1,t2不知道你什么...

在c语言里变量的定义和声明int a;和int a=1; 这两个既可以叫声明,也可以叫定义, “int a=1;”相当于“ int a;a=1;”两条语句, “int a;”是简单地定义一个变量,编译器会为其在内存中分配一个内存单元,该内存单...

C语言 C语言 C语言简介C语言 C语言 C语言简介,C语言简介:C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现过程...

C语言缓冲区在哪里C语言缓冲区在哪里,C语言里如何设置缓冲区缓冲区具体在哪里是与操作系统、编译器相关的 以VC++为例。察看getchar的源代码(src\fgetchar.c),有: int __cdecl _fgetchar (void){ r...

C语言中的缓冲区问题C语言中的缓冲区问题,c语言中怎么给lua分配缓冲区:输出缓冲区: C标准规定fflush()函数实现,用来刷新输出(stdout)缓存的,对于(stdin)是么有意义的,GCC也不能使用fflush(stdin)来刷新,因...

推荐阅读
图文推荐