ACCESS数据库防下载方法
下面的方法分别适用有IIS控制权和 虚拟空间的用户!
1:修改
数据库名。这是常用的方法,将数据库名改成怪异名字或长名字以防他人猜测。如果被猜到数据库名则还能下载该数据库文件,但机率不大。如:将数据库database.mdb改成fjds$^&ijjkgf.mdb这种名称。
2:修改数据库后缀名。如改成database.inc、database.dwg、database.dll等等,请注意要在IIS中设置这些后缀的文件可以被解析,这样直接访问这个数据库文件时将会象程序一样被执行而不会被下载,以避免数据库被其他人获取而使网站安全受到影响。( 请不要修改为ASP、ASA这样的后缀名,因为黑客仍可以通过ASP的漏洞进行代码攻击从而获取数据库的名称达到攻击数据库的目的)
3:将数据库database.mdb改成#database.mdb。这是最简单有效的办法。假设别人得到你的数据库地址是:
http://www.yourserver.com/folder/#data#base.mdb,但实际上得到将是:http://www.yourserver.com/folder/,因为#在这里起到间断符的作用。地址串遇到#号,自动认为访问地址串结束。注意:不要设置目录可访问。用这种方法,不管别人用何种工具都无法下载,如flashget,网络蚂蚁等。
注:只要数据库文件名任何地方含有'#',别人都无法正常下载。同理,空格号也可以起到'#'号作用,但必须是文件名中间出现空格。
4:修改IIS设置。 只要修改一处,无需修改代码,即使暴露了数据库的目标地址,整个站点的数据库仍然可以防止被下载。
我们在 IIS属性---主目录---配置--- 映射---添加对.mdb文件的应用解析。
即任意找个.dLL文件解析MDB文件。如图:
通过以上设置,数据库可正常使用,但在直接下载数据库mdb文件时则会显示404错误。
5:加密数据库 适合没有IIS控制权
先在本机上打开ACCESS服务器,从菜单栏上,点“文件”->“打开”,在弹出的窗口里,选中你要打开的ACCESS数据库,点右下方的“打开”按钮时,应注意,要选择“以独占方式打开(v)”如图:
ACCESS 数据库打开后,就可以设置密码了,如图:
加密后修改数据库连接文件:conn.asp, 然后找到下面这段代码:
Sub OpenConn() On Error Resume Next If SystemDatabaseType = " SQL" Then ConnStr = "Provider = Sqloledb; User ID = " & SqlUsername & "; Password = " & SqlPassword & "; Initial Catalog = " & SqlDatabaseName & "; Data Source = " & SqlHostIP & ";" Else ConnStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Server.MapPath(db) |
修改这行 ConnStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Server.MapPath(db) 为下面样式
ConnStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Server.MapPath(db) &";Jet OLEDB:Database Password=数据库的密码;Persist Security Info=False"
这几种方法中,只有第4种方法是一次修改配置后,整个站点的数据库都可以防止下载;其他几种方法,需要修改数据库连接文件。
这几种方法各有长短,请自己选择性地使用,也可几种方法同时使用。但最主要还是需要系统和IIS本身设置足够安全并且加上好的防火墙软件, 否则再好的安全设置也仍然会被攻破!
Linux高端内存管理之永久内核映射 与直接映射的物理内存末端、高端内存的始端所对应的线性地址存放在high_memory变量中,在x86体系结构上,高于896MB的所有物理内存的范围大都是高端内存,它并不会永久地或自动地映射到内核地址空间,尽管x86处理器能够寻址物理RAM的范围达到4GB(启用PAE可以寻址到64GB)。一旦这些页被分配,就必须in射到内核的逻辑地址空间上。在x86上,高端内存中的页被映射到3GB-4GB。
内核可以采用三种不同的机制将页框映射到高端内存;分别叫做永久内核映射、临时内核映射以及非连续内存分配。在这里,只总结前两种技术,第三种技术将在后面总结。
建立永久内核映射可能阻塞当前进程;这发生在空闲页表项不存在时,也就是在高端内存上没有页表项可以用作页框的“窗口”时。因此,永久内核映射不能用于中断处理程序和可延迟函数。相反,建立临时内核映射绝不会要求阻塞当前进程;不过,他的缺点是只有很少的临时内核映射可以同时建立起来。
使用临时内核映射的内核控制路径必须保证当前没有其他的内核控制路径在使用同样地映射。这意味着内核控制路径永远不能被阻塞,后者其他内核控制路径有可能使用同一个窗口来映射其他的高端内存页。
永久内存映射
永久内核映射允许内核建立高端页框到内核地址空间的长期映射。他们使用住内核页表中一个专门的页表,其地址存放在变量pkmap_page_table中,这在前面的页表机制管理区初始化中已经介绍过了。页表中的表项数由LAST_PKMAP宏产生。因此,内核一次最多访问2MB或4MB的高端内存。
/*这里由定义可以看出永久内存映射为固定映射下面的4M空间*/
#define PKMAP_BASE ((FIXADDR_BOOT_START - PAGE_SIZE * (LAST_PKMAP + 1)) \
& PMD_MASK)
该页表映射的线性地址从PKMAP_BASE开始。pkmap_count数组包含LAST_PKMAP个计数器,pkmap_page_table页表中的每一项都有一个。
高端映射区逻辑页面的分配结构用分配表(pkmap_count)来描述,它有1024项,对应于映射区内不同的逻辑页面。当分配项的值等于0时为自由项,等于1时为缓冲项,大于1时为映射项。映射页面的分配基于分配表的扫描,当所有的自由项都用完时,系统将清除所有的缓冲项,如果连缓冲项都用完时,系统将进入等待状态。
/* 高端映射区逻辑页面的分配结构用分配表(pkmap_count)来描述,它有1024项, 对应于映射区内不同的逻辑页面。当分配项的值等于零时为自由项,等于1时为 缓冲项,大于1时为映射项。映射页面的分配基于分配表的扫描,当所有的自由 项都用完时,系统将清除所有的缓冲项,如果连缓冲项都用完时,系 统将进入等待状态。 */ static int pkmap_count[LAST_PKMAP]; /*last_pkmap_nr:记录上次被分配的页表项在pkmap_page_table里的位置,初始值为0,所以第一次分配的时候last_pkmap_nr等于1*/ static unsigned int last_pkmap_nr; |
为了记录高端内存页框与永久内核映射包含的线性地址之间的联系,内核使用了page_address_htable散列表。该表包含一个page_address_map数据结构,用于为高端内存中的每一个页框进行当前映射。而该数据结构还包含一个指向页描述符的指针和分配给该页框的线性地址。
* Hash table bucket */ static struct page_address_slot { struct list_head lh; /* List of page_address_maps */ spinlock_t lock; /* Protect this bucket's list */ } ____cacheline_aligned_in_smp page_address_htable[1<<PA_HASH_ORDER]; /* * Describes one page->virtual association */ struct page_address_map { struct page *page; void *virtual; struct list_head list; }; |
page_address()函数返回页框对应的线性地址
* Returns the page's virtual address. */ /*返回页框对应的线性地址*/ void *page_address(struct page *page) { unsigned long flags; void *ret; struct page_address_slot *pas; /*如果页框不在高端内存中*/ if (!PageHighMem(page)) /*线性地址总是存在,通过计算页框下标 然后将其转换成物理地址,最后根据相应的 物理地址得到线性地址*/ return lowmem_page_address(page); /*从page_address_htable散列表中得到pas*/ pas = page_slot(page); ret = NULL; spin_lock_irqsave(&pas->lock, flags); if (!list_empty(&pas->lh)) {/*如果对应的链表不空, 该链表中存放的是page_address_map结构*/ struct page_address_map *pam; /*对每个链表中的元素*/ list_for_each_entry(pam, &pas->lh, list) { if (pam->page == page) { ret = pam->virtual;/*返回线性地址*/ goto done; } } } done: spin_unlock_irqrestore(&pas->lock, flags); return ret; } |
kmap()函数建立永久内核映射。
/*高端内存映射,运用数组进行操作分配情况 分配好后需要加入哈希表中;*/ void *kmap(struct page *page) { might_sleep(); if (!PageHighMem(page))/*如果页框不属于高端内存*/ return page_address(page); return kmap_high(page);/*页框确实属于高端内存*/ } /** * kmap_high - map a highmem page into memory * @page: &struct page to map * * Returns the page's virtual memory address. * * We cannot call this from interrupts, as it may block. */ void *kmap_high(struct page *page) { unsigned long vaddr; /* * For highmem pages, we can't trust "virtual" until * after we have the lock. */ lock_kmap();/*保护页表免受多处理器系统上的 并发访问*/ /*检查是否已经被映射*/ vaddr = (unsigned long)page_address(page); if (!vaddr)/*如果没有*/ /*把页框的物理地址插入到pkmap_page_table的 一个项中并在page_address_htable散列表中加入一个 元素*/ vaddr = map_new_virtual(page); pkmap_count[PKMAP_NR(vaddr)]++;/*分配计数加一,此时流程都正确应该是2了*/ BUG_ON(pkmap_count[PKMAP_NR(vaddr)] < 2); unlock_kmap(); return (void*) vaddr;/*返回地址*/ } static inline unsigned long map_new_virtual(struct page *page) { unsigned long vaddr; int count; start: count = LAST_PKMAP; /* Find an empty entry */ for (;;) { /*加1,防止越界*/ last_pkmap_nr = (last_pkmap_nr + 1) & LAST_PKMAP_MASK; /* 接下来判断什么时候last_pkmap_nr等于0,等于0就表示1023(LAST_PKMAP(1024)-1)个页表项已经被分配了 ,这时候就需要调用flush_all_zero_pkmaps()函数,把所有pkmap_count[] 计数为1的页表项在TLB里面的entry给flush掉 ,并重置为0,这就表示该页表项又可以用了,可能会有疑惑为什么不在把pkmap_count置为1的时候也 就是解除映射的同时把TLB也flush呢? 个人感觉有可能是为了效率的问题吧,毕竟等到不够的时候再刷新,效率要好点吧。 */ if (!last_pkmap_nr) { flush_all_zero_pkmaps(); count = LAST_PKMAP; } if (!pkmap_count[last_pkmap_nr]) break; /* Found a usable entry */ if (--count) continue; /* * Sleep for somebody else to unmap their entries */ { DECLARE_WAITQUEUE(wait, current); __set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&pkmap_map_wait, &wait); unlock_kmap(); schedule(); remove_wait_queue(&pkmap_map_wait, &wait); lock_kmap(); /* Somebody else might have mapped it while we slept */ if (page_address(page)) return (unsigned long)page_address(page); /* Re-start */ goto start; } } /*返回这个页表项对应的线性地址vaddr.*/ vaddr = PKMAP_ADDR(last_pkmap_nr); /* v set_pte_at(mm, addr, ptep, pte)函数在NON-PAE i386上的实现其实很简单,其实就等同于下面的代码: static inline void native_set_pte(pte_t *ptep , pte_t pte) { *ptep = pte; } */ set_pte_at(&init_mm, vaddr,/*设置页表项*/ &(pkmap_page_table[last_pkmap_nr]), mk_pte(page, kmap_prot)); /*接下来把pkmap_count[last_pkmap_nr]置为1,1不是表示不可用吗, 既然映射已经建立好了,应该赋值为2呀,其实这个操作 是在他的上层函数kmap_high里面完成的(pkmap_count[PKMAP_NR(vaddr)]++).*/ pkmap_count[last_pkmap_nr] = 1; /*到此为止,整个映射就完成了,再把page和对应的线性地址 加入到page_address_htable哈希链表里面就可以了*/ set_page_address(page, (void *)vaddr); return vaddr; } |
kunmap()函数撤销先前由kmap()建立的永久内核映射
如果页确实在高端内存中,则调用kunmap_high()函数
* kunmap_high - map a highmem page into memory * @page: &struct page to unmap * * If ARCH_NEEDS_KMAP_HIGH_GET is not defined then this may be called * only from user context. */ void kunmap_high(struct page *page) { unsigned long vaddr; unsigned long nr; unsigned long flags; int need_wakeup; lock_kmap_any(flags); vaddr = (unsigned long)page_address(page); BUG_ON(!vaddr); nr = PKMAP_NR(vaddr);/*永久内存区域开始的第几个页面*/ /* * A count must never go down to zero * without a TLB flush! */ need_wakeup = 0; switch (--pkmap_count[nr]) {/*减小这个值,因为在映射的时候对其进行了加2*/ case 0: BUG(); case 1: /* * Avoid an unnecessary wake_up() function call. * The common case is pkmap_count[] == 1, but * no waiters. * The tasks queued in the wait-queue are guarded * by both the lock in the wait-queue-head and by * the kmap_lock. As the kmap_lock is held here, * no need for the wait-queue-head's lock. Simply * test if the queue is empty. */ need_wakeup = waitqueue_active(&pkmap_map_wait); } unlock_kmap_any(flags); /* do wake-up, if needed, race-free outside of the spin lock */ if (need_wakeup) wake_up(&pkmap_map_wait); } |
摘要:
/*createtablespacesystemv datafile'/opt/oracle/oradata/ibm/systemv01.dbf'size10m autoextendon;*/ /*droptablespacesystemv includingcontentsanddatafiles;*/ createuser"SYSTEMV" identifiedby"123456"defaulttablespace"SYSTEMV" accountunlock; grantcreateanydirectory,unlimitedtablespace,connect,resourceto"SYSTEMV"; /*dropusersystemvcascade;*/ /*connectsystemv/123456@192.168.254.99/ibm*/ |
正文:
步骤一:删除用户及其所有对象
drop user "aaaa" cascade
步骤二:创建表空间,并设置相关属性,先查询出一般的数据库文件都存放在哪里。 SQL> select * from v$dbfile;
FILE# NAME
--------------------------------------------------------------------------------
4 /mc/oracle/oradata/mc/users01.dbf
--创建表空间,并指定数据文件的位置(必须去除多余空格才能执行)
CREATE TABLESPACE AAAA
DATAFILE '/mc/oracle/oradata/mc/AAAA.dbf' SIZE 50M
extent management local autoallocate
--更改数据文件增长方式为自动增长
alter database
DATAFILE '/mc/oracle/oradata/mc/AAAA.dbf'
autoextend on
注意:上面的粗体字部分必须全部为大写;否则sqlplus将无法登陆,导数据也会出问题;如果这里大写了,将来登录用户名小写也是没问题的!
$ sqlplus "aaaa/aaaa";$ sqlplus "AAAA/aaaa" 以上两个都可以登录!
步骤三:授予用户适当权限
GRANT CREATE ANY DIRECTORY TO "AAAA"
GRANT UNLIMITED TABLESPACE TO "AAAA"
GRANT "CONNECT" TO "AAAA"
GRANT "RESOURCE" TO "AAAA"
或者
GRANT CREATE ANY DIRECTORY, UNLIMITED TABLESPACE, CONNECT, RESOURCE TO "AAAA" 查看创建好的用户
select * from dba_users select * from dba_tablespaces |
创建临时表空间【tempfile参数必须有】
create temporary tablespace zfmi_temp tempfile 'D:\oracle\oradata\zfmi\zfmi_temp.dbf' size 32m autoextend on next 32m maxsize 2048m extent management local; //创建数据表空间【datafile参数必须有 】 create tablespace zfmi logging datafile 'D:\oracle\oradata\zfmi\zfmi.dbf' size 100m autoextend on next 32m maxsize 2048m extent management local; //删除用户以及用户所有的对象 drop user zfmi cascade; //cascade参数是级联删除该用户所有对象,经常遇到如用户有对象而未加此参数则用户删不了的问题,所以习惯性的加此参数 //删除表空间 |
前提:删除表空间之前要确认该表空间没有被其他用户使用之后再做删除
drop tablespace zfmi including contents and datafiles cascade onstraints; //including contents 删除表空间中的内容,如果删除表空间之前表空间中有内容,而未加此参数,表空间删不掉,所以习惯性的加此参数 //including datafiles 删除表空间中的数据文件 //cascade constraints 同时删除tablespace中表的外键参照 //如果在清除表空间之前,先删除了表空间对应的数据文件,会造成数据库无法正常启动和关闭。 可使用如下方法恢复(此方法已经在oracle9i中验证通过): 下面的过程中,filename是已经被删除的数据文件,如果有多个,则需要多次执行;tablespace_name是相应的表空间的名称。 $ sqlplus /nolog SQL> conn / as sysdba; |
如果数据库已经启动,则需要先执行下面这行:
SQL> shutdown abort SQL> startup mount SQL> alter database datafile 'filename' offline drop; SQL> alter database open; SQL> drop tablespace tablespace_name including contents; //创建用户并指定表空间【identified by 参数必须有】 create user zfmi identified by zfmi default tablespace zfmi temporary tablespace zfmi_temp; //授予message用户DBA角色的所有权限 GRANT DBA TO zfmi; //给用户授予权限 grant connect,resource to zfmi; (db2:指定所有权限) -------------------------------------------------------------------华丽的分割线---------------------------------------------------------------------- --理解 recover datafile,表空间offline如果有immediate参数(此时将脏数据保存在system的延迟回退段中),那么下次online前必须recover。 alter tablespace zbb offline immediate SQL> recover datafile 13; alter tablespace zbb online ========================================= --给表空间增加新的数据文件 alter tablespace zbtbs add datafile '/disk2/oracle/oradata/zbtbs02.dbf' size 10M reuse ========================================= --重新指定数据文件的大小 alter database datafile '/disk2/oracle/oradata/zbtbs02.dbf' resize 100M ========================================= |
查看表空间的online或offline情况
select * from v$datafile
验证用户
验证指的是对要使用数据、资源或应用程序的用户、设备或其它实体的身份进行验证。通过对该身份进行验证可建立一种信任关系,从而可进一步执行交互。通过验证可将访问和操作与特定的身份联系起来,从而实现可靠性。完成验证后,验证流程可允许或限制该实体许可的访问和操作的级别。
SQLNET.ORA参数文件中的参数SQLNET.AUTHENTICATION_SERVICES设置
PFILE(SPFILE)参数文件中的参数REMOTE_LOGIN_PASSWORDFILE设置拥有数据字典
口令文件orapw$SID(
Linux) | PWD$SID.ora(
Windows) 是否存SYSTEM 帐户授予了 DBA 角色。
Oracle权限认证的基本顺序
先由SQLNET.AUTHENTICATION_SERVICES的设置值来决定是使用OS认证还是口令文件认证
如果使用口令文件认证的话就要同时满足下面两个条件才能认证成功:
1、REMOTE_LOGIN_PASSWORDFILE参数设置为非NONE
2、口令文件存在就能正常使用口令文件认证,否则将会认证失败
创建用户时,必须确定要使用的验证方法,以后可修改此方法。
口令:又称为 Oracle 数据库验证。创建的每一个用户都有一个关联口令,用户尝试建立连接时,必须提供这个口令。设置口令时,可以使该口令立即失效,这会强制用户在首次登录后更改口令。如果决定要使用户口令失效,请确保用户能够更改口令。有些应用程序不具备此功能。
在(客户机/服务器之间和服务器/服务器之间)建立网络连接期间,系统总是先通过使用修改过的数据加密标准 (DES) 算法,以自动透明方式对口令加密,然后通过网络发送这些口令。
conn / as sysdba既是操作系统认证,即使用操作系统用户登录数据库(root用户不可以),该用户必须同时添加到dba组和oinstall中,如果只添加dba组也不可以
只能用在本地 因为数据库软件安装在操作系统之上
密码文件验证:
口令认证:必须启动监听,用于网络连接,否则认证失败。
密码文件存储的位置 $ORACLE_HOME/dbs/orapw$ORACLE_SID
实验环境:
[oracle@tyger ~]$ id uid=54321(oracle) gid=54321(oinstall) groups=54321(oinstall),54322(dba) [oracle@tyger ~]$ sqlplus / as sysdba SQL*Plus: Release 10.2.0.1.0 - Production on Fri Feb 28 09:15:35 2014 Copyright (c) 1982, 2005, Oracle. All rights reserved. Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production With the Partitioning, OLAP and Data Mining options SYS@ORCL>select * from v$version; BANNER ---------------------------------------------------------------- Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod PL/SQL Release 10.2.0.1.0 - Production CORE 10.2.0.1.0 Production TNS for Linux: Version 10.2.0.1.0 - Production NLSRTL Version 10.2.0.1.0 - Production |
SQLNET.AUTHENTICATION_SERVICES参数在SQLNET.ORA(位于$ORACLE_HOME/network/admin目录中) 文件中对于不同的操作系统SQLNET.AUTHENTICATION_SERVICES的取值会有些不一样,通常我们会用到下面的一些设置值:
linux下: none all nts 不设置或BEQ 四种情况
第一种情况:
参数SQLNET.AUTHENTICATION_SERVICES不设置或设置为BEQ---------口令认证和操作系统认证都启动
[oracle@tygeradmin]$ pwd /u01/app/oracle/product/10.2.0/db_1/network/admin [oracle@tyger admin]$ ls listener.ora samples shrept.lst sqlnet.ora tnsnames.ora [oracle@tyger admin]$ vim sqlnet.ora NAME.DIRECTORY_PATH=(tnsnames,ezconnect) SQLNET.AUTHENTICATION_SERVICES=(BEQ) [oracle@tyger admin]$ lsnrctl status LSNRCTL for Linux: Version 10.2.0.1.0 - Production on 28-FEB-2014 09:52:19 Copyright (c) 1991, 2005, Oracle. All rights reserved. Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=tyger )(PORT=1521))) STATUS of the LISTENER ------------------------ Alias LISTENER Version TNSLSNR for Linux: Version 10.2.0.1.0 - Production Start Date 28-FEB-2014 09:48:44 Uptime 0 days 0 hr. 3 min. 34 sec Trace Level off Security ON: Local OS Authentication SNMP OFF Listener Parameter File /u01/app/oracle/product/10.2.0/db_1/network/admin/listener.ora Listener Log File /u01/app/oracle/product/10.2.0/db_1/network/log/listener.log Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=tyger )(PORT=1521))) (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC0))) Services Summary... Service "ORCL" has 1 instance(s). Instance "ORCL", status READY, has 1 handler(s) for this service... Service "ORCLXDB" has 1 instance(s). Instance "ORCL", status READY, has 1 handler(s) for this service... Service "ORCL_XPT" has 1 instance(s). Instance "ORCL", status READY, has 1 handler(s) for this service... Service "PLSExtProc" has 1 instance(s). Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service... The command completed successfully [oracle@whgg admin]$ sqlplus / as sysdba SQL*Plus: Release 10.2.0.1.0 - Production on Fri Feb 28 09:52:50 2014 Copyright (c) 1982, 2005, Oracle. All rights reserved. Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production With the Partitioning, OLAP and Data Mining options SYS@ORCL>exit Disconnected from Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production With the Partitioning, OLAP and Data Mining options [oracle@tyger admin]$ cd /u01/app/oracle/product/10.2.0/db_1/dbs/ [oracle@tyger dbs]$ ls hc_ORCL.dat initdw.ora init.ora lkORCL orapwORCL spfileORCL.ora [oracle@tyger dbs]$ sqlplus sys/oracle@ORCL as sysdba SQL*Plus: Release 10.2.0.1.0 - Production on Fri Feb 28 09:53:51 2014 Copyright (c) 1982, 2005, Oracle. All rights reserved. Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production With the Partitioning, OLAP and Data Mining options SYS@ORCL> |
第二种情况:
参数SQLNET.AUTHENTICATION_SERVICES设置为 all -----------------------屏蔽口令认证都启用操作系统认证
[oracle@tyger admin]$ pwd /u01/app/oracle/product/10.2.0/db_1/network/admin [oracle@tyger admin]$ vim sqlnet.ora NAME.DIRECTORY_PATH=(tnsnames,ezconnect) SQLNET.AUTHENTICATION_SERVICES=(ALL) [oracle@tyger admin]$ sqlplus / as sysdba SQL*Plus: Release 10.2.0.1.0 - Production on Fri Feb 28 09:59:20 2014 Copyright (c) 1982, 2005, Oracle. All rights reserved. Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production With the Partitioning, OLAP and Data Mining options SYS@ORCL>exit Disconnected from Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production With the Partitioning, OLAP and Data Mining options [oracle@tyger admin]$ sqlplus sys/oracle@ORCL as sysdba SQL*Plus: Release 10.2.0.1.0 - Production on Fri Feb 28 09:59:39 2014 Copyright (c) 1982, 2005, Oracle. All rights reserved. ERROR: ORA-12641: Authentication service failed to initialize Enter user-name: |
第三种情况:
参数SQLNET.AUTHENTICATION_SERVICES 设置为 NONE 或NTS ----------------屏蔽操作系统认证都启用口令认证
[oracle@tyger admin]$ vim sqlnet.ora NAME.DIRECTORY_PATH=(tnsnames,ezconnect) SQLNET.AUTHENTICATION_SERVICES=(NTS) [oracle@tyger admin]$ sqlplus / as sysdba SQL*Plus: Release 10.2.0.1.0 - Production on Fri Feb 28 10:36:35 2014 Copyright (c) 1982, 2005, Oracle. All rights reserved. ERROR: ORA-01031: insufficient privileges [oracle@tyger admin]$ sqlplus sys/oracle@ORCL as sysdba SQL*Plus: Release 10.2.0.1.0 - Production on Fri Feb 28 10:36:52 2014 Copyright (c) 1982, 2005, Oracle. All rights reserved. Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production With the Partitioning, OLAP and Data Mining options SYS@ORCL> |
第四种情况:
当数据库屏蔽了操作系统认证,启用口令认证方式的话,需要检查remote_login_passwordfile参数,如果该参数设置为NONE,该值表示不使用口令文件,因此,此时数据库将不能登录
解决办法:启动操作系统认证,登录数据库后将remote_login_passwordfile参数修改EXCLUSIVE,然后再屏蔽操作系统认证,启用口令认证。
> remote_login_passwordfile参数可以设置为3个值 none、exclusive、shared
[oracle@tyger admin]$ cat sqlnet.ora NAME.DIRECTORY_PATH=(tnsnames,ezconnect) SQLNET.AUTHENTICATION_SERVICES=(NTS) [oracle@tyger admin]$ sqlplus sys/oracle@ORCL as sysdba SQL*Plus: Release 10.2.0.1.0 - Production on Fri Feb 28 10:48:15 2014 Copyright (c) 1982, 2005, Oracle. All rights reserved. Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production With the Partitioning, OLAP and Data Mining options SYS@ORCL>show parameter remote NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ remote_archive_enable string true remote_dependencies_mode string TIMESTAMP remote_listener string remote_login_passwordfile string EXCLUSIVE remote_os_authent boolean FALSE remote_os_roles boolean FALSE SYS@ORCL>alter system set remote_login_passwordfile=none scope=spfile; System altered. ---静态参数,重启数据库生效 SYS@ORCL>shutdown immediate Database closed. Database dismounted. ORACLE instance shut down. SYS@ORCL>startup ORA-12514: TNS:listener does not currently know of service requested in connect descriptor [oracle@tyger admin]$ vim sqlnet.ora NAME.DIRECTORY_PATH=(tnsnames,ezconnect) #SQLNET.AUTHENTICATION_SERVICES=(NTS) [oracle@tyger admin]$ sqlplus / as sysdba SQL*Plus: Release 10.2.0.1.0 - Production on Fri Feb 28 10:57:25 2014 Copyright (c) 1982, 2005, Oracle. All rights reserved. Connected to an idle instance. SYS@ORCL>startup ORACLE instance started. Total System Global Area 285212672 bytes Fixed Size 1218992 bytes Variable Size 96470608 bytes Database Buffers 184549376 bytes Redo Buffers 2973696 bytes Database mounted. Database opened. SYS@ORCL>show parameter remote NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ remote_archive_enable string true remote_dependencies_mode string TIMESTAMP remote_listener string remote_login_passwordfile string NONE remote_os_authent boolean FALSE remote_os_roles boolean FALSE SYS@ORCL>alter system set remote_login_passwordfile=exclusive scope=spfile; System altered. SYS@ORCL>shutdown immediate Database closed. Database dismounted. ORACLE instance shut down. SYS@ORCL>startup ORACLE instance started. Total System Global Area 285212672 bytes Fixed Size 1218992 bytes Variable Size 96470608 bytes Database Buffers 184549376 bytes Redo Buffers 2973696 bytes Database mounted. Database opened. SYS@ORCL>show parameter remote NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ remote_archive_enable string true remote_dependencies_mode string TIMESTAMP remote_listener string remote_login_passwordfile string EXCLUSIVE remote_os_authent boolean FALSE remote_os_roles boolean FALSE SYS@ORCL>exit Disconnected from Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production With the Partitioning, OLAP and Data Mining options [oracle@tyger admin]$ sqlplus sys/oracle@ORCL as sysdba SQL*Plus: Release 10.2.0.1.0 - Production on Fri Feb 28 11:04:16 2014 Copyright (c) 1982, 2005, Oracle. All rights reserved. Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production With the Partitioning, OLAP and Data Mining options SYS@ORCL> |
性能测试之进程篇(windows)
查看进程的%Processor Time值
每个进程的%Processor Time反映进程所消耗的处理器时间。用不同进程所消耗的处理器时间进行对比,可以很容易的看出具体是哪个进程在[url=]性能测试[/url]过程中消耗了最多的处理器时间,从而可以据此针对应用进行优化。
查看每个进程产生的页面失效
可以用每个进程产生的页面失效(通过Process\Page Failures/sec计数器获得)和系统的页面失效(可通过Memory\Page Failures/sec计数器获得)的比值,来判断哪个进程产生了最多的失效页面,这个进程要么是需要大量内存的进程,要么是非常活跃的进程,可以对其进行中的分析。
了解进程的Process\Private Bytes
Process\Private Bytes是指进程所分配的无法与其他进程共享的当前字节数量。该计数器主要用拉判断进程在性能测试过程中有无内存泄漏。
例如:对于一个IIS之上的web应用,我们可以重点监控inetinfo进程的Private Bytes,如果在性能测试过程中,该进程的Private Bytes计数器值不断增加,或是性能测试停止后一段时间,该进程的Private Bytes仍然持续在高水平,则说明应用存在内存泄漏。
(备注:进程分析方法用到的计数器主要有:Process\%Processor Time、Page Failures/sec、Page Failures/sec、Private Bytes)
相关链接:
① 内存映射文件机制
内存映射文件是利用虚拟内存把文件映射到进程的地址空间中去,在此之后进程操作文件,就像操作进程空间里的地址一样了,省去了读和写I/O的时间。
比如使用memcpy等内存操作的函数。这种方法能够很好的应用在需要频繁处理一个文件或者是一个大文件的场合,这种方式处理IO效率比普通IO效率要高。
利用内存映射文件您可以认为操作系统已经为您把文件全部装入了内存,然后您只要移动文件指针进行读写即可了。这样您甚至不需要调用那些分配、释放内存块和文件输入/输出的API函数,另外您可以把这用作不同的进程之间共享数据的一种办法。运用内存映射文件实际上没有涉及实际的文件操作,它更象为每个进程保留一个看得见的内存空间。至于把内存映射文件当成进程间共享数据的办法来用,则要加倍小心,因为您不得不处理数据的同步问题,否则您的应用程序也许很可能得到过时或错误的数据甚至崩溃。
内存映射文件本身还是有一些局限性的,譬如一旦您生成了一个内存映射文件,那么您在那个会话期间是不能够改变它的大小的。所以内存映射文件对于只读文件和不会影响其大小的文件操作是非常有用的。当然这并不意味着对于会引起改变其大小的文件操作就一定不能用内存影射文件的方法,您可以事先估计操作后的文件的可能大小,然后生成这么大小一块的内存映射文件,然后文件的长度就可以增长到这么一个大小。我们的解释够多的了,接下来我们就看看实现的细节:
·调用CreateFile打开您想要映射的文件。
·调用CreateFileMapping,其中要求传入先前CreateFile返回的句柄,该函数生成一个建立在CreateFile函数创建的文件对象基础上的内存映射对象。
·调用MapViewOfFile函数映射整个文件的一个区域或者整个文件到内存。该函数返回指向映射到内存的第一个字节的指针。
·用该指针来读写文件。
·调用UnmapViewOfFile来解除文件映射。
·调用CloseHandle来关闭内存映射文件。注意必须传入内存映射文件的句柄。
调用CloseHandle来关闭文件。注意必须传入由CreateFile创建的文件的句柄。性能计数器(counter)是描述服务器或
操作系统性能的一些数据指标。计数器在
性能测试中发挥着“监控和分析”的关键作用,尤其是在分析系统的可扩展性、进行性能瓶颈的定位时,对计数器的取值的分析非常关键。但必须说明的是,单一的性能计数器只能体现系统性能的某一个方面,对性能测试结果的分析必须基于多个不同的计数器。
与性能计数器相关的另一个术语是“资源利用率”。该术语指的是系统各种资源的使用状况。为了方便比较,一般用“资源的实际使用/总的资源可用量”形成资源利用率的数据,用以进行各种资源使用的比较。
性能测试之内存篇(windows)
要监视内存不足的状况,请从以下的对象计数器开始:
· Memory\ Available Bytes
· Memory\ Pages/sec
Available Bytes剩余的可用物理内存,单位是兆字节(参考值:>=10%)。表明进程当前可使用的内存字节数。Pages/sec 表明由于硬件页面错误而从磁盘取出的页面数,或由于页面错误而写入磁盘以释放[url=]
工作[/url]集空间的页面数。
如果 Available Bytes 的值很小(4 MB 或更小),则说明计算机上总的内存可能不足,或某程序没有释放内存。如果 Pages/sec 的值为 20 或更大,那么您应该进一步研究页交换活动。Pages/sec 的值很大不一定表明内存有问题,而可能是运行使用内存映射文件的程序所致。
操作系统经常会利用磁盘交换的方式提高系统可用的内存量或是提高内存的使用效率。下列四个
指标直接反映了操作系统进行磁盘交换的频度。
Page Faults/sec
当处理器在内存中读取某一页出现错误时,就会产生缺页中断,也就是 page Fault。如果这个页
位于内存的其他位置,这种错误称为软错误,用Transition Fault/sec 来衡量;如果这个页位于硬盘上,必须从硬盘重新读取,这个错误成为硬错误。硬错误会使系统的运行效率很快将下来。Page Faults/sec这个计数器就表示每秒钟处理的错误页数,包括硬错误和软错误。
Page Input/sec
表示为了解决硬错误而写入硬盘的页数(参考值:>=Page Reads/sec)
Page Reads/sec
表示为了解决硬错误而从硬盘上读取的页数。(参考值: <=5)
Pages/sec
表示为了解决硬错误而从硬盘上读取或写入硬盘的页数(参考值:00~20)
必须同时监视 Available Bytes、Pages/sec 和 Paging File % Usage,以便确定是否发生这种情况。如果正在读取非缓存内存映射文件,还应该查看缓存活动是否正常。
Cathe Bytes
文件系统的缓存(默认为50%的可用物理内存)
内存泄露
· Memory\Available Bytes
· Memory\ Committed Bytes
如果您怀疑有内存泄露,请监视 Memory\Available Bytes 和 Memory\ Committed Bytes,以观察内存行为,并监视你认为可能在泄露内存的进程的 Process\ Private Bytes、Process\ Working Set 和Process\ Handle Count。如果您怀疑是内核模式进程导致了泄露,则还应该监视 Memory\ Pool Nonpaged Bytes、Memory\ Pool Nonpaged Allocs 和 Process(process_name)\ Pool Nonpaged Bytes。
private Bytes
进程无法与其他进程共享的字节数量。该计数器的值较大时,有可能是内存泄露的信号
检查过于频繁的页交换
由于过多的页交换要使用大量的硬盘空间,因此有可能将导致将页交换内存不足,这容易与导致页交换的磁盘瓶颈混淆。因此,在研究内存不足不太明显的页交换的原因时,您必须跟踪如下的磁盘使用情况计数器和内存计数器:
· Physical Disk\ % Disk Time
· Physical Disk\ Avg.Disk Queue Length 例如,包括 Page Reads/sec 和 % Disk Time 及 Avg.Disk Queue Length。如果页面读取操作速率很低,同时 % Disk Time 和 Avg.Disk Queue Length的值很高,则可能有磁盘瓶径。但是,如果队列长度增加的同时页面读取速率并未降低,则内存不足。
要确定过多的页交换对磁盘活动的影响,请将 Physical Disk\ Avg.Disk sec/Transfer 和 Memory\ Pages/sec 计数器的值增大数倍。如果这些计数器的计数结果超过了 0.1,那么页交换将花费百分之十以上的磁盘访问时间。如果长时间发生这种情况,那么您可能需要更多的内存。
研究程序的活动
接下来,检查正在运行的程序导致的过多的页交换。如果可能,请停止具有最高工作集值的程序,然后查看页交换速率是否有显著变化。如果您怀疑存在过多的页交换,请检查 Memory\ Pages/sec 计数器。该计数器显示由于页面不在物理内存中而需要从磁盘读取的页面数。(注意该计数器与 Page Faults/sec 的区别,后者只表明数据不能在内存的指定工作集中立即使用。)
性能测试之处理器篇(windows)
监视“处理器”和“系统”对象计数器可以提供关于处理器使用的有价值的信息,帮助您决定是否存在瓶颈。需要包含下列内容:
·Processor\ % Total Processor Time 获得处理器整体使用情况。
该计数值用于体现服务器整体的处理器利用率,对多处理器的系统而言,该计数值体现的是所有CPU的平均利用率。如果该值的数值持续超过90%,则说明整个系统面临着处理器方面的瓶颈,需要通过增加处理器来提高性能。
要注意的是,由于操作系统本身的特性,在某些多CPU系统中,该数据本身并不大,但此时CPU之间的负载状况极不均衡,此时也应该视作系统产生了处理器方面的瓶颈。
·监视 Processor\ % Processor Time、Processor\ % User Time 和 % Privileged Time 以获得详细信息。
Processor\ % User Time是指系统的非核心操作消耗的CPU时间,如果该值较大,可以考虑是否通过优化算法等方法降低这个值。如果该服务器是数据库服务器,Processor\ % User Time大的原因很可能是数据库的排序或是函数操作消耗了过多的CPU时间,此时可以考虑对数据库系统进行优化。
·System\ Processor Queue Length 用于瓶颈检测。
%Total Processor Time
系统中所有处理器都处于繁忙状态的时间百分比,对于多处理器系统来说,该值可以反映所有处理器的平均繁忙状态,该值为100%,如果有一半的处理器为繁忙状态,该值为50%
File Data Operations/sec
计算机对文件系统进行读取和写入操作的频率,但是不包括文件控制操作
Process Queue Length
线程在等待分配CPU资源所排队列的长度,此长度不包括正在占有CPU资源的线程。如果该队列的长度大于处理器个数+1,就表示处理器有可能处于阻塞状态(参考值:<=处理器个数+1)
%Processor Time
CPU利用率,该计数器最为常用,可以查看处理器是否处于饱和状态,如果该值持续超过 95%,就表示当前系统的瓶颈为CPU,可以考虑增加一个处理器或更换一个性能更好的处理器。(参考值:<80%)
%Priviliaged Time
CPU在特权模式下处理线程所花的时间百分比。一般的系统服务,进城管理,内存管理等一些由操作系统自行启动的进程属于这类
%User Time
与%Privileged Time计数器正好相反,指的是在用户状态模式下(即非特权模式)的操作所花的时间百分比。如果该值较大,可以考虑是否通过算法优化等方法降低这个值。如果该服务器是数据库服务器,导致此值较大的原因很可能是数据库的排序或是函数操作消耗了过多的CPU时间,此时可以考虑对数据库系统进行优化。
%DPC Time
处理器在网络处理上消耗的时间,该值越低越好。在多处理器系统中,如果这个值大于50%并且%Processor Time非常高,加入一个网卡可能会提高性能。
观察处理器使用情况的值
要测量处理器的活动,请查看 Processor\ % Processor Time 计数器。该计数器显示处理器忙于执行非空闲线程所耗时间的百分比。
检查处理器使用时,请考虑计算机的角色和所完成[url=]工作[/url]的类型。根据计算机进行的工作,较高的处理器值意味着系统正有效地处理较重的工作负载或正在努力维持。例如,如果正在监视用户的计算机,并且该计算机用于计算,计算程序可能容易使用 100% 的处理器时间。即使这会造成该计算机中[url=]其他[/url]应用程序的性能受到影响,但可以通过改变负载来解决。
另一方面,在处理许多客户请求的服务器计算机中,100% 左右的值表示这些过程在队列中,正在等待处理器时间,并且造成瓶颈。如此持续高层次的处理器使用对服务器而言是无法接受的。
考察处理器瓶颈
进程的线程所需要的处理器周期超出可用周期时,处理器瓶颈将逐步显示出来。可以建立较长的处理器队列,并且系统响应会受到影响。处理器瓶颈两种常见的原因是 CPU 限制程序和产生过多中断的驱动程序或子系统组件。
要决定是否由于对处理器时间的要求较高而存在处理器瓶颈,请查看 System\ Processor Queue Length 计数器。队列中包含两个或更多的项目则表明存在瓶颈。如果多个程序进程竞争大多数处理器时间,安装更快速的处理器会提高吞吐量。如果正在运行多线程的进程,附加处理器会有所帮助,但是请注意,附加处理器可能只有有限的益处。
此外,跟踪计算机的服务器工作队列当前长度的 Server Work Queues\ Queue Length 计数器会显示出处理器瓶颈。队列长度持续大于 4 则表示可能出现处理器拥塞。此计数器是特定时间的值,而不是一段时间的平均值。
要决定中断活动是否造成瓶颈,请观察 Processor\ Interrupts/sec 计数器的值,该计数器测量来自输入/输出 (I/O) 设备的服务请求的速度。如果此计数器的值明显增加,而系统活动没有相应增加,则表明存在硬件问题。
也可以对生成中断的磁盘驱动器、网卡和其他设备活动的间接指示器监视 Processor\ % Interrupt Time 时间。注意
要检测可能影响处理器性能的硬件问题,例如 IRQ 冲突,请观察 System\ File Control Bytes/second 的值。
监视多处理器系统
要观察多处理器计算机的效率,请使用下列附加计数器。
性能测试之磁盘篇(windows)
监测对象:PhysicalDisk
如果分析的计数器指标来自于数据库服务器、文件服务器或是流媒体服务器,磁盘I/O对这些系统来说更容易成为瓶颈。
每磁盘的I/O数可用来与磁盘的I/O能力进行对比,如果经过计算得到的每磁盘I/O数超过了磁盘标称的I/O能力,则说明确实存在磁盘的性能瓶颈。
下表给出了每磁盘I/O的计算公式:
%Disk Time
表示磁盘驱动器为读取或写入请求提供服务所用的时间百分比,如果只有%Disk Time比较大,硬盘有可能是瓶颈
Average Disk Queue Length
表示磁盘读取和写入请求提供服务所用的时间百分比,可以通过增加磁盘构造磁盘阵列来提高性能(<=磁盘数的2倍)
Average Disk Read Queue Length
表示磁盘读取请求的平均数
Average Disk write Queue Length
表示磁盘写入请求的平均数
Average Disk sec/Read
磁盘中读取数据的平均时间,单位是s
Disk Bytes/sec 提供磁盘系统的吞吐率。
决定工作负载的平衡
要平衡网络服务器上的负载,需要了解服务器磁盘驱动器的繁忙程度。使用 Physical Disk\ % Disk Time 计数器,该计数器显示驱动器活动时间的百分比。如果 % Disk Time 较高(超过 90%),请检查 Physical Disk\ Current Disk Queue Length 计数器以查看正在等待磁盘访问的系统请求数量。等待 I/O 请求的数量应当保持在不大于组成物理磁盘的主轴数的 1.5 到 2 倍。
Average Disk sec/Transfer
磁盘中写入数据的平均时间,单位是s
计数器反映磁盘完成请求所用的时间。较高的值表明磁盘控制器由于失败而不断重试该磁盘。这些故障会增加平均磁盘传送时间。一般来说,定义该值小于15ms最为优异,介于15-30ms之间为良好,30-60ms之间为可以接受,超过60ms则需要考虑更换硬盘或硬盘的RAID方式了
Average Disk Bytes/Transfer
值大于 20 KB 表示该磁盘驱动器通常运行良好;如果应用程序正在访问磁盘,则会产生较低的值。例如,随机访问磁盘的应用程序会增加平均 Disk sec/Transfer 时间,因为随机传送需要增加搜索时间。
性能测试之网络篇(windows)
监测对象:Network Interface
网络分析是一件[url=]技术[/url]含量很高的[url=]工作[/url],在一般的组织中都有专门的网络管理人员进行网络分析,对测试工程师来说,如果怀疑网络是系统的瓶颈,可以要求网络仍有来写真进行网络方面的检测。
Network Interface\Bytes Total/sec为发送和接收字节的速率(包括帧字符在内)。可以通过该计数器的值判断网络连接速度是否是瓶颈,具体操作方法是用该计数器的值与目前的网络带宽进行比较。
Byte Total/sec
表示网络中接受和发送字节的速度,可以用该计数器来判断网络是否存在瓶颈(参考值:该计数器和网络带宽相除,<50%) 性能测试之进程篇(windows)
查看进程的%Processor Time值
每个进程的%Processor Time反映进程所消耗的处理器时间。用不同进程所消耗的处理器时间进行对比,可以很容易的看出具体是哪个进程在[url=]性能测试[/url]过程中消耗了最多的处理器时间,从而可以据此针对应用进行优化。
查看每个进程产生的页面失效
可以用每个进程产生的页面失效(通过Process\Page Failures/sec计数器获得)和系统的页面失效(可通过Memory\Page Failures/sec计数器获得)的比值,来判断哪个进程产生了最多的失效页面,这个进程要么是需要大量内存的进程,要么是非常活跃的进程,可以对其进行中的分析。
了解进程的Process\Private Bytes
Process\Private Bytes是指进程所分配的无法与其他进程共享的当前字节数量。该计数器主要用拉判断进程在性能测试过程中有无内存泄漏。
例如:对于一个IIS之上的web应用,我们可以重点监控inetinfo进程的Private Bytes,如果在性能测试过程中,该进程的Private Bytes计数器值不断增加,或是性能测试停止后一段时间,该进程的Private Bytes仍然持续在高水平,则说明应用存在内存泄漏。
(备注:进程分析方法用到的计数器主要有:Process\%Processor Time、Page Failures/sec、Page Failures/sec、Private Bytes)
相关链接:
① 内存映射文件机制
内存映射文件是利用虚拟内存把文件映射到进程的地址空间中去,在此之后进程操作文件,就像操作进程空间里的地址一样了,省去了读和写I/O的时间。
比如使用memcpy等内存操作的函数。这种方法能够很好的应用在需要频繁处理一个文件或者是一个大文件的场合,这种方式处理IO效率比普通IO效率要高。
利用内存映射文件您可以认为操作系统已经为您把文件全部装入了内存,然后您只要移动文件指针进行读写即可了。这样您甚至不需要调用那些分配、释放内存块和文件输入/输出的API函数,另外您可以把这用作不同的进程之间共享数据的一种办法。运用内存映射文件实际上没有涉及实际的文件操作,它更象为每个进程保留一个看得见的内存空间。至于把内存映射文件当成进程间共享数据的办法来用,则要加倍小心,因为您不得不处理数据的同步问题,否则您的应用程序也许很可能得到过时或错误的数据甚至崩溃。
内存映射文件本身还是有一些局限性的,譬如一旦您生成了一个内存映射文件,那么您在那个会话期间是不能够改变它的大小的。所以内存映射文件对于只读文件和不会影响其大小的文件操作是非常有用的。当然这并不意味着对于会引起改变其大小的文件操作就一定不能用内存影射文件的方法,您可以事先估计操作后的文件的可能大小,然后生成这么大小一块的内存映射文件,然后文件的长度就可以增长到这么一个大小。我们的解释够多的了,接下来我们就看看实现的细节:
·调用CreateFile打开您想要映射的文件。
·调用CreateFileMapping,其中要求传入先前CreateFile返回的句柄,该函数生成一个建立在CreateFile函数创建的文件对象基础上的内存映射对象。
·调用MapViewOfFile函数映射整个文件的一个区域或者整个文件到内存。该函数返回指向映射到内存的第一个字节的指针。
·用该指针来读写文件。
·调用UnmapViewOfFile来解除文件映射。
·调用CloseHandle来关闭内存映射文件。注意必须传入内存映射文件的句柄。
调用CloseHandle来关闭文件。注意必须传入由CreateFile创建的文件的句柄。