




已阅读5页,还剩10页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
AIX 5L 上的共享库内存占用George Cross (), 高级软件开发人员, Business Objects AmericasGeorge Cross 是 Business Objects Americas 的一名高级软件开发人员,他拥有在 UNIX 上使用 C+ 开发服务器应用程序的经验。他拥有加拿大西蒙菲莎大学的计算机科学学士学位。简介:了解 IBM AIX 上的共享库机制和内存占用情况。本文对于开发人员编写服务器代码或管理员管理生产 AIX 系统来说非常重要。本文为开发人员和管理员提供了分析 AIX 上的服务器进程的内存需求所需的命令、技巧和知识。本文还有助于开发人员和管理员避免出现使用 ps 或 topas 等其他标准运行时分析工具时无法识别的资源短缺。本文是面向 AIX 系统管理员或本机应用程序开发人员。引言本文阐述 32 位 AIX 5L (5.3) 上共享库占用内存的方式,并演示下列命令: ps svmon slibclean procldd procmap genkld genld 本文讨论进程的虚拟地址空间和内核共享库段,以及如何查看它们和如何解释上述多种诊断实用工具的输出。本文还讨论如何诊断内核共享段完全占用的情况,以及解决该问题的可能方法。在贯穿全文的示例中,我们碰巧使用了来自软件产品 Business Objects Enterprise Xir2 的进程。这种选择无关紧要,因为这些概念适用于在 AIX 5L 上运行的所有进程。 回页首回顾为了保持思维同步,让我们简单回顾一下 32 位体系结构。为了达到目标,我将采用最有用的“bc”命令行计算器。在 32 位处理器中,寄存器能够保存 232 大小的值, $ bc2324294967296obase=16232100000000这是 4GB 的范围。这表示在系统中运行的程序能够访问 0 到 232 1 范围内的任何函数或数据地址。$ bc 232 - 1 FFFFFFFFobase=10232 - 1 4294967295现在,如您所知,任何操作系统都可能同时运行数百个程序。即使其中每个系统都能访问 4GB 的内存范围,这并不表示它们各自拥有 4GB 的物理内存分配。这是不切实际的。实际上,操作系统在适量物理内存和文件系统中被指定为交换(或分页)空间的区域之间实现了非常复杂的代码和数据交换方案。而且,虽然每个进程能够访问 4GB 的内存空间,但其中大部分空间都不会被使用。因此,操作系统仅为每个特定进程加载或交换所需数量的代码和数据。图 1. 虚拟内存的概念图该机制通常称为虚拟内存和虚拟地址空间。在可执行文件运行时,操作系统的虚拟内存管理器查看文件包含的代码和数据,并决定将其中哪些部分加载到内存或交换空间中,或从文件系统引用。同时,虚拟内存管理器建立一些结构以将物理位置映射到 4GB 范围内的虚拟位置。其中 4GB 范围表示进程的最大理论范围(有时包括用于表示它的 VMM 结构),被称为进程的虚拟地址空间。在 AIX 上,将 4GB 虚拟地址空间划分为 16 个 256MB 的段。这些段具有预定的功能,下面对其中一些段进行说明: 段 0 预留给内核相关数据。 段 1 预留给代码。 段 2 预留给堆栈和动态内存分配。 段 3 预留给内存映射文件,即 mmap。 段 d 预留给共享库代码。 段 f 预留给共享库数据。 与之相比,HP-UX 将地址空间划分为 4 个象限(quadrants)。如果使用 chatr 命令并采用 +q3p enable 和 +q4p enable 选项进行指定,则象限 3 和象限 4 可用于共享库映射。回页首共享库加载到何处共享库本身是用于共享的。具体而言,二进制映像的只读部分(即代码,也称为“文本”)和只读数据(常量数据,以及可以写入时复制的数据)可以一次加载到物理内存中,然后将其多次映射到需要该数据的任何进程中。 为了演示此概念,请准备一台运行 AIX 的计算机,然后查看已加载的共享库: su # genkldText address Size File d1539fe0 1a011 /usr/lib/libcurses.ashr.o d122f100 36732 /usr/lib/libptools.ashr.o d1266080 297de /usr/lib/libtrace.ashr.o d020c000 5f43 /usr/lib/nls/loc/iconv/ISO8859-1_UCS-2 d7545000 161ff /usr/java14/jre/bin/libnet.a d7531000 135e2 /usr/java14/jre/bin/libzip.a. lots more libs .d1297108 3a99 /opt/rational/clearcase/shlib/libatriastats_svr.aatriastats_svr-shr.o d1bfa100 2bcdf /opt/rational/clearcase/shlib/libatriacm.aatriacm-shr.o d1bbf100 2cf3c /opt/rational/clearcase/shlib/libatriaadm.aatriaadm-shr.o. lots more libs . d01ca0f8 17b6 /usr/lib/libpthreads_compat.ashr.o d10ff000 30b78 /usr/lib/libpthreads.ashr.o d00f0100 1fd2f /usr/lib/libC.ashr.o d01293e0 25570 /usr/lib/libC.ashrcore.o d01108a0 18448 /usr/lib/libC.aansicore_32.o. lots more libs . d04a2100 fdb4b /usr/lib/libX11.ashr4.o d0049000 365c4 /usr/lib/libpthreads.ashr_xpg5.o d0045000 3c52 /usr/lib/libpthreads.ashr_comm.o d05bb100 5058 /usr/lib/libIM.ashr.o d05a7100 139c1 /usr/lib/libiconv.ashr4.o d0094100 114a2 /usr/lib/libcfg.ashr.o d0081100 125ea /usr/lib/libodm.ashr.o d00800f8 846 /usr/lib/libcrypt.ashr.o d022d660 25152d /usr/lib/libc.ashr.o结果很有趣,我们立刻可以看到这台计算机正在运行 Clearcase 和 Java。让我们从中任选一个公共库,假定选择 libpthreads.a。浏览该库并查看它实现了哪些函数:# dump -Tv /usr/lib/libpthreads.a | grep EXP278 0x00002808 .data EXP RW SECdef noIMid pthread_attr_default279 0x00002a68 .data EXP RW SECdef noIMid pthread_mutexattr_default280 0x00002fcc .data EXP DS SECdef noIMid pthread_create281 0x0000308c .data EXP DS SECdef noIMid pthread_cond_init282 0x000030a4 .data EXP DS SECdef noIMid pthread_cond_destroy283 0x000030b0 .data EXP DS SECdef noIMid pthread_cond_wait284 0x000030bc .data EXP DS SECdef noIMid pthread_cond_broadcast285 0x000030c8 .data EXP DS SECdef noIMid pthread_cond_signal286 0x000030d4 .data EXP DS SECdef noIMid pthread_setcancelstate287 0x000030e0 .data EXP DS SECdef noIMid pthread_join. lots more stuff .嗯,真棒!现在,我们来查看目前系统中有哪些正在运行的进程加载了该库:# for i in $(ps -o pid -e | grep 0-9 ) ; do j=$(procldd $i | grep libpthreads.a); if -n $j ; then ps -p $i -o comm | grep -v COMMAND; fi ; doneportmaprpc.statdautomountdrpc.mountdrpc.ttdbserverdtexecdtloginradiusdradiusdradiusddtexecdttermprocldd : no such process : 24622dttermxmwlmdtwmdttermdtgreetdtexecttsessiondttermdtexecrdesktopprocldd : no such process : 34176javadtsessiondttermdtexecdtexec真棒!现在,我们以更简洁的方式显示相同的结果:# cat mand.out.txt | sort | uniq automountddtexecdtgreetdtlogindtsessiondttermdtwmjavaportmapradiusdrdesktoprpc.mountdrpc.statdrpc.ttdbserverttsessionxmwlm于是,我们得到了目前正在执行并加载了 libpthreads.a 库的二进制文件的排序列表。请注意,列出的进程只占当时系统中正在运行的进程的一小部分: # ps -e | wc -l 85接下来,我们看一下每个进程加载 libpthreads.a 的位置:# ps -e | grep java 34648 - 4:13 java# procmap 34648 | grep libpthreads.ad0049000 217K read/exec /usr/lib/libpthreads.ashr_xpg5.of03e6000 16K read/write /usr/lib/libpthreads.ashr_xpg5.od0045000 15K read/exec /usr/lib/libpthreads.ashr_comm.of03a3000 265K read/write /usr/lib/libpthreads.ashr_comm.o# ps -e | grep automountd 15222 - 1:00 automountd 25844 - 0:00 automountd# procmap 15222 | grep libpthreads.ad0049000 217K read/exec /usr/lib/libpthreads.ashr_xpg5.of03e6000 16K read/write /usr/lib/libpthreads.ashr_xpg5.od0045000 15K read/exec /usr/lib/libpthreads.ashr_comm.of03a3000 265K read/write /usr/lib/libpthreads.ashr_comm.od10ff000 194K read/exec /usr/lib/libpthreads.ashr.of0154000 20K read/write /usr/lib/libpthreads.ashr.o# ps -e | grep portmap 12696 - 0:06 portmap 34446 - 0:00 portmap# procmap 12696 | grep libpthreads.ad0045000 15K read/exec /usr/lib/libpthreads.ashr_comm.of03a3000 265K read/write /usr/lib/libpthreads.ashr_comm.od10ff000 194K read/exec /usr/lib/libpthreads.ashr.of0154000 20K read/write /usr/lib/libpthreads.ashr.o# ps -e | grep dtlogin 6208 - 0:00 dtlogin 6478 - 2:07 dtlogin 20428 - 0:00 dtlogin# procmap 20428 | grep libpthreads.ad0045000 15K read/exec /usr/lib/libpthreads.ashr_comm.of03a3000 265K read/write /usr/lib/libpthreads.ashr_comm.od0049000 217K read/exec /usr/lib/libpthreads.ashr_xpg5.of03e6000 16K read/write /usr/lib/libpthreads.ashr_xpg5.o请注意,每个进程每次都在相同的地址加载该库。不要为库中的 .o 的构成列表感到困惑。在 AIX 上,您可以共享归档库(通常是 .a 文件)以及动态共享库(通常是 .so 文件)。这样做的目的是能够在链接时绑定符号,就像传统的归档链接,但不需要将构成对象(归档中的 .o 文件)复制到最终二进制映像中。但是,不执行动态(或运行时)符号解析,动态共享库(.so/.sl 文件)也是如此。 还要注意,libpthreads.a 代码部分(那些标记为 read/exec 的部分)被加载到段 0xd 中。如上所述,该段在 AIX 中被指定为预留给共享库代码。也就是说,内核将该共享库的可共享段加载到在同一内核上运行的所有进程所共享的区域。 您可能注意到数据部分也加载到同一段中:共享库段 0xf。但是,这并不表示每个进程也共享 libpthreads.a 的数据部分。这一点没有明确定义(这样的安排方式无法正常工作),因为不同的进程将需要在不同的时间维护不同的数据值。段 0xf 对于每个使用 libpthreads.a 的进程是独立的,即使虚拟内存地址相同也是如此。svmon 命令可以显示进程在虚拟内存管理器中的段 ID (Vsid)。我们将看到共享库的代码段都具有相同的 Vsid,而共享库的数据段都具有不同的 Vsid。Esid 表示有效段 ID (Effective Segment ID),是位于进程地址空间范围内的段 ID(仅仅是术语,不要为此感到困惑)。# svmon -P 17314- Pid Command Inuse Pin Pgsp Virtual 64-bit Mthrd 16MB 17314 dtexec 20245 9479 12 20292 N N N Vsid Esid Type Description PSize Inuse Pin Pgsp Virtual 0 0 work kernel segment s 14361 9477 0 14361 6c01b d work shared library text s 5739 0 9 5786 19be6 f work shared library data s 83 0 1 87 21068 2 work process private s 56 2 2 58 18726 1 pers code,/dev/hd2:65814 s 5 0 - - 40c1 - pers /dev/hd4:2 s 1 0 - - # svmon -P 20428- Pid Command Inuse Pin Pgsp Virtual 64-bit Mthrd 16MB 20428 dtlogin 20248 9479 23 20278 N N N Vsid Esid Type Description PSize Inuse Pin Pgsp Virtual 0 0 work kernel segment s 14361 9477 0 14361 6c01b d work shared library text s 5735 0 9 5782 7869e 2 work process private s 84 2 10 94 parent=786be 590b6 f work shared library data s 37 0 4 41 parent=7531d 6c19b 1 pers code,/dev/hd2:65670 s 29 0 - - 381ae - pers /dev/hd9var:4157 s 1 0 - - 40c1 - pers /dev/hd4:2 s 1 0 - - 4c1b3 - pers /dev/hd9var:4158 s 0 0 - - 回页首执行计算看看目前共享段 0xd 中有多少空间。我们将再次使用 bc 计算器工具。理所当然,我们将验证段 0xd 的大小。# bc ibase=16E0000000-D0000000268435456ibase=A268435456/(10242)256看起来不错。如上所述,每个段为 256MB。接下来,看看目前使用了多少容量。 $ echo ibase=16; $(genkld | egrep 8 | awk print $2 | tr a-f A-F | tr n + ) 0 | bc39798104$ bc 39798104/(10242) EOF37也就是说,目前使用了 37MB。然后启动 XIr2,并进行比较: $ echo ibase=16; $(genkld | egrep 8 | awk print $2 | tr a-f A-F | tr n + ) 0 | bc266069692$ bc 266069692/(10242) EOF253现在使用了 253MB。这非常接近于限值 256MB。任意选择一个进程,如 WIReportServer,然后查看有多少共享库已放入共享空间,以及有多少共享库必须独立映射。因为我们了解共享段是从地址 0xd000000 开始的,因此我们可以将其从 procmap 的输出结果中筛选出来。请记住,只有代码段会映射到段 0xd 中,因此我们仅查找带有 read/exec 的行:$ procmap 35620 | grep read/exec | grep -v d10000000 10907K read/exec boe_fcprocd31ad3000 14511K read/exec/crystal/sj1xir2a/xir2_r/bobje/enterprise115/aix_rs6000/libEnterpriseFramework.so3167b000 3133K read/exec/crystal/sj1xir2a/xir2_r/bobje/enterprise115/aix_rs6000/libcpi18nloc.so3146c000 1848K read/exec/crystal/sj1xir2a/xir2_r/bobje/enterprise115/aix_rs6000/libBOCP_1252.so31345000 226K read/exec/crystal/sj1xir2a/xir2_r/bobje/enterprise115/aix_rs6000/btlat300.so看起来上面四个库无法映射到共享段。因此,它们映射到私有段 0x3 中,该私有段供通过调用 mmap() 例程分配的任何通用内存使用。 有几种条件会强制共享库独立映射到 32 位 AIX 上: 共享段 0xd 中的空间不足(如上所述)。 共享库没有组或其他角色的执行权限。您可以指定 rwxr-xr-x 权限来更正此问题;但是,开发人员将希望使用私有权限(例如 rwx-),这样他们就不必在每次重新编译和为测试而部署共享库时运行 slibclean。 一些文档说明共享库是通过 nfs 加载的。 如果同一个库来自不同的位置,那么 AIX 内核甚至会将该库两次加载到共享内存中:sj2e652a-chloe:/e652_rgenkld | grep libcplib.so d5180000 678c6 /space2/home/sj2e652a/e652_r/lib/libcplib.so d1cf5000 678c6 /home/sj1e652a/xir2_r/lib/libcplib.so回页首处理错误如果运行部署在不同目录中的 XIr2 的另一个实例,我们将看到进程占用内存有明显区别:$ ps -e -o pid,vsz,user,comm | grep WIReportServer28166 58980 jbrown WIReportServer46968 152408 sj1xir2a WIReportServer48276 152716 sj1xir2a WIReportServer49800 152788 sj1xir2a WIReportServer50832 152708 sj1xir2a WIReportServer帐户“jbrown”的实例首先启动,然后启动帐户“sj1xir2a”的实例。如果我们要执行一些微小、存在风险的操作,例如在我们的 bobje/setup/env.sh 文件中的适当位置进行设置: LIBPATH=jbrown/vanpgaix40/bobje/enterprise115/aix_rs6000:$LIBPATH在启动第二个实例之前,我们将看到内存占用恢复正常了(我改用进程 boe_fcprocd,因为在这项 LIBPATH 测试中无法启动 WIReportServer)。$ ps -e -o pid,vsz,user,comm | grep boe_fcprocd 29432 65036 jbrown boe_fcprocd35910 67596 jbrown boe_fcprocd39326 82488 sj1xir2a boe_fcprocd53470 64964 sj1xir2a boe_fcprocd我们看到 procmap 显示文件按预期从 jbrown 加载:53470 : /crystal/sj1xir2a/xir2_r/bobje/enterprise115/aix_rs6000/boe_fcprocd-name vanpg 10000000 10907K read/exec boe_fcprocd3000079c 1399K read/write boe_fcprocdd42c9000 1098K read/exec/home7/jbrown/vanpgaix40/bobje/enterprise115/aix_rs6000/libcrypto.so33e34160 167K read/write/home7/jbrown/vanpgaix40/bobje/enterprise115/aix_rs6000/libcrypto.so33acc000 3133K read/exec/home7/jbrown/vanpgaix40/bobje/enterprise115/aix_rs6000/libcpi18nloc.so33ddc697 349K read/write/home7/jbrown/vanpgaix40/bobje/enterprise115/aix_rs6000/libcpi18nloc.so回页首清理工作关闭应用程序后,共享库可能仍然驻留在共享段 0xd 中。在这种情况下,您可以使用实用工具“slibclean”卸载不再引用的任何共享库。该实用工具不需要参数:slibclean还可以使用实用工具 genld,在传递 -l 选项时,该工具可以显示类似于 procmap 的结果,但它会显示系统中的所有现有进程: genld -l有时,在运行 slibclean 后,您可能仍然无法复制共享库。例如:$ cp /build/dev/bin/release/libc3_calc.so /runtime/app/lib/cp: /runtime/app/lib/libc3_calc.so: Text file busy您可能已经运行了 slibclean,并且运行“genld l”时未显示任何进程加载了该库。但是系统仍然在保护该文件。您可以通过以下方法解除此限制:首先删除目标位置的共享库,然后复制新的共享库:$ rm /runtime/app/lib/libc3_calc.so$ cp /build/dev/bin/release/libc3_calc.so /runtime/app/lib/在开发共享库时,如果您要执行重复的编译、链接、执行和测试练习,您可以通过将共享库设置为只有所有者才能执行(例如,r_xr_r_)来避免在每个周期中运行 slibclean 的麻烦。这将导致您用于测试的进程单独地加载和映射您的共享库。但是,请确保让所有人都可以执行它(例如,产品发布时设为 r_xr_xr_x)。回页首总结我希望您能够
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 旅游民宿退房协议范本及清洁维护标准
- 理发店员工招聘与职业规划辅导劳务合作合同
- 跨学科研究生委托培养与技术转移转化合同范本
- 产业园区物业合同终止及产业创新服务协议
- 建筑工程合同审计与财务管理要点解析
- 企业核心技术人员竞业禁止补偿标准合同范本
- 离婚后共同财产分割与同居期间居住权益协议范本
- 签订国际贸易合同时的汇率风险管理与法律应对
- 离婚财产分割补充协议涉及遗产继承权与分割调整
- 通信工程施工合同签订所需的技术标准及通信保障协议
- 湘教版六年级下册科学实验报告单 (湘教版)
- 中小学数学专业常用词汇中英文对照
- 01第一章 井田概况及地质特征09.9
- 青岛汽轮机调速系统使用说明书
- 管理学原理(南大马工程)
- 初中语文系列 批注式阅读课件
- 六年级上册数学课件-1.3 包装的学问丨苏教版 (共19张PPT)
- 部编人教版五年级上册道德与法治全册课件
- 高血压护理查房ppt
- 全关节镜下FiberTape治疗后交叉韧带胫骨止点撕脱骨折课件
- 《临建布置方案》word版
评论
0/150
提交评论