반응형

- 출처

https://www.ibm.com/support/knowledgecenter/ko/SSYKE2_7.0.0/com.ibm.java.aix.70.doc/diag/problem_determination/aix_cmd_ps.html

https://www.ibm.com/support/knowledgecenter/ko/ssw_aix_71/com.ibm.aix.cmds4/ps.htm


프로세스의 ps 모니터링을 시작하려면 다음을 입력하십시오.


ps -fp <PID>


출력 내용은 다음과 같습니다.

UID     PID     PPID      C    STIME    TTY    TIME    CMD

user12  29730   27936    0    21 Jun   -      12:26   java StartCruise



이에 대한 설명은 다음과 같습니다.


UID

프로세스 소유자의 사용자 ID입니다. 로그인 이름은 -f 플래그 아래에 인쇄됩니다.


PPID

상위 프로세스 ID입니다.


PID

프로세스 ID입니다.


C

CPU 활용도로서, 프로세스가 실행 중이고 시스템 클럭 틱이 발생할 때마다 증분됩니다. 

스케줄러가 값을 매초 2로 나눠서 값이 줄어듭니다. 

sched_other 정책에서, CPU 활용도는 프로세스 스케줄링 우선순위를 결정하는 데 사용됩니다. 

큰 값이 CPU 집약적 프로세스를 나타내고 따라서 낮은 프로세스 우선순위를 갖는 반면, 작은 값은 입출력 집약적 프로세스를 나타내고 보다 높은 우선순위를 갖게 됩니다.

+

프로세스 또는 스레드의 CPU 사용량이며, 시스템 클럭이 째깍거리고 프로세스나 스레드가 실행 중임을 발견할 때마다 증가됩니다. 

값은 스케줄러에 의해 초당 2로 나뉘어져서 감소됩니다. sched_other 정책의 경우, CPU 사용량은 프로세스 스케줄링 우선순위를 판별하는 데 사용됩니다. 

큰 값은 CPU 집중 프로세스를 표시하며 결과적으로 프로세스 우선순위가 낮아지는 반면, 작은 값은 입출력 집중 프로세스를 표시하며 결과적으로 프로세스 우선순위가 높아집니다.



STIME

프로세스의 시작 시간입니다(시, 분, 초). 프로세스의 시작 시간은 ps 조회가 실행되기 24시간 이상 전에 시작됩니다(월, 일).


TTY

프로세스의 제어 워크스테이션입니다.


TIME

프로세스의 총 실행 시간입니다. 실행시간이 100분에 도달하면 시간이 mm:ss 또는 mmmm:ss 형식으로 표시되며, 이는 -o time 플래그를 사용할 때 표시된 형식과는 다릅니다


CMD

전체 명령 이름 및 해당 매개변수입니다.

아직 실행 중인 스레드를 확인하려면 다음을 입력하십시오







아직 실행 중인 스레드를 확인하려면 다음을 입력하십시오.


ps -mp <PID> -o THREAD


출력 내용은 다음과 같습니다.

    USER        PID   PPID     TID ST  CP PRI SC    WCHAN        F     TT BND COMMAND

    user12    29730  27936       - A    4  60  8        *   200001 pts/10   0 java StartCruise

           -      -      -   31823 S    0  60  1 e6007cbc  8400400      -   0 -

           -      -      -   44183 S    0  60  1 e600acbc  8400400      -   0 -

           -      -      -   83405 S    2  60  1 50c72558   400400      -   0 -

           -      -      -  114071 S    0  60  1 e601bdbc  8400400      -   0 -

           -      -      -  116243 S    2  61  1 e601c6bc  8400400      -   0 -

           -      -      -  133137 S    0  60  1 e60208bc  8400400      -   0 -

           -      -      -  138275 S    0  60  1 e6021cbc  8400400      -   0 -

           -      -      -  140587 S    0  60  1 e60225bc  8400400      -   0 -



이에 대한 설명은 다음과 같습니다.


USER

프로세스를 실행 중인 사용자의 이름입니다.


TID

각 스레드의 커널 스레드 ID입니다.


ST

다음과 같은 스레드의 상태입니다.


1) O - 존재하지 않습니다.

2) R - 실행 중입니다.

3) S - 휴면 상태입니다.

4) W - 스왑되었습니다.

5) Z - 취소되었습니다.

6) T - 중지되었습니다.


CP

스레드의 CPU 활용도입니다.


PRI

스레드의 우선순위입니다.


SC

일시중단 수입니다.


ARCHON

대기 채널입니다.


F

플래그입니다.


TAT

제어 중인 터미널입니다.


BAND

스레드가 바인드되는 CPU입니다.



반응형
반응형

au-mallocdebug.zip


AIX에서 메모리 릭을 디텍팅 하기 위해서는 다양한 툴들을 사용할 수 있지만 아래의 방법도 있으니 참고.


출처 : http://ieggstory.blogspot.kr/2007/12/aix-memory-leak.html




환경변수를 이용하여 malloc, free 를 추적할 수 있다.


MALLOCDEBUG=report_allocations,output:/tmp/alloc_output.txt

ex)
export MALLOCTYPE=debug
export MALLOCDEBUG=report_allocations,stack_depth:5,output:/tmp/alloc_output.txt

프로그램이 실행되는 동안 위의 환경변수가 설정되어 있는 경우 /tmp/alloc_output.txt
파일로 alloc, free 되는 정보가 출력된다. 프로그램이 실행되는 동안은 alloc,
free 할때마다 그 기록을 메모리상에 가지고 있다가 종료가 되면 해제되지
않은 alloc 정보만 /tmp/alloc_output.txt 로 출력된다.

더 자세한 사항은 AIX 5L Version 5.3 General Programming Concepts: Writing
and Debugging Programs 에 나와 있다. 





출처 : http://www.ibm.com/developerworks/aix/library/au-mallocdebug.html#list3


useage : format_mallocdebug_op.sh alloc_output.txt


위에서 출력된 출력 파일을 사용하여 memory leak에 대해서 일반 사용자가 보기 편하게 변경해주는 쉘 스크립트가 있다(다운로드 가능)

또한 OS 환경 변수 뿐만 아니라 관련 옵션들에 대해서도 위의 출처에 자세히 나와있음.


사용해보도록 하자.

반응형
반응형



출처 : http://blog.naver.com/PostView.nhn?blogId=bumsukoh&logNo=110114643995






안녕하세요!  이번에는 IBM AIX의 내부적인 Memory 관리 방법(Not human but machine doing that)과 모니터링 방법(Not machine but human doing that)에 대해 설명드리도록 하겠습니다.

 

저의 경우 매번 시스템 튜닝이나 모니터링하면서도 항상 헤갈리게 하는 Memory Management 부분입니다. 아마 모니터링 툴마다 보여주는 수치들의 의미때문에 그런것 같은데요.

전혀 모르것도 아닌것이 그렇다고 아는것도 아닌것이 아무 애매모호한 경우가 너무 많아서 이번에 쫑찍어 볼려고 합니다.

위에서 제가 설명드린 "모니터링 툴마다 보여주는 수치들의 의미가 다른부분"의 대표적인 예가 이런 경우일 것 같은데요.

vmstat의 page in, page out과 topas의 page in, page out  부분일텐데요. 잘 아실지 모르지만 이 두개가 의미하는 내용은 완전히 다릅니다. 모르셨던 분들은 황당하실텐데요.

 vmstat의 page in, page out은 말그대로 paging space(swap이라 보시면 되겠네요)로의 page in, page out 입니다. 즉 프로세스의 메모리 정보가 file system으로 내려가거나, 다시 메모리로 로딩하거나 하는 것이지요.

그런데 topas의 page in, page out은 file system과 매핑된 즉 file과 매핑된 page들에 대한 page in, page out에 대한 부분입니다. 이 중에는 paging space로의 page in, page out은 제외됩니다.

즉 Memory segment중 Persistent segment와 Client segment에 대한 page들이 in, out 되는 것이죠.

이렇게 다른 내용을 같은 내용으로 이해 한다면 잘못된 판단을 할 수 있겠죠.

이러한 이유로 AIX 내부적으로 Memory를 관리하는 방법과 모니터링에 대한 정확한 방법을 한번 정리하는 것이 이번 포스트의 목적입니다.

 

자, 그럼 AIX 내부적인 Memory 관리 방법에 설명하도록 하겠습니다.

 

AIX 뿐 아니라 모든 Unix 시스템은 가용한 Physical memory 보다 더 많은 양의 메모리 address를 효율적으로 할당할 수 있도록 하기 위해 Virtual memory를 사용합니다. 이건 Unix 시스템에 대해 아시는 분들은 모두 아시는 부분입니다. 문제의 발단은 여기서 부터 시작됩니다.

Virtual Memory를 사용함으로써 이를 효과적으로 관리하기 위한 각종 효율적인 방법들이 필요하게 됩니다. 그러면서 굉장히 복잡한 Memory management mechanism이 생겨나게 됩니다.

 

AIX 내부적인 Memory를 관리하는 방법을 알기 위해서는 다음의 기능들에 대해 숙지하고 있어야 합니다.

- Paging space 란 ?

paging space는 현재 Virtual memory상에는 존재하지만 현재 access 되고 있지 않는 데이터를 저장하기 위해 disk 공간으로 할당된 logical volume입니다.

이러한 logical volume을 일반적으로 우리는 paging space또는 swap space라고 부릅니다.

paging space라는 용어의 개념을 잘 알고 있어야 뒤에 나오는 각종 내용들에 대해 혼란이 없게됩니다.

System의 Physical memory(RAM)의 여유공간의 양이 적으면, 현재 사용하고 있지 않은 프로그램(프로세스)이나 데이터는 다른 activity 작업에게 메모리를 할당하기 위해 paging space로 이동되게 됩니다. 뭐.. 이 내용은 우리가 잘 알고 있는 swap에 대한 내용이라 할 수 있습니다. 그래서 paging space가 작게되면 프로세스들이 유실되게 되고, 이렇게 되면 paging space가 고갈되게 되면 System panic이 발생할 수 있습니다.

 

이러한 문제를 감지하게 되면 새로운 volume을 생성하여 paging space로 할당하거나 기존의 volume의 크기를 증가시켜 문제를 해결 할 수 있습니다.

 

이러한 paging space에는 paging space를 할당하기 위한 다양한 정책(Late, Early, Deferred등)과 paging space의 부족 시 paging space회수를 위한 다양한 방법(npswarn, npskill,nokilluid등)등이 있습니다. 해당 부분들은 필요 시 설명하도록 하겠습니다.

 

예전에는 작은 Physical memory 시스템에 과중한 업무들을 구동하다 보니 paging space에 대한 page in, page out이 지속적으로 발생하여 성능상의 문제가 빈번히 있었지만,

 

요즘은 Physical memory의 가격보다 안정적인 시스템 운영을 위해 충분한 Physical memory를 처음부터 확보하고 시스템을 운영하기 때문에 Paging space가 부족하여 System에 크게 문제되는 경우는 별로 없는것 같습니다. 

 

- Memory Segments 란 ?

AIX는 다양한 memory segment간에 기능들이 구분됩니다.

AIX의 VMM을 이해하기 위해 persistent,working 그리고 client segment들간의 차이점을 이해하는 것이 중요합니다.

 

Persistent segment는 disk상의 permanent storage location을 가집니다. Data나 execution programe의 file은 persistent segment에 매핑됩니다.

 

Working segment는 프로세스가 사용하는 동알 존재하는 일시적인 것입니다. 따라서 permanent disk storage에 위치를 가지지 않습니다.

프로세스 stack, data 영역이 working segment와 shared library text segment에 매핑됩니다.

 

Client segment는 remote file system에 위치한 permanent location을 네트워크를 통해 저장됩니다. CD-ROM과 JFS2 page들은 client segment 입니다.

 

Memory segment는 private으로 유지되거나 processor간 공유될 수 있습니다.

 

- VMM(Virtual memory manager) 란 ?

VMM은 System과 application에서 요청하는 메모리를 할당하는 역할을 담당합니다.

VMM을 통해 할당되는 segment들의 단위를 page라고 부릅니다. 이러한 page는 Physical memory나 필요 시까지 disk(paging space)에 위치됩니다.

이렇게 Physical memory와 disk(paging space)에 저장된 page들을 VMM이 관리하게 됩니다. 그래서 virtual memory의 양은 system의 실제 physical 메모리의 크기를 넘어 사용될 수 있습니다.

VMM의 기능 측면에서는 다음과 같은 성능 향상을 위한 기능을 가지고 있습니다.

- paging으로 인한 processor의 사용과 disk bandwidth를 최소화함

- 프로세스의 paging으로 인한 응답속도 저하를 최소화홤

 

AIX에서는 virtual memory segment는 4kb(4096byte) 단위로 page로 나뉘어집니다.

VMM은 이러한 page들에 대해 사용가능한 free list를 유지 관리합니다.

VMM은 현재 Physical memory상의 page들에 대해 free list로 재할당해야 할 page들을 찾기 위해 page-replacement algorithm을 사용합니다.

이 page-replacement algorithm은 virtual memory segment인 working segment와 비교하여 persistent 존재 비율 및 repaging등을 고려해야 합니다.

 

VMM은 할당되지 않은 page들의 최소양을 유지하기 위해 free 공간을 늘리고 이 공간을 free list에 할당하기 위한 page out과 page steal을 사용합니다.

 

- Paging mechanism 에 대해

Paging mechanism은 VMM이 page들의 free list를 관리하기 위한 방법입니다. 위에서 VMM이 page-replacement algorithm을 사용한다고 말씀드렸는데요. 이러한 것들이 Paging mechanism에 대한 하나의 방법입니다.

 

VMM은 안정적인 page fault를 가능하게 하기 위해 free memory page frame의 리스트를 유지합니다. 이러한 list가 바로 우리가 알고 있는 free list입니다.

 

여기서 page fault는 virtual memory address는 가지고 있으나 현재 physical memory에 해당 page가 없을 경우 발생합니다.

이러한 page fault는 보통 다음과 같이 두가지 유형이 있습니다.

new page fault로써 가장 처음 참조되어 physical memory가 없는 경우와 이미 page out된 page인 경우입니다. 즉 page fault가 발생하면 free list가 있는 경우 자동으로 해당 page에 대한 메모리를 바로 할당하게 됩니다.

 

메모리의 free list page의 수가 작게되면 page stealer가 발생하게 됩니다.

이 page stealer는 steal 대상 page들을 찾기 위해 Page Frame Table(이하 PFT) entry들을 평가하는 mechanism입니다.

PFT는 참고되고 있는 page와 수정된 page들을 표시하는 flag들을 가지고 있습니다.

Page stealer가 참고되고 있는 PFT내의 page를 찾게되면 해당 page를 steal하지 않습니다.

오히려 참조 flag를 reset 하게 됩니다. 다음번에 page stealer가 PFT에서 해당 page를 검사할때 해당 page가 참조되고 있지 않다면 해당 page는 steal 됩니다.

그리고 page stealer가 처음부터 참조되지 않은 page들 만나게 되면 바로 해당 page들을 steal됩니다.

 

PFT의 page가 참조되지 않고 modify flag가 설정되어있으면 해당 page가 memory에 위치한 후 변경되었다는것을 page stealer에게 표시하게 됩니다. 이러한 경우는 page steal 전에 page out이 호출됩니다. Page들이 working segment의 부분이라면 pageing space에 기록될것이며, 반면에 persistent segment의 부분이라면 disk의 permanent 위치에 기록될것입니다.

 

프로세스가 종료하게 되면 해당 프로세스의 working storage는 해제되며 메모리의 page들도 free가 되어 free list로 반환됩니다.  반면 프로세스에 의해 open된 file들은 메모리에 남아 있을수 있습니다.

 

- Memory load control mechanism 에 대해

Active virtual memory page들의 수가 Physical memory page들을 초과할 경우, Physical memory page내에 위치할 수 없는 page들을 위해 paging space를 사용하게 됩니다.

Application이 page out된 page들에 접근하게 되면 VMM은 paging space로 부터 해당 page들을 physical memory page로 로드하게 됩니다.

이때, free physical memory page의 수가 작게되면 paging space에서 page로 로딩하기 전에 physical memory내의 다른 또 다른 free page가 필요하게 됩니다.

VMM이 free 대상의 page를 찾게되면, 강제로 해당 page들은 paging space로 page out됩니다.

심각한 경우 VMM은 paging space로 부터 physical memory로 다른 page를 로딩하기 전에 항상 paging space로 page를 page out 해야 할 필요가 생길 수 있습니다.

이러한 경우는 thrashing이라 부릅니다. 이러한 thrashing 상황에서는 프로세스들은 dispatche(run queue에서 cpu 할당받음)되자 마자 page fault에 직면하게 됩니다. 그러면 프로세스들은 어떠한 중요 절차도 수행하지 못하게 될뿐 아니라 system의 성능은 떨어지게 됩니다.

 

OS들은 이러한 thrashing 상황이 시작되는지에 대한 감지하기 위한 memory load control mechanism을 가지고 있습니다.

thrashing이 감지되면 system은 active process들을 suspend 시키기 시작하고 새로운 process의 시작을 지연시키게 되며 이러한 작용이 thrashing으로 빠지는 것을 방지합니다.

 

- Page replacement algorithm 에 대해

free list 상의 page 수가 설정한 값(minfree)보다 낮을 경우 page replacement algorithm은 physical memory page를 free 시키기를 시도하게 됩니다. 이러한 page replacement algorithm은 free list상의 page수의 최대값(maxfree+8)보다 free list의 page가 확보될때까지 지속됩니다.

이러한 page replacement algorithm 수행의 기준이 되는 minfree, maxfree값을 적정하게 설정하는 것을 중요한 부분입니다.

보통 minfree값의 기본은 maxfree보다 8 작은 값이거나 memory pool(보통 CPU당 메모리 SUBPOOL이 있음)만큼 작은 값입니다.

maxfree는 VMM의 page steal을 중지시키게 하는 기준을 결정합니다. maxfree값은 다음과 같이 결정될 수 있습니다.

maxfree = lesser of (number of memory pages / 128) --> IBM 가이드 문서 내용입니다.

이러한 값들은 system의 memory를 모니터링하여 필요 시 재설정을 통해 성능을 튜닝할 필요가 있습니다.

 

 

그럼 AIX 내부적인 Memory 관리 방법이 이해되었다면, 이제는 모니터링 하는 방법에 대해 알아보겠습니다.

주요하게 사용하는 Memory 모니터링 툴에 대해 설명하겠습니다.

 

- vmstat

가장 효과적으로 사용할 수 있는 툴입니다.

vmstat에 나오는 메모리 항목을 위주로 설명드리도록 하겠습니다.

vmstat은 크게 kthr, memory, page, faults, cpu 이렇게 5개 대항목으로 정보를 출력합니다.

이 중 Memory 관리와 관련된 부분은 memory, page 부분이 되겠습니다.

 


 

각 항목에 대해 알아보겠습니다.

- avm

Active Virtual Memory를 말하며, access되는 virtual page의 수를 표시합니다. 때로 이것을 available memory로 잘못알고 있는 경우가 있습니다.

- fre

free list의 크기를 표시합니다. 실제 physical memory의 많은 영역이 file system data를 cache로 활용되기도 합니다. 따라서 해당 크기가 작다고 해서 꼭 비정상적인 것은 아닙니다.

- re

초당 reclaime한 page수입니다. 해당 page가 free list에 있고, 재할당되지 않았을때 해당 page에 page fault는 초기화를 위한 신규 I/O request가 없으므로 reclaim이 고려됩니다.

- pi

page in request의 수입니다. page fault에 의해 paging space에 paging되어 있는 page가 physical memory로 page되는 수입니다.

초당 지속적으로 5 page 보다 많은 값이 보이면 문제가 있는 것으로 볼 수 있습니다.

- po

page out 처리된 page 수입니다. 초당 paging space로 이동한 page들의 수를 말합니다. 해당 page는 더 많은 memory가 요청될때 VMM에 의해 paging space로 page out됩니다. page out된 page는 필요 시 page in 될 수 있습니다.

page out이 높으면 minfree와 maxfree 값과 paging allocation policy값인 PSALLOC값을 확인할 필요가 있습니다.

- fr

free 된 page의 수입니다. VMM이 메모리를 필요로 할때 VMM의 page-replacement algorithm이 steal 대상 page들을 결정하기 위해 PFT(Page Frame Table)을 scan하도록 합니다. page들이 마지막 scan이후에 참조되지 않았다면 해당 page는 steal될 수 있습니다.

- sr

page-replacement algorithm에 의해 scan이 이루어진 page를 표시합니다. page steal이 발생하면 physical memory내의 page들은 page steal 대상인지를 확인하기 위해 scan됩니다.

메모리의 과대사용을 확인하기 위해 fr에 비해 sr의 비율이 높은지 확인해야함 높은 비율은 page stealer가 steal하기 위한 메모리를 찾기위해 작업 부하가 발생하는 것을 의미합니다.

- cy

page-replacement algorithm이 steal할 page를 찾기위해 PFT(Page Frame Table) 전체를 scan한 횟수를 나타냅니다.

이 값이 0 보다 크면 심각한 memory부족을 의미합니다.

page-replacement algorithm은 maxfree+8 값 만큼 free list page를 확보하기 위해 PFT를 scan하게 되는데 이때 PFT를 한번 모두 scan한 후에도 free list page의 수가 maxfree+8 보다 작으면 계속적으로 page steal을 위한 scan이 발생하며 이미 scan한 page들을 만나게 되면 cy값은 1씩 증가하게 됩니다.

이렇게 scan하다 maxfree+8 값만큼 steal이 발생하여 free list가 증가하면 그때 비로서 cy값이 0으로 설정됩니다.

 

- topas

topas도 시스템 모니터링을 위해 유용한 툴입니다. 처음에 말씀드렸듯이 memory에 관련해서는 그 항목이 vmstat과 조금 달라 확실히 의미하는 바를 알고 있어야 혼선이 없습니다.

 


 

항목 중 paging, memory, paging space 부분이 memory와 관련된 항목입니다.

- Faults

faults 수입니다.

- Steals

초당 VMM에 의해 steal된 page수입니다.

- PgspIn

Paging space로 부터 읽어들인 page 수입니다. (일반적인 page in 입니다.)

- PgspOut

Paging space로 write된 page 수입니다. (일반적인 page out 입니다.)

- PageIn

초당 읽어들인 page 수입니다. (paging space로부터의 page in을 제외한 모든 page in, persistent segment에 대한 page in이 포함됩니다.)

- PageOut

초당 write 된 page 수입니다. (paging space로 page out을 제외한 모든 page out, ㅔpersistent segment에 대한 page out이 포함됩니다.)

- Sios

VMM에 의해 발생된(page stealer) 초당 input/output page의 요청 수입니다.

- Real

Megabyte 단위의 실제 physical memory의 크기를 보여줍니다.

- %Comp

Computational page에 할당된 real memory 량입니다.

- %Noncomp

Non-computational page에 할당된 real memory 량입니다.

- %Client

Remotely mounted file들에 대해 cache로 사용되는 메모리의 량입니다.

 

- svmon

svmon은 현재 시스템의 메모리 사용량에 대한 정보를 상세하게 확인할 수 있습니다.



 

위와 같이 전체 시스템의 memory 사용율이 나오게 됩니다.

 

- memory
     real memory의 사용율에 대한 정보 출력됩니다.
     - size : real memory frame의 수입니다.
     - inuse : page들을 포함하고 있는 frame의 수입니다.
     - free : 모든 memory pool의 free frame의 수입니다.
     - pin : pinned page를 포함하고 있는 frame의 수입니다.
     - virtual : working segment를 위한 system virtual space에 할당된 page 수입니다.
   - pg space
     쉽게 swap 대한 정보 출력합니다.
     - size : 전체 paging 공간 크기입니다.
     - inuse : 사용중인 paging 공간입니다.
   - pin
     고정 영역에 대한 상세 정보입니다.
     - work : 작업 세그먼트 페이지를 포함하는 page 수입니다.
     - pers : 영구 세그먼트 페이지를 포함하는 page 수입니다.
     - clnt : 클라이언트 세그먼트 페이지를 포함하는 page 수입니다.

- vmo

vmo는 memory관련된 튜닝을 위해 VMM setting을 위한 툴입니다.

vmo 에는 다양한 tuning parameter가 있으며, 이러한 parameter를 활용하여 시스템에서 메모리 관리에 관련된 효과적인 방법을 제시할 수 있습니다.

 

 

굉장히 다양한 parameter들이 있습니다. 흔히 접하게 되는 값들로는 maxclient%, maxfree, maxperm%, maxpin%, minfree, minperm%등이 있습니다.

vmo의 값 parameter에 대해서는 따로 포스팅하기로 하겠습니다.

 

이렇게 기본적으로 AIX에서 내부적인 memory관리를 이해하기 위한 내용과 모니터링 부분에 대해 알아보았습니다.

위의 내용을 기본으로 좀더 세부적인 메카니즘을 알아가 보시는 것도 재미있을것 같습니다.

반응형
반응형

출처 : http://wonmaum.net/bbs/board.php?bo_table=AIX&wr_id=2



CPU
. %sys + %user 가 80% 이상이면 병목으로 판단
- sys : kernel 부분이 수행되는 영역, 프로세스 스케줄링, I/O, drive, network과 관련
- wait : 디스크 I/O 작업이 끝날 때가지 기다리는 idle time
- user : 사용자 프로세스, application, database등
- idle
. 모니터링 명령어
# sar 1 5 : 1초 5회 평균 CPU 사용율
# sar -P ALL 1 5 : 각 Processor 별 사용율
# sar -q 1 5 : 시스템에서 사용한 평균 queue 및 process 표시
- runq-sz : 수행되고 있는 kernel thread의 평균 수
- %runocc : queue 가 실행된 시간의 백분율
- swpq-sz : wait 상태인 kernel thread의 평균 수
- swpocc : swap 상태인 시간의 백분율
# vmstat 1 5 : cpu 및 memory 사용율
- r : 수행중인 kernel thread 수
- b : swap에 대기중인 kernel thread 수
# ps aux
- %CPU : 프로세스가 수행된 후 사용한 CPU 시간을 전체 경과시간으로 나눈 백분율
- %MEM : 프로세스가 수행될 때 사용한 실 메모리 백분율
- SZ : 프로세스의 data 영역을 위해 할당된 virtual page size로 1Kbyte 단위
- RSS : 프로세스의 실 메모리 크기 1Kbyte 단위
Memory
. paging space In/Out이 10 이상이거나 page fault가 1000번 이상 발행하면 병목으로 판단
. memory 부족인지 user application이나 file cache에 의한 것인지 고려
- free : file cache나 프로세스가 사용하고 있지 않는 영역
- fie cache : 사용 가능한 메모리를 파일 작업시 I/O 성능 향상을 위해 cache로 사용
- paging(4KB) : 실 메모리가 부족한 경우 발생, 실 메모리에서 사용되지 않았던 영역을 디스크로 옮기고
그 부분을 free 영역으로 전환하여 process를 처리
- page fault : kernel이 필요한 data나 process의 페이지를 실 메모리에서 찾지 못하는 횟수
- page In : 필요한 page만큼 virtual memory manager(VMM)에 의해 paging space에서 read하는 초당 횟수
page out 값에 따라 발생하는 real I/O 값
- page Out : 실 메모리 free 영역 확보를 위해 VMM이 paging space에서 read out하는 초당 회수
page in 값에 따라 발생하는 real I/O 값
- page space In : paging 영역에서만 발생하는 page read
- page space out : paging 영역에서만 발생하는 page out
. 모니터링 명령어
# vmstat 1 5
- avm : 프로세스가 수행되는 동안 paging 공간에 할당된 active virtual page
- fre : VMM이 필요시 사용할 수 있는 memory free list
- re : page input/output list
- pi : paging space에서 read in 된 page
- po : paging space에서 read out 된 page
- fr : paged freed(page replacement)
- sr : page-replacement 알고리즘에 따라 page 찾기
- cy : page-replacement 알고리즘에 따른 clock cycle
# svmon -G
- memory : 실 메모리 사용 통계
. size
. inuse : 프로세스나 file cache로 사용되는 메모리
. free
. pin : pinned 영역에서 사용되는 메모리
. virtual : virtual 영역에 할당된 메모리
- pg sapce : paging 영역의 사용 통계
. size
. inuse
- pin : pinned 영역의 사용 통계
. work : working(프로세스) 메모리 중 pinned 영역에서 사용되는 메모리
. pers : persistent(file cache) 메모리 중 pinned 영역에서 사용되는 메모리
. clnt : client(NFS, cd) 메모리 중 pinned 영역에서 사용되는 메모리
- in use : 실 메모리 사용 통계
. work
. pers
. clnt
DISK I/O
. %iowait가 40% 이상이거나 사용자 application에 의해 특정 disk의 %tm_act가 70%를 초과하는 경우 병목으로 판단
- read : 초당 read 하는 데이터 크기 1Kbyte 단위
- write
- busy% : 디스크에 작업한 시간을 경과 시간으로 나눈 백분율
. 모니터링 명령어
# iostat
- %tm_act : 물리적 디스크에서 작업한 시간의 백분율
일반적으로 40%를 초과하게 되면 I/O를 완료하는 시간이 길어져 응답시간이 증가
- Kbps : 초당 디스크에 이동된 데이터 양 Kbype 단위
- tps : 초당 디바이스 드라이브 단계에서 해당 물리적 디스크로 I/O를 요청하는 횟수
- Kb_read : 물리적 디스크에 read한 양 Kbyte 단위
- Kb_wrtn : 물리적 디스크에 write한 양 Kbypte 단위
Network Traffic
. network bandwidth의 30% 이상을 사용하는 경우 병목으로 판단
- read
- write
. 모니터링 명령어
# netstat -m
# netstat -v
# netstat -ni
topas 명령어를 이용한 모니터링

1. CPU
. Kernel : CPU의 현재 사용량, 70이 넘어가면 점검 필요
. User : 각 프로세스들이 사용하는 CPU 사용량
. Wait : 처리 대기중인 프로세스의 양(10미만)
. Idle :
2. Memory
. Real,MB : 메모리의 실제 크기(MByte)
. %Comp : 현재 메모리 사용율이며, 높을수록 좋다
. %Noncomp : file cache로 할당된 영역
. %Client : aix의 file system을 위한 영역
3. Paging Space
. Size,MB : Paging Memory로 할당된 크기
. %Used : 사용중인 양, 낮을수록 좋다
. %Free
=================================================
# uname –amML : 서버 정보 확인
# uname -L : 서버 시리얼넘버 확인
# oslevel –s : OS버전확인(TL SP확인)
# instfix –i |grep ML(and SP) : OS버전 확인
# ls –al .*Com* : 패치 확인
# lsattr –El mem0 : 메모리 용량 확인
# topas : 시스템(프로세스, 메모리, 네트워크) 체크.
# lsdev –Cc disk : 디스크 확인
# lspv : 디스크 활성상태확인
# lsvg –l [볼륨그룹명] : 볼륩그룹 확인
# ifconfig – a : ip정보확인
# netstat –rn : 라우트 정보 확인 (디폴트게이트웨이 확인)
# ping [IP or Host Name] : ip 접근확인
# lsdev –Cc if : 네트워크 인터페이스 확인
# lsdev –Cc adapter : 네트워크 카드 확인
# lsdev –Cc pci : pci슬롯 확인.
# lscfg –v : FRU 확인. (lsdev –Cc, lsdev –P)
# lsconf : 장치정보
# df –k : 파일시스템 용량체크 [ -k (kilo bytes), -m (mega bytes), -g (giga bytes) ]
# lsdev –Cc processor : 프로세tm 수 확인
# ps –ef | grep [ Process Name or Pid] : 실행중인 프로세스 검색
# du –sk * : 하위 디렉토리 및 파일 용량정보 출력
=================================================
****************** IBM bundles install. ****************************
#vi /usr/sys/inst.data/user_bundles/MyBundle.bnd
I:sysmgt.websm.security. // write the file which you want to install.
#smitty easy_install
// select Mybundle which you've made and Enter.
lslpp -Lb Mybundle // verify whethere bundle was installed successfully.
smitty list_installed // verify what is installed in server.
******************** AIX 용량 확장하기 ******************************
lsvg rootvg
chfs -a size=+100M /
******************** AIX 네트워크 설정하기 **************************
smit chgenet
smitty mktcpip -> N/W interface 선택
******************** 파일셋 및 fix(AIX) 설치 여부 확인 **************
lslpp -l bos.adt.base // 파일 셋 인스톨 여부 체크
instfix -i -k "IY4390" // fix 설치 여부 체크

******************** AIX 데몬 재시작 ********************************
refresh -s inetd
startsrc -g inetd
IBM filesets 설치

#oslevel -r // OS 레벨 확인
#instfix -i|grep ML // 파일셋 버전별 설치 현황
#instfix -icqk 5300-02_AIX_ML|grep :-: // 업데이트가 필요한 filesets
download site.
www.ibm.com/servers/eserver/support/pseries/aixfixes.html
***************************** cd mount ************************************
#mount -vcdrfs -oro /dev/cd0 /mnt
#geninstall -d/dev/cd0 bos.alt_disk_install.rte // install fileset in cd.
lspv // see hard-drive information.
#bootlist -m normal hdisk1 hdisk13 // select which disk you want to boot
# bootlist -m normal -o // see which disk is on.
hdisk13

반응형
반응형

출처 : http://ttend.tistory.com/112



ㅇ 실제 메모리 용량 확인

서버가 사용하고 있는 물리적 메모리의 양은 다음 명령어로 확인할 수 있다.

# lsattr -El sys0 -a realmem

# lsattr -El sys0 -a realmem

realmem 31457280 Amount of usable physical memory in Kbytes False

31457280은 KB이며 /1024/1024 해보면 30G임을 알 수 있다

제일 뒤 "false"는 명령을 통해 변경될 수 없다는 의미이다. 


ㅇ paging space

paging space는 물리적 RAM의 추가설치에 대한 경제적 대안이다. 즉 디스크의 일부분을 RAM처럼 사용하면서 프로그램의 활성부분은 RAM에 위치시키고 비활성 부분은 paging space에 위치시켜서 프로그램이 사용하는 RAM의 용량을 늘릴 수 있기 때문이다. 

RAM과 paging space는 페이지 프레임이라는 4KB 섹션으로 나뉘어 있다. RAM에 있는 모든 페이지 프레임에 대해, paging space의 하나 이상의 페이지 프레임이 하드 디스크 상에 존재한다. 시스템이 더 많은 RAM을 필요로 할 때, 정보의 페이지 프레임은 RAM에서 나와 하드 디스크로 이동한다. 이를 페이지 아웃(paging out)이라고 한다. 반대로 디스크에 있는 정보가 RAM으로 이동하는 것을 페이지 인(paging in)이라고 한다


ㅇ 가상 메모리 관리자(VMM)

가상 메모리 관리자(VMM)이 페이지의 이동을 관리한다. VMM은 최근에 사용되지 않은 페이지 프레임을 선택해서 디스크의 paging space으로 옮긴다


ㅇ 스래싱(thrashing)

VMM이 막 사용되려던 페이지 프레임을 페이지 아웃한 경우, VMM은 이 페이지 프레임을 곧바로 페이지 인해야 한다. 시스템이 하고자 하는 작업을 수행하는 대신 RAM에 페이지 프레임을 넣고 꺼내는 데(shuffling in/out) 더 많은 시간을 소비할 때, 이 시스템은 스래싱 중이라고 말한다. 물리 메모리의 양이 적으면 스래싱을 자주 일으킬 수 있다. (시스템이 스래싱 중이라면 시스템의 응답이 느려지고 디스크의 불이 끊임없이 반짝거릴 것이다)


ㅇ 사용가능한 paging space

시스템은 사용 가능한 paging space량을 모니터링하고 있다. 사용 가능한 paging space량이 임계값(paging space 경고 레벨이라고 함) 아래로 떨어지면, 시스템은 모든 프로세스(커널 프로세스 제외)에 SIGDANGER 신호를 보내고 이 신호는 프로세스에게 정상적으로 종결하도록 지시한다.

빈 paging space량이 두 번째 임계값(paging space kill 레벨) 아래로 더 떨어지면, 시스템은 대부분의 paging space을 사용 중인 프로세스에 SIGKILL 신호를 보내고, 이 신호는 프로세스에게 강제적으로 종결하도록 지시한다.


ㅇ 기본 paging space

AIX를 설치하면, 설치 디스크(일반적으로 하드 디스크 hdisk0) 상에 paging space을 자동으로 작성한다. 

이 paging space의 이름은 항상 hd6이다. 

더 많은 paging space가 필요한 경우, hd6의 크기를 증가시키는 대신 새로운 paging space을 작성해야 한다. 


ㅇ paging space 확인

명령어 lsps로 확인할 수 있다

# lsps -a

Page Space      Physical Volume   Volume Group    Size %Used Active  Auto  Type

hd6             hdisk0            rootvg       10240MB     2   yes   yes    lv

위 그림에서 paging space는 hdisk0에 위치하고 현재 2%를 사용하고 있음을 알 수 있다.

만약 paging space을 두 개 이상 사용하고 있다면 lsps -s 명령어로 전체 paging space의 크기와 사용률을 알 수 있다


ㅇ paging space 경고

페이지 공간이 계속 70% 이상을 사용하고 메모리가 부족하면 단말에 다음과 같은 메시지가 표시된다. 

- INIT: paging space가 부족함 

- 메모리가 충분하지 않음 

- Fork 기능 실패 

- Fork() 시스템 호출 실패 

- Fork할 수 없습니다. 프로세스가 너무 많습니다. 

- Fork 실패 사용할 수 있는 메모리가 충분하지 않음 

- Fork 기능을 지원하지 않음. 사용할 수 있는 메모리가 충분하지 않음 

- Fork할 수 없음. 공간이 충분하지 않음


ㅇ paging space 설정 팁

- 디스크 당 둘 이상의 paging space을 갖지 않는 것이 좋다. paging space는 라운드 로빈(round-robin) 방식으로 할당되어 모든 페이징 영역을 동등하게 사용하기 때문에 하나의 디스크에 두 개의 페이징 영역이 있으면, 더 이상 활동을 여러 디스크에 전개할 수 없다. 

- paging space에는 많은 활동을 하지 않는 디스크를 사용하는 것이 유리하다. paging space는 다른 활동들과 경쟁하지 않을 때에 최상의 성능을 발휘할 수 있다. 

- paging space는 대략 같은 크기여야 한다. 라운드 로빈(Round-robin) 기법을 사용하므로 같은 크기가 아닐 경우, 사용의 균형이 맞지 않게 된다

- paging space을 여러 실제 볼륨으로 확장하지 않는 것이 좋다. 페이징 영역(일반 논리 볼륨처럼)을 여러 디스크에 걸쳐 전개할 수 있더라도, 라운드 로빈 (round-robin) 기법은 이 페이징 영역을 단일 페이징 영역으로 취급하므로, 이 활동은 디스크에 고르게 전개되지 않기 때문이다. 


------------------------------------------------------------------------------------------------------

출처 : http://blog.boxcorea.com/wp/archives/1458



1.현재 paging device 확인



2. swap 사용량확인




3. swap 추가하기
여기서는 foxvg에 1GB swap을 추가한다. foxvg의 PP size는 256MB 이다. 따라서 1GB 추가하려면, 4개의 LP를 사용한다.



4. 추가한 swap 사용하기
paging space를 사용하려면, swapon 커맨드로 swap을 활성화해준다.



5. swap 삭제하기
삭제전, swap 을 사용하지 않도록 설정한다.


6. 기타
chps : paging space의 속성을 변경할 때 사용한다.
예) 재부팅했을때, ps 사용하기



paging space 관련 화일: /etc/swapspaces






-----------------------------------------------------------------------------------------------

pageSpace 확장법 : http://serendipity777.tistory.com/155

Physical 메모리 100% 사용안하는 경우 : http://cafe.naver.com/aix/13491

실제 메모리를 많이 쓰는것 같지 않은데 메모리 사용률이 높게 나올때 : http://blog.naver.com/lyg1019?Redirect=Log&logNo=90126726851






반응형
반응형

출처 : http://estenpark.tistory.com/133



사실 여러가지 방법으로 메모리 확인 방법을 생각 해봤다.
ps -ef -o rssize,comm 으로 전체의 합을 전체 메모리를 나눠서 계산하는 방법을 했지만 정확한 데이터가 나오지 않았다.

관제 대상을 가지고 있는 어떠한 툴로 사용하면 좀 더 정확한 UI형식의 결과물을 볼 수 있을 수 있을 것이다.

소개하려는 명령어는  svmon 명령어 이다.
메모리의 현재 상태에 관련하고 실제 메모리의 스냅샵을 구성하는 것이 아니라 명령어의 인터럽트가 가능한 사용자 레벨에서 수행 가능 하다. 즉 root 권한만 수행 할 수 있는 명령어라고 할 수 있다.

중요한 개념을 잡아야 하는데 그 이유는  svmon명령어는 페이지 별로 통계 해준다는 것이다.

  • 1페이지 가상 메모리의 4K 블록
  • 1프레임은 실제 메모리의 4K 블록
  • 어떠한 명시가 없다면 기본적으로 통계는 4096바이트 메모리 페이지 단위


# svmon
1.
                   size               inuse               free           pin            virtual
memory          1831616        2028009           5412         391022       1082699
pg space         526500           5021

2.
               work               pers                   clnt
pin          390788             0                        234
in use      1082491           0                         945518

3.
PageSize       PoolSize         inuse           pgsp           pin                virtual
s   4 KB              -               1947705        4781           349758          1002187
m  64 KB             -                5019             25               2579               5032


* 수치는 임의대로 적어서 다릅니다.
  • 1번의 실제 메모리 사용 설명
    • 전체 사이즈 [ size ] : 1831616
    • 페이지 포함 프레임 수 [ inuse ] : 2028009
    • 모든 메모리 중 남은 공간(프레임수) [ free ] : 5412
    • 고정 페이지의 프레임 수 [ pin ] : 391022
    • 가상 영역의 할당된 페이지 수 [ virtual ] : 1082699
  • 2번의 실제 메모리의 서브세트
    • 작업 세그먼트 페이지를 포함하는 프레임 수 [ work ] : 390788
    • 영구 세그먼트 페이지를 포함하는 프레임 수 [ pers ] : 0
    • 클라이언트 세그먼트 페이지를 포함하는 프레임 수 [  clnt ] : 234
    • in use ( 사용중인 실제 메모리의 서브세트)
    • pin(고정된 페이지가 있는 실제 메모리의 서브세트)
  • 3번 페이지 공간의 사용을 설명하는 통계


svmon -G
시스템 전체 메모리 사용량 통계 확인

전체 메모리 사이즈는 1831616*4096byte/1024/1024 = 127MB.
Free Memory는 5412*4096/1024/1024 = 41MB


svmon -U root -d
root 사용자가 사용하는 메모리의 내역


svmon -C inetd
inetd 데몬에 의해 사용되는 메모리의 통계


svmon -P (pid)
프로세스 메모리 사용량 통계




메모리 스왑/실제 메모리 통계 스트립트

#!/usr/bin/csh
 
# Swap 점검
/usr/sbin/swap -l | /usr/bin/tail -1 |sed 's/MB//g' |awk '{printf"%0.0f\n",100-(($5/$4)*100)}'
 
# Real Memory 점검
# 계산방법: 100 - ( ( FreeSize / TotSize ) * 100
svmon -G |grep memory |perl -ane 'printf"%0.1f \n", 100 - ( ( $F[3] / $F[1] ) * 100 ) '
  • 위의 스크립트를 보면  awk처리와 perl 처리를 두가지 버전으로 만들어 봤다.
  • 둘다 장단점은 있지만 확실히 perl로 하는 것이 더 좋다는 생각이 든다.




참고한 자료
http://www.sung-ho.pe.kr/index.php?p=20391

반응형
반응형
출처 : http://blog.daum.net/hogi2271/10

AIX 5에서 공유 라이브러리 메모리 크기


   

난이도 : 초급

George Cross, 선임 소프트웨어 개발자, Business Objects Americas

옮긴이: 박재호 이해영 dwkorea@kr.ibm.com

2008 년 9 월 16 일

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비트 프로세서에서 레지스터는 2^32개의 가능한 값을 담을 수 있다.

	$ bc
	2^32
	4294967296
	obase=16
	2^32
	100000000


이 범위는 4기가바이트다. 이는 시스템에서 동작하는 프로그램이 0에서 2^32 - 1 범위 내에서 함수나 자료 주소에 접근할 수 있음을 의미한다.

	$ bc
 	2^32 - 1 
	FFFFFFFF
	obase=10
	2^32 - 1 
	4294967295


이미 알고 있듯이, 운영체제는 잠재적으로 수백 개에 이르는 프로그램을 동시에 돌릴 수 있다. 응용 프로그램 각각이 4GB 메모리 범위에 접근이 가능할지라도, 개별 프로그램마다 물리 RAM을 4GB만큼 할당 받는다는 뜻은 아니다. 이렇게 하기란 비현실적이다. 그 대신 운영체제는 적당한 물리 RAM과 스왑(또는 페이징) 영역으로 지정된 파일 시스템 사이에서 코드와 자료를 스와핑하는 복잡한 정책을 구현했다. 또한 각 프로세서가 4GB라는 메모리 영역에 접근이 가능할지라도, 대다수 프로세서는 이 영역을 완전히 사용하지 않는다. 따라서 운영체제는 특정 프로세스마다 요구하는 코드와 자료를 올리고 스왑하기만 하면 된다.


그림 1. 가상 메모리를 개념으로 설명하는 도식
가상 메모리 관리

이런 방법은 종종 가상 메모리나 가상 주소 공간으로 부른다.

실행 파일이 동작할 때, 운영체제에 들어있는 가상 메모리 관리자는 파일을 구성하는 코드와 자료를 살펴서 어느 부분을 램으로 올리고 어느 부분을 스왑으로 올리고 어느 부분을 파일 시스템에서 참조할지 결정한다. 동시에, 운영체제는 몇몇 구조체를 만들어 4GB 범위 내에서 물리 영역을 가상 영역으로 사상한다. 이 4GB 범위는 (종종 VMM 구조와 함께) 프로세스의 이론적인 최대 범위를 표현하며, 프로세스의 가상 주소 공간으로 알려져 있다.

AIX에서 4GB 가상 공간은 256메가바이트짜리 세그먼트 16개로 나뉜다. 세그먼트에는 미리 정해진 기능이 있다. 몇 가지를 정리해보았다.

  • 세그먼트 0: 커널 관련 자료
  • 세그먼트 1: 코드
  • 세그먼트 2: 스택과 동적 메모리 할당
  • 세그먼트 3: 사상된 파일을 위한 메모리, mmap으로 설정한 메모리
  • 세그먼트 d: 공유 라이브러리 코드
  • 세그먼트 f: 공유 라이브러리 자료

반면에 HP-UX®에서 주소 공간은 4분면으로 나뉜다. 3사분면과 4사분면은 +q3p enable과 +q4p enable 옵션을 켜서 chatr 명령을 내릴 경우 공유 라이브러리 사상 목적으로 사용이 가능하다.




위로


공유 라이브러리가 메모리에 올라오는 위치

당연한 이야기지만, 공유 라이브러리는 공유할 목적으로 만들어졌다. 좀 더 구체적으로 말하자면, 코드("텍스트"로 알려진)와 읽기 전용 자료(상수 자료, 기록 시점에서 복사 가능한 자료)를 포함한 이진 파일 이미지에서 읽기 전용 영역을 물리적인 메모리에 올리고 나면 이를 요구하는 프로세스에 여러 번 사상할 수 있다.

이를 확인하기 위해, AIX가 동작하는 기계를 구해 현재 메모리에 올라온 공유 라이브러리를 살펴보자.

> su 
# genkld
Text address     Size File

    d1539fe0    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-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.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 java
 34648      -  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 automountd
 15222      -  1:00 automountd
 25844      -  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 portmap
 34446      -  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 dtlogin
  6208      -  0:00 dtlogin
  6478      -  2:07 dtlogin
 20428      -  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]

각 프로세스는 libpthreads.a를 매번 동일 주소에 올린다는 사실에 주목하자. 라이브러리를 구성하는 목록에 현혹되지 말자. AIX에서는 동적 공유 라이브러리(보통 .so 파일)는 물론이고 아카이브 라이브러리(보통 .a 파일)도 공유할 수 있다. 이런 공유 기능은 전통적인 링크와 마찬가지로 링크 시점에서 심볼을 결정하지만 최종 이진 파일로 구성 목적 파일(아카이브에서 .o 파일) 복사가 필요하지 않다. 그렇기 때문에 동적 공유 라이브러리(.so/.sl 파일)와는 달리 동적(실행 중) 심볼 결정을 수행하지 않는다.

또한 read/exec로 표시된 libpthreads.a 코드 영역은 세그먼트 0xd에 올라왔다는 사실에 주목하자. 이 세그먼트는 앞서 언급한 바와 같이 공유 라이브러리를 위한 세그먼트로 AIX에서 지정되어 있다. 다시 말해 커널은 공유 라이브러리의 공유 가능한 세그먼트를 동일한 커널에서 동작 중인 모든 프로세스가 공유하는 영역에 올린다.

자료 섹션 역시 동일한 세그먼트(공유 라이브러리 세그먼트 0xf)에 위치한다는 사실을 눈치챘을지도 모르겠다. 하지만 이는 각 프로세스가 libpthreads.a의 자료 섹션까지 공유함을 의미하지는 않는다. 조금 느슨하게 정의해 보자면, 이런 배치는 동작하지 않는다. 각 프로세스 별로 다른 이름으로 다른 자료 값을 유지할 필요가 있기 때문이다. 물론 가상 메모리 주소는 동일할지 몰라도 세그먼트 0xf는 libpthreads.a를 사용하는 각 프로세스마다 다르다.

svmon 명령어는 프로세스에 대한 Vsid(가상 메모리 관리자에서 세그먼트 ID)를 보여준다. 공유 라이브러리 코드 세그먼트는 Vsid가 같지만, 공유 라이브러리 자료 세그먼트는 Vsid가 제각각이다. 유효 세그먼트 ID인 Esid는 프로세스의 주소 공간 범위 내에서 세그먼트 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=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에 사상된다는 사실을 기억하자. 따라서 read/exec 행만 살펴보면 된다.

$ 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

위에 나타난 네 가지 라이브러리는 공유 세그먼트로 사상될 수 없는 듯이 보인다. 필연적으로 네 가지 라이브러리는 mmap() 루틴을 호출해 할당한 범용 메모리로 쓰이는 내부 세그먼트 0x3에 사상되었다.

공유 라이브러리를 32비트 AIX에서 내부적으로 강제로 사상하기 위해서는 몇 가지 조건이 필요하다.

  • (위에서 발생한 상황처럼) 공유 세그먼트 0xd 영역이 꽉 차 있다.
  • 그룹과 다른 사람에 대한 실행 권한이 공유 라이브러리에 없다. 이런 문제를 해결하려면 접근 허가를 rwxr-xr-x로 지정하면 된다. 하지만 개발자들은 자신에게만 접근 허가를 주기를 원하므로(예: rwx------), 테스트 목적으로 공유 라이브러리를 컴파일해 배포할 때마다 sibclean을 돌릴 필요가 없다.
  • 몇몇 문서는 nfs 위에서 공유 라이브러리를 메모리에 올리면 이렇게 된다고 말한다.

AIX 커널은 동일한 라이브러리라도 다른 위치에서 시작했다면 공유 메모리에 두 번 올릴 것이다.

sj2e652a-chloe:~/e652_r>genkld | 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 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

메모리 사용량이 정규화된 상태를 확인할 것이다(이 LIBPATH 테스트에서는 WIReportServer를 시동할 수 없기에 프로세스 boe_fcprocd를 사용했다).

$ 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

또한 -l 옵션을 추가하면 procmap과 비슷한 결과를 보여주는 genld라는 유틸리티는 현재 시스템에 존재하는 모든 프로세스를 보여준다.

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 시스템에서 돌아가는 프로세스에 대한 메모리 사용량 구성 요소를 분석할 수 있을 것이다.



반응형
반응형

출처 : google "가상 메모리 관리 (AIX Virtual Memory Management) 검색 결과의 Doc 문서.


가상 메모리 관리 (AIX Virtual Memory Management)


Virtual Address Space

Virtual address space
란 프로세스가 참조하는 어드레스 범위이며, AIX에서는 16개의 Segment와 각 segment 256MB로 구성된다. 따라서 최대 4GB virtual address space를 가지고 있다. Kernel의 경우 virtual address space를 모두 사용할 수 있지만, Process의 경우에는 제한된 공간만 참조할 수 있다.

Demand Paging

Data
는 참조되는 순간에만 실제 Page(Real Memory 최소 관린 단위)에 복사되며, Mapping은 사용자가 인식할 수 없는 순간에 수행된다.

Data
:
    A page from the page space.
    A page from a file on disk.

AIX
에서는 kernel 또한 페이징을 사용하며, 페이징되지 않는 영역을 'pinned'라고 한다. 하지만, 대부분의 Kernel 영역은 페이징 영역을 사용하고 있다. Pager daemon은 실제 Page(Real Memory 최소 관린 단위) pool로 유지하기 위해, 사용 가능한 page 개수가 high-water mark 이하이면 low-water mark에 도달할 때 까지 가장 오래된 pager를 삭제하게 된다(LRU 알고리즘).

Memory Management Definitions

  • Page - 고정된 Memory의 최소단위(Size : 4096 bytes for AIX)
  • Paging Space - Inactive 상태인 메모리 페이지를 유지하기 위해 memory manager에 의해 사용되는 disk 공간
  • Real Memory - 시스템 내부에 장착된 실제 메모리
  • Virtual Memory - system memory manager에 의해 프로그램 및 프로세스에 주어진 메모리
  • Address Space - 메모리를 접근하는 프로그램에서 활용하는 address set

Virtual Memory

Virtual Memory 개념을 도입함으로써, 연속적인 address space를 가지는 사용자 프로그램이 대용량 메모리를 사용할 수 있으며 시스템의 physical memory 크기보다 큰 공간도 할당할 수 있다.


  • Virtual Memory Mapping
    H/W에 의해 이루어지며, 보통 실 메모리와 paging space에 펼쳐진다.
  • H/W & S/W에 의해 관리되는 최소 단위는 1Page 이며, Page Fault 발생시 Virtual Memory Manager virtual memory address를 사용하는 프로그램 및 프로세스에 page fault 발생한 내용을 보내기 위해 작업을 시작한다.

Hardware Address Translation

32bit virtual address

  • Segment register : 가장 앞 단의 4 bit( segment ID를 포함 )
  • Virtual page index : segment register이후의 16bit( segment page )
  • Byte offset : 마지막 12 bit( page offset )

2^4 = 16 ( 가장 앞 단위 4bit 16개의 segment register중 하나를 선택한다. )
2^28 = 256 MB(
segment 256 MB로 구성: virtual page index + byte offset )
2^12 = 4K(
page 단위는 4K )
16 segment * 256 MB/segment = 4 GB
2^32 = 4GB( 32 bit virtual address space )


    T=0 - Always 0 for memory space
    Ks - Supervisor-state protection key
    Kp - User-state protection key
    N - No-execute protection

64-bit Segment Table




Memory Segments

1.     각각의 Segment page 단위로 분리된다.

o    Segment는 프로세스간에 공유될 수 있다.

o    추가의 virtual page Segment mapping 될 수 있다.

o    이미 사용중인 segment는 프로세스로 지정될 수 도 있고 분리될 수 도 있다.

o    신규 segment는 프로세스에 의해 할당되거나 제거된다.

 

2.     Virtual address segment register로 구성된다.

3.     Segment type

o    Working: 프로그램 실행동안 stack/data 영역으로 사용되는 temporary memory

o    Persistent: Local file system을 위해 file data를 저장하는 memory

o    Client: NFS or CD-ROM과 같이 client file system를 위해 사용되는 memory

o    Log: Journalling 작업동안 file system이 쓰고 읽는데 사용되는 memory

o    Mapping: Application이 동일한 memory segment에 여러 object를 배치하도록 mmap() interface를 지원하기 위해 사용

 

4.     Virtual Page는 실제 memory page 또는 disk drive와 같은 이차 저장매체와 연관되어 있다.

5.     Memory Segment 종류

o    Kernel

o    User Text

o    Shared Library Text

o    Shared Data

o    Process Private

o    Shared Library Data

Segment Register Map in 32-bit User Mode

Segment
-----------------------------------------------------
 0x0         Kernel Segment (only parts visible)
 0x1         User Text
 0x2         User Data, Initial User Thread Stack
 0x3         Available for User (shmat, mmap)
 0x4-0xb     Available for User (shmat, mmap)
 0xc         Available for User (shmat, mmap)
 0xd         System Shared Library Text Segment
 0xe         Available for User (shmat, mmap)
 0xf         Pre-Process Shared Library Data Segment

Large Address Space Model in 32-bit

AIX
에서는 user data 영역으로 256MB 이상을 지원하며, 이 경우 maxdata binder option을 지정하여야 한다. 또한 Large user data 프로그램은 segment 3에서 malloc를 수행하여, 최대 8개의 segments(1020*1024*256*8, 2GB) 사용할 수 있다. 하지만 이 경우에도 여전히 segment 1 user text User Stack segment 2 256MB로 제한되며, segment 11 12 large address space model에 의해 사용할 수 없다.

Large Address Model Compile Option

기본 option으로 Compile을 하는 경우 하나의 Segment가 가질 수 있는 256MB 이상을 참조할 수 없다. 그래서 Large Address가 필요한 프로그램의 경우 아래와 같은 Option을 주어야 가능하다.

cc sample.o -bmaxdata:0x80000000 ->
필요에 따라 segment 개수를 변경할 수 있으며, 최대 8개의 segment를 지정할 수 있음.




-----------------------------------------------------------------------------------------------------------------


출처 : https://www.spec.org/mpi2007/flags/IBM-AIX.html


그렇다면 AIX 관련 컴파일 옵션 및 관련 설명을 보도록 하자.

IBM AIX: Environment Settings and Utilities

IBM AIX 5L V5.3

IBM AIX V6

Last updated: 04-Aug-2008

Sections

Selecting one of the following will take you directly to that section:


Optimization Flags

    • -bdatapsize:64K
    • -bdatapsize:64K\b
    • Specifies a non-default page size of 64K for the program data segment.

    • -bstackpsize:64K
    • -bstackpsize:64K\b
    • Specifies a non-default page size of 64K for the program stack segment.

    • -btextpsize:64K
    • -btextpsize:64K\b
    • Specifies a non-default page size of 64K for the program text segment.

    • -blpdata
    • -blpdata\b
    • Sets the bit in the file's XCOFF header indicating that this executable will request the use of large pages when they are available on the system and when the user has an appropriate privilege

    • -D__IBM_FAST_VECTOR
    • -D__IBM_FAST_VECTOR\b
    • The __IBM_FAST_VECTOR macro defines a different iterator for the std::vector template class. This iterator results in faster code, but is not compatible with code using the default iterator for a std::vector template class. All uses of std::vector for a data type must use the same iterator. Add -D__IBM_FAST_VECTOR to the compile line, or "#define __IBM_FAST_VECTOR 1" to your source code to use the faster iterator for std::vector template class. You must compile all sources with this macro.

    • -D__IBM_FAST_SET_MAP_ITERATOR
    • -D__IBM_FAST_SET_MAP_ITERATOR\b
    • The __IBM_FAST_SET_MAP_ITERATOR macro defines a different iterator for the std::vector template class. This iterator results in faster code, but is not compatible with code using the default iterator for a std::vector template class. All uses of std::vector for a data type must use the same iterator. Add -D__IBM_FAST_SET_MAP_ITERATOR to the compile line, or "#define __IBM_FAST_SET_MAP_ITERATOR 1" to your source code to use the faster iterator for std::vector template class. You must compile all sources with this macro.

    • -D_ILS_MACROS
    • -D_ILS_MACROS\b
    • Causes AIX to define "ischar()" (and friends) as macro's and not subroutines.


System and Other Tuning Information

  • drmgr -r -c cpu
  • Deconfigures one core from the active partition. Use it N times to deconfigure N cores.

  • smtctl -m on|off -w now|boot

  • Controls the enabling and disabling of processor simultaneous multi-threading mode.

  • vmo -r -o lgpg_regions=n -o lgpg_size=16777216

  • Sets the size of large pages to 16M, and set the number to use, with -r, takes effect on the next IPL.

  • bosboot -q

  • Regenerates the IPL boot to set the options specified with smtctl and vmo.

  • ulimit

  • Controls resources allowed to be used by processes. All resource are set to unlimited, of primary importance is the "stack" and "data/heap" settings for SPEC CPU2006 and MPI2007.

  • chsyscfg -m system -r prof -i name=profile,lpar_name=partition,lpar_proc_compat_mode=POWER6_enhanced

  • This command enables the POWERPC architecture optional instructions supported on POWER6.

    Usage: chsyscfg -r lpar | prof | sys | sysprof | frame
                    -m <managed system> | -e <managed frame>
                    -f <configuration file> | -i "<configuration data>"
                    [--help]
    
    Changes partitions, partition profiles, system profiles, or the attributes of a
    managed system or a managed frame.
    
        -r                        - the type of resource(s) to be changed:
                                      lpar    - partition
                                      prof    - partition profile
                                      sys     - managed system
                                      sysprof - system profile
                                      frame   - managed frame
        -m <managed system>       - the managed system's name
        -e <managed frame>        - the managed frame's name
        -f <configuration file>   - the name of the file containing the
                                    configuration data for this command.
                                    The format is:
                                      attr_name1=value,attr_name2=value,...
                                    or
                                      "attr_name1=value1,value2,...",...
        -i "<configuration data>" - the configuration data for this command.
                                    The format is:
                                      "attr_name1=value,attr_name2=value,..."
                                    or
                                      ""attr_name1=value1,value2,...",..."
        --help                    - prints this help
    
    The valid attribute names for this command are:
        -r prof     required: name, lpar_id | lpar_name
                    optional: ...
                              lpar_proc_compat_mode (default | POWER6_enhanced)
    
  • bindprocessor $$ <n>

  • The next program is to be bound to the specified processor.

    Environment variables set before the run:

  • MEMORY_AFFINITY=MCM

  • Cause the OS to alloc memory "closest" to the chip that first requests it.

  • XLFRTEOPTS=intrinthrds=1

  • Causes the Fortran runtime to only use a single thread.

  • MALLOCOPTIONS=POOL

  • Selects the OS malloc option that allocates/frees small objects very quickly.

실제 옵션들을 o 파일 컴파일 시 옵션으로 넣어서 컴파일 하니 256메가에서 프로그램이 메모리 할당에 실패했던 문제가 해소되었다.



반응형
반응형

아래의 명령어를 쳐서 설정으로 들어가자

AIX는 smitty라는걸로 OS설정을 꽤나 많이 하는 것 같다.


#smitty  tcpip


----------------------------------------------------------

Move cursor to desired item and press Enter.


  Minimum Configuration & Startup

  Further Configuration

  Use DHCP for TCPIP Configuration & Startup

  IPV6 Configuration

  Quality of Service Configuration & Startup

  Configure IP Security (IPv4)

  Configure IP Security (IPv6)

----------------------------------------------------------

위와 같은 설정들을 할 수 있다.


ifup이나 ifdown 같은것도 안 먹고 게이트 웨이 설정이나 dns 설정 어디서 하는건지 헤매다가 찾음...

CUI로 되어 있으며 방향키와 esc+명령 등으로 손쉽게 네트워크 관련 설정을 할 수 있다.


실제로 설정하다가 esc와 6키를 누르면 실제 해당 명령은 cmd 창에서 어떻게 명령어로 처리할 수 있는지도 나온다.

친절도 하셔라.... 설정하다가 안되면 에러 내용도 다양하게 확인할 수 있으니 참고!



라우팅 테이블 정보는 아래와 같이 확인할 수 있다.


netstat -rn

[root@/etc]#netstat -rn

Routing tables

Destination        Gateway           Flags   Refs     Use  If   Exp  Groups


Route Tree for Protocol Family 2 (Internet):

default              xx.xx.xx.xx        UG        0             991 en0      -      -

xx.xx.xx.xx         xx.xx.xx.xx         UHSb      0               0 en0      -      -   =>

.

.

.


Route Tree for Protocol Family 24 (Internet v6):

::1%1               ::1%1              UH         1       71496 lo0      -      -



반응형
반응형


갑자기 AIX 5.3 이 뻗었다.




errpt로 보니 

어느날 부터 갑자기 쌓이기 시작한 BA431EB7 ...


aix53:root@/] errpt

BA431EB7   0306172114 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306172014 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306171914 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306171814 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306171714 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306171714 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306171614 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306171514 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306171414 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306171314 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306171214 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306171114 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306171014 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306171014 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306170914 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306170814 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306170714 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306170614 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306170514 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306170414 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306170314 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306170314 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306170214 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306170114 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306170014 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306165914 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306165814 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306165714 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306165614 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306165614 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306165514 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306165414 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306165314 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306165214 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306165114 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306165014 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306165014 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306164914 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306164814 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306164714 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306164614 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306164514 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306164414 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306164314 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306164314 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306164214 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306164114 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306164014 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306163914 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306163814 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306163714 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306163614 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306163614 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306163514 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306163414 P S SRC            SOFTWARE PROGRAM ERROR

BA431EB7   0306163314 P S SRC            SOFTWARE PROGRAM ERROR

.

.

.


BA431E7 에러를 확인해보니 tracelogd 라는 모듈에서 발생.

---------------------------------------------------------------------------

LABEL:          SRC_RSTRT

IDENTIFIER:     BA431EB7


Date/Time:       Thu Mar  6 17:01:29 2014

Sequence Number: 2487335

Machine Id:      00C02F6A4C00

Node Id:         aix53

Class:           S

Type:            PERM

Resource Name:   SRC


Description

SOFTWARE PROGRAM ERROR


Probable Causes

APPLICATION PROGRAM


Failure Causes

SOFTWARE PROGRAM


        Recommended Actions

        VERIFY SUBSYSTEM RESTARTED AUTOMATICALLY


Detail Data

SYMPTOM CODE

       65024

SOFTWARE ERROR CODE

       -9035

ERROR CODE

           0

DETECTING MODULE

'srchevn.c'@line:'222'

FAILING MODULE

tracelogd

---------------------------------------------------------------------------




왜 그러는지는 아직 알수가 없다.


일단 추이를 지켜보고 정 안되면 해당 부분을 삭제하던지 아니면 정기적으로 errclear 0 을 하던지 해야할 듯..

혹시 해결 방안 아시는분 계시면 댓글 좀 ㅠㅠ




해당 모듈 삭제 관련 참고.

--------------------------------------------------------------------

BA431EB7 0000009 P S SRC SOFTWARE PROGRAM ERROR

Error:

BA431EB7 0000009 P S SRC SOFTWARE PROGRAM ERROR

Server1:root errpt -a -j BA431EB7 -s 0421030109 pg
---------------------------------------------------------------------------
LABEL: SRC_RSTRT
IDENTIFIER: BA431EB7
Date/Time:
Sequence Number: 917660
Machine Id:
Node Id:
Class: S
Type: PERM
Resource Name: SRC
Description
SOFTWARE PROGRAM ERROR
Probable Causes
APPLICATION PROGRAM
Failure Causes
SOFTWARE PROGRAM
Recommended Actions
VERIFY SUBSYSTEM RESTARTED AUTOMATICALLY
Detail Data
SYMPTOM CODE
589833
SOFTWARE ERROR CODE
-9035
ERROR CODE
0
DETECTING MODULE
'srchevn.c'@line:'217'
FAILING MODULE
tracelogd

Solution:

Need to uninstall the csm.hpsnm File Set.

Server1 /-->ps -ef grep tracelogd
root 7569408 2056434 0 00:54:49 - 0:00 /opt/csm/hpsnm/bin/tracelogd
root 7831764 7630990 0 00:55:33 pts/1 0:00 grep tracelogd


Server1 /-->lslpp -w /opt/csm/hpsnm/bin/tracelogd
File Fileset Type
----------------------------------------------------------------------------
/opt/csm/hpsnm/bin/tracelogd csm.hpsnm File


lslpp -l csm.hpsnm
Fileset Level State Description
----------------------------------------------------------------------------
Path: /usr/lib/objrepos
csm.hpsnm 1.4.1.12 COMMITTED IBM Switch Network Manager
Path: /etc/objrepos
csm.hpsnm 1.4.1.12 COMMITTED IBM Switch Network Manager

installp –u csm.hpsnm

Once we unistalled this Fileset. errpt stop generatting this error.








반응형
반응형

출처 : http://blog.naver.com/wonic?Redirect=Log&logNo=29195810



errclear 명령


목적

오류 로그에서 항목을 삭제합니다.


구문

errclear [ -d ErrorClassList ] [ -i File ] [ -J ErrorLabel [ ,Errorlabel ] ] | [ -K ErrorLabel [,Errorlabel ] ] [ -l SequenceNumber ] [ -m Machine ] [ -n Node ] [ -N ResourceNameList ] [-R ResourceTypeList ] [ -S ResourceClassList ] [ -T ErrorTypeList ] [ -y FileName ] [ -jErrorID [ ,ErrorID ] ] | [ -k ErrorID [ ,ErrorID ] ] Days


설명

errclear 명령은 Days 매개변수에서 지정한 일수보다 오래된 오류 로그 항목을 삭제합니다. 모든 오류 로그 항목을 삭제하려면, Days 매개변수에 0 값을 지정하십시오.


errclear 명령을 -i 플래그와 함께 사용하지 않으면, errclear는 오류 로그 구성설정 데이터베이스에서 지정한 오류 로그 파일을 지웁니다. (오류 로그 구성설정 데이터베이스내의 정보를 열람하려면,errdemon 명령을 사용하십시오)

주: errclear 명령은 지정된 항목은 삭제하나 오류 로그 파일의 크기를 줄이지는 않습니다.



웹 기반 시스템 관리자(wsm)에 있는 시스템 응용프로그램을 사용하여 시스템 특성을 변경할 수 있습니다. SMIT(시스템 관리 인터페이스 도구) smit errclear 단축 경로를 사용하여 이 명령을 실행할 수도 있습니다.


플래그

-d ListList 변수로 지정된 오류 클래스에 있는 오류 로그를 삭제합니다.List 변수 값을 ,(쉼표)로 분리하거나 " "(큰 인용 부호)로 묶어서 쉼표 또는 공백 문자로 분리할 수 있습니다. 유효한 List 변수 값은H(하드웨어), S(소프트웨어), O(errlogger 메시지) 및 U(판별되지 않음)입니다.
-iFileFile 변수에서 지정하는 오류 로그 파일을 사용합니다. 이 플래그를 지정하지 않으면, errclear 명령은 오류 로그 구성설정 데이터베이스로부터 값을 사용합니다.
-j ErrorID[,ErrorID]ErrorID(오류 ID) 변수에서 지정하는 오류 로그 항목을 삭제합니다.ErrorID 변수 값을 ,(쉼표)로 분리하거나 " "(큰 인용 부호)로 묶어서 쉼표나 공백 문자로 분리할 수 있습니다.
-JErrorLabelErrorLabel 변수에서 지정하는 오류 로그 항목을 삭제합니다.ErrorLabel 변수 값을 ,(쉼표)로 분리하거나, " " (큰 인용 부호)로 묶어서 쉼표 또는 공백 문자로 분리할 수 있습니다.
-k ErrorID[,ErrorID]ErrorID(오류 ID) 변수가 지정하는 오류 로그 항목 외에 모든 오류 로그 항목을 삭제합니다. ErrorID 변수 값을 ,(쉼표)로 분리하거나 " "(큰 인용 부호)로 묶어서 쉼표나 공백 문자로 분리할 수 있습니다.
-KErrorLabelErrorLabel 변수가 지정하는 오류 로그 항목 외에 모든 오류 로그 항목을 삭제합니다. ErrorLabel 변수 값을 ,(쉼표)로 분리하거나, " " (큰 인용 부호)로 묶어서 쉼표 또는 공백 문자로 분리할 수 있습니다.
-lSequenceNumber지정된 일련번호의 오류 로그 항목을 삭제합니다.SequenceNumber 변수 값을 ,(쉼표)로 분리하거나 " "(이중 인용부호)로 묶어서 쉼표 또는 공백 문자로 분리할 수 있습니다.
-m MachineMachine 변수가 지정하는 시스템에 대한 오류 로그 항목을 삭제합니다. uname -m 명령이 Machine 변수 값을 리턴합니다.
-n NodeNode 변수가 지정하는 노드에 대한 오류 로그 항목을 삭제합니다.uname -m 명령이 Node 변수 값을 리턴합니다.
-N ListList 변수로 지정된 자원 이름에 대한 오류 로그 항목을 삭제합니다.List 변수는 오류를 발견한 자원의 이름 리스트입니다. 소프트웨어 오류의 경우, 이들은 오류를 검출한 자원의 이름입니다. 하드웨어 오류의 경우, 이들은 장치나 시스템 구성요소의 이름입니다. 이는 부품에 장애가 있거나 교체가 필요함을 의미하지는 않습니다. 대신 오류를 분석하는데 사용될 적당한 진단 모듈을 판별하는 데 사용됩니다. List 변수 값을 ,(쉼표)로 분리하거나 " "(큰 인용 부호)로 묶어서 쉼표 또는 공백 문자로 분리할 수 있습니다.
-R ListList 변수로 지정된 자원 유형에 대한 오류 로그 항목을 삭제합니다. 하드웨어 오류의 경우, List 변수는 장치 유형입니다. 소프트웨어 오류의 경우, List 변수의 값은 LPP입니다. List 변수 값을 ,(쉼표)로 분리하거나 " "(큰 인용 부호)로 묶어서 쉼표 또는 공백 문자로 분리할 수 있습니다.
-S ListList 변수로 지정된 자원 클래스에 대한 오류 로그 항목을 삭제합니다. 하드웨어 오류의 경우, List 변수는 장치 클래스입니다. List 변수 값을 ,(쉼표)로 분리하거나 " "(큰 인용 부호)로 묶어서 쉼표 또는 공백 문자로 분리할 수 있습니다.
-T ListList 변수가 지정하는 오류 유형에 대한 오류 로그 항목을 삭제합니다. 유효한 List 변수 값은 다음과 같습니다. PERMTEMP,PERF, PENDINFO 및 UNKNList 변수 값을 ,(쉼표)로 분리하거나 " "(큰 인용 부호)로 묶어서 쉼표 또는 공백 문자로 분리할 수 있습니다.
-yFileNameFileName 변수가 지정하는 오류 레코드 템플리트 파일을 사용합니다.


보안

액세스 제어: 루트 사용자만 이 명령을 실행할 수 있습니다.


예제

  1. 오류 로그에서 전체 항목을 삭제하려면 다음을 입력하십시오.

    errclear 0
  2. 오류 로그에서 소프트웨어 오류로 분류된 모든 항목을 삭제하려면 다음을 입력하십시오.

    errclear -d S 0
  3. 대체 오류 로그 파일 /var/adm/ras/errlog.alternate에서 모든 항목을 제거하려면 다음을 입력하십시오.

    errclear -i /var/adm/ras/errlog.alternate 0
  4. 대체 오류 로그 파일 /var/adm/ras/errlog.alternate에서 모든 하드웨어 항목을 제거하려면 다음을 입력하십시오.

    errclear -i /var/adm/ras/errlog.alternate -d H 0


파일

/etc/objrepos/SWservAt소프트웨어 서비스 지원 속성 오브젝트 계층, 즉 오류 로그 구성설정 데이터베이스를 포함합니다.


반응형
반응형

출처 : http://blog.naver.com/xers1?Redirect=Log&logNo=140155690851


<errpt 참조화일등의 정보출력>

TESTSvr:/var/adm/ras> /usr/lib/errdemon -l
Error Log Attributes
---------------------------------------------
Log File                /var/adm/ras/errlog
Log Size                1048576 bytes
Memory Buffer Size      32768 bytes
Duplicate Removal       true
Duplicate Interval      10000 milliseconds
Duplicate Error Maximum 1000 

데몬은 /usr/lib/errdemon

TESTSvr:/var/adm/ras> ps -ef|grep errpt


    root   61586       1   0   Feb 19      -  0:00 /usr/lib/errdemon 
    root  106688       1   0   Feb 19      -  0:00 errpt -c -s 0219005512 -d H -T TEMP 
    root  184754       1   0   Feb 19      -  0:00 errpt -c -s 0219005512 -d H -T PERM

 

※참조 : http://cafe.naver.com/aix.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=14666& (IBM 카페)

 

 

<사용법>

#errpt -d H  (H/W error)
#errpt -d S  (S/W error)

#errpt -a : error (세부내용 보기)
#errpt -s 1015084110  (1015084110 이후에 발생한 에러 출력)
#errpt -d S -s 1015084110 -T PERM  (1015084110 이후에 발생한 SW 에러중 Permanent 에러 출력)
#errpt -d S -s 1015084110 -T PERF  (1015084110 이후에 발생한 SW 에러중 Performance 에러 출력)
#errpt -d H -s 1015084110 -T PERF  (1015084110 이후에 발생한 HW 에러중 Performance 에러 출력)

[출처] errpt 사용법 (AIX)|작성자 


반응형
반응형


dump 명령을 사용하면 실행파일이 런타임 링킹을 사용한 파일인지 아닌지 알아낼 수 있다. 

dump 명령과 -H 옵션으로 예제 프로그램 a.out에 대한 결과를 헤더정보와 함께 볼 수 있다.


어플리케이션에서는 모듈 func2.so의 심볼을 전혀 참조하지 않지만, 런타임 링킹 공유 오브젝트 func2.so가 의존 모듈 목록 (dependent module list)에 포함되어 있다. -brtl 옵션없이 실행파일을 컴파일하면, 의존 모듈 목록에 func2.so가 포함되지 않는다.


런타임 링커 (librtl.a의 아카이브 멤버 shr.o)가 의존 모듈 목록에 포함되어 있다.


$ dump -H a.out

.

.

.

***Import File Strings***

INDEX             PATH                                     BASE             MEMBER

0            /usr/lpp/xlopt:/usr/lib:/lib

1                                                             func1.so

2                                                             func2.so

3                                                             func3.so

4                                                             libc.a                 shr.o

5                                                             librtl.a                shr.o


실행파일 헤더에 기록된 런타임 링킹 공유 오브젝트의 순서는 실행파일을 만들 때 링커 명령어에서 오브젝트를 지정한 순서와 동일하다.

$ xlc main.c func1.so func2.so func3.so -brtl


dump 명령과 -Tv 옵션을 사용하면 어플리케이션이 참조한 심볼에 대한 정보를 볼 수 있다. 

위에서 가장 중요한 점은 func1.c의 func1이 호출하는 func3에 대한 진입점 (entry point)이 없다는 것이다.이전에 설명한 것처럼 모든 심볼은 프로그램을 링크할 때 해석이 되어야 하고, 해석된 심볼의 정보는 XCOFF 로더 섹션에 보여야 한다. 그러나 런타임 링킹의 경우 런타임 링커가 해석한 심볼은 XCOFF 로더 섹션에 보이지 않는다. .


$ dump -Tv a.out


[Index]        Value        Scn        IMEX            Sclass        Type                    IMPid            Name

[0]        0x20000448        .data                           RW         SECdef                 [noIMid]      __rtinit

.

.

.




공유 오브젝트 모듈 func1.so의 헤더정보를 보여주고 있다. 제일 마지막 줄의 .. 는 이 모듈 내의 해석되지 않은 심볼을 해석하려면 적어도 1개 이상의 런타임 링킹 공유 오브젝트가 필요함을 의미한다.



$ dump -H func1.so

func1.so:


***Import File Strings***

INDEX                PATH                                 BASE                                             MEMBER

0                   /usr/lib:/lib

1                                                                 .....


$ dump -Tv func1.so

의존하는 공유 오브젝트 모듈 func1.so의 로더 섹션 정보를 보여준다. 이 모듈에는 반입된 심볼 printf, func3 가 있다20. IMPid 컬럼의 .. 는 프로그램을 로드할 때 런타임 링커가 심볼을 해석하게 됨을 의미한다.


main 프로그램을 런타임 링킹 공유 오브젝트로 만들려면 다음과 같은 과정을 따른다.(볼드처리 된 부분 및 명령어 옵션은 달라질 수 있다)

$ xlc -c main.c func1.c func2.c func3.c

main.c:

func1.c:

func2.c:

func3.c:


$ ld -G -o main.so main.o -bexpall

ld: 0711-327 WARNING: Entry point not found: __start


$ ld -G -o func1.so func1.o -bnoentry -bexpall

$ ld -G -o func2.so func2.o -bnoentry -bexpall -lc

$ ld -G -o func3.so func3.o -bnoentry -bexpall -lc

$ xlc -o a.out main.so func1.so func2.so func3.so -brtl


LIBPATH를 지정하면, 프로그램은 다음과 같은 결과를 보여준다.

$ export LIBPATH=$PWD

$ ./a.out

within function func1 at line number: 7 in func1.c

within function func3 at line number: 7 in func3.c


a.out 의 참조 심볼 정보를 보고자 한다면 아래의 dump 옵션으로 확인할 수 있다.

$ dump -Tv a.out

 

어플리케이션에서 필요로 하는 모든 공유 오브젝트를 런타임 링킹 가능하도록 만드는 일은 기술적으로는 가능하지만, 어플리케이션의 성능 때문에 이렇게 하지 않는 편이 좋다. 일반적으로 AIX 아키텍쳐를 최대한 활용하려면 공유 모듈은 가능한 스스로를 포함하는 방식이어야 한다. 런타임 링킹은 반드시 필요한 때만 사용하는 편이 좋다. 다른 벤더의 UNIX 시스템에서 가져와서 포팅한 어플리케이션의 경우는 이러한 종류의 구성방식을 따르지 않기 때문에 AIX에서 구동하려면 포팅에 좀더 수고가 들게 된다. 모듈간에 인터페이스를 잘 정의해서 어플리케이션이 잘 조직된 구조로 만들어졌을 때 AIX에서 가장 좋은 성능을 발휘할 수 있다.


-brtl 링커 옵션을 써서 런타임 링크 방법으로 실행파일을 링크하면, 링커는 심볼 해석을 위해 공유 오브젝트와 라이브러리를 찾는데 이때 확장 탐색 순서 (extended search order)를 사용한다. 이러한 확장 탐색 순서를 사용하려면 런타임 링킹 공유 오브젝트는 libname.so 와 같은 방식의 이름을 가져야 한다.


-brtl 링커 옵션을 지정하면 링커는 libname.a와 libname.so를 찾게 되는데, -L 옵션으로 지정한 디렉토리와 디폴트 디렉토리(/usr/lib 와 /lib)에서 찾는다. libname.a 이름을 지정하는 것처럼 -l 옵션을 써서 libname.so 도 지정할 수 있다.


예를 들어 /project/lib 디렉토리에 저장되어 있는 런타임 링킹 공유 오브젝트 libfunc1.so와 a.out 을 링크할 때 오브젝트를 지정하기 위해 다음과 같은 방법을 사용할 수 있다. libname.so 와 같은 형식의 이름으로 하려면 런타임 링킹 공유 오브젝트의 이름을 이러한 방식으로 바꾸던가 라이브러리로 파일을 아카이브하면 된다.


1. xlc main.c /project/lib/libfunc1.so -brtl 이 방법은 런타임 링킹 방법의 이점을 약화시킨다. 프로그램을 실행할 때 /project/lib 디렉토리에 libfunc1.so이 있어야 하고, 프로그램을 로드할 때 libfunc1.so을 로드하게 된다.


2. cp /project/lib/libfunc1.so .; xlc main.c libfunc1.so -brtl 모든 런타임 링킹 공유 오브젝트가 현재 디렉토리에 있을 때 이러한 방법은 매우 유용하다. 그러나 한번 이렇게 고정된 방식으로 프로그램을 만들고 나면 특정 디렉토리에 계속 파일을 두어야 하는 불편한 점이 있으므로 세 번째 방법이 더 좋다.


3. xlc main.c -lfunc1 -L/project/lib -brtl 런타임 링킹 방법을 이용하여 파일을 생성할 때 가장 추천할 만한 방법이다. 




반응형
반응형


런타임 링킹을 사용하려면, 주 프로그램과 링크하기 이전에 이미 런타임 링킹 공유 오브젝트를 만들어 놓아야 한다. 런타임 링킹 공유 오브젝트를 만들려면 다음과 같다.


1. 소스 파일을 컴파일 한 다음 오브젝트 파일을 만든다.

2. -G 링커 옵션을 사용하여 오브젝트 파일을 다시 링크시킨 다음 런타임 링킹 공유 오브젝트 (.so)를 만든다.

(여러 오브젝트 파일로 한 개의 런타임 링킹 공유 오브젝트를 만들 수 있다.)

3. 런타임 링킹 공유 오브젝트를 라이브러리 아카이브(libname.a)에 넣는다. 이 과정은 필수과정은 아니다.


특정 옵션을 사용한다는 점만 제외하고, 위 과정은 보통의 공유 오브젝트를 만드는 과정과 동일하다.


func1.c, func2.c, func3.c 세 개의 파일로 런타임 링킹 공유 오브젝트를 만들려면 다음과 같이 하면 된다.

$ xlc -c func1.c func2.c func3.c

func1.c:

func2.c:

func3.c:

$ ld -G -o func1.so func1.o -bnoentry -bexpall

$ ld -G -o func2.so func2.o -bnoentry -bexpall -lc

$ ld -G -o func3.so func3.o -bnoentry -bexpall -lc

$ ls *.o *.so

func1.o func1.so func2.o func2.so func3.o func3.so


위 예제에서 사용한 링커 옵션은 다음과 같다.


-bnoentry

결과파일에는 시작위치(entry point)가 없다. 필요한 심볼을 유지하려면 -u 플랙을 사용하거나 반출파일을 사용해야 한다. -r, -bnogc, -bgcbtpass 옵션을 사용하면 오브젝트 파일에 모든 반출 심볼을 유지할 수 있다. -bnoentry 옵션이나 -bnox 옵션 중 어느것도 사용하지 않으면 시작위치(entry point)를 찾지 못하므로 경고메시지가 나온다.


-bexpall

반입심볼, 아카이브 멤버의 참조되지 않은 심볼, _로 시작하는 심볼을 제외하고 모든 전역심볼을 반출한다. 반출파일에 심볼을 명시하면 더 많은 심볼을 반출할 수 있다. 이 옵션은 -bautoexp 옵션으로 반출한 심볼에 영향을 주지 않는다. 이 옵션은 AIX 4.2 이후 버전에서만 적용된다.

이 옵션을 사용하면 반출파일을 따로 사용하지 않아도 된다. 그러나 반출파일을 사용하면 어떤 심볼을 반출할 지에 대해 확실히 지정할 수 있으며, 공유 오브젝트안의 전역심볼을 사용할 때 다른 공유 오브젝트에서 반출된 심볼과 충돌이 일어날 염려를 줄여줄 수 있다. 디폴트는 -bnoexpall 이다.


-lc

참조할 라이브러리를 지정한다. func2.o나 func3.o의 경우 printf()같은 심볼을 해석하려면 표준 C 라이브러리를 지정해야 한다. func1.o의 경우 func3함수를 호출하는 외에는 다른 함수를 호출하지 않기 때문에 라이브러리를 지정하지 않아도 된다.


-G

-G 링커 옵션을 사용하면 아래의 모든 옵션을 지정한 것과 동일하게 된다. 컴파일러 드라이버도 -G 옵션이 있다. 오브젝트 파일로 런타임 링킹 공유 오브젝트를 만들 때 컴파일러의 -G 옵션을 사용하지 마시오.


 옵션

 설명

 -berok

 해석하지 못한 심볼이 있어도 억지로 오브젝트 파일을 생성한다.

 -brtl

 런타임 링킹을 가능하게 한다. 명령행에서 나열한 모든 공유 오브젝트 (아카이브 멤버가 아닌 파일들)는 출력파일에 나열된다. 어플리케이션 프로그램을 시작할 때 시스템 로더는 모든 공유 모듈을 로드하고, 이 공유 오브젝트에서 반출된 심볼은 런타임 링커에서 사용된다.

 -bsymbolic

 특별히 특성을 지정하지 않고 심볼을 반출한 경우 심볼에 특성을 할당한다.

 -bnoautoexp

 런타임 링커 라이브러리에 대한 참조를 제거한다. -G 옵션으로 만든 모듈(-bnortllib 옵션을 포함한다)을 런타임 링킹시 활성화시키지만, 런타임 링커 라이브러리에 대한 참조는 제거된다. 런타임 라이브러리는 주요 실행파일과 링크할 때만 참조되어야 한다.

 -bnoautoexp

 심볼이 자동으로 반출되지 못하도록 한다.

 -bM:SRE

 공유(shared)되면서 다시 사용할 수 있는(reusable) 상태로 모듈을 만든다.



런타임 링킹 공유 오브젝트와 링크시켜서 프로그램을 만들려면 다음 과정을 따라야 한다.

1. main() 함수를 포함하는 소스 프로그램을 컴파일하여 오브젝트 파일을 만든다.

2. -G 링커 옵션으로 오브젝트 파일을 다시 링크시켜서 런타임 링킹 공유 오브젝트 (.so)를 만든다.

3. main 소스 프로그램과 런타임 링킹 공유 오브젝트를 -brtl 링커 옵션을 사용하여 링크한다.


main()이 포함된 소스 프로그램으로 만든 오브젝트 파일이 런타임 링킹 기능이 활성화되어 있지 않다면 다음과 같은 작업을 해줘야 한다.

적절한 컴파일러 드라이버를 사용해서(링커가 아니다) main()을 포함하는 소스 프로그램을 컴파일한 다음 -brtl 옵션을 사용하여 런타임 링킹 공유 오브젝트 파일과 링크시켜야 한다.


예제에서는 좀더 간단한 방법으로 a.out 을 만들었다.

$ ls *.o *.so

func1.o func1.so func2.o func2.so func3.o func3.so

$ xlc main.c func1.so func2.so func3.so -brtl

$ ls a.out

a.out

프로그램을 실행하면 의존하는 모듈인 func1.so를 시스템 로더가 찾을 수 없기 때문에 프로그램은 다음과 같은 에러메시지를 내보내며 수행되지 않는다.


$ ./a.out

exec(): 0509-036 Cannot load program ./a.out because of the following errors:

0509-150 Dependent module func1.so could not be loaded.

0509-022 Cannot load module func1.so.

0509-026 System error: A file or directory in the path name does not exist.


LIBPATH 값이 정의되어 있다면 다음처럼 동작할 것이다.

$ export LIBPATH=$PWD

$ ./a.out

within function func1 at line number: 7 in func1.c

within function func3 at line number: 7 in func3.c


컴파일러 드라이버(xlc)대신 링커 명령(ld)을 사용하면 다음과 같다.

$ xl-c main.c

$ ld main.o func1.so func2.so func3.so -brtl


생성한 실행파일이 필요한 시작(startup) 루틴을 가지고 있지 않기 때문에 다음과 같은 에러를 발생시킨다.

$ export LIBPATH=$PWD

$ ./a.out

exec(): 0509-036 Cannot load program ./a.out because of the following errors:

0509-151 The program does not have an entry point or the o_snentry field in the auxiliary header is invalid.

0509-194 Examine file headers with the 'dump -ohv' command.




반응형
반응형


AIX에서 실행파일을 만들거나 수행할 때, 공유 오브젝트와 라이브러리는 두 단계로 사용한다.


1. 링크할 때, 링커 에디터(ld 명령)는 실행파일에서 참조하는 정의되지 않은 심볼을 해석하기 위해 공유 오브젝트와 라이브러리를 찾는다. 만약 공유 오브젝트와 라이브러리가 참조된 모든 심볼을 가지고 있다면, 실행파일의 XCOFF헤더의 로더섹션은 그 공유 오브젝트나 라이브러리에 대한 참조를 포함하고 있어야 한다. 다시 말해서 심볼은 공유 오브젝트나 라이브러리에서 반출 (export)되고 실행파일로 반입 (import)된다.


2. 프로그램을 로드할 때, 시스템 로더 (새로운 프로세스를 시작하는 커널 구성요소)는 실행파일의 XCOFF 헤더 정보를 읽은 다음 참조한 공유 라이브러리의 위치를 찾는다. 참조하는 모든 공유 오브젝트와 라이브러리를 찾으면, 실행파일을 시작할 수 있다. 다음 시스템 로더는 실행파일의 여러 섹션을 해당되는 프로세스 주소 공간의 분할된 세그먼트로 로드한다. 프로그램에서 처음 참조하는 오브젝트라면 우선 공유 오브젝트의 프로그램 텍스트와 라이브러리를 전체 시스템 메모리로 로드하고, 추후 다른 프로그램들이 이를 공통으로 이용할 수 있게 된다.


오브젝트, 라이브러리와 어플리케이션 프로그램 코드를 링크시키기 위해 AIX에서는 몇가지의 링크 방법을 지원하고 있으며  이 기법들은 서로 상충되는 기법이 아니다.(단 lazy loading과 런타임 링킹의 경우는 제외한다.) 따라서 한가지 이상의 링킹 방법으로 실행파일을 만들 수 있다.


링킹 기법        심볼해석        실볼 rebound        모듈 로딩                링커 옵션            해당 섹션

디폴트                 링크시                  N/A               프로그램 로드시                    N/A                 AIX 디폴트 랭킹

정적                    링크시                  N/A               프로그램 로드시                 -bstatic               정적링킹

lazy loading         링크시                  N/A                       N/A                          -blazy                lazy loading

런타임                 링크시         프로그램 로드시        프로그램 로드시                 -brtl                   런타임링킹

동적로딩              런타임시           런타임시                   런타임시                       N/A                 동적 로딩


a. 정적으로 링킹된 오브젝트와 아카이브 멤버의 프로그램 텍스트는 실행파일 안에 포함된다.

b. lazy loading은 디폴트 링킹의 변종이다. 참조하는 공유 모듈을 로드하는 시간만을 제외하고, 다른 모든 점은 디폴트 링킹과 아주 흡사하다.

c. 동적 로딩은 링커 옵션이나 오브젝트 파일의 타입보다는 서브루틴에서 제공하는 일종의 프로그래밍 기법으로 볼 수 있다.


다음 옵션을 사용하지 않는 한 실행파일을 만들 때는 디폴트 링킹 방법을 사용하게 된다.


링킹 방식             옵션

정적 링킹              -bstatic

lazy loading          -blazy

런타임 링킹           -brtl


링커는 입력으로 두 종류의 파일(오브젝트 파일과 라이브러리)을 처리할 수 있다. AIX에서 오브젝트 파일과 라이브러리에 들어있는 아카이브 멤버는 모두 정적 파일일 수도 있고 동적 파일일 수도 있다. 정적 파일이던 동적파일이던 간에 디폴트 링킹에서는 링커에게 동일한 방법으로 파일이름을 지정한다. 정적 오브젝트는 항상 정적으로 링크되며, 실행파일 안에 포함된다. 공유 오브젝트는 보통 동적으로 링크되므로, 공유 라이브러리 코드는 실행파일 안에 포함되지 않는다. 그러나 공유 오브젝트는 정적으로 링크시킬 수 있다. 공유 오브젝트를 링크하면, 공유 프로그램 텍스트가 시스템 공유 라이브러리 세그먼트로 로드되고 참조하는 모든 프로세스에서 공유하게 된다.


공유 오브젝트가 미리 메모리에 로드되어 있지 않다면, 공유 오브젝트를 필요로 하는 프로그램을 처음 실행할 때 메모리에 로드하게 된다. 필요로 하는 페이지의 위치에 따라 VMM (virtual memory manager:가상 메모리 관리자)이 로딩과정을 수행하고, 이때 로드되는 페이지의 실제 크기는 현재 VMM의 옵션 설정에 따라 결정된다. VMM의 옵션은 AIX5L 버전 5.2 이상에서는 vmo 에서 설정하고, 그 외 버전의 AIX에서는 vmtune 명령으로 설정한다.


특히 공유 라이브러리를 C++ 로 작성한 경우에는 라이브러리끼리 서로 참조를 많이 하게 된다. 이런 경우는 페이지 요청이 있을 때마다 라이브러리를 로드하기보다는, 프로그램을 시작할 때 한꺼번에 필요한 라이브러리를 모두 메모리로 읽어 들이는 편이 더 빠르다.


이런 경우를 위해 환경변수를 다음처럼 설정한다.

LDR_CNTRL=PREREAD_SHLIB


1) Staic Linking

링커에서 공유 오브젝트와 라이브러리를 어떻게 다룰지 결정할 수 있도록 AIX에서는 -bdynamic과 -bstatic 옵션을 지원한다(-bdynamic, -bstatic 링커 옵션은 AIX 4.3부터 지원). 이 옵션은 토글옵션이며 같은 링커 명령에서 반복해서 사용할 수 있다. -bdynamic 옵션은 디폴트 옵션이며 공유 오브젝트를 공유하는 상태로 처리한다. 반면 -bstatic 옵션을 사용하게 되면 참조하는 모든 오브젝트를 정적으로 링크하고 공유 오브젝트도 정적으로 링크한다. 


xlc -o a.out main.o -lone -static func1.o -ltwo -bdynamic -lthree -bstatic -lfour -bdynamic

예를 들어 위와 같은 명령으로 프로그램을 만들게 되면 func1.o, -ltwo, -lfour 는 정적 오브젝트로 처리하고 -lone, -lthree 는 공유 오브젝트로 처리한다. 따라서 오브젝트 모듈 func1.o, 라이브러리 libone.a 와 libfour.a 에서 참조한 아카이브 멤버는 main.o와 정적으로 링크된다.


-bstatic 옵션을 사용하면 형식적으로 -bdynamic 옵션을 링크 명령의 제일 마지막에 써줘야 링커에서 시스템 라이브러리를 공유 오브젝트로 다루게 된다. 만약 -bdynamic 옵션을 제일 마지막에 써주지 않으면 시스템 라이브러리를 정적으로 링크하게 되므로 최종 실행파일의 크기가 훨씬 커지고, 특정 버전의 시스템 라이브러리와 정적으로 링크하기 때문에 다른 버전의 AIX에서는 프로그램이 수행되지 않을 수 있다. 명령문 제일 뒷 부분에 -bdynamic 옵션을 써줘야 libc.a 같은 시스템 라이브러리를 공유 오브젝트로 처리한다. 단 공유 오브젝트나 공유 아카이브 멤버를 정적으로 링크하는 방법은 64bit 개발환경에서 지원하지 않는다.


2) Lazy Loading

Lazy loading은 디폴트 링킹을 약간 바꾼 변종이며, 모듈내 함수를 실제로 실행할 때까지 모듈의 로딩을 늦추는 방법이다. 모듈을 로드할 때 시스템 로더는 디폴트로 연관관계가 있는 모듈을 모두 함께 로드한다. -blazy 링커 옵션을 써서 모듈을 링킹시키면 모듈 안의 함수를 실제로 호출할 때 모듈을 로드하지만, 심볼 해석은 링크할 때 이미 수행한다.


실행파일을 만들 때 런타임 링커 (-brtl 옵션 사용)를 지정하지 않은 경우에만 lazy loading이 동작한다. 참조하는 모듈정보가 모두 함수호출일 때만 모듈을 lazy loading 방식으로 로드할 수 있다. 만약 모듈 내의 변수를 참조하는 경우라면, 모듈은 정상적인 방법으로 로드된다.


예를 들어 main()에서 myfunc1()을 호출하고, myfunc1()은 libone.so 공유 모듈에 정의되어 있다고 하자. 그리고 myfunc1()이 공유 모듈 libtwo.so 의 myfunc2()를 조건에 따라 호출할 가능성이 있다면, libtwo.so는 lazy loading할 모듈에 해당한다. 만약 myfunc1()이 myfunc2()를 호출하지 않는다면, libtwo.so는 로드되지 않는다. 그러나 myfunc1()이 myfunc2()를 호출하면 lazy loading 코드가 load() 함수를 수행하여 libtwo.so를 로드하고, 함수 디스크립터를 수정해서 함수를 호출할 수 있도록 한다. 만약 libtwo.so를 로드할 수 없게 된다면 lazy loader의 에러 처리기(error-handler)를 호출하게 된다.


lazy loading을 사용한다고 해서 프로그램에 영향을 주지는 않지만, 다음 세가지의 예외상황이 있다.

1. 모듈이 다른 순서로 로드될 수 있기 때문에, 모듈의 로드 순서에 의존하는 프로그램의 경우에는 영향을 받는다. 심지어 어떤 경우는 모듈이 로드되지 않는 경우도 있으므로 주의하자.

2. lazy loading을 사용한다면 함수포인터를 비교하는 경우에 주의해야 한다. 보통 함수는 공유하는 주소영역을 가지므로 함수 포인터를 비교하여 동일한 함수를 참조하고 있는지 알아낼 수 있다. 그러나 모듈을 lazy loading하면 늦게 로드된 모듈의 함수주소는 다른 모듈에서 계산한 결과와 달라질 수 있다. 함수 포인터를 비교하고 이에 영향을 받는 프로그램은 lazy loading을 사용하면 안 된다.

3. 모듈을 상대경로 값으로 로드하고 프로그램이 작업 디렉토리를 바꾼 경우, 필요한 모듈을 찾지 못해서 로드하지 못할 수 있다. lazy loading을 사용하려면 링크할 때 필요한 모듈을 모두 절대경로로 지정해줘야 한다.


lazy loading을 사용할 지 여부는 링크시 결정하며 모듈에 따라 다르다. 한 개의 프로그램에서는 lazy loading을 사용하는 모듈과 lazy loading을 사용하지 않는 모듈을 섞어서 사용할 수 있다. 한 개의 모듈을 링크할 때 다른 모듈에 있는 변수를 참조한다면 이 모듈은 당연히 lazy loading이 안 된다. 만약 모듈에 대한 참조가 모두 함수호출에 관련된 참조라면, 이 모듈은 모두 lazy loading이 가능하다.


3) Runtime Linking

 AIX 디폴트 링킹”에서 설명했듯 AIX에서 디폴트, 정적, lazy loading 링킹 방법을 사용하여 실행파일을 만들면 링크할 때 모든 심볼을 해석(resolve)한다. 미처 해석되지 못한 심볼은 일단 실행파일을 만들고 나면 다시 바인딩되지 않는다. 그러나 런타임 링킹에서는 링크할 때가 아니라 프로그램을 로드할 때 참조하는 심볼을 해석할 수 있도록 한다. 이 기능은 프로그램을 일단 시작한 다음 정의되지 않았거나 공유 모듈내의 연기되지 않은(non-deferred) 심볼을 해석할 수 있도록 한다. 그리고 런타임 정의( ex)프로그램을 링크할 때 미처 함수 정의를 알지 못한 경우)와 심볼 재바인딩 기능을 제공한다. 예를 들어 main()은 libfunc1.so의 func1()을 호출하고 다음 libfunc2.so의 func2()를 호출하는 경우를 생각해보자. libfunc1.so와 libfunc2.so는 런타임링킹을 지원한다고 할 때, main()에서 또 다른 func2()함수를 정의해서 사용하며, 원래의 libfunc2.so의 func2() 정의를 무시하도록 할 수 있다. 이때 주 어플리케이션도 런타임 링킹을 지원하도록 만들어야 한다. 필요한 모듈만 런타임 링킹 라이브러리로 링크하는 방법만으로는 충분하지 않다. 모듈뿐 아니라 어플리케이션 내 함수도 런타임 링킹이 가능해야 한다.


AIX에서는 런타임 링킹을 사용한다고 하더라도, 연기된(deferred) 심볼을 제외한 모든 심볼은 프로그램을 로드할 때 해석해야 한다. 그러나 다른 UNIX OS에서는 함수심볼 해석을 실제 함수를 호출할 때까지 연기하는 경우가 있다.(변수참조는 로드할 때 해석된다.) 이 경우 심볼을 참조하는 모듈이 로드된 다음 함수정의가 로드된다.


런타임 링킹을 사용하려면 다음 사항을 알고 있어야 한다.

1. 런타임 링킹을 사용하려면 -brtl 옵션으로 런타임 링크 라이브러리(/usr/lib/librtl.a)를 지정해줘야 한다. -brtl 옵션과 -blazy 옵션은 함께 사용할 수 없다.

2. 오직 런타임 링킹 공유 오브젝트만 런타임 링킹시킬 수 있다. 런타임 공유 오브젝트가 아닌 오브젝트와 아카이브 멤버는 디폴트 링크 방식으로 링크해야 한다.

3. 런타임 링킹 공유 오브젝트는 주요 코드와 링크시키기 이전에 미리 만들어 놓아야 한다. 

4. 런타임 링킹 공유 오브젝트는 libname.so와 같은 파일이름을 사용해야 한다. 이런 방식의 이름을 사용해야 런타임 링킹 공유 오브젝트와 다른 파일을 구분하기 쉽고, 명령행에서 파일이름을 지정하기 쉽다.


런타임 링킹을 사용하면 개발자는 모듈간 상관성에 관한 사항이나 반입/반출 목록에 신경 쓰지 않아도 된다. -bexpall 링커 옵션을 사용하면 모든 공유 오브젝트는 모든 심볼을 반출하고, 모듈간의 상관관계를 해석하기 위해 런타임 링커를 사용하게 된다.


반응형
반응형

genkld명령은 이미 시스템 메모리에 올라간 공유 오브젝트를 보는데 사용한다.

다음의 genkld8결과에서 이 테스트 시스템의 시스템 전역 메모리(system global memory)에 libc.a 로부터 세 개의 공유 오브젝트 모듈이 올라와 있음을 알 수 있다.


$ genkld | grep 'libc.a'

d2023070     1df           /usr/lib/libc.a/dl.o

d012cd7a    1da          /usr/lib/libc.a/pse.o

d01cfbe0     1e6257     /usr/lib/libc.a/shr.o


위의 예제에서 libc.a의 shr.o만 필요하지만 나머지 두개의 파일은 다른 프로그램에서 필요하기 때문에 올라와 있다.

다른 UNIX OS는 공유 라이브러리 (동적 링킹 라이브러리 혹은 DLL-dynamic link library 라고도 한다)가 실제로 공유 오브젝트인 반면 AIX는 한 개의 라이브러리 안에 여러 개의 공유 오브젝트를 포함할 수 있는 점이 AIX와 다른 UNIX OS와의 큰 차이점이라고 할 수 있다.


공유 라이브러리와 공유 오브젝트라는 용어는 다른 UNIX OS에서는 같은 의미로 사용할 수 있지만 AIX에서는 서로 다른 의미가 된다.


공유 오브젝트

 공유 오브젝트는 XCOFF 헤더에 SHROBJ 플랙이 설정된 한 개의 오브젝트 파일이다. 

AIX에서 공유 오브젝트는 보통 name.o 형식의 이름을 갖는데 AIX에서는 일반적으로 공유 오브젝트에 대해 다른 UNIX에서 사용하는 .so 확장자를 사용하지 않는다. 이 이름은 컴파일러에서 디폴트로 만드는 파일이름의 확장자이다.


공유 라이브러리

 공유 라이브러리는 ar포맷으로 아카이브된 라이브러리 파일인 ar 명령으로 만든 파일을 말한다.

그 라이브러리 파일은 멤버로 하나 이상의 공유 오브젝트를 가진다. 그러나 아카이브 멤버로 공유 오브젝트 외에도 일반적인 비공유 오브젝트 파일도 있으며 이 파일은 링커에서 일반적인 방법으로 처리하게 된다. AIX에서 공유 라이브러리는 libname.a와 같은 형식의 이름이 된다.


링커는 파일이 올바른 오브젝트 파일인지 아닌지 알아보기 위해 파일의 매직넘버를 사용한다. 따라서 .o를 확장자로 하지 않는 파일을 공유 오브젝트로 사용할 수 있다.(물론 사용자가 헛갈릴 위험이 있다) 그러나 라이브러리는 반드시 libname.a과 같은 형식의 이름을 사용해야 하며 이렇게 하지 않으면 링커가 -l 옵션으로 지정한 라이브러리를 찾지 못한다.


AIX상에서 공유 오브젝트와 정적 오브젝트의 차이점에 대해서 알아보자.

AIX의 링킹/로딩 메커니즘에서는 공유 오브젝트와 정적 오브젝트를 사용하기 위해 AIX만의 파일이름형식을 사용하게 된다. 대부분의 UNIX OS에서 공유 오브젝트 파일은 “.so”확장자(shared object를 의미한다)를 사용하고 정적 오브젝트 파일은 “.o”확장자(object를 의미한다)를 사용한다.


그러나 AIX에서는 파일이 공유 오브젝트인지 정적 오브젝트인지에 관계없이 “.o”를 사용한다. 따라서 AIX에서는 단순히 확장자만 보고 이 파일이 공유 오브젝트 파일인지 정적 오브젝트 파일인지 구분할 수 없다. (AIX에서도 다른 UNIX OS처럼 파일확장자가 “so”인 공유 오브젝트를 지원하며 이 파일은 실시간 링킹에 사용된다.)


오브젝트 파일이 공유 오브젝트인지 정적 오브젝트인지 구분하려면 dump 명령을 사용해야 한다. dump 명령 뒤 Flags 줄에 SHROBJ 키워드가 나오는데 이 경우 이 오브젝트 파일은 공유 오브젝트이고 이 키워드가 안 나오면 정적 오브젝트이다.


$ dump -ov shr.o

shr.o:

***Object Module Header***

# Sections Symbol Ptr # Symbols Opt Hdr Len Flags

5 0x00251764 26925 72 0x3002

Flags=( EXEC DYNLOAD SHROBJ )

Timestamp = "Feb 03 08:59:14 2003"

Magic = 0x1df (32-bit XCOFF)


라이브러리의 아카이브 멤버가 공유 오브젝트인지 정적 오브젝트인지 알아보려면 dump 명령과 함께 -g 옵션(dump명령에서 -g 옵션을 사용하면 지정한 라이브러리에서 아카이브 멤버를 검사한다)을 사용해야 한다. 


예를 들어 예제 2-4에서 frexp.o 아카이브 멤버는 정적 오브젝트인 반면 /usr/lib/libc.a 의 shr.o는 공유 오브젝트이다.


$ dump -gov /usr/lib/libc.a

/usr/lib/libc.a[frexp.o]:

***Object Module Header***

# Sections Symbol Ptr # Symbols Opt Hdr Len Flags

3 0x0000030c 34 28 0x0000

Flags=( )

Timestamp = "Sep 15 16:12:35 2002"

Magic = 0x1df (32-bit XCOFF)


/usr/lib/libc.a[shr.o]:

***Object Module Header***

# Sections Symbol Ptr # Symbols Opt Hdr Len Flags

5 0x00250c0c 26913 72 0x3002

Flags=( EXEC DYNLOAD SHROBJ )

Timestamp = "Sep 19 00:14:43 2002"

Magic = 0x1df (32-bit XCOFF)



------------------------------------------------------------------------------------------------------------------


AIX에서는 링크할 때 심볼 해석을 하게 되며 프로그램 로드 시에 다시 심볼 해석을 하지 않는다. 

실행파일을 생성하면 동일한 경로 정보를 이용하여 의존관계가 있는 공유 오브젝트와 라이브러리의 아카이브 멤버를 참조할 수 있어야 한다. 

만약 이렇게 안되면 실행파일을 수행할 수 없다.


그러나 의존 관계가 있는 공유 오브젝트와 라이브러리의 아카이브 멤버가 항상 같은 디렉토리에 있어야 하는 것은 아니다. 

만약 오브젝트나 관련된 멤버에게 경로정보를 따로 주지 않으면, 시스템 로더는 -L 링커 옵션에서 지정한 몇 개의 디렉토리를 자동으로 찾게 되어 있다. 다음 LIBPATH 환경변수에서 지정한 디렉토리를 찾고 디폴트 라이브러리 경로인 /usr/lib, /lib 를 찾는다.

이렇게 정해진 방식에 의해 움직이므로 모듈을 로드할 때 시스템 로더의 작업이 좀더 쉬워지고 속도도 개선될 수 있다.


경로정보는 PATH 칼럼에서 Index 0(첫번째) 다음에 보이는데, 이 PATH 칼럼은 연관성 있는 모듈에 대해서 optional path component라고 부른다.

공유 오브젝트나 라이브러리를 만들 때 그리고 실행파일을 만들 때 optional path component 값이 없는 편이 좋다.

연관성 있는 모듈을 찾을 때 엉뚱한 파일을 찾을 위험성이 있기 때문이다.


$ dump -H a.out

a.out:

.

.

.

***Import File Strings***

INDEX     PATH                                 BASE         MEMBER

0         /usr/lpp/xlopt:/usr/lib:/lib

1         /tmp                                     libc.a             shr.o


$ cp /usr/lib/libc.a /tmp

$ ls -l /tmp/libc.a

-r-x------ 1 k5 k5 6793964 Apr 18 15:35 /tmp/libc.a

$ chmod a+r /tmp/libc.a

$ ls -l /tmp/libc.a

-r-xr--r-- 1 k5 k5 6793964 Apr 18 15:35 /tmp/libc.a

$ xlc helloworld.c /tmp/libc.a


$ ./a.out

Hello World

$ rm -i /tmp/libc.a

rm: Remove /tmp/libc.a? y

$ ./a.out

exec(): 0509-036 Cannot load program ./a.out because of the following errors:

0509-150 Dependent module /tmp/libc.a(shr.o) could not be loaded.

0509-022 Cannot load module /tmp/libc.a(shr.o).

0509-026 System error: A file or directory in the path name does not exist.


만약 위 예제의 소스를 다음과 같이 다시 컴파일하면


$ xlc helloworld.c

아래에서는 libc.a에 대해 XCOFF 헤더에서 아무 PATH 정보도 가지지 않는다.

(링커가 호출하기 전 컴파일러 드라이버가 이미 디폴트로 -lc 를 추가한다.)

***Import File Strings***

INDEX     PATH                                 BASE         MEMBER

0         /usr/lpp/xlopt:/usr/lib:/lib

1                                                      libc.a             shr.o


libc.a 가 PATH에 아무 정보도 포함하고 있지 않기 때문에, 시스템 로더는 우선 실행파일의 XCOFF헤더첫번째 로더헤더 섹션 (Index 0)에 기록된 대로 /usr/lpp/xlopt:/usr/lib/:/lib 디렉토리에서 라이브러리를 찾는다.



따라서 프로그램에서 라이브러리를 참조하려고 한다면 직접 라이브러리 이름을 적어주는 것보다 링커 옵션인 -L과 -l 을 쓰는 편이 더 좋다.

예를 들어 /project/test/lib 의 라이브러리 libabc.a를 사용하려면 아래처럼 하면 된다.


$ xlc -o a.out main.c -labc -L/project/test/lib

링커는 참조할 공유 오브젝트나 라이브러리를 찾기 위해 여러 경로를 검색하게 되는데


/project/test/lib 디렉토리를 디폴트 라이브러리 디렉토리보다 더 우선 순위에 놓는다.

 이 경우 실행파일의 XCOFF헤더 중 로더 헤더 섹션의 첫번째 엔트리(Index 0)에 디렉토리 /project/test/lib 가 들어간다. 

공유 오브젝트와 라이브러리는 실행파일의 XCOFF 로더 헤더섹션에 다른 선택적 경로정보(optional path component)를 가지고 있으면 안 된다.


$ dump -H a.out

.

.

.

***Import File Strings***

INDEX     PATH                                                             BASE         MEMBER

0        /project/test/lib:/usr/lpp/xlopt:/usr/lib:/lib

1                                                                                  libc.a             shr.o


링커는 입력으로 두 가지 종류의 파일(오브젝트 파일과 라이브러리)을 받을 수 있다.

이 두 가지 파일은 링커명령으로 지정할 수 있으며 아래처럼 명령행에서 직접 사용할 수 있다.


1) 오브젝트 파일을 절대경로까지 함께 지정한다. 

 $ xlc -o a.out main.c /prod/obj/shr1.o

2) 오브젝트 파일을 상대경로로 지정한다.

xlc -o a.out main.c ../../prod/obj/shr1.o

3) 현제 디렉토리에 오브젝트 파일이 있다면 파일이름만 지정한다.  

$ ls main.c shr.o main.c shr.o 

$ xlc -o a.out main.c shr1.o


마지막 경우만 제외하고, 생성된 실행파일은 의존하는 공유 오브젝트가 있을 경우 공유 오브젝트 shr.o를 검색하는 추가탐색경로를 

XCOFF헤더에 두게 된다.


라이브러리를 절대경로까지 함께 지정한다. 

xlc -o a.out main.c /prod/lib/libabc.a

라이브러리를 상대경로로 지정한다. 

xlc -o a.out main.c ../../prod/lib/libabc.a

현재 디렉토리에 라이브러리 파일이 있다면 파일 이름만 지정한다.

$ ls 

main.c libabc.a libabc.a main.c

$ xlc -o a.out main.c libabc.a

-L이나 -l 옵션으로 라이브러리가 설치되어 있는 디렉토리를 지정한다. 

xlc -o a.out main.c -L/prod/lib -labc


마지막 두 경우를 제외하고, 생성된 실행파일은 의존하는 공유 라이브러리가 있을 경우 공유 라이브러리 libabc.a를 검색하는 추가탐색경로를 XCOFF헤더에 두게 된다. 링커옵션 -bnoipath는 결과 모듈에 파일경로 이름이 포함되지 않도록 한다. 디폴트 옵션은 -bipath이며, 파일경로에 관한 정보를 포함한다.


실행파일이 공유 오브젝트를 참조하거나 공유 아카이브 멤버를 포함하는 라이브러리를 참조할 때, 시스템 로더는 오브젝트와 아카이브 멤버를 찾기 위해 LIBPATH 환경변수에서 지정한 디렉토리를 검색한다. 링커는 공유 오브젝트 파일과 라이브러리를 찾기 위해 LIBPATH 값을 이용하지 않는다.



LIBPATH값이 정의되어 있다면, 시스템 로더는 모듈을 로드할 때 다음 과정을 따른다.

1. 실행파일의 XCOFF헤더의 첫번째(Index 0) 로더 헤더 섹션에 저장되어 있는 PATH정보 바로 앞에 LIBPATH에 정의되어 있는 텍스트 정보를 추가함

2. 1번에서 만들어진 디렉토리 순서에 따라 시스템 로더는 공유 오브젝트와 라이브러리를 찾게 된다.

root가 아닌 사용자가 setuid, setgid가 설정된 실행파일을 수행하면 실행파일의 헤더섹션에 기록되어 있는 디렉토리만 검색하고 LIBPATH값에 저장된 디렉토리 값은 무시한다. LIBPATH값을 지정해줘도 역시 이 값을 무시한다.


예를 들어 LIBPATH 환경변수를 다음처럼 정의한 다음 앞에 나왔던 프로그램을 수행해보자.


LIBPATH=/project/build/lib

이때 시스템 로더는 공유 오브젝트와 라이브러리를 다음과 같은 순서로 찾는다.

1. /project/build/lib

2. /project/test/lib

3. /usr/lpp/xlopt

4. /usr/lib

5. /lib


공유 오브젝트와 라이브러리는 XCOFF 로더 헤더 섹션에 LIBPATH 환경변수에서 지정한 추가 경로값 정보를 가지고 있으면 안 된다.


예를 들어 다음 상황을 가정해보자.

실행파일 a.out 을 만들기 위해 main.o와 공유 오브젝트 shr.o를 링크 시킨다.

shr.o와 main.o는 모두 현제 디렉토리에 있다.


이제 실행파일을 만들기 위해 shr.o 파일이름을 다음 두 가지 방법으로 지정해줄 수 있다.

1. xlc -o a.out main.o shr.o

2. xlc -o a.out main.o ./shr.o


첫번째 방법으로 만든 실행파일은 예제 2-7과 같이 shr.o에 대한 로더정보를 가지게 된다. 이 경우, 시스템 로더는 /usr/lpp/xlopt, /usr/lib, /lib 디렉토리에서 shr.o 파일을 찾는다. 만약 shr.o 파일이 이 세 디렉토리중 한 군데에라도 들어있다면 검색을 멈추고 LIBPATH 까지 가지 않는다. 만약 shr.o가 이 세 디렉토리외에 다른 디렉토리에 들어있다면, LIBPATH에 그 디렉토리값을 넣어줘야 한다.


예를 들어 shr.o가 현재 디렉토리에 있다면, LIBPATH 환경변수를 다음처럼 바꾼 다음 명령을 수행하자.

$ export LIBPATH=$PWD ;./a.out


만약 shr.o을 /project/lib 디렉토리로 옮기려 하면, 다음과 같은 명령을 수행하면 된다.

$ export LIBPATH=/project/lib ;./a.out


두번째 방법으로 생성한 실행 파일이라면, dump -H 의 결과가 제일 마지막 한줄이 달라진다.

***Import File Strings***

INDEX         PATH                                 BASE             MEMBER

0             /usr/lpp/xlopt:/usr/lib:/lib

1                                                          libc.a               shr.o

2 .                                                        shr.o


PATH 컬럼의 . 는 shr.o의 추가경로정보이며 앞의 경우와 큰 차이가 있다. 두 번째 방법으로 생성한 실행파일을 수행하면, 시스템 로더는 shr.o를 찾기 위해 LIBPATH도 참조하지 않고 첫번째(Index 0) 로더 헤더 섹션(이 예제에서는 /usr/lpp/xlopt:/usr/lib:/lib 디렉토리)도 찾지 않는다. 따라서 이 실행파일을 수행할 때는 현재 디렉토리에 shr.o가 항상 같이 있어야 한다.



반응형
반응형



실행파일을 수행할 때 시스템 로더가 공유 오브젝트를 찾지 못하면, 다음과 비슷한 에러메시지가 나올 것이다.


exec(): 0509-036 Cannot load program ex1 because of the following errors:

0509-022 Cannot load library libone.so.

0509-026 System error: A file or directory in the path name does not exist.


찾지 못한 오브젝트는 0509-022 에러메시지 부분에 나와 있다. find 명령을 사용해서 공유 오브젝트를 찾아보자. 

공유 오브젝트를 찾으면, 그 오브젝트가 위치하는 디렉토리를 LIBPATH 변수에 추가한 다음 어플리케이션을 다시 수행한다. 

또 그 오브젝트나 라이브러리가 읽기가능(read permission)인지 살펴보자.


시스템 로더가 지정한 공유 오브젝트는 찾았지만, 심볼을 해석할 수 없을 때에도 비슷한 에러 메시지가 보인다. 실행파일과 호환되지 않는 버전의 공유 오브젝트를 사용하면 이런 경우가 발생할 수 있다. 에러메시지는 다음과 비슷하다.


exec(): 0509-036 Cannot load program ./example because of the following errors:

0509-023 Symbol func1 in ex1 is not defined.

0509-026 System error: Cannot run a file that does not have a valid format.


해석하지 못한 심볼은 0509-023 메시지에서 알 수 있다. 이 심볼 이름을 우선 적어놓은 다음(여기에서는 func1) dump -Tv 명령을 사용하여 실행파일에서는 어느 공유 오브젝트에 이 심볼이 정의되어 있는 것으로 알고 있는지 알아보자.


# dump -Tv example | grep func1

[4] 0x00000000 undef IMP DS EXTref libone.a(shr1.o) func1


이 경우 실행파일은 func1 심볼이 공유 오브젝트 shr1.o에 있으며 shr1.o 파일은 libone.a 의 아카이브 멤버라고 알고 있다. 

이러한 정보를 이용하여 문제해결에 도움을 줄 수 있다.

반응형
반응형


우선 기본적으로 유닉스에서 정적 라이브러리를 만드는 방법은 간단하다.

ar 를 사용해서 생성하는데 이는 AIX 뿐만 아니라 모든 유닉스/리눅스가 동일할 것이다. 

단 ar 옵션의 차이는 있다.


아래와 같은 함수가 포함된 3개의 파일을 정적 라이브러리로 만들어서 실제 사용하는 부분까지 확인해보도록 하자.


파일 명 : f1.c

-------------------------------------------------------

#include<stdio.h>

int funcreturnzero()

{

return 0;

}

-------------------------------------------------------


파일 명 : f2.c

-------------------------------------------------------

#include<stdio.h>

void funcnewline()

{

printf("\n");

}

-------------------------------------------------------


파일 명 : f3.c

-------------------------------------------------------

#include<stdio.h>

int funcreturnone()

{

return 1;

}

-------------------------------------------------------


1) c 파일 오브젝트 파일로 컴파일

$ xlc -c f1.c f2.c f3.c 

$ ls

f1.o, f2.o, f3.o 


2) libtest.a 라이브러리로 세 개의 파일을 아카이브

$ ar -vq libtest.a f1.o f2.o f3.o

ar: 아카이브 파일 libtest.a을(를) 작성합니다.

q - f1.o

q - f2.o

q - f3.o

$ ls

f1.o, f2.o, f3.o libtest.a


3) 아카이브 내부 오브젝트 파일을 보려면 -t 옵션을 주면 되며 -v 옵션을 주면 상세 옵션이 추가적으로 표시된다.

$ ar -t libtest.a

f1.o

f2.o

f3.o

$ ar -v -t libtest.a

rw-r--r--   202/201      956  1월  9일 15:42 2014 f1.o

rw-r--r--   202/201     1125  1월  9일 15:42 2014 f2.o

rw-r--r--   202/201      953  1월  9일 15:42 2014 f3.o


만약 기존의 libtest.a 라이브러리가 없었다면 위 명령은 libtest.a 라이브러리를 새로 만들고 여기에 f1.o, f2.o, f3.o 오브젝트의 복사본을 넣는다. 

그러나 기존의 libtest.a 라이브러리가 이미 있었다면 이 명령은 라이브러리 내에 함수 정의나 변수가 겹치는지 검사하지 않은 채로 기존의 라이브러리 뒤에 오브젝트 파일을 추가한다. -v 옵션은 verbose 옵션이며 ar 명령이 진행되는 상태를 보여준다.


4) 아카이브에 새 오브젝트를 추가하러나 기존 멤버를 바꾸려면 -r 옵션을 사용하면 된다.

$ ar -v -r libtest.a f1.o f4.o


5) 바뀐 멤버를 갱신하려면 -r -u 옵션을 추가.

$ ar -v -r -u libtest.a f2.o 


6) 아카이브 내부 멤버 오브젝트를 추출하려면 -x 옵션.

$ ar -v -x libtest.a f1.o f3.o


7) 아카이브 내부 멤버 오브젝트를 제거하려면 -d 옵션.

$ ar -v -d libtest.a f2.o


단 해당 부분은 모두 정적 오브젝트에 해당한다. 
















반응형
반응형


해당 부분은 AIX 전용 컴파일러인 xlc와 xlc의 컴파일 옵션을 사용하여 컴파일 하는 방식에 대해 소개합니다.


정적/동적 라이브러리를 생성하기 전 오브젝트(.o) 파일을 먼저 생성해야 한다.

해당 오브젝트 파일을 생성할 때 해당 오브젝트가 32비트/64비트인지 결정해야 하는데 시스템에 기본적으로 설정되어 있는 OBJECT_MODE에 따라 컴파일 옵션을 입력하지 않았을 때 기본 적용되는 비트 숫자가 다르다. 만약 명시적으로 컴파일 비트 숫자를 기입하려면 아래를 참고.


-q64 : 64비트 컴파일 옵션

-q32 : 32비트 컴파일 옵션

-qarch : 64비트 서브옵션 지원


만약 일관성 없이 해당 부분이 미지정 된다면 다음의 우선순위로 비트가 결정된다.


1. OBJECT_MODE 환경변수

2. 환경설정 파일

3. 명령행 옵션


-qarch 옵션과 함께 사용할 때 이 옵션은 목표하는 아키텍쳐 용으로 기계어와 모드를 결정하게 되는데, -q32, -q64옵션은 -qarch 옵션보다 우선순위가 높다. 그리고 한 줄에 -q32와 -q64 옵션을 모두 써주면 최종적으로 써준 옵션에 따라 모드가 결정된다. -qarch=com 으로 하면 앞으로의 호환성을 위해 좀더 일반적인 기계어를 사용하고 이외에는 특정 아키텍쳐에 많이 의존하게 된다.


64bit 모드에서 -qarch=com 은 -qarch=ppc 와 동일하게 취급된다.


컴파일할 때마다 매번 모드를 일일이 지정해줘야 한다면 매우 귀찮은 작업이 될 것이다.

(예를 들어 링킹 단계에서 일일이 32bit와 64bit를 구분해줘야 한다고 해보자) 

만약 개발 중 오직 한가지 모드로만 컴파일한다면 OBJECT_MODE 환경변수를 디폴트 모드로 바꿔주면 된다. 

OBJECT_MODE 환경변수에 대입할 수 있는 값은 다음과 같다.


(unset) 32bit 오브젝트를 생성/사용한다.

32 32bit 오브젝트를 생성/사용한다.

64 64bit 오브젝트를 생성/사용한다.

32_64 32bit/64bit 오브젝트를 모두 허용한다.


컴파일러, 링커에서는 OBJECT_MODE=32_64 를 허용하지 않는다. 환경변수를 이와 같이 설정하면 다음과 같은 에러가 발생한다.

1501-254 OBJECT_MODE=32_64 is not a valid setting for the compiler.


OBJECT_MODE 환경변수를 사용하면 컴파일러나 링커뿐만 아니라 개발과정 중 필요한 다른 어플리케이션도 이 변수를 참고하는 경우가 있으므로 편리하게 사용할 수 있다.


단 디폴트 모드를 결정하기 위해 OBJECT_MODE를 사용하고 있는 것을 일반 사용자가 모르고 있다면 심각한 문제가 발생할 수 있다. 

예를 들어 OBJECT_MODE가 64bit로 설정되어 있을 때 사용자가 64bit로 설계되지 않은 프로그램을 컴파일한다면 자동으로 64bit 코드가 생긴다. 

따라서 컴파일하기 전 사용자는 반드시 OBJECT_MODE를 검사해야 하고 자기가 의도한 모드로 설정되어 있는지 확인해야 한다.


링커 ld는 디폴트로 -b32 옵션을 사용하며 32bit 링킹을 지원하고, -b64 옵션을 사용하면 64bit 링킹을 지원할 수 있다. 

컴파일러 드라이버는 기본적으로 -q32나 -q64 옵션을 보고 링킹 옵션을 결정하므로 특별히 링커 옵션을 따로 정해줄 필요는 없다.


다음 명령어는 오브젝트 파일을 다룰 때 사용 하며 디폴트로 오브젝트 파일을 32bit XCOFF(eXtended Common Object File Format)로 가정한다.


ar - 링커에서 사용하는 인덱스 처리된 라이브러리를 관리한다.

dump - 오브젝트 파일에서 선택한 영역을 덤프한다.

lorder - 오브젝트 라이브러리에서 멤버 파일의 가장 적당한 순서를 찾는다.

nm - 오브젝트 파일, 실행 파일, 오브젝트 파일 라이브러리에서 심볼에 대한 정보를 보여준다.

ranlib - 아카이브 라이브러리를 랜덤 라이브러리로 변환한다.

size - XCOFF 오브젝트 파일의 섹션 크기를 보여준다.

strip - 바인더와 심볼릭 디버그 프로그램에서 사용하는 정보를 제거해서 XCOFF 오브젝트 파일의 크기를 줄인다.


64bit XCOFF 오브젝트 포맷을 지원하기 위해 위 명령어에는 -X 옵션이 추가되었다. 

-X 옵션은 명령어가 검사할 오브젝트 파일의 타입을 지정하며 다음 값을 지정할 수 있다.


32 32bit 오브젝트 파일만을 처리한다.

64 64bit 오브젝트 파일만을 처리한다.


32_64 32bit / 64bit 오브젝트 파일을 모두 처리한다.

단 위 명령어는 모두 OBJECT_MODE 환경변수를 참고한다. 그러나 -X 옵션으로 지정한 값이 더 우선순위가 높다.

64bit 어플리케이션을 개발하기 전에 우선 그 어플리케이션에서 사용할 라이브러리도 역시 64bit인지 살펴보아야 한다. AIX에서 제공하는 대부분의 C/C++ 라이브러리는 하이브리드 모드 아카이브(32bit, 64bit 오브젝트가 모두 들어있다)지만 써드파티 제품인 경우에는 해당되지 않을 수 있다.


해당 파일이 몇 비트 오브젝트인지 확인하기 위해서는 file objecname.o 를 사용하면 확인할 수 있다.

64비트의 경우 출력부에 64-bit가 명시된다.


반응형
반응형

출처 : Developing_C_C++_Application_on_AIX_AIX_DIY(SE)


AIX에서는 2가지의 프로그래밍 모델을 제공한다.

- ILP32

- LP64


ILP32는 integer/long/pointer가 32bit임을 의미하며 AIX의 32bit 프로그래밍 환경을 사용하게 된다.

이는 32bit 주소 공간을 사용하는 것을 의미하며 이론적으로 4GB 까지 메모리 제한이 있다.


LP64는 long/pointer가 64bit임을 의미하며 AIX의 64bit 프로그래밍 환경을 사용하게 된다. 64bit 주소공간을 사용하게 되므로 참조할 수 있는 메모리는 4GB를 넘어가게 된다. 일반적으로 데이터 타입 크기와 얼라인먼트 차이를 제외하고, LP64는 ILP32모델 프로그래밍 모델을 지원하며 널리 사용되는 int 데이터 타입에 대해서는 소급하여 호환성을 유지하게 된다.


C/C++ 표준에 의하면 int, short는 적어도 16bit여야 하며 long은 적어도 int와 같거나 그 이상의 크기여야 하고 32bit보다는 작아야 한다. 이 표준은 LP64모델에도 적용된다.


sizeof(char) ≤ sizeof(short) ≤ sizeof(int) ≤ sizeof(long)


LP64 데이터 모델은 대부분의 주요 벤더의 UNIX기반 시스템에서 지원되는 사실상의 표준이다. 따라서 LP64 모델을 따르는 어플리케이션은 다른 벤더로 포팅하는 작업이 매우 쉽다.


다음 테이블 2-1은 AIX의 ILP32, LP64 모델에서 기본 C/C++ 데이터 타입에 해당하는 크기를 보여주고 있다. (단위 비트)



 데이터 타입

 IP32 

 LP64 

 char

 8

 8 

 short

 16 

 16

 int

 32 

 32

 long

 32 

 64

 long long

 64

 64

 pointer

 32 

 64 

 float

 32

 32

 double

 64 

 64

 long double 

 64/128 

 64/128


* long double의 크기는 -qlongdouble옵션이나 cc128, cc128_r 등 컴파일러 드라이버 이름에 128이 붙었는지의 여부로 결정된다.

반응형
반응형

 

AIX에서 사용하는 컴파일러는 기본적으로 xl c/C 인데

xlc는 c Compiler이며 xlC는 C++ Compiler가 되겠다.

 

리눅스는 gcc/g++ , HP-UX는 cc/aCC 와 매칭되는 컴파일러들인데

해당 시스템에 해당 컴파일러가 어디에 위치하고 설치되어 있는데 그리고 각각 어떠한 Fileset을 가지고 있는지 알아보자

 

우선 일반적으로 AIX 시스템에는 /usr/bin에 해당 컴파일러들의 심볼릭 링크가 걸려있는데 xlc, xlC 등의 실행은 이곳에서도 실행 시킬 수 있다.

문제는 각각 C/C++ Compiler Fileset이 설치가 되어 있는지 안 되어 있는지 확인하고자 할 때 어떻게 해야 하냐는 건데

 

우선 일반적으로 바이너리가 설치되는 위치를 살펴보자.

 

/usr/vac/bin     <- XL C Compiler Binary 설치 위치

/usr/vacpp/bin  <- XL C++ Compiler Binary 설치 위치

 

각각의 디렉토리에 가보면 xlc, xlc_r, xlC, xlC_r 부터 시작해서 뭐 이상한 바이너리가 잔뜩 있는데...

ls -la 해서 가만히 살펴보면 심볼릭 링크가 되어 있는 것을 따라가다 보면 신기하게도 죄다 xlc로 귀결된다.

어떤 바이너리를 실행시켜도 결국에는 xlc가 실행된다는건데, 이는 AIX의 XL 컴파일러가 내부적으로 실행 시킨 바이너리 파일을 기준으로

다른 전처리 옵션을 타는게 아닌가 싶은데.. 뭐 자세한 동작 원리는 아직 잘 모르겠다.

 

우선적으로 AIX 시스템의 경우 /usr/lpp에 보면 xlC 부분도 있긴 한데 이는 SW Directory로 해당 소프트웨어의 Description을 확인할 수 있는 뭐... 그런거 같다. 정확하게는 이것도 아직 공부 중임. 어쨋거나 AIX에서 소프트웨어가 설치될때 installp 를 사용하는데 이를 사용하여 설치된 소프트웨어는 /usr/lpp에서 관리된다는 사실 알아놓으면 좋을꺼 깥다.

 

그렇다면 IBM 공식 홈페이지에 적혀 있는 각각 Compiler의 Fileset을 살펴보자

각각의 Fileset이 현재 AIX 서버 머신에 설치되어 있는지 확인하고자 한다면

 

lslpp -la | grep [fileset 명] 을 입력해주면 되겠다.

 

(XL C/C++ V8.0 for AIX 기준)

 

XL C compiler filesets

The following filesets are included in the XL C compiler.

Table 3. XL C compiler filesets
Fileset name Fileset description
vac.C IBM XL C compiler
vac.include IBM XL C compiler include files
vac.man.LANG
Note:
LANG is one of: en_US, EN_US, ja_JP, Ja_JP, JA_JP, zh_CN, Zh_CN, ZH_CN.
IBM XL C compiler manual pages
vac.lib IBM XL C compiler libraries
vac.aix50.lib IBM XL C compiler libraries for AIX 5
vac.lic IBM XL C license files
Note:
For licensed customers only
vac.msg.LANG.C
Note:
LANG is one of: en_US, EN_US, ja_JP, Ja_JP, JA_JP, zh_CN, ZH_CN.
IBM XL C compiler messages

 

XL C++ compiler filesets

The following filesets are included in the XL C/C++ compiler.

Note:
All of the filesets required for the XL C compiler, except vac.ndi and vac.licAgreement, are also required for the XL C/C++ compiler.

Table 4. XL C/C++ compiler filesets
Fileset name Fileset description
vacpp.cmp.aix50.lib IBM XL C/C++ libraries for AIX 5.1, 5.2 and 5.3
vacpp.cmp.aix50.tools IBM XL C/C++ tools for AIX 5.1, 5.2 and 5.3
vacpp.cmp.core IBM XL C/C++ compiler
vacpp.cmp.include IBM XL C/C++ compiler include files
vacpp.cmp.lib IBM XL C/C++ libraries
vacpp.cmp.rte IBM XL C/C++ compiler application runtime
vacpp.cmp.tools IBM XL C/C++ tools
vacpp.lic IBM XL C/C++ license files
vacpp.licAgreement IBM XL C++ electronic license agreement files
vacpp.memdbg.aix50.lib IBM XL C/C++ user heap/memory debug AIX 5.1, 5.2 and 5.3 libraries
vacpp.memdbg.aix50.rte IBM XL C/C++ user heap/memory debug AIX 5.1, 5.2 and 5.3 runtime
vacpp.memdbg.lib IBM XL C/C++ user heap and memory debugger static library
vacpp.memdbg.rte IBM XL C/C++ user heap and memory debugger runtime
vacpp.msg.LANG.cmp.core
Note:
LANG is one of: en_US, EN_US, ja_JP, Ja_JP, JA_JP, zh_CN, ZH_CN.
IBM XL C/C++ compiler messages
vacpp.msg.LANG.cmp.tools
Note:
LANG is one of: en_US, EN_US, ja_JP, Ja_JP, JA_JP, zh_CN, ZH_CN.
IBM XL C/C++ tools messages
vacpp.man.LANG
Note:
LANG is one of: en_US, EN_US, ja_JP, Ja_JP, JA_JP, zh_CN, ZH_CN.
IBM XL C/C++ compiler manual pages

C++ runtime filesets

The following filesets are included in the IBM XL C/C++ Enterprise Edition V8.0 for AIX compiler installation package, and must be installed with the compiler.

Table 5. C++ runtime filesets
Fileset name Fileset description
xlC.adt.include C Set ++ application development toolkit
xlC.aix50.rte C Set ++ runtime for AIX 5.1, 5.2 and 5.3
xlC.msg.LANG.rte
Note:
LANG is one of: en_US, ja_JP, Ja_JP.
C Set ++ runtime messages
xlC.rte C Set ++ runtime

 

 

 

반응형

'OS > AIX::' 카테고리의 다른 글

AIX xlc 컴파일러 비트 설정  (0) 2014.01.09
AIX의 2가지의 프로그래밍 모델  (0) 2014.01.09
AIX Thread Dump 분석 방법  (0) 2012.08.22
AIX 라이브러리 버전 확인  (0) 2012.07.12
AIX 컴파일 정보  (0) 2011.10.05
반응형

이번엔 AIX... Thread Dump 분석 방법이다.

최근에 발견한 최고의 포스팅.

 

http://blog.naver.com/bumsukoh/110114573021

 

 

안녕하세요. 이번에는 AIX에서 제공하는 Thread 모니터링 관련 툴을 소개하겠습니다.

AIX에서 가장 유용하게 사용할 수 있는 프로세스와 Thread 모니터링 툴로는 ps 명령어입니다.

"왠 ps 명령어 !" 라고 하실 수 있을텐데요.

 

사실 ps 명령어는 생각보다 굉장히 많은 정보를 제공하고 있습니다. man page를 보시면 더욱 실남나게 느기실텐데요.

그래도 ps 하면 가장 많이 사용하는 명령어가 "ps -ef" 정도겠죠.

 

AIX에서는 ps 명령어를 통해 Thread 레벨의 정보를 확인할 수 있는 기능을 제공합니다.

Solaris의 prstat이나 HP-UX의 glance처럼 막강하지는 않지만 나름대로 프로세스의 Thread레벨에 대한 정보를 확인하는데는 유용하게 사용하실 수 있습니다.

 

ps를 통한 Thread 레벨 모니터링 방법은 다음과 같습니다.

# ps -mp [프로세스 IDs] -o THREAD

ps 명령어는 다들 잘 아실테니 옵션부분만 설명하도록 하겠습니다.

- "m" 은 프로세스 뿐만 아니라 Kernel Thread에 대한 리스트를 출력합니다.

"-o" 옵션과 같이 사용하면 다양한 정보를 출력할 수 있습니다.

- "p" 는 프로세스 ID를 설정합니다. ","를 사용하여 여러개의 프로세스 ID를 지정할 수 있습니다.

- "o" 는 Format 지정을 지정합니다. Thread는 "THREAD"로 지정합니다.

다음은 ps -mp 명령어의 출력 결과 예입니다.

 

 

위와 같이 프로세스의 전체 정보와 그 밑으로 Thread 별(TID)로 정보가 출력됩니다.

구분 설명
TID Kernel thread ID for threads
ST The state of the process or kernel thread
CP The CPU utilization of the process or kernel thread
PRI The priority of the process or kernel thread
SC The suspend count of the process or kernel thread

그외 WCHAN, F, TT, BND, COMMA 정보가 있습니다.

자세한 사항은 ps man page나 메뉴얼을 참조하시기 바랍니다.

명령어 결과에서 Thread 상태 항목인 "ST" 부분과 CPU 사용율 항목인 "CP" 부분, 그리고 Thread의 Suspend 횟수 항목인 "SC" 부분을 주의깊게 볼 필요가 있습니다. 그 이유는 성능에 관련된 항목들이기 때문입니다.

위의 항목 중 Thread 상태 항목인 "ST" 부분에는 다음과 같은 상태 코드가 있습니다.

 

- "O" 는 Nonexistent 상태입니다.

- "R" 은 Running 상태입니다.

- "S" 는 Sleeping 상태입니다.

- "W" 는 Swapped 상태입니다.

- "Z" 는 Canceled 상태입니다.

- "T" 는 Stopped 상태입니다.

Java 프로세스의 경우 대부분이 "R" 또는 "S" 상태입니다.

TID(Thread ID)는 Java Thread dump 분석 시 Java Thread와 매핑하기 위한 key가 됩니다.

이 부분은 차후에 Thread dump 분석 시 설명드리도록 하겠습니다.

그 다음으로는 Solaris와 HP-UX에서 살펴보았던 pstack과 유사한 procstack 명령어입니다.

procstack 은 Solaris와 HP-UX에서 프로세스의 Native Stack을 확인할 수 있듯이 AIX에서 프로세스의 Native Stack을 확인하기 위한 명령어 입니다.

Solaris와 HP-UX에서는 p로 시작하는 프로세스 명령어 대신 AIX에서는 proc로 시작하는 프로세스 명령어가 있습니다. 두 종류가 거의 비슷한 기능을 제공합니다.

자세한 사항은 다음 포스트를 참고하시면 됩니다. (http://blog.naver.com/bumsukoh/110098535739)

명령어 사용법은 다음과 같습니다.

 

# procstack [프로세스 ID]

 

출력 결과는 다음과 같습니다.

 

위와 같이 JVM을 구현한 Native Stack 입니다. Java 1.6(64bit) 버전의 Jeus 서버에 대한 Thread Native Stack 입니다.

각 Thread 별로 tid와 pthread id 에 대한 내용이 출력되며, 여기서의 tid는 위에서 "ps -mp"의 TID와 동일한 값을 나타냅니다.

 

"ps -mp"의 모니터링 결과 CPU 점유가 높은 Thread에 대해 procstack으로 Native Stack 확인이 가능하게 됩니다. 물론 Java 프로세스의 경우 procstack으로 Java Stack 확인이 불가능하지만 그런데로 도움은 됩니다. 그 이후에 필요하다면 Thread dump(javacore 파일)을 생성하여 Java Stack을 확인할 수 있습니다.

 

위의 Native Stack은 모두 Java의 SocketInputStream의 socketread() 부분에서 대기중(상태"SLEEP")이며, 최종 Native Stack은 poll() 함수인 것을 알 수 있습니다.

 

poll()함수는 Thread를 즉시 "SLEEP"시키고 해당 STREAM(파일 FD)에서 Data input event가 감지되면 Thread를 wake-up시켜 데이터를 처리할 수 있도록하는 기능을 하는 함수입니다.

 

즉, Java의 socket read는 내부적으로 poll() 함수로 구현되었다는것을 알 수 있는 부분입니다.

그 외에 프로세스에 대한 degugging을 위한 dbx나 프로파일 툴인 tprof등을 사용할 수 있습니다.

프로파일 툴인 tprof는 java 기반(java stack 제공)의 프로파일을 할 수 있어 전문적인 프로파일링 툴이 없을 경우 유용하게 사용할 수 있습니다. (tprof 참고 : http://blog.naver.com/bumsukoh/110104594318)

 

이것으로 AIX에서 유용하게 사용할 수 있는 Thread 관련 명령어에 대해 알아 보았습니다.

다음 포스트에서는 본격적으로 Thread dump에 대한 내용을 설명드리도록 하겠습니다.

어제 엄청난 호우로 많은 지역이 피해를 입은 것 같습니다. 저도 어제 비와 천둥소리로 잠을 설칠 정도 였습니다. 모두들 호우에 피해를 입지 않도록 각별히 신경 쓰셔야 할 것같습니다.

그럼 이만.. 다음에 뵙겠습니다.

 

반응형

'OS > AIX::' 카테고리의 다른 글

AIX의 2가지의 프로그래밍 모델  (0) 2014.01.09
AIX 컴파일 정보 2  (0) 2012.12.05
AIX 라이브러리 버전 확인  (0) 2012.07.12
AIX 컴파일 정보  (0) 2011.10.05
AIX malloc - free 시 혹은 new - delete 시의 메모리 반환  (0) 2011.08.21

+ Recent posts