数据管理一般公司都用什么软件,数据管理一级学科
在前面的章节中,我们讨论了资源限制的主题。在本章中,我们将讨论管理资源分配的方法,然后讨论多个用户连续处理文件的方法。最后,我们将讨论Linux系统提供的工具如何处理使用普通文件作为数据存储介质的限制问题。
我们可以将数据管理总结为以下三个方面:
动态内存管理:做什么和Linux不允许我们做什么
文件锁:协作锁、共享文件锁区和死锁避免。
Dbm:一个不基于SQL数据库的基本函数库,由大多数Linux系统提供。
管理内存
内存是所有计算机系统中的稀缺资源。无论有多少内存,都会显得不够用。以前已经不是这样了:1M的可寻址内存被认为足够所有人使用,但现在512M的内存已经成为最低配置。
从最早的操作系统版本开始,Unix风格的操作系统就有非常明确的内存管理方式,Linux也是如此,因为它实现了X/Open规范。Linux程序,除了一些特殊的嵌入式程序,从来不允许直接访问物理内存。程序看到的只是精心管理的场景。
Linux使用一个清晰的可直接寻址的内存空间来提供程序。另外,它提供了保护,所以不同的程序会相互保护,允许程序透明地访问比机器内部实际物理内存大得多的内存空间,只要机器配置好,有足够的交换空间。
简单的内存分配
我们使用malloc调用来分配标准C库中的内存。
#包含stdlib.h
void * malloc(size _ t size);
注意,Linux(遵循X/Open规范)不同于某些Unix实现,因为它不需要特定的malloc.h include文件。还要注意,指定要分配的字节数的size参数不是int,尽管它通常是一个无符号整数。
在大多数Linux系统上,我们可以分配大量内存。让我们从一个非常简单的程序开始,但这不适用于基于MS-DOS的旧程序,因为它们不允许访问PC以外的640K内存。
实验-简单的内存分配
输入以下程序,memory1.c:
#包括unistd.h
#包含stdlib.h
#包含stdio.h
#定义一个_兆字节(1024 * 1024)
int main()
{
char * some _ memory
int兆字节=A _兆字节;
int退出代码=退出失败;
some_memory=(char *)malloc(兆字节);
如果(某_内存!=NULL) {
sprintf(some_memory,“Hello World/n”);
printf("%s ",some _ memory);
退出代码=退出成功;
}
exit(exit _ code);
}
当我们运行这个程序时,它的输出结果如下:
$ ./内存1
你好世界
操作原理
这个程序要求malloc库指定一个指向1M内存的指针。我们需要检查以确保malloc函数被成功调用,然后使用它的一些内存来证明它的存在。当我们运行这个程序时,我们应该能够看到打印出来的Hello World字符串,这表明malloc确实返回了可用的兆字节空间。我们还没有检查所有分配的字节空间,我们需要信任malloc代码!
注意,因为malloc返回一个void *指针,我们把它转换成我们需要的char *类型。malloc函数确保返回对齐的内存空间,因此它可以转换为任何类型的指针。
原因很简单,大多数Linux系统使用32位整数和32位指针来指向内存,这允许我们指定高达4GB的内存空间。使用32位指针而不使用段寄存器或其他技巧直接寻址的技术称为普通32位内存模式。此模式也用于Windows XP和Windows 9x/Me的32个程序。我们不应该依赖32位的整数,因为也有64位版本的Linux在使用。
分配大内存
现在我们已经看到Linux已经超过了MS-DOS内存模式的极限,我们就来问一个更难的问题。在下面的程序中,我们会要求分配大于机器中实际物理内存大小的内存空间,所以我们会预计malloc函数会因实际内存量而失败,因为内核和其他正在运行的进程会占用一定的内存量。
测试-需要所有物理内存。
在memory2.c中,我们会要求分配比机器实际内存更多的内存。也许我们需要根据我们实际的物理内存来调整PHY MEM MEGS的值。
#包括unistd.h
#包含stdlib.h
#包含stdio.h
#定义一个_兆字节(1024 * 1024)
#定义PHY MEM MEGS 256/*根据需要调整该数字*/
int main()
{
char * some _ memory
size _ t size _ to _ allocate=A _ MEGABYTE;
int megs _ acquired=0;
while(megs _ acquired(PHY _ MEM _ MEGS * 2)){
some _ memory=(char *)malloc(size _ to _ allocate);
如果(某_内存!=NULL) {
megs _获得;
sprintf(some_memory,《Hello World》);
printf("%s -现在分配了%d兆字节/n ",some_memory,
megs _获得);
}
否则{
退出(EXIT _ FAILURE);
}
}
退出(EXIT _ SUCCESS);
}
该程序将产生类似如下的输出:
$ ./内存2
你好世界-现在分配了1兆字节
你好世界-现在分配2兆字节
.
你好世界-现在分配了511兆字节
你好世界-现在分配了512兆字节
操作原理
这个程序与前面的例子非常相似。他只是做了一个简单的循环,要求分配越来越多的内存。令人惊讶的是,他仍然可以正常工作,因为我们创造了一个可以使用所有物理的程序。注意,这里我们对malloc调用使用size_t类型。
另一个有趣的特点是,至少在我们测试的机器上,运行这个程序时屏幕会闪烁。因此,我们不仅使用所有的内存,而且我们可以快速完成所需的工作。
下面我们来讨论一下这个特性,看看我们可以在memory3.c中分配多少内存现在我们很清楚Linux可以智能地处理内存请求。现在一次只分配1K的内存,得到的每个内存都写。
测试可用内存
以下是memory3.c的内容自然这个程序对系统极其不友好,会严重影响一台多用户机器。如果我们没有意识到这种风险,那么最好不要运行这个程序;如果不运行,也不会影响我们对这个程序的理解。
#包括unistd.h
#包含stdlib.h
#包含stdio.h
#定义一个_K (1024)
int main()
{
char * some _ memory
int size _ to _ allocate=ONE _ K;
int megs _ acquired=0;
int ks _ acquired=0;
while (1) {
for(ks _ acquired=0;ks _获得1024;ks _获得){
some _ memory=(char *)malloc(size _ to _ allocate);
if(some _ memory==NULL)EXIT(EXIT _ FAILURE);
sprintf(some_memory,《Hello World》);
}
megs _获得;
printf("现已分配%d兆字节/n ",megs _ acquired);
}
退出(EXIT _ SUCCESS);
}
该程序的输出结果如下:
$ ./内存3
现在分配了1兆字节
.
现在分配了377兆字节
现在分配了378兆字节
内存不足:终止进程2365
被杀死的
而这次节目结束了。程序运行只需要几秒钟,接近机器实际物理内存时变慢,明显使用硬盘。但是,程序分配的内存超过了机器中的实际物理内存。最后,系统停止这个入侵程序并杀死它。在某些系统上,当malloc调用失败时,程序会直接退出。
操作原理
程序分配的内存由Linux内核管理。每当一个程序请求分配内存并试图读写分配的内存时,Linux内核就会接管管理权,决定如何处理这些请求。
一开始内核只是简单的利用空闲的物理内存来满足程序的内存分配请求,但是一旦内存用完,就会使用所谓的交换空间。在Linux系统上,这是安装系统时分配的独立磁盘空间。如果我们熟悉Windows,Linux交换空间有点类似于隐藏的Windows交换文件。然而,与Windows不同,我们不需要担心代码中的本地堆、全局堆或可处置内存段——Linux内核将为我们管理这些。
内核在物理内存和交换空间中移动数据和程序代码,这样我们每次读写内存时,数据看起来就像是在物理内存中,但实际上,数据在我们试图访问它们之前就已经定位了。
此外,Linux实现了虚拟页面内存系统。所有用户程序员看到的内存都是虚拟的;也就是说,它实际上并不存在于用户使用的物理地址中。Linux将所有内存分成页,通常一页是4096字节。当一个程序试图访问内存时,它会进行从虚拟内存到物理内存的转换,尽管它的实现和所花的时间取决于我们使用的实际硬件。当被访问的内存不是实际的物理内存时,将发生页面故障,控制权将被传递给内核。
Linux内核将检测被访问的地址,如果是合法的程序地址,内核将确定可以访问物理内存的哪一页。然后,内核会分配内存。如果之前没有数据被写入该页面内存,或者如果该页面内存存在于交换空间的磁盘中,则包含相应数据的内存页面将被读入物理内存(可能需要从磁盘中移除一个页面)。然后,在映射虚拟内存地址以匹配物理地址之后,内核允许用户程序继续运行。Linux程序不需要担心这些活动,因为这些实现完全隐藏在内核中。
事实上,当程序耗尽物理内存和交换空间,或者超过最大堆栈大小时,内核最终会拒绝额外的内存请求,并可能提前终止程序。
那么这对程序的程序员来说意味着什么呢?基本上,一切都是好消息。Linux非常擅长管理内存,允许程序使用大量内存,甚至大量单独的内存空间。然而,我们需要清楚的是,分配两个内存块不会产生连续的内存地址。我们得到的就是我们所要求的:两个独立的内存空间。
那么这是不是看起来对内存的支持有限,杀死进程是不是意味着不需要检查malloc返回的结果?当然不是。在C程序中使用动态分配内存时,最常见的问题之一是在超出分配内存的空间中写入数据。当这种情况发生时,程序不会立即退出,但是我们可能已经覆盖了malloc库例程中使用的一些数据。
通常情况下,malloc的调用结果会失败,不是因为没有内存可供分配,而是因为内存结构被破坏了。这些问题很难追踪,在程序中,越早发现错误,追踪原因的机会就越大。在第10章,调试和优化,我们将讨论一些工具,可以帮助我们跟踪内存问题。
滥用记忆
假设我们试图用记忆做坏事。在下面的程序memory4.c中,我们分配了一块内存,然后尝试在内存末尾之外写入一些数据。
实验-滥用记忆
#包含stdlib.h
#定义一个_K (1024)
int main()
{
char * some _ memory
char * scan _ ptr
some _ memory=(char *)malloc(ONE _ K);
if(some _ memory==NULL)EXIT(EXIT _ FAILURE);
scan _ ptr=some _ memory
while(1) {
* scan _ ptr=/0 ;
scan _ ptr
}
退出(EXIT _ SUCCESS);
}
输出结果如下:
美元/内存4
分段故障(核心转储)
操作原理
Linux内存管理系统将保护系统的其余部分免受内存滥用。为了保证一个行为怪异的程序不会危害到其他程序,Linux会结束这个程序。
第一个运行在Linux系统上的程序只会看到自己的内存映射,和其他程序的内存映射是不一样的。只有操作系统才知道物理内存是如何安排的,它不仅为用户程序管理内存,还在用户程序之间起到保护作用。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。