本文研究了共享库如何在32位AIX 5L™(5.3)上占用内存,并演示了以下命令:

  • ps
  • svmon
  • slibclean
  • 禁止
  • 进程图
  • Genkld
  • 风格

本文讨论了进程的虚拟地址空间,以及内核共享库段,如何检查它们以及如何解释上述各种诊断实用程序的输出。 本文还讨论了如何诊断内核共享段已满的情况,以及解决该情况的可能方法。

在整个示例中,我们碰巧使用了软件产品Business Objects EnterpriseXir2®中的流程。 这是任意的,因为这些概念将适用于在AIX 5L上运行的所有进程。

评论

恰好我们都处于同一思维框架中,让我们回顾一下32位体系结构。 为此,我将采用最有用的“ bc”命令行计算器。

在32位处理器中,寄存器能够保存2 ^ 32个可能的值,

$ bc2^324294967296obase=162^32100000000

这是4 GB的范围。 这意味着在系统上运行的程序能够访问0到2 ^ 32-1范围内的任何功能或数据地址。

$ bc2^32 - 1 FFFFFFFFobase=102^32 - 1 4294967295

如您所知,现在任何操作系统都可能同时运行数百个程序。 即使他们每个人都能够访问4GB的内存范围,但这并不意味着他们每个人都有自己的4GB物理RAM分配。 那将是不切实际的。 而是,OS实施了一种复杂的方案,在中等数量的物理RAM与文件系统的指定为交换(或分页)空间的区域之间交换代码和数据。 而且,即使每个进程都能够访问4GB的内存空间,许多进程甚至都不使用其中的大部分。 因此,操作系统仅为每个特定进程加载或交换所需数量的代码和数据。

图1.虚拟内存的概念图

这种机制通常称为虚拟内存和虚拟地址空间。

运行可执行文件时,操作系统的虚拟内存管理器将查看组成文件的代码和数据,并决定将哪些部分加载到RAM中,或加载到交换文件中,或从文件系统中引用。 同时,它建立了一些结构以将物理位置映射到4GB范围内的虚拟位置。 这个4GB的范围代表了进程的最大理论范围,并且(有时也与代表它的VMM的结构一起)被称为进程的虚拟地址空间。

在AIX上,4GB虚拟地址空间分为16个256 MB的段。 这些段具有预定功能,下面描述其中一些功能:

  • 段0用于与内核相关的数据。
  • 段1用于代码。
  • 段2用于堆栈和动态内存分配。
  • 段3用于映射文件的内存,mmap的内存。
  • 段d用于共享库代码。
  • 段f用于共享库数据。

相比之下,在HP-UX®上,地址空间分为四个象限。 如果使用带有+ q3p启用+ q4p启用选项的chatr命令指定了第三象限和第四象限,则它们可用于共享库映射。

共享库的加载位置

共享库自然是要共享的。 更具体地说,二进制映像的只读部分(即代码(也称为“文本”))和只读数据(const数据以及可以写时复制的数据)可以一次加载到物理文件中。内存,并多次映射到需要它的任何进程中。

为了说明这一点,请使用一台正在运行的AIX机器,并查看当前正在加载哪些共享库:

> su
# genkld
Text address     Size Filed1539fe0    1a011 /usr/lib/libcurses.a[shr.o]d122f100    36732 /usr/lib/libptools.a[shr.o]d1266080    297de /usr/lib/libtrace.a[shr.o]d020c000     5f43 /usr/lib/nls/loc/iconv/ISO8859-1_UCS-2d7545000    161ff /usr/java14/jre/bin/libnet.ad7531000    135e2 /usr/java14/jre/bin/libzip.a
.... [ lots more libs ] ....
d1297108 3a99 /opt/rational/clearcase/shlib/libatriastats_svr.a
[atriastats_svr-shr.o]d1bfa100    2bcdf /opt/rational/clearcase/shlib/libatriacm.a[atriacm-shr.o]d1bbf100    2cf3c /opt/rational/clearcase/shlib/libatriaadm.a[atriaadm-shr.o]
.... [ lots more libs ] ....d01ca0f8     17b6 /usr/lib/libpthreads_compat.a[shr.o]d10ff000    30b78 /usr/lib/libpthreads.a[shr.o]d00f0100    1fd2f /usr/lib/libC.a[shr.o]d01293e0    25570 /usr/lib/libC.a[shrcore.o]d01108a0    18448 /usr/lib/libC.a[ansicore_32.o]
.... [ lots more libs ] ....d04a2100    fdb4b /usr/lib/libX11.a[shr4.o]d0049000    365c4 /usr/lib/libpthreads.a[shr_xpg5.o]d0045000     3c52 /usr/lib/libpthreads.a[shr_comm.o]d05bb100     5058 /usr/lib/libIM.a[shr.o]d05a7100    139c1 /usr/lib/libiconv.a[shr4.o]d0094100    114a2 /usr/lib/libcfg.a[shr.o]d0081100    125ea /usr/lib/libodm.a[shr.o]d00800f8      846 /usr/lib/libcrypt.a[shr.o]d022d660   25152d /usr/lib/libc.a[shr.o]

作为一个有趣的观察,我们可以立即在这台机器上看到Clearcase和Java™正在运行。 让我们采用这些通用库中的任何一个,例如libpthreads.a 。 浏览库,看看它实现了哪些功能:

# dump -Tv /usr/lib/libpthreads.a | grep EXP
[278]   0x00002808    .data      EXP     RW SECdef        [noIMid] pthread_attr_default
[279] 0x00002a68 .data EXP RW SECdef [noIMid]pthread_mutexattr_default
[280]   0x00002fcc    .data      EXP     DS SECdef        [noIMid] pthread_create
[281]   0x0000308c    .data      EXP     DS SECdef        [noIMid] pthread_cond_init
[282]   0x000030a4    .data      EXP     DS SECdef        [noIMid] pthread_cond_destroy
[283]   0x000030b0    .data      EXP     DS SECdef        [noIMid] pthread_cond_wait
[284]   0x000030bc    .data      EXP     DS SECdef        [noIMid] pthread_cond_broadcast
[285]   0x000030c8    .data      EXP     DS SECdef        [noIMid] pthread_cond_signal
[286]   0x000030d4    .data      EXP     DS SECdef        [noIMid] pthread_setcancelstate
[287]   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  ; done
portmap
rpc.statd
automountd
rpc.mountd
rpc.ttdbserver
dtexec
dtlogin
radiusd
radiusd
radiusd
dtexec
dtterm
procldd : no such process : 24622
dtterm
xmwlm
dtwm
dtterm
dtgreet
dtexec
ttsession
dtterm
dtexec
rdesktop
procldd : no such process : 34176
java
dtsession
dtterm
dtexec
dtexec

凉! 现在,让我们得到相同的结果,但是消除冗余:

# cat prev.command.out.txt | sort | uniq automountd
dtexec
dtgreet
dtlogin
dtsession
dtterm
dtwm
java
portmap
radiusd
rdesktop
rpc.mountd
rpc.statd
rpc.ttdbserver
ttsession
xmwlm

在那里,我们有了一个不错的,离散的,当前正在执行的二进制文件列表,并且都加载了libpthreads.a 。 请注意,此时此系统上的进程比该进程多得多:

# ps -e | wc -l   85

现在,让我们看看每个进程在哪里加载libpthreads.a

# ps -e | grep java34648      -  4:13 java
#
# procmap 34648 | grep libpthreads.a
d0049000         217K  read/exec      /usr/lib/libpthreads.a[shr_xpg5.o]
f03e6000          16K  read/write     /usr/lib/libpthreads.a[shr_xpg5.o]
d0045000          15K  read/exec      /usr/lib/libpthreads.a[shr_comm.o]
f03a3000         265K  read/write     /usr/lib/libpthreads.a[shr_comm.o]
#
# ps -e | grep automountd15222      -  1:00 automountd25844      -  0:00 automountd
#
# procmap 15222 | grep libpthreads.a
d0049000         217K  read/exec      /usr/lib/libpthreads.a[shr_xpg5.o]
f03e6000          16K  read/write     /usr/lib/libpthreads.a[shr_xpg5.o]
d0045000          15K  read/exec      /usr/lib/libpthreads.a[shr_comm.o]
f03a3000         265K  read/write     /usr/lib/libpthreads.a[shr_comm.o]
d10ff000         194K  read/exec         /usr/lib/libpthreads.a[shr.o]
f0154000          20K  read/write        /usr/lib/libpthreads.a[shr.o]
#
# ps -e | grep portmap              12696      -  0:06 portmap34446      -  0:00 portmap
#
# procmap 12696 | grep libpthreads.a
d0045000          15K  read/exec      /usr/lib/libpthreads.a[shr_comm.o]
f03a3000         265K  read/write     /usr/lib/libpthreads.a[shr_comm.o]
d10ff000         194K  read/exec         /usr/lib/libpthreads.a[shr.o]
f0154000          20K  read/write        /usr/lib/libpthreads.a[shr.o]
#
# ps -e | grep dtlogin6208      -  0:00 dtlogin6478      -  2:07 dtlogin20428      -  0:00 dtlogin
#
# procmap 20428 | grep libpthreads.a
d0045000          15K  read/exec      /usr/lib/libpthreads.a[shr_comm.o]
f03a3000         265K  read/write     /usr/lib/libpthreads.a[shr_comm.o]
d0049000         217K  read/exec      /usr/lib/libpthreads.a[shr_xpg5.o]
f03e6000          16K  read/write     /usr/lib/libpthreads.a[shr_xpg5.o]

请注意,每个进程每次都将其加载到相同的地址。 不要对库中.o的成分清单感到困惑。 在AIX上,您可以共享归档库(​​通常是.a文件)以及动态共享库(通常是.so文件)。 这样做的目的是能够在链接时绑定符号,就像传统的存档链接一样,但不要求将构成对象(存档中的.o文件)复制到最终的二进制映像中。 但是,与动态共享库(.so / .sl文件)一样,不执行动态(或运行时)符号解析。

还要注意libpthreads.a代码段(标记为已读/执行)已加载到段0xd中。 如上所述,该段在AIX上指定为共享库代码的段。 也就是说,内核将这个共享库的可共享段加载到由同一内核上运行的所有进程共享的区域中。

您可能会注意到,数据段也被加载到同一段:共享库段0xf。 但这并不意味着每个进程还共享libpthreads.a的数据部分。 松散地定义,这种安排将行不通,因为不同的流程将需要在不同的时间维护不同的数据值。 即使虚拟内存地址相同,段0xf对于使用libpthreads.a每个进程也是不同的。

svmon命令可以在虚拟内存管理器(Vsid)中为进程显示段ID。 我们将看到共享库代码段均具有相同的Vsid,而共享库数据段均具有不同的Vsid。 Esid表示有效细分ID,是流程地址空间范围内的细分ID(仅是术语;不要让您感到困惑)。

# svmon -P 17314-------------------------------------------------------------------------------Pid Command          Inuse      Pin     Pgsp  Virtual 64-bit Mthrd  16MB17314 dtexec           20245     9479       12    20292      N     N     NVsid      Esid Type Description              PSize  Inuse   Pin Pgsp Virtual0         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  16MB20428 dtlogin          20248     9479       23    20278      N     N     NVsid      Esid Type Description              PSize  Inuse   Pin Pgsp Virtual0         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=786be590b6         f work shared library data          s     37     0    4    41 parent=7531d6c19b         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=16
E0000000-D0000000
268435456
ibase=A
268435456/(1024^2)
256

看起来不错。 如上所述,每个段为256MB。 好的,现在让我们看看当前正在使用多少。

$ echo "ibase=16; $(genkld | egrep ^\ \{8\} | awk '{print $2}' | tr '[a-f]' '[A-F]' \|  tr '\n' '+' ) 0" | bc
39798104
$
$ bc <<EOF
> 39798104/(1024^2)
> EOF
37

也就是说,当前正在使用37MB。 让我们启动XIr2,并进行比较:

$ echo "ibase=16; $(genkld | egrep ^\ \{8\} | awk '{print $2}' | tr '[a-f]' '[A-F]' \|  tr '\n' '+' ) 0" | bc
266069692
$
$ bc <<EOF
> 266069692/(1024^2)
> EOF
253

现在使用了253MB。 这非常接近256MB的限制。 让我们选择一个随机过程,例如WIReportServer,看看有多少个共享库进入共享空间,以及有多少个必须私有映射。 由于我们知道共享段从地址0xd000000开始,因此我们可以将其过滤出procmap的输出。 请记住,只有代码段被映射到段0xd,所以我们只寻找可读取/执行的行:

$ procmap 35620 | grep read/exec | grep -v ^d
10000000       10907K  read/exec         boe_fcprocd
31ad3000       14511K  read/exec
/crystal/sj1xir2a/xir2_r/bobje/enterprise115/aix_rs6000/libEnterpriseFramework.so
3167b000        3133K  read/exec
/crystal/sj1xir2a/xir2_r/bobje/enterprise115/aix_rs6000/libcpi18nloc.so
3146c000        1848K  read/exec
/crystal/sj1xir2a/xir2_r/bobje/enterprise115/aix_rs6000/libBOCP_1252.so
31345000         226K  read/exec
/crystal/sj1xir2a/xir2_r/bobje/enterprise115/aix_rs6000/btlat300.so

似乎以上四个库无法映射到共享段中。 因此,它们被映射到专用段0x3,该段用于通过调用mmap()例程分配的任何常规内存。

有一些条件迫使共享库在32位AIX上私有映射:

  • 它在共享段0xd中空间不足(如上所述)。
  • 共享库没有组或其他的执行权限。 您可以使用rwxr-xr-x m的权限指定来纠正此问题; 但是,开发人员可能希望使用私有权限(例如rwx ------),因此不必在每次重新编译共享库并将其部署进行测试时都运行slibclean。
  • 一些文档说共享库是通过nfs加载的。

如果AIX内核来自不同的位置,它甚至会将同一个库两次加载到共享内存中:

sj2e652a-chloe:~/e652_r>genkld | grep libcplib.sod5180000    678c6 /space2/home/sj2e652a/e652_r/lib/libcplib.sod1cf5000    678c6 /home/sj1e652a/xir2_r/lib/libcplib.so

当出现问题时

如果运行在不同目录中部署的XIr2的另一个实例,则会发现进程占用空间存在显着差异:

$ ps -e -o pid,vsz,user,comm | grep WIReportServer
28166 58980   jbrown WIReportServer
46968 152408 sj1xir2a WIReportServer
48276 152716 sj1xir2a WIReportServer
49800 152788 sj1xir2a WIReportServer
50832 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_fcprocd
35910 67596   jbrown boe_fcprocd
39326 82488 sj1xir2a boe_fcprocd
53470 64964 sj1xir2a boe_fcprocd

我们看到procmap向我们展示了按预期从〜jbrown加载文件:

53470 : /crystal/sj1xir2a/xir2_r/bobje/enterprise115/aix_rs6000/boe_fcprocd
-name vanpg
10000000       10907K  read/exec         boe_fcprocd
3000079c        1399K  read/write        boe_fcprocd
d42c9000        1098K  read/exec
/home7/jbrown/vanpgaix40/bobje/enterprise115/aix_rs6000/libcrypto.so
33e34160         167K  read/write
/home7/jbrown/vanpgaix40/bobje/enterprise115/aix_rs6000/libcrypto.so
33acc000        3133K  read/exec
/home7/jbrown/vanpgaix40/bobje/enterprise115/aix_rs6000/libcpi18nloc.so
33ddc697         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)。

摘要

我希望您能够更详细地了解共享库如何占用内存以及用于检查它们的实用程序。 有了它,您将能够更好地评估应用程序的大小要求,并分析AIX系统上运行的进程的内存占用量的组成部分。


翻译自: https://www.ibm.com/developerworks/aix/library/au-slib_memory/index.html

aix 进程占用内存_AIX 5L上的共享库内存占用量相关推荐

  1. AIX 5L 上的共享库内存占用

    http://blog.chinaunix.net/uid-10218589-id-348867.html 级别: 初级 George Cross (george.cross@excite.com), ...

  2. oracle limsize,Oracle9i AIX上单进程占用内存过多问题

    Oracle9i AIX上单进程占用内存过多问题 作者:Piner 这个问题最早应当是gototop发现的,那已经是很多年以前的事情了,不过,一直到现在,这个问题其实没有最终解决,所以,这个补丁还是不 ...

  3. wsappx关不掉_win10系统下wsappx.exe进程占用内存大能关闭吗

    有不少win10系统用户在查看任务管理器的时候,发现有一个wsappx.exe进程占用内存大,但是又不知道wsappx.exe是什么进程,可以关闭吗?针对这个问题,小编这就给大家讲解一下win10系统 ...

  4. 查看linux每个进程占用内存多少,Linux下如何查看哪个进程占用内存多?

    1.top top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器 可以直接使用top命令后,查看%MEM的内容.可以选择按进程查看或者 ...

  5. 【修电脑】Windows11主机输入法不受控制频繁中英文切换/Vmmem进程占用内存大

    文章目录 [修电脑]Windows11主机输入法不受控制频繁中英文切换/Vmmem进程占用内存大 系统环境 问题描述 问题解决 题外话 [修电脑]Windows11主机输入法不受控制频繁中英文切换/V ...

  6. linux查看进程占用的内存大小,查看进程占用内存大小的几种方法,占用内存几种方法...

    查看进程占用内存大小的几种方法,占用内存几种方法 1. pmap -x pid 2. ps -aux | grep 进程名 ps -e -o 'pid,comm,args,pcpu,rsz,vsz,s ...

  7. Java进程占用内存超高分析

    Java进程占用内存超高分析_ 1. 报错 2. 解决 3. 我用到的解决方法 写了一个Java服务,没有定时服务,没有线程池,没有重度的读写,只是对外提供了几个接口,接口的访问量并不高,结果占用内存 ...

  8. Java进程占用内存过高,排查解决方法

    Java进程占用内存过高,排查解决方法 参考文章: (1)Java进程占用内存过高,排查解决方法 (2)https://www.cnblogs.com/eeexu123/p/10913389.html ...

  9. 电脑svchost进程占用内存

    近期电脑svchost进程占用内存超大,有时候会超过1G,于是在网上找了一些解决的办法. superfetch服务禁用, C:\Windows\SoftwareDistribution\Downloa ...

最新文章

  1. c#数据结构———二叉查找树
  2. linux正则表达式awk讲解
  3. e-cology在保险行业——泛微保险行业解决方案
  4. RH413-测试文件的a属性
  5. 使用SQLite3存储和读取数据
  6. [html] 如何设置打印尺寸?
  7. js获取request中的值_基于node.js的开发框架 — Koa
  8. [Git] warning: Clone succeeded, but checkout failed.
  9. 使用windows2008R2自带磁盘管理进行分区
  10. 数据库的海量数据的存储解析
  11. win10系统怎么改奇摩输入法_Yahoo!奇摩輸入法 1.1.2535 for Windows (32-bit) : 軟體王 2020 - 軟體資訊...
  12. android一键改机之真改机build.prop
  13. c语言迷宫算法入门,基于C语言实现的迷宫算法示例
  14. Why School Essay 写作指南
  15. java微信公众号上传永久素材,微信公众号开发-永久素材的上传
  16. iKuai软路由模拟环境搭建
  17. cannot be cast to
  18. C语言:约瑟夫环(简单版)
  19. 波许教授的《最后一课》有感
  20. JS通过List列表生成树结构

热门文章

  1. 增删改查测试场景(菜市场的大妈都能看懂)
  2. ANTLR4学习总结
  3. 有意思的软件需求漫画
  4. ☆ C/C++ 十进制转二进制
  5. 达内看软件工程师的职业规划
  6. Sjtu模板问题系列
  7. springboot校园交友网站
  8. zsh和bash的区别
  9. 华为 WATCH GT Cyber 智能手表 评测
  10. 地理坐标系与投影坐标系区别