반응형

출처 : http://shaharear.blogspot.kr/2013/06/recover-database-from-ora-00333-redo.html



아래의 step을 차근차근 따라하면 해소된다. 

빨간 글씨는 직접 입력 내용이다.

파란 글씨는 출력 내용중 핵심 내용이다.



In development environment, it is very common scenario that we have multiple databases in a single machine by using VMware (i.e, each VMware contains one database). Again those machines doesn't have consistant power backup. Therefore we have to face power failure or VMware hang-up. So, we are forced to restart the machine while databases are still up & running. After restarting the machine, we have mostly got he following error:


   ORA-00333: redo log read error block count .

Here are the steps to overcome the error
SQL> startup
ORACLE instance started.
Total System Global Area ***** bytes
Fixed Size               ***** bytes
Variable Size            ***** bytes
Database Buffers         ***** bytes
Redo Buffers             ***** bytes
Database mounted.
 
 ORA-00333: redo log read error block *Number* count *Number*
 
Step 1: As the Db is in mount mode, We can query v$log & v$logfile to identify the status of log file group and their member.
 SQL> select l.status, member from v$logfile inner join v$log l using (group#); 
 STATUS  MEMBER
 ------------- --------------------------------------
 CURRENT /oracle/fast_recovery_area/redo01.log
 INACTIVE /oracle/fast_recovery_area/redo02.log
 INACTIVE /oracle/fast_recovery_area/redo03.log
 
Step 2: Recover the database using ackup controlfile.
 SQL> recover database using backup controlfile;
ORA-00279: change  generated at  needed for thread 1
ORA-00289: suggestion : /oracle/fast_recovery_area/archivelog/o1_mf_1_634_%u_.arc
ORA-00280: change  for thread 1 is in sequence #
Specify log: {=suggested | filename | AUTO | CANCEL}

Step3: Give 'CURRENT' log file member along with location as input. If it does not work give other log file members along with location in input prompt. In our case we give (위의 step 1의 current log 파일을 입력하면 됨)

/oracle/fast_recovery_area/redo01.log
Log applied.
Media recovery complete.

Step 4: Open the database with reset logfile
SQL> alter database open resetlogs;
Database altered.


반응형
반응형

출처 : http://blog.daum.net/99lib/9

가져온 곳 : 
블로그 >System engineer
|
글쓴이 : bonnie_clyde| 원글보기




파일시스템 개념을 잡고 가야할듯..

ext4 가 확장성이 있고 ext3는 확장성이 없다는데, 내 기억으로는 LVM을 확장해줬던 기억이 있어서 갑자기 혼란스러웠다.

파일시스템 자체를 확장하는 것이 아니라 논리볼륨을 더 확장한 것 뿐이라서 결국엔 아닌 것이었으나 내가 본론적으로 잘 이해를 못하고 있음을 깨달아

다시 정리하고자 한다.

 

* 보통은 ~~

디스크를 붙이고 -> 파티션을 생성하고 -> 해당 파티션을 포맷하고(파일시스템을 만들고) -> 마운트

* 요기선~

디스크를 붙이고 -> 파티션을 LVM타입으로 생성하고 -> 물리볼륨을 만들고 -> 볼륨그룹을 만들고 -> 볼륨그룹에서 논리볼륨을 만들고 -> 포맷 -> 마운트

 

우선 LVM을 만드는 순서부터 살펴보자면,

 

 

 

 

  1. 하드디스크를 LVM을 만들 수 있게 파티션 생성
  2. 물리볼륨 생성 (pvcreate)
  3. 위 물리볼륨들을 볼륨그룹을 생성하여 묶는다. (vgcreate)
  4. 위 볼륨그룹을 원하는 크기대로 나눠 논리볼륨 생성 (lvcreate)
  5. 파일시스템으로 포맷

 

 

1. 하드디스크를 LVM 타입으로 파티션 생성 .. (이라는데 굳이 그럴 필욘 없는듯..) 

1)  fdisk -l 하여 LVM 설정할 하드드라이브 (디스크)의 디바이스명을 확인

(fdisk -l /dev/sda 이런 식으로 하면 /dev/sda 의 파티션 내용을 확인하는 것이고, 생략하면 모든 하드드라이브의 파티션을 보여준다.)

ex) fdisk -l 실행화면

 

이런 식으로, fdisk -l /dev/sda 를 하면 sda 하드 드라이브의 논리적 파티션들의 정보가 보여진다.

df -h 를 하게 되면 , /dev/sda 인 하드드라이브가 보이는 것이 아니라 sda1, sda2... 이런 파티션들의 정보가 보여진다. sda는 안 보인다.

2)  fdisk를 사용하여 LVM 타입으로 파티션을 생성한다.

# fdisk /dev/hdb

n 엔터 (새 파티션 추가)

-> p 엔터 (primary partition (1-4)) ; 주파티션이면 p, 확장파티션이면 e

-> 1 엔터 (파티션 넘버 입력)

-> 엔터 (First cylinder 1-1792, default 1:)

-> 엔터 (last cylinder)

-> t 엔터 (change a partition's system id)

-> l 엔터 (type L to list codes)

-> 8e (linux LVM이 8e다)

-> w 엔터 (write table to disk and exit)

# fdisk /dev/hdc , hdd 위와 동일하게 설정

3)  fdisk -l 하여 LVM 타입으로 파티션이 설정되었음을 확인

 

2. 물리볼륨 생성

1) pvcreate 로 물리볼륨을 생성

 

[root@localhost ~]# pvcreate /dev/hdb1

Physical volume "/dev/hdb1" successfully created

 

(윗단계에서 fdisk /dev/hdb 했으니깐... 이 디스크가 hdb1, hdb2 ... 이런 식으로 쪼개졌을 거란 말이지. 근데 위에선 그냥 한 디스크를 통으로 한 파티션으로 생성..한듯.)

 

[root@localhost ~]# pvcreate /dev/hdc1

[root@localhost ~]# pvcreate /dev/hdd1

 

2) pvdisplay하여 물리볼륨 확인

 

 

3. 볼륨그룹 설정

1) vgcreate 하여 볼륨그룹 설정 (위에서 생성했던 물리볼륨들을)

[root@localhost ~]# vgcreate myvg /dev/hdb1 /dev/hdc1 /dev/hdd1

               Volume group "myvg" successfully created

2) vgdisplay 하여 볼륨그룹을 확인

 

4. 논리볼륨 생성

1) lvcreate 하여 논리볼륨을 두 개 (하나는 7GB , 하나는 나머지 공간) 생성

  (여기서 소문자 l을 쓰면 pe 의 개수로 용량을 지정하게 된다. 상세  LVM 내용은 다음 포스트 참조.)

 

[root@localhost ~]# lvcreate -n dtlv -L 7GB myvg

Logical volume "dtlv" created

[root@localhost ~]# lvcreate -n bklv -l 100%FREE myvg

Logical volume "bklv" created

 

2) lvdisplay 하여 논리볼륨 확인

 

 

 

 

5. 파일시스템 포맷 및 마운트

 

이제서야 포맷을 하게 된다~!

 

1) 위에서 생성한 논리볼륨을 파일시스템 포맷

 

[root@localhost ~]# mkfs.ext3 /dev/myvg/dtlv

....

[root@localhost ~]# mkfs.ext3 /dev/myvg/bklv

 

2) 마운트

 

[root@localhost ~]# mkdir /mnt/data

[root@localhost ~]# mkdir /mnt/back

[root@localhost ~]# mount -t ext3 /dev/myvg/dtlv /mnt/data

[root@localhost ~]# mount -t ext3 /dev/myvg/bklv /mnt/back

 

3) df -l 하여 마운트 확인

 

4) 부팅 시 자동으로 디스크를 읽어줄 수 있게 fstab 설정

#vi /etc/fstab

/dev/myvg/dtlv         /mnt/data         ext3      defaults     0    0

 

 

fdisk 해서 나중에 -l 치면 나오는 애들은.... list known partition types 이다. 파일시스템 리스트가 아니라 파티션 타입~!

/proc/filesystems는 파일시스템 타입이고..

 

즉, 처음에 내가 가졌던 의문,

기본적으로 fdisk해서 만들었던 파티션들이 df -T 하면 나오는 파일시스템 타입에는 왜 ext3가 있느냐,

fdisk 해서 l로 치면 나오는 타입에는 ext3가 없는데?

라는 우문에는, 파티션 타입이라 다른거고..

기본적으로 fdisk로 해서 만든 파티션을 만든 후 반드시 포맷하고 마운트를 시켜야 한다.

나는 fdisk하면 바로 포맷이 되서 쓸 수 있는 건줄 착각하고 있었다....ㅋㅋ

 

 

+) 그런데 굳이 물리볼륨을 만들 필요 없이 바로 파티션을 볼륨그룹으로 묶을 순 없는건가?

왜 굳이 물리볼륨을 중간에 추가적으로 만들어서 (그냥 파티션을 그것도) 작업을 한번 더하는거지?..

 

 

+) dmc-emass 이관 작업시, cx4-80 스토리지의 디스크를 추가로 할당하여 붙여줄 ?,

스토리지 엔지니어가 미리 파티션까지 다 할당해놓았었다...

나는 이 때 파티션을 LVM  타입으로 만들어야 했는데 엔지니어가 말도 없이 그냥 리눅스 타입으로 해서 당황스러웠었다 ㅋㅋㅋ

LVM이 잘 생성되긴 했었는데...

그런데 fdisk -l 하면 파티션 테이블이 존재하지 않는다는 메시지가 뜬다.

나는 여튼 이미 엔지니어가 파티션까지 다 만들어버렸으니 바로 물리볼륨그룹 작업으로 들어갔었는데...



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

출처 : http://attiadmin.guyweb.co.kr/linux/lvm.html



1. LVM이란?
 (1) 개요: 리눅스 설치시나 하드디스크 추가시에 파티션이라는 것을 나누고 공간을 할당한다. 이 
          때 한번 설정한 공간을 고정이 되어 변경이나 추가가 불가능하다. LVM(Logical Volume 
          Manager)은 파티션을 원하는 대로 추가하거나 제거하고 그 크기도 조절할 수 있도록 
          해주는 방법이다.
 (2) 관련용어
   1) 물리적 볼륨(PV:Physical Volume): 실제로 나눈 파티션을 말한다. 즉 /dev/hda8, /dev/hdb1 등
                                      을 말한다. LVM에서는 이러한 물리적 볼륨을 하나의 구성원
                                      으로 받아 들이는 형식이다.
   2) 물리적 확장(PE:Physical Extents): 일종의 블럭같은 것으로 실제 데이터가 저장되는 공간을 
                                       말한다. 보통 1PE가 약 4MB정도 차지한다.
   3) 볼륨그룹(VG:Volume Group): 물리적 볼륨이 모여서 하나의 VG를 이룬다. 이것은 더 크게 말하
                                면 지정한 크기의 PE가 모여 생성되는 하나의 큰 덩어리라고 할 수
                                있다.
   4) 논리적볼륨(LV:Logical Volume): 이 논리적 볼륨이 우리가 흔히 쓰는 정규파티션과 같다. 실제
                                    만들어서 사용하는 것이 바로 이 LV이다.

2. LVM 설정하기
 (1) 설명: /dev/hda8(약 800MB)과 /dev/hda9(약 800MB)을 lvm이라는 볼륨그룹으로 생성하고 1.2GB는
          /data라는 디렉토리로 400MB는 /backup으로 구성해보자. 여기서 /data는 처음에 1GB로 
          할당하고 추가로 영역을 200MB 확장하는 형태로 구성한다.
 (2) 설정1 : 1000MB의 /data 로 구성
   1) fdisk를 이용하여 파티션 속성을 변경: fdisk /dev/hda 실행후에 t, 해당 파티션 선택, 8e, w 
                                          을 누르고 재부팅한다.
   2) 디스크에 있는 볼륨그룹을 검색하고 /etc/lvmtab 파일 생성
     [root@www root]# vgscan
   3) 물리적 볼륨(PV:Physical Volume) 생성
     [root@www root]# pvcreate /dev/hda8
     pvcreate -- physical volume "/dev/hda5" successfully created

     [root@www root]# pvcreate /dev/hda9
     pvcreate -- physical volume "/dev/hda8" successfully created
   4) 생성된 PV를 특정한 볼륨그룹(lvm)에 추가시킨다.
     [root@www root]# vgcreate lvm /dev/hda8 /dev/hda9
     vgcreate -- INFO: using default physical extent size 4 MB
     vgcreate -- INFO: maximum logical volume size is 255.99 Gigabyte
     vgcreate -- doing automatic backup of volume group "lvm"
     vgcreate -- volume group "lvm" successfully created and activated
   5) 생성된 볼륨그룹 검사한다.
     [root@www root]# vgdisplay -v lvm
     --- Volume group ---
     VG Name               lvm
     VG Access             read/write
     VG Status             available/resizable
     VG #                  0
     MAX LV                256
     Cur LV                0
     Open LV               0
     MAX LV Size           255.99 GB
     Max PV                256
     Cur PV                2
     Act PV                2
     VG Size               1.66 GB
     PE Size               4 MB
     Total PE              424
     Alloc PE / Size       0 / 0
     Free  PE / Size       424 / 1.66 GB
     VG UUID               RBimFr-2W6o-O6Wr-E4Ox-egs1-z87V-cha1DA

     --- No logical volumes defined in "lvm" ---


     --- Physical volumes ---
     PV Name (#)           /dev/hda8 (1)
     PV Status             available / allocatable
     Total PE / Free PE    212 / 212

     PV Name (#)           /dev/hda9 (2)
     PV Status             available / allocatable
     Total PE / Free PE    212 / 212
   6) 논리적 볼륨(LV:Logical Volume) 생성
     [root@www root]# lvcreate -L 1000M -n data lvm
     lvcreate -- doing automatic backup of "data"
     lvcreate -- logical volume "/dev/lvm/data" successfully created
   7) LV생성확인
     [root@www root]# lvscan
     lvscan -- ACTIVE            "/dev/lvm/data" [1000 MB]
     lvscan -- 1 logical volumes with 1000 MB total in 1 volume group
     lvscan -- 1 active logical volumes
   8) VG 확인
     [root@www root]# vgdisplay -v lvm
     --- Volume group ---
     VG Name               lvm
     VG Access             read/write
     VG Status             available/resizable
     VG #                  0
     MAX LV                256
     Cur LV                1
     Open LV               0
     MAX LV Size           255.99 GB
     Max PV                256
     Cur PV                2
     Act PV                2
     VG Size               1.66 GB
     PE Size               4 MB
     Total PE              424
     Alloc PE / Size       250 / 1000 MB
     Free  PE / Size       174 / 696 MB
     VG UUID               RBimFr-2W6o-O6Wr-E4Ox-egs1-z87V-cha1DA

     --- Logical volume ---
     LV Name                /dev/lvm/data
     VG Name                data
     LV Write Access        read/write
     LV Status              available
     LV #                   1
     # open                 0
     LV Size                1000 MB
     Current LE             250
     Allocated LE           250
     Allocation             next free
     Read ahead sectors     1024
     Block device           58:0
     

     --- Physical volumes ---
     PV Name (#)           /dev/hda8 (1)
     PV Status             available / allocatable
     Total PE / Free PE    212 / 0

     PV Name (#)           /dev/hda9 (2)
     PV Status             available / allocatable
     Total PE / Free PE    212 / 174
      => 논리적 볼륨부분이 나타나고 물리적 볼륨에서 /dev/hda8은 모두 사용중인 것으로 나타난다.
   9) 파일시스템 생성
     [root@www root]# mkfs -t ext3 /dev/lvm/data
   10) 마운트하여 사용한다.
      [root@www root]# mount -t ext3 /dev/lvm/data /data
 (3) 참고
   1) 설명: LVM을 시스템 재부팅후에도 사용하려면 /etc/fstab파일에 등록하면 된다.
   2) 예
     /dev/lvm/data              /data                ext3    defaults        0 0
 (4) 설정2: /data 디렉토리 200MB 추가하기
   1) 설명: lvextend 명령을 이용하여 공간을 늘리고 lvscan명령으로 확인하도록 한다.
   2) 방법
    ㄱ. [root@www root]# lvextend -L +200M /dev/lvm/data
          => 기존의 용량에 추가로 200MB를 할당한다.
    ㄴ. [root@www root]# lvscan
 (5) 설정2: 남은 공간(약 400MB)를 /backup 디렉토리로 사용하기
   1) 설명: 남은 공간을 확인하려면 vgdisplay -v 명령을 내려서 Free PE값을 확인하고 해당 PE값을
           할당하는 것이 좋다. lvcreate 로 남은 PE값을 지정하고 Logical Volume을 생성한다.
   2) 방법
    ㄱ. [root@www root]# lvcreate -l 124 -n backup lvm
         => lvm이라는 볼륨그룹에 backup 이라는 Logical Volume을 생성하고 크기는 약 124PE
          (약 496MB)를 할당한다.
    ㄴ. [root@www root]# mkfs -t ext3 /dev/lvm/backup
         => 파일시스템을 생성한다.
    ㄷ. [root@www root]# mount -t ext3 /dev/lvm/backup /backup
         => 마운트하여 사용한다.

3. LVM 관련명령어
 (1) vgscan
   1) 설명: 디스크에 있는 볼륨그룹(VG:Volume Group)를 검색하여 /etc/lvmtab 파일을 생성한다. 
           fdisk를 이용하여 파티션을 속성을 LVM으로 지정한 후에 이 명령을 사용한다.
   2) 사용법
     vgscan
 (2) pvcreate
   1) 설명: 물리적 볼륨(PV:Physical Volume)을 생성하는 명령어이다. fdisk를 이용하여 파티션을 
           분할하고 LVM 속성으로 지정한 뒤에 해당 파티션을 PV로 만들 때 사용하는 명령이다.
   2) 사용법
     pvcreate 디바이스명
   3) 사용예
     pvcreate /dev/hdb1
 (3) vgcreate
   1) 설명: 볼륨그룹을 생성하는 명령어로 생성된 PV를 지정한 볼륨그룹에 포함시키면서 생성한다.
   2) 사용법
     vgcreate 볼륨그룹명 디바이스명 디바이스명
   3) 사용예
     vgcreate lvm /dev/hda7 /dev/hdb1
      => lvm 이라는 볼륨그룹을 생성하고 /dev/hda7, /dev/hdb1 이라는 PV를 포함시킨다.
 (4) vgdisplay
   1) 설명: 볼륨그룹의 속성과 정보를 보여주는 명령어이다.
   2) 사용법
     vgdisplay [option] [볼륨그룹명]
   3) option
     -v: 좀 더 자세히 보여주는 옵션으로 Volume Group이외에 gical Volume과 Physical Volume도
        같이 보여준다.
   4) 사용예
    ㄱ. [root@www root]# vgdisplay
         => Volume Group의 내용을 보여준다. 
    ㄴ. [root@www root]# vgdisplay -v lvm
         => lvm이라는 볼륨그룹의 내용을 자세히 보여준다.
 (5) lvcreate
   1) 설명: 볼륨그룹안에 LV(Logical Volume)을 생성하는 명령이다.
   2) 사용법
     lvcreate 옵션 볼륨그룹명
   3) option
     -L: LV의 사이즈를 지정하는 옵션으로 K(kilobytes), M(megabytes), G(gigabytes), T(terabyt
        es) 단위를 붙여 지정가능하다.
     -l: LV의 사이즈를 지정하는 옵션으로 pe의 개수로 용량을 지정한다. 참고로 보통 1pe당 4MB
        이다.
     -n: LV의 이름을 지정하는 옵션이다. 
   4) 사용예
    ㄱ. [root@www root]# lvcreate -L 2000M -n backup lvm
         => lvm이라는 볼륨그룹에 backup라는 이름으로 2Gigabytes 용량으로 LV을 생성한다.
    ㄴ. [root@www root]# lvcreate -l 250 -n data lvm
         => lvm이라는 볼륨그룹에 data라는 이름으로 250pe(약 1GB)용량으로 LV을 생성한다.
 (6) lvscan
   1) 설명: 디스크에 있는 Logical Volume을 찾아준다.
   2) 사용법
     lvscan [option]
   3) option
     -v: 정보를 자세히 보여준다.
   4) 사용예
     lvscan
 (7) lvdisplay
   1) 설명: Logical Volume의 정보를 보여준다.
   2) 사용법
     lvdisplay [option] LV명
   3) option
     -v: 정보를 자세히 보여준다.
   4) 사용예
     [root@www root]# lvdisplay -v /dev/lvm/data
       => /dev/lvm/data라는 LV의 정보를 자세히 보여준다.
 (8) vgextend
   1) 설명: 미리 생성된 Volume Group에 추가로 Phycical Volume을 추가할 때 사용한다.
   2) 사용법
     vgextend 볼륨그룹명 새PV명
   3) 사용예
     [root@www root]# vgextend lvm /dev/hdc1
       => lvm이라는 볼륨그룹에 /dev/hdc1을 추가한다.
 (9) vgreduce
   1) 설명: 볼륨그룹에 있는 Physical Volume을 삭제하는 명령이다.
   2) 사용법
     vgreduce 볼륨그룹명 PV명
   3) 사용예
     [root@www root]# vgreduce lvm /dev/hdc1
       => lvm이라는 볼륨그룹에서 /dev/hdc1을 삭제한다.
 (10) lvextend
   1) 설명: Logical Volume의 용량을 확장하는 명령이다.
   2) 사용법
     lvextend 옵션 [볼륨그룹명] LV명
   3) option
     -l +사이즈: 지정한 PE수만큼 용량을 늘린다.
     -L +사이즈[kmgt]: 지정한 사이즈만큼 용량을 늘린다. 단위를 표시하지 않으면 기본 Megabytes
                      단위이다.
   4) 사용예
     [root@www root]# lvextend -L +200M /dev/lvm/data
       => 기존의 용량에 추가로 200MB를 할당한다.
 (11) lvreduce
   1) 설명: Logical Volume의 용량을 줄이는 명령이다.
   2) 사용법
    lvreduce 옵션 [볼륨그룹병] LV명
   3) option
     -l -사이즈: 지정한 PE수만큼 용량을 줄인다.
     -L -사이즈: 지정한 사이즈만큼 용량을 줄인다. 단위를 표시하지 않으면 기본 단위는 Megabytes
                이다.
   4) 사용예
     [root@www root]# lvreduce -L -500 /dev/lvm/data
      => /dev/lvm/data의 용량을 500MB 줄인다.
 (12) vgchange
   1) 설명: 볼륨그룹을 속성을 변경하는 명령으로 볼륨그룹을 사용가능여부, 최대 LV 갯수등을 변경
           할 수 있다.
   2) 사용법
     vgchange 옵션 볼륨그룹명
   3) option
     -a y|n : 볼륨그룹의 사용여부를 지정한다.
     -l 갯수: 해당 볼륨그룹에 생성할 수 있는 최대 Logical Volume수를 지정한다.
   4) 사용예
    ㄱ. [root@www root]# vgchange -a y lvm
         => lvm이라는 볼륨그룹을 활성화시킨다.
    ㄴ. [root@www root]# vgchange -a n lvm
         => lvm이라는 볼륨그룹을 비활성화시킨다.
    ㄷ. [root@www root]# vgchange -l 100 lvm
         => lvm이라는 볼륨그룹을 최대 Logical Volume수를 100개로 지정한다.
 (13) vgremove 
   1) 설명: 볼륨그룹을 제거하는 명령이다.
   2) 사용법
     vgremove 볼륨그룹명
   3) 사용예
     [root@www root]# vgremove lvm
      => lvm이라는 볼륨그룹을 삭제한다.

- rename


To rename an existing logical volume, use the lvrename command.

Either of the following commands renames logical volume lvold in volume group vg02 to lvnew.

lvrename /dev/vg02/lvold /dev/vg02/lvnew
lvrename vg02 lvold lvnew

 

반응형
반응형


Take a look at document #A4678152 ("Comparing page size for vmstat, top, glance, ps -el").


1. Top reports free memory in 1kb chunks so to get them to match you must divide tops free amount by 4 to get the true number of 4kb pages free and have it match vmstat. In other words, top reports in 1kb pages so these numbers must be multiplied by 4 to get 4kb kernel pages numbers.

2. For vmstat, avm (active virtual pages) and free (size of the free list) memory are reported in 4kb pages sizes.

3. Glance reports 1kb page sizes. This number will often be significantly different from ps -el since glance reports usage of shared memory also.

From the Glance help window for RSS (* PROC_MEM_RES): The number of KB of resident memory for the process. This consists of text, data, stack, as well as the process' portion of shared memory. This value is similar to the SZ field of the ps -el command, except that the ps command shows only data, stack, and text areas, and it reports their sizes in page units rather than KB. On some systems ps reports the virtual rather than
resident size.

4. ps -el reports in 4kb kernel page sizes.



vsz = The size in kilobytes (1024 byte units) of the core image of the process. See column sz, above.
sz = The size in physical pages of the core image of the process, including text, data, and stack space.

Glance RSS = RSS(* PROC_MEM_RES): The number of KB of resident memory for the process. This consists of text, data, stack, as well as the process' portion of shared memory. This value is similar to the SZ field of the ps -el command, except that the ps command shows only data, stack, and text areas.

반응형

'OS > HP-UX::' 카테고리의 다른 글

HP-UX depot 패키지 설치  (0) 2014.06.11
HP-UX 11.11 gcc 설치  (0) 2014.06.11
HP-UX Thread dump 및 프로세스 분석 툴 Glance  (0) 2012.08.22
HP-UX 컴파일러 관련 정보  (0) 2011.12.01
반응형
출처 : http://nicejoo.blogspot.kr/2012/02/memory-leak.html
출처 : http://stormaa.tistory.com/5
출처 : http://ysoftman.blogspot.kr/2012/05/linux-valgrind.html
출처 : http://www.solanara.net/solanara/memoryleak ( 다양한 릭 디텍팅 방식 가이드)
출처 : http://h21007.www2.hp.com/portal/download/files/unprot/devresource/Tools/wdb/doc/011310/memdebug-updated.pdf (WDB)
-----------------------------------------------------------------------------------------------

1. Valgrind 설치

wget http://www.valgrind.org/downloads/valgrind-3.3.0.tar.bz2(새 창으로 열기)
tar xvfj valgrind-3.3.0.tar.bz2
cd valgrind-3.3.0
./configure
make
make install

2. Valgrind 테스트
valgrind --leak-check=yes main

3. 간단 실행법
valgrind --tool=memcheck --leak-check=full --show-reachable=yes --log-file=memcheck.txt [프로그램] [실행인자들...]
valgrind --leak-check=full --log-file=memcheck.txt -v --error-limit=no [프로그램경로] [인자]


--leak-check=full : 메모릭에러가 날 경우 소스파일명과 라인위치 출력

               이 옵션을 사용할려면 디버깅컴파일을 해야합니다. (컴파일시 -g 옵션)
--log-file : 체크결과를 저장할 로그파일명


// 항목별 메모리 블럭 누수를 확인 할 수 있다.
definitely lost: 블럭 해제(free) 코드를 사용하지 않은 명백한 메모리 누수가 있음을 나타낸다.
indirectly lost: 블럭을 가르키는 포인터를 상실한 경우로 예를들어 이진트리의 루트노드를 잃어버리면 자식 노드 블럭 포인터를 간접적으로 잃어버리는 경우를 나타낸다.
possibly lost: 내부 포인터가 해제 되지 않은 경우로, 자신이 모르는 내부 포인터인 경우 신경 쓰지 않아도 된다.
still reachable: 메모리 블럭을 아직까지 사용하고 있는 경우, 프로그램 종료되기전에 해제해야될 메모리 블럭을 나타낸다.


반응형

'UTIL > Leak Detect' 카테고리의 다른 글

Monitoring and Tuning Memory Use  (0) 2015.08.17
반응형

출처 : http://community.snu.ac.kr/blog/blog.log.view.screen.do?blogId=145&logId=333


시스템의 메모리는 항상 거의 다 채워진 상태로 사용된다. 현재 실행되는 프로그램이 모든 메모리를 사용하고 있지 않을지라도 운영체제는 이전에 실행된 프로그램의 텍스트나 파일들을 메모리에 보관하고 있다. 이렇게 보관하는 것으로 인한 시스템 부하는 없다. 왜냐하면, 어쨌든 메모리가 사용되고 있는 것이 아니기 때문이다. 메모리에 보관되고 있는 프로그램이나 파일들이 다시 사용되게 될 때, 추가적인 디스크 I/O를 줄일 수 있는 장점이 있다.


ꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏ

Determining How Much Memory Is Being Used


vmstat

  현재 시스템의 모든 프로세스가 사용하고 있는 가상 메모리(active virtual memeory)와 free list에 등록된 실 메모리의 여유공간을 보여준다.

  시스템의 메모리가 부족한지 튜닝이 필요한지는 vmstat 명령을 여러번 일정한 간격으로 실행하여 pi, po 필드의 값을 검사하여 지속적으로 1이상의 값이 나오면, 메모리가 성능의 제약이 되고 있다고 볼 수 있다. 가끔씩 1 이상의 값이 나오는 것은 무시해도 된다.

  높은 wa와 b 필드값이 동시에 표시되는 경우는 페이징 스페이스에 대한 I/O 때문인 경우가 대부분이다.

kthr     memory             page              faults        cpu

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

 r  b   avm   fre  re  pi  po  fr   sr  cy  in   sy  cs us sy id wa

 1  1 37636  1757   0   0   0   2    9   0 468  320 348  0  0 99  0

 0  0 37642  1751   0   0   0   0    0   0 454 1354 357  0  0 99  0

 0  0 37642  1751   0   0   0   0    0   0 452 1301 345  0  0 99  0

 0  0 37643  1750   0   0   0   0    0   0 453 1302 349  0  0 99  0

 0  0 37643  1750   0   0   0   0    0   0 452 1298 345  0  0 99  0

 0  0 37643  1750   0   0   0   0    0   0 453 1299 343  0  0 99  0


VMM과 관련된 성능 문제를 확인하기 위해서는 memory, page 부분을 검사한다.

․ memory

  - avm(active virtual memory)

디폴트 정책인 deferred page space policy를 사용하는 경우에는 이 값이 사용되는 페이징 공간의 크기보다 클 수 있다. 이 값에 file page를 포함되지 않는다.

  - fre

4KB 단위의 사용가능한 실 메모리 페이지 수. free list의 최소유지 값은 vmtune의 minfree 파라미터에 의해서 결정된다. 응용 프로그램이 실행 종료되면, 모든 working page는 즉시 free list에 등록되지만, file page는 메모리에 남게 된다. 만일, 해당 파일이 지워지게 되면, file page도 free list에 등록된다. 이와 같은 이유 때문에 fre 필드의 값이 실제로 시스템의 가용 메모리를 나타낸다고 할 수 없는 것이다.

․ page

  - re

4 버전 이상에서는 더 이상 의미가 없다.

  - pi

페이징 공간에서부터 메모리로 읽혀진 페이지 수. 페이징 공간은 디스크에 존재하며, 메모리에 여유 공간이 없을 경우, 사용된다. pi 필드 값이 존재한다면, 이전에 po 필드에 해당하는 페이지가 out된 기록이 있게 된다. 초당 5이상의 값이 일반적인 기준으로 사용되며, 환경에 따라 달라진다. 절대적인 기준이란 있을 수 없다.

  - po

메모리 부족으로 인해 페이징 공간으로 out된 페이지 수.

  - fr/sr

vmtune의 minfree 파라미터 값 이하로 fr 컬럼의 페이지 수가 감소하게 되면, 페이지 교체 알고리즘이 적용된다. 따라서, VMM은 필요한 메모리를 확보하기 위해서 PFT(page frame table)을 검사하여 할당 해제할 페이지를 찾는다. maxfree 값까지 free 메모리 페이지를 확보할 때까지 페이지를 검사하는데, 이 때 검사한 페이지 수를 sr 필드에 표시하며, 결과적으로 할당 해제된 페이지 수를 fr 필드에 표시하게 된다. 메모리에 사용되지 않는 file page가 많다면, 할당 해제할 페이지를 쉽게 찾을 수 있을 것이며, 이때, sr값이 fr보다 별로 크지 않을 것이다. fr:sr의 비가 높을수록 메모리가 부족하다는 의미다. 1:4(fr:sr) 이라면, 하나의 여유 메모리를 확보하기 위해서  4개의 페이지를 검사해야만 한다는 뜻이다.

  - cy

페이지 교체를 위해서 PFT를 scan한 초당 횟수. 보통, PFT를 다 검사하는 경우는 없으므로 이 필드 값은 보통 0으로 표시된다. 만약, 이 필드 값이 0이 아니다면, 페이지 교체를 위해서 PFT를 검사하는데, 다 검사하도록 원하는 페이지를 얻을 수 없었다는 의미로 시스템의 메모리가 거의 모두 사용되고 있다는 의미다.


  시스템의 RAM이 어느 정도가 필요하나를 대략적으로 추정하는 방법은 vmstat의 avm의 최대값이 얼마인가를 보는 것이다. 이상적으로는 avm 값이 메모리보다 작아야 한다. 이 2값의 차이만큼 페이징이 발생했다는 것을 의미한다. avm이 RAM양 보다 적은데도 페이징 공간에 대한 페이징이 발생한다면, 실 메모리가 file page로 많이 사용되기 때문이다. 이러한 경우에는 minperm/maxperm 파라미터 값을 조절할 수 있다.


vmstat -I

  kthr      memory             page              faults        cpu

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

 r  b  p   avm    fre    fi  fo  pi  po  fr  sr   in   sy     cs  us sy id wa

 2  1  0 1490301  1396   3   2   0   0   1    4 2719 141591 49393 10 12 78  1

 p 필드는 raw device에 대한 I/O를 기다리는 쓰레드로 파일 시스템에 대한 것은 포함되지 않는다. fi/fo는 file page에 대한 페이징이다.


vmstat -s

  시스템이 부팅된 이후부터의 누적된 통계치를 보여준다. 메모리 사용에 대한 정보를 얻기 위해서는 이 명령을 주기적으로 수행하여 결과치의 차이를 보아야 한다.


ps

  ps v PID 명령을 통해서 각 프로세스마다의 메모리 사용을 알 수 있다.

# ps v 52930

   PID    TTY STAT  TIME PGIN  SIZE   RSS   LIM  TSIZ   TRS %CPU %MEM COMMAND

 52930      - A     7:17  484  2424   208    xx   370    24  0.0  0.0 ./ns-admi

PGIN

    페이지 폴트로 인해 발생한 page in 수

    모든 페이지 폴트는 I/O 유발하므로 I/O 규모 측정에 사용될 수 있다.

SIZE

    프로세스의 데이터 부분의 가상 크기(페이징 공간), KB 단위

    프로세스의 working segment pages 수와 동일하다.

    다른 플래그의 SZ 필드와 동일하다.

    일부 페이지가 page-out 된 경우에는 사용하고 있는 실 메모리 양보다 크게 표시됨

    private segment, shared-library data segment를 포함하고 있다.

RSS

    프로세스의 실 메모리 크기, KB 단위

    working segment + code segment

    code segment는 프로그램의 모든 인스턴스에 의해서 공유된다.

TSIZ

    프로그램의 text section 크기.

    프로그램의 text section은 touch 될 경우에만 메모리로 로드된다.

    이 값은 active memory 사용량에는 영향을 주지 않는다.

    dump -ov 명령을 통해서 알아낼 수 있다.

TRS

    resident set of text size, number of code segment pages

    인스턴스가 많은 프로그램의 경우, 메모리 사용량을 과장해서 보여준다.

    TSIZ 보다 크게 나오는데, 그 이유는 다른 헤더 정보 등이 추가되기 때문이다.

%MEM

    프로그램이 사용하는 메모리를 전체 메모리로 나눈 것.

    RSS처럼 메모리 사용이 과장되게 나올 수 있다.


※ ps 명령은 shared memory segment나 memory-mapped segment에 의해서 사용되는 메모리는 포함하고 있지 않다. 따라서, 보다 정확한 정보를 보기 위해서는 svmon 명령을 사용해야 한다.

# dump -ov /usr/bin/ksh

/usr/bin/ksh:

                        ***Object Module Header***

# Sections      Symbol Ptr      # Symbols       Opt Hdr Len     Flags

         4      0x00000000              0                72     0x1007

Flags=( RELFLG EXEC LNNO DYNLOAD )

Timestamp = "Apr 04 06:19:10 2003"

Magic = 0x1df  (32-bit XCOFF)

                        ***Optional Header***

Tsize        Dsize       Bsize       Tstart      Dstart

0x0002ed30  0x00005858  0x000073b8  0x10000100  0x20000e30

SNloader     SNentry     SNtext      SNtoc       SNdata

0x0004      0x0002      0x0001      0x0002      0x0002

TXTalign     DATAalign   TOC         vstamp      entry

0x0005      0x0003      0x200061d0  0x0001      0x20005ee0

maxSTACK     maxDATA     SNbss       magic       modtype

0x00000000  0x00000000  0x0003      0x010b        1L

ftp:/home/admin> ps v 14596

   PID    TTY STAT  TIME PGIN  SIZE   RSS   LIM  TSIZ   TRS %CPU %MEM COMMAND

 14596  pts/0 A     0:00   76   568   788 32768   188   224  0.0  0.0 /usr/bin/


svmon


  현재 메모리에 대한 snapshot을 잡은 것이지만, 사용자 인터럽트를 사용하는 것이므로 진정한 의미의  snapshot이라 할 수 없다.


How Much Memory is in Use

# svmon -G

               size      inuse       free        pin    virtual

memory      2359296    2357650       1646     398806    1492391

pg space    1589248     163665

               work       pers       clnt      lpage

pin          398806          0          0          0

in use      1402168          0     955482          0

․ memory

    size : total size of memory(4KB)

    inuse = size - free

    free : free list 의 페이지 수

    pin : RAM에 pinned된 페이지 수

․ in use / pin

    work : working pages

    pers : persistent pages

    clnt : client pages(remote file pages)


Who is Using Memory?

# svmon -Put 10

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

     Pid Command          Inuse      Pin     Pgsp  Virtual 64-bit Mthrd LPage

   16952 atmsvcd           7482     2485     2011     9152      N     N     N

    Vsid      Esid Type Description              LPage  Inuse   Pin Pgsp Virtual

       0         0 work kernel seg                   -   3901  2483 1593  4576

    f01e         d work shared library text          -   2723     0   34  3573

    9d33         2 work process private              -    611     2  381   992

    2084         - pers /dev/hd2:10282               -    126     0    -     -

    c999         - pers /dev/hd2:10303               -     40     0    -     -

     1a0         1 pers code,/dev/hd2:5656           -     31     0    -     -

    508a         - pers /dev/hd2:10287               -     17     0    -     -

    708e         - pers /dev/hd2:10288               -      9     0    -     -

    60cc         - pers /dev/hd4:4120                -      6     0    -     -

    dd3b         f work shared library data          -      4     0    3    11

    50ca         - pers /dev/hd4:4123                -      4     0    -     -

    606c         - pers /dev/hd2:10283               -      3     0    -     -

    21c4         - pers /dev/hd2:10304               -      3     0    -     -

    . . . .

  결과는 요약부분과 상세 설명 부분으로 나뉘며, 메모리 사용량이 많은 프로세스부터 상위 10개를 보여준다.

  segment는 여러 프로세스에 의해서 공유될 수 있는데, 그런 세스먼트에 속하는 페이지는 여러 프로세스에 중복되어 나타날 수 있다. 따라서, inuse 필드 값을 다 더하면, 실 메모리 양보다 많아지게 된다.

  segment id=2084 는 persistent segment이며, /dev/hd2, 즉, /usr 파일시스템에 속하는 파일이며, 126페이지가 실 메모리에 있으며, 페이징 공간에 페이징 되지는 않은 상태이다.

  segment id=60cc는 / 파일시스템에 속하며, 해당 파일의 inode 값은 4120이다.

# ncheck -i 4120 /

4120    /etc/objrepos/CuAt

# find / -xdev -inum 4120 -print

/etc/objrepos/CuAt

Vsid는 virtual segment ID, Esid는 effective segment ID이고 해당 페이지에 접근하는데 사용되는 segment register를 반영한다.


Detailed Information on a Specific Segment ID

# svmon -D 9d33 -b

Segid: 9d33

Type:  working

LPage: N

Address Range: 0..995 : 65312..65535

Size of page space allocation: 381 pages (  1.5 MB)

Virtual: 992 frames ( 3.9 MB)

Inuse: 611 frames ( 2.4 MB)

           Page      Frame    Pin        Ref        Mod  ExtSegid    ExtPage

          65339      80707     Y          Y          Y         -          -

          65340      80708     Y          Y          Y         -          -

          65314      80374     N          Y          Y         -          -

             26      80413     N          Y          Y         -          -

          65338      78852     N          Y          Y         -          -

          65341      81922     N          Y          Y         -          -

          65337      82007     N          Y          Y         -          -

             25      80174     N          Y          Y         -          -

  2개 페이지가 메모리에 pinned 되어 있으며, 대부분의 페이지가 현재 참조되고 있고 변경되어 있다는 것을 알 수 있다. 이는 working segment 이기 때문이다.

※ -D 옵션을 사용하면, 성능에 영향을 주므로 주의해서 사용해야 한다.


List of Top Memory Usage of Segments

# svmon -Sut 10


    Vsid      Esid Type Description              LPage  Inuse   Pin Pgsp Virtual

    4e00         - pers /dev/backup:17               -  71465     0    -     -

    780f         - work kernel heap                  -   7214  3787  329  7245

    8c38         - pers /dev/backup:27               -   6025     0    -     -

    700e         - work misc kernel tables           -   4886     0  673  4886

       0         - work kernel seg                   -   3901  2483 1593  4576

    f01e         - work                              -   2718     0   34  3573

    19ea         - pers large file /dev/hd9var:247   -   2237     0    -     -

    8010         - work page frame table             -   1899  1899    0  1899

    fa56         - pers /dev/backup:24               -   1766     0    -     -

    8831         - work                              -   1665  1665    0  1665


svmon and vmstat

  vmstat free 필드 = svmon memory free 필드

  vmstat avm 필드 = svmon memory virtual 필드


svmon and ps

# svmon -P 9088


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

     Pid Command          Inuse      Pin     Pgsp  Virtual 64-bit Mthrd LPage

    9088 bash              6882     2485     1627     8277      N     N     N


    Vsid      Esid Type Description              LPage  Inuse   Pin Pgsp Virtual

       0         0 work kernel seg                   -   3901  2483 1593  4576

    f01e         d work shared library text          -   2718     0   34  3573

    748e         1 pers code,/dev/hd10opt:2421       -    135     0    -     -

    4a80         2 work process private              -     91     2    0    91

    5a82         f work shared library data          -     37     0    0    37

    6de5         - pers /dev/hd2:12307               -      0     0    -     -

# ps v 9088

   PID    TTY STAT  TIME PGIN  SIZE   RSS   LIM  TSIZ   TRS %CPU %MEM COMMAND

  9088  pts/0 A     0:00    2   512  1052 32768   498   540  0.0  0.0 bash


SIZE = virtual size in KB of data section of the process in paging space

      = number of working segment pages of the process have been touched

      = svmon의 private, lib data에서 Virtual 필드 값

      = 91 + 37 pages = 128 × 4 KB = 512

RSS = real memory size in KB of the process

     = sum of the number of working and code segment pages in memory

     = 91 + 37 + 135 pages = 263 × 4 KB = 1052

TRS = size of real memory of text

     = number of code segment pages(not include the shared text of the process)

     = 135 pages = 135 × 4 KB = 540


Calculating Minimum Memory Requirement of a Program


  total memory = T + ( N × ( PD + LD ) ) + F

    T : Number of pages for text(shared by all users)

    N : Number of instance of program

    PD : working segment pages in process private segment

    LD : shared library data pages used by the process

    F : file pages (shared by all users)

예) # svmon -P 8956

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

     Pid Command          Inuse      Pin     Pgsp  Virtual 64-bit Mthrd LPage

    8956 cron              6796     2485     1627     8260      N     N     N

    Vsid      Esid Type Description              LPage  Inuse   Pin Pgsp Virtual

       0         0 work kernel seg                   -   3901  2483 1593  4576

    f01e         d work shared library text          -   2718     0   34  3573

    91d2         2 work process private              -     65     2    0    65

    92d2         f work shared library data          -     46     0    0    46

    3ac7         - pers large file /dev/hd9var:21    -     46     0    -     -

    7acf         1 pers code,/dev/hd2:4256           -      8     0    -     -

    88b1         - pers /dev/hd2:6144                -      5     0    -     -

    70ae         - pers /dev/hd2:4099                -      3     0    -     -

    80b0         - pers /dev/hd2:2                   -      1     0    -     -

    18e3         - pers /dev/hd9var:17               -      1     0    -     -

      a0         - pers /dev/hd4:4103                -      1     0    -     -

    4088         - pers /dev/hd3:2                   -      1     0    -     -

    52ca         - pers /dev/hd2:78282               -      0     0    -     -

   T : 7acf = 8

   PD : 91d2 = 65

   LD : 92d2 = 46

   F : 88b1, 70ae, 80b0, 18e3, a0, 4088, 52ca = 12


ꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏ

Finding Memory-Leaking Programs


  memory leak은 프로그램 에러로 인해 메모리 해제를 하지 않고 계속 할당해서 사용함으로써 메모리가 부족하게 되는 현상이다. svmon 명령을 반복적으로 실행해서 프로세스의 working segment 영역이 계속해서 증가하는가를 검사한다. kernel segment의 leak은 mbuf leak이나 device driver, kernel extention, kernel 등에 의해서 발생할 수 있다.

  문제가 되는 서브루틴이나 코드의 줄을 구분하는 것은 매우 어려운 일이다. realloc()은 실제로 에러가 아닌 경우에도 memory leak과 같은 현상을 발생시키게 된다. realloc을 자주 사용하게 되면, 프로세스의 working segment가 점점 증가하게 된다.

  private working segment의 Inuse, Pgspace, Address Range 필드 값이 계속해서 증가할 경우, memory leak을 의심해야 한다.


ꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏ

RMSS simulation


  rmss(Reduced-Memory System Simulator)는 시스템의 메모리 보드를 교체하지 않고도 시스템의 메모리를 감소시킨 상황을 시뮬레이션할 수 있는 도구이다. 시스템의 메모리를 감소시키면서 시스템의 상황 변화를 모니터링 할 수 있다. rmss는 다음과 같은 질문에 답을 얻을 수 있는 자료를 제공한다.

  “일정한 성능을 얻기 위해 필요한 시스템의 메모리는 몇 MB인가?”

  “특정 메모리 양을 가지고 동시에 몇 명의 사용자에게 서비스를 할 수 있는가?”

  rmss는 capacity plan tool로 부하를 감당하기 위해 필요한 메모리 양을 산출하는데 이용되며, problem determination tool로도 사용될 수 있다.


2 Sytles of Using rmss

  - to change the memory size and exit

주어진 메모리 크기에서 응용 프로그램의 실행 상황을 살핀다. 응용 프로그램이 복잡하여 하나의 명령으로 실행할 수 없을 경우 또는 프로그램이 다수의 인스턴스로 실행되는 환경에서 사용한다.

  - as a driver program

응용 프로그램을 메모리 크기를 변화시켜 가면서 실행한다.

※ rmss 명령을 실행하기 전에, memory load control을 off로 설정해야 한다.

        /usr/samples/kernel/schedtune -h 0


to change the memory size and exit

  단위는 MB이며, 8MB에서 시스템 메모리 사이의 값을 줄 수 있다. 시스템의 환경에 따라서 어느 값이하로는 설정할 수 없을 수 있다. 그런 경우에는 에러 메시지를 보여준다.

  rmss는 free page frame의 페이지들을 unusable frame pool에 보관하는 방식으로 메모리를 줄이며, 메모리 크기를 원상태로 하면, pool에서 페이지들을 free list에 추가한다. 또한, rmss는 메모리 크기에 따라 자동적으로 시스템 환경변수와 데이터 구조를 변경한다. 변경하는데 걸리는 시간은 줄이는 메모리 크기에 비례한다.

  # rmss -c 128      memory size = 128 MB

  # rmss -p           current memory size

  # rmss -r           reset to total system memory size

※ rmss 명령은 실제로 사용 가능한 메모리 크기를 보여준다. 따라서, 메모리에 불량 부분이 있으면, 원래 값보다 적게 나온다. 성능에 대한 정보를 따로 제공하지 않기 때문에 다른 도구를 이용하여 성능을 측정하여야 한다.


as a driver program

  # rmss -s 시작메모리 -f 최소메모리 -d 변화량 -n 반복횟수 -o 결과파일 프로그램

  예) rmss -s 16 -f 8 -d 1 -n 1 -o rmss.out foo

Hostname:  widgeon.austin.ibm.com

Real memory size:   16.00 Mb

Time of day:  Thu Jan  6 19:04:04 2000

Command:  foo

Simulated memory size initialized to  16.00 Mb.

Number of iterations per memory size = 1 warm-up + 1 measured = 2.


Memory size  Avg. Pageins  Avg. Response Time    Avg. Pagein Rate

(megabytes)                     (sec.)           (pageins / sec.)

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

16.00            115.0           123.9                 0.9

15.00            112.0           125.1                 0.9

14.00            179.0           126.2                 1.4

13.00             81.0           125.7                 0.6

12.00            403.0           132.0                 3.1

11.00            855.0           141.5                 6.0

10.00           1161.0           146.8                 7.9

9.00            1529.0           161.3                 9.5

8.00            2931.0           202.5                 14.5

Avg. Pageins : 프로그램 실행 동안 발생한 모든 page in

Avg. Response Time : 프로그램 실행 시간

Avg. Pagein Rate : Pageins의 평균 비율

  위의 예에서는 14MB까지는 성능에 별다른 영향이 없으나, 13MB 부터는 성능이 점점 저하되는 것을 볼 수 있다. 현재 16MB에서의 성능치가 만족할 수 없다고 메모리를 추가하는 것은 성능에 이점이 없다는 것을 보여준다.


ꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏ

Tuning VMM Memory Load Control


h parameter

  memory load control에 의해서 프로세스가 suspend되는 시점을 정의한다. 임계값을 측정하는데는 po, fr 2가지 값이 사용된다.

        

  h = 0으로 설정되면, 사용하지 않겠다는 의미이다. 메모리가 128MB 이상이라면 디폴트 값은 0이고, 그렇지 않으며, 6이다. 메모리가 128MB 이상인 경우에는 보통 memory load control을 사용하지 않은 경우가 thrashing 상황을 더 잘 처리한다.

  시스템 설정에 관계없이 po/fr 값이 낮으면, thrashing 상태가 아니다.

        # /usr/samples/kernel/schedtune -h 4

        # /usr/sbin/schedo -o v_repage_hi=4


p parameter

  중지시킬 프로세스를 선택하는 기준으로 사용된다.

  r : number of repages         f : number of page faults

        

  디폴트 값은 4이다. 따라서, r/f 값이 0.25 이상이면 프로세스가 thrashing 현상을 발생시키고 있다고 볼 수 있다.

        # /usr/samples/kernel/schedtune -p 6

        # /usr/sbin/schedo -o v_repage_proc=6


m parameter

  멀티 프로그램의 최소 한계로, 이 값은 active process 수로 지정된다. 실행되고 있거나 페이지 I/O를 기다리는 프로세스는 active process 이고, 이벤트를 기다리거나 중지된 프로세스나 wait 프로세스는 제외된다.

  memory load control이 실행되더라도 m개의 active process가 실행되고 있도록 하는 것이다.


w parameter

  중지된 프로세스가 기다려야 할 시간.


e parameter

  한 번 중지된 프로세스는 지정한 시간 동안은 다시 중지되지 않는다.


ꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏ

Tunning with vmtune


minfree and maxfree

  free list를 관리하는 파라미터로 minfree 값이하로 free list가 감소하면, 페이지 스틸이 발생하여 maxfree 값이 될 때까지 페이지 스틸이 이루어진다. 미리 free memory page를 확보함으로써 메모리 할당 요청에 대비하며, 불필요한 I/O 발생을 제거한다.

  디폴트 값은 다음과 같다.

        

        minfree = maxfree - 8

        단, (maxfree - minfree) >= maxpgahead

  memory pool이 하나 이상인 경우에는 각각의 memory pool에 대해서 파라미터 값을 지정할 수 있으며, vmtune에 표시되는 값은 모든 풀의 값을 더한 값이다.

  minfree 페이지는 그 만큼 메모리를 낭비하는 것이다. minfree는 미래의 메모리 할당 요청에 대해 대비하는 것으로 응용 프로그램의 종류와 메모리 사용하는 방식에 대해서 알면, 효과적으로 대처할 수 있다. minfree 값을 설정할 때, 주요 프로그램이 사용하는 메모리를 svmon으로 확인하여 필요한 만큼의 메모리를 minfree로 지정할 수 있다. 이 때의 어려움은 프로그램이 한 번에 많은 메모리를 요구하지 않을 수 있기 때문에 불필요하게 메모리를 낭비하는 결과를 가져올 수도 있기 때문이다.

  minfree = 120 × # of CPUs

  maxfree = minfree + 8 × # of CPUs

  maxfree - minfree <= 100


memory pool

        # vmtune -m N

        # vmo -r -o mempools=N

  시스템 부팅시 메모리 풀 수를 변경하게 된다. 이 값은 커널 설정 파일에 기록된다. 디폴트로는 /usr/lib/boot/unix_mp 파일이며, vmtune은 변경 이전의 파일을 .sav 로 저장한다.


lrubucket

        # vmtune -l N

        # vmo -o lrubucket=N

  대량의 메모리를 가진 시스템에서 LRU 알고리즘에 따른 메모리 스캔의 부하를 감소시키기 위해서 lrubucket 파라미터를 조절할 필요가 있다.

  LRU 알고리즘에 따라 메모리를 스캔하면서 참조비트가 off인 페이지를 스틸하고 참조비트를 리셋한다. 이 과정에서 메모리가 큰 경우에는 많은 페이지를 스캔해야 한다. 따라서, 메모리 frame을 bucket으로 나누어서 관리한다. LRU 알고리즘은 하나의 bucket을 스캔하고 필요한 만큼의 메모리를 확보하지 못하면, 다른 bucket을 스캔하기 전에, 2번째 스캔을 하게 된다.

  디폴트 값은 131072 또는 512 MB 이다.


minperm / maxperm

        # vmtune -p n -P N

        # vmo -o minperm%=n

        # vmo -o maxperm%=N

  numperm : number of file pages in memory

        ․ numperm > maxperm,         steal only file pages

        ․ maxperm > numperm > minperm, repage 비율에 따라서 steal

        ․ numperm < minperm,          page 종류를 가리지 않고 아무거나 steal

  파일 I/O가 주요한 성능 제한 사항인지, computational page를 메모리에 유지하는 것이 중요한지 등에 따라서 설정 값을 변경할 수 있다. 특히, NFS를 사용하는 시스템에서는 보다 많은 file pages를 메모리에 보관할 수 있도록 하는 것이 성능향상에 도움이 된다.

w  File System으로 구성된 Oracle : minperm  10%, maxperm  30%

w  SAP R3(File System Oracle) : minperm  5%, maxperm  10%



strict_maxperm

        # vmtune -h 0|1

        # vmo -o strict_maxperm=0|1

  persistent file cache 에 대한 hard limit을 설정할 것인가? 1로 설정되면, maxperm 값이 hard limit으로 설정되며, 이 값 이상으로 file pages가 증가하게 되면, LRU 알고리즘에 따라 페이지 교체가 file pages 에 대해서 실행된다.

※ 사용할 때, 주의해서 사용하지 않으면, 예기치 않은 결과를 가져올 수 있다.


maxclient

        # vmtune -t N

        # vmo -o maxclient%=N

  JFS2 파일 시스템은 buffer cache로 client pages라는 메모리 페이지를 이용한다. 이 페이지들은 maxperm, minperm 임계값의 영향을 받지 않는다. 이 client pages에 대한 최대값을 지정하는 파라미터가 maxclient 이다.

  사용량이 maxclient 설정값에 도달하면, LRU는 client pages를 스틸한다. client pages를 스틸하고도 모자라면 다른 종류의 페이지도 스틸하게 된다. maxclient 값을 줄임으로써 LRU가 working segment pages를 스틸하지 못하도록 해야 할 필요가 있다. 또한, maxperm 이하로 값을 설정해야 한다.


ꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏ

Tuning Paging Space


´페이징 스페이스 부족과 관련된 에러 메시지는 다음과 같다.

"INIT: Paging space is low"

          "ksh: cannot fork no swap space"

      "Not enough memory"

          "Fork function failed"

          "fork () system call failed"

          "Unable to fork, too many processes"

          "Fork failure - not enough memory available"

          "Fork function not allowed. Not enough memory available."

          "Cannot fork: Not enough space"


npswarn

        # vmtune -w N

        # vmo -o npswarn=N

  페이징 공간의 가용한 페이지 수가 N이하로 줄어들면, OS는 프로세스에게 SIGDANGER 시그널을 보내게 된다. 프로세스는 이 시그널을 무시하거나, 종료하거나, disclaim()을 사용하여 메모리를 해제한다.

  디폴트 값은  max( 512, 4×npskill )


npskill

        # vmtune -k N

        # vmo -o npskill=N

  페이징 공간의 가용한 페이지 수가 N이하로 줄어들면, OS는 프로세스에게 SIGKILL 시그널을 보내고 강제로 종료시키기 시작한다. SIGDANGER 시그널에 응답한 프로세스나 early 할당 정책을 사용하는 프로세스는 영향을 받지 않는다.

  디폴트 값 = max(64, NumberOfPagingSpacePages/128)


nokilluid

        # vmtune -n N

        # vmo -o nokilluid=N

  uid가 N 이하인 사용자 프로세스는 npskill 파라미터의 영향을 받지 않는다.


fork() retry interval

  페이징 공간 부족으로 새로운 프로세스를 fork하지 못할 경우, 스케줄러는 5번 재시도한다. 이 때, 재시도 간격은 10clock tick이 디폴트이다.

        # schedtune -f N (clock tick)


ꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏ

Page Space Allocation Method


LPSA(Late Page Space Allocation)

  ․ allocated when actually touched(the page was modified somehow)

  ․ 페이지는 프로세스가 page-out 될 때, 할당된다.

  ․ 프로세스가 page-out될 가용한 공간을 항상 보장할 수 없다.

EPSA(Early Page Space Allocation)

  ․ paging space pages reserved when processes use malloc()

  ․ 프로세스가 페이징 공간 부족으로 kill되지 않는 것을 보장한다.

  ․ PSALLOC=early

DPSA(Deferred Page Space Allocation)

  ․ allocation delayed until necessary to page out the page

  ․ additional overcommitment of paging space

  ․ 한 번 page-out 페이지가 다시 RAM에 page-in 되더라도 그 공간은 reserved 됨.

  ․ 다음 경우에 할당된 페이지가 해제된다.

    - working segment로 page-in된 페이지

    - 쓰레드가 할당을 해제한 경우

    - thread exit

# vmtune -d 0|1      (DPSA=1)

# vmo -o deffps=0|1

  vmstat(avm), ps(SIZE, SZ) 등의 도구들은 DPSA 정책에 따라 실제로 access된 가상 메모리 크기를 보여준다. 반면에 svmon은 실제로 사용된 페이징 공간 크기를 보여주므로, 이 값은 vmstat의 avm 값보다 작게 출력된다.

  lsps -a는 실제로 사용되는 페이징 공간만을 보여준다, 그러나. lsps -s는 사용되지 않고 있지만, reserve된 페이징 공간도 고려해서 보여준다. 따라서, lsps -s 명령을 사용하는 것이 좀 더 정확하다고 할 수 있다.


ꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏ

Shared Memory


  shmat(), mmap()을 사용하여 파일들을 명시적으로 메모리에 매핑시킬 수 있다. 이렇게 함으로써 버퍼링과 시스템 콜로 인한 부하를 피할 수 있다. 이러한 메모리 영역을 shared segments라 한다. 4.2.1 버전 이후부터 32비트 응용 프로그램에만 적용된다. 11개의 shared memory segments 제공된다. 각 segment는 256MB 크기다. 응용 프로그램은 이러한 공유메모리 세그먼트에 read/write 함으로써 파일에 대한 read/write을 수행할 수 있다. 또한, 세그먼트에 대한 포인터를 사용하기 때문에 read/write system call로 인한 부하를 피할 수 있다.

  파일과 데이터는 다수의 프로세스에 의해서 공유될 수 있는데, 공기화 문제는 응용 프로그램에서 해결해야 한다. 전형적인 예로는 데이터베이스 프로그램이 공유 세그먼트를 데이터 베이스 버퍼 캐쉬로 사용한다.

  shared memory segments에 대한 페이징 공간도 할당된다.


EXTSHM(Extended Shared Memory)

  각 shared memory region은 크기에 관계없이 256MB 크기의 메모리 공간을 사용한다. 4.2.1 버전부터는 EXTSHM을 통해서 1바이트에서 256MB까지 크기를 지정할 수 있다.

  EXTSHM을 통해서 11개 세그먼트의 제한은 사라지게 되었다. EXTSHM을 사용하기 위해서는 프로그램의 환경 설정에 EXTSHM=ON으로 설정하면 사용할 수 있다. 프로세스가 사용할 수 있는 segment의 수에 대한 제한은 없으며, 사용하는 메모리 공간의 크기는 여전히 256MB 의 배수이다.


ꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏꠏ

Memory Affinity Support


  POWER 기반의 SMP 장비들은 다수의 MCM을 포함하고 있다. 시스템 메모리는 이러한 MCM에 부착되어 있다. 모든 프로세서가 어떤 메모리에도 접근할 수 있지만, 자신의 MCM에 부착되어 있는 메모리에 접근하는 것이 제일 빠르다.

  따라서, page fault를 발생시킨 프로세서의 MCM에 부착된 메모리에서 page fault를 해결하도록 하는 것이 memory affinity support이다.

        # vmtune -y 0|1

        # vmo -r -o memory_affinity=0|1

    ※ bosboot, reboot를 반드시 해줘야만 효과가 있다.

  응용 프로그램에서 이 기능을 사용하기 위해서는 환경 변수를 설정해야 한다.

        # export MEMORY_AFFINITY=MCM

반응형

'UTIL > Leak Detect' 카테고리의 다른 글

Linux 메모리 릭 체킹 Valgrind  (0) 2015.08.17
반응형

출처 : 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://coffeenix.net/board_view.php?bd_code=36



제  목 : 유용한 find 명령어 예 모음
작성자 : 좋은진호(truefeel, http://coffeenix.net/ )
작성일 : 수시로 추가했음

아래는 제가 자주 쓰는 find 명령인데, 유용할 듯 해서.
지금까지 적어뒀던 것과 아주 보편적이라고 생각되는 것입니다.
계속 추가됩니다. ^^

-------------------------------------------------------
1. 현재 디렉토리( . ) 이하에 확장자가 .html( -name "*.html" ) 인 파일만 ( -type -f )

find . -name "*.html" -type f -ls

2. 파일 크기

# 파일 크기가 300KB 이상( -size +300k )인 파일만 
# (호스팅되는 홈피내에 큰 사이트의 파일이 있는지 찾을 때 유용)
find . -size +300k -ls

# 파일 크기가 500bytes 이하( -size -500c )인 파일만  
find . -size -500c -ls 

3. 수정일

# 수정한지 20일 이상( -mtime +20 )된 파일과 디렉토리
find . -mtime +20 -ls 

# 수정한지 20일 이상된 파일만
find . -mtime +20 -type f -ls

# 수정한지 20일 이상된 파일만 삭제 ( -exec rm {} \; ) 
# (정기적으로 20일이 지난 파일을 삭제할 때 유용)
find . -mtime +20 -type f -ls -exec rm {} \;

# 수정한지 3일 이내( -mtime -3 )의 파일만 (백업할 때 유용)
find . -mtime -3 -type f -ls

# 수정한지 30분 이내( -mmin -30 )의 파일만
find . -mmin -30 -type f -ls

4. 퍼미션 및 파일 소유

# 파일시스템 전체( / )에서 SUID/SGID가 설정된 모든 파일 목록을 얻음
find / -type f \( -perm -04000 -o -perm -02000 \) -ls

# 소유자가 없는 파일 목록을 얻음 (사용자는 이미 삭제했는데, 파일이 남은 경우)
find / -nouser -o -nogroup

5. 출력 형식 지정

# 출력 형식을 printf로 만들어서 (출력 결과를 다른 프로그램에서 받아서 쓸 때 유용)
# %h = 경로, %f = 파일명, %k = KB, %s = Bytes

# 형식 : <경로/파일명> <파일크기KB>
find . -printf "%h/%f \t %kKB \n"
... 생략 ...
./public_html/phps/icon/type/pcx.gif      4KB
./public_html/phps/icon/type/ra.gif       4KB
./public_html/phps/icon/type/sound.gif    4KB
./public_html/phps/icon/type/text.gif     4KB

# 형식 : <경로/파일명> <파일크기Bytes>
find . -printf "%h/%f \t %sKB \n"
... 생략 ...
./public_html/phps/icon/type/movie.gif    912Bytes
./public_html/phps/icon/type/mp3.gif      958Bytes
./public_html/phps/icon/type/pcx.gif      897Bytes
./public_html/phps/icon/type/ra.gif       903Bytes
./public_html/phps/icon/type/sound.gif    932Bytes

6. 홈페이지 포팅할 때 퍼미션 안 맞는 경우 유용한 것

# 확장자가 .htm* .gif, .js, .css 인 것만 퍼미션을 644(rw-r--r--)로
find . -name "*.htm*" -o -name "*.gif" -o -name "*.js" -o -name "*.css" -exec chmod 644 {} \;

# 파일은 퍼미션을 644로
find . -type f -exec chmod 644 {} \;

# 디렉토리는 퍼미션을 701로
find . -type d -exec chmod 701 {} \;

# 하위의 모든 퍼미션을 바꾸지 않고 depth를 지정하여 제한을 둘 때
# 옵션 : -maxdepth 숫자  (1=현재디렉토리만, 2=현재디렉토리 포함하여 한단계 하위디렉토리까지만)
find . -maxdepth 1 -type d -exec chmod 701 {} \;

※ -maxdepth는 -type나 -perm 등의 조건연산자가 아닌 옵션이다. 
   따라서 조건연산자보다 먼저 사용해야한다. (다른 명령처럼 옵션을 먼저쓰는 것으로 이해하면 됨)
   find . -type -d -maxdepth 1 과 같이 사용하는 것은 옳지 않다.


반응형
반응형

출처 : http://kuaaan.tistory.com/trackback/142



delete와 delete[], new와 new[]를 구분해서 사용해야 하는 이유 :

delete를 사용하든 delete[]를 사용하든 메모리는 정상적으로 해제된다. 하지만 4바이트 INT 타입의 10개짜리 Array를 메모리해제할 경우 delete[]를 사용하면 4바이트씩 10번 해제하지만 delete를 사용하면 40바이트짜리 메모리를 한번 해제한다. 

내부적으로 얘기하자면 new[] 를 사용할 경우 할당하는 메모리 앞에 4바이트 메모리를 더 할당하여 배열의 Size를 저장해놓는다. 이 메모리를 해제할 때 delete[]를 사용하면 이 값(배열의 Size)을 확인하지만 delete를 사용하면 확인하지 않는다. 따라서 delete[]를 사용해야 Array가 Class Type Array인 경우 각각의 Entry에 대해 배열의 Size만큼의 생성자/소멸자를 호출해 줄 수 있다.
http://minjang.egloos.com/1414494
요약하면, class array를 메모리 해제할때 delete[]를 사용하지 않고 그냥 delete를 사용할 경우 소멸자가 한번만 호출되어버리는 문제가 발생한다.

실제로 테스트를 해보니 맞다. ^^
  1. class CTest  
  2. {  
  3. public:  
  4.     CTest()  
  5.     {  
  6.         printf("Constructer(0x%08x)\r\n"this);  
  7.     }  
  8.     ~CTest()  
  9.     {  
  10.         printf("Destructor(0x%08x)\r\n"this);  
  11.     }  
  12. };  
  13.   
  14. int _tmain(int argc, _TCHAR* argv[])  
  15. {  
  16.     CTest* pTest = new CTest[10];  
  17.     delete pTest; // 여기!!  
  18. //  delete[] pTest;   
  19.     return 0;  
  20. }  


위와 같은 소스코드를 실행시키면 다음과 같이 된다.
Constructer(0x003e3c1c)
Constructer(0x003e3c1d)
Constructer(0x003e3c1e)
Constructer(0x003e3c1f)
Constructer(0x003e3c20)
Constructer(0x003e3c21)
Constructer(0x003e3c22)
Constructer(0x003e3c23)
Constructer(0x003e3c24)
Constructer(0x003e3c25)
Destructor(0x003e3c1c)
계속하려면 아무 키나 누르십시오 . . .

10개의 인스턴스가 해제되었는데, 소멸자는 한번만 호출되었음을 알 수 있다.
만약 소멸자에서 해제해 주는 메모리나 리소스가 있었다면 9개씩의 Leak이 발생했을 것이다.

delete를 delete[]로 수정해주고 나니 아래와 같이 정상적으로 소멸자가 호출된다.
Constructer(0x003e3c1c)
Constructer(0x003e3c1d)
Constructer(0x003e3c1e)
Constructer(0x003e3c1f)
Constructer(0x003e3c20)
Constructer(0x003e3c21)
Constructer(0x003e3c22)
Constructer(0x003e3c23)
Constructer(0x003e3c24)
Constructer(0x003e3c25)
Destructor(0x003e3c25)
Destructor(0x003e3c24)
Destructor(0x003e3c23)
Destructor(0x003e3c22)
Destructor(0x003e3c21)
Destructor(0x003e3c20)
Destructor(0x003e3c1f)
Destructor(0x003e3c1e)
Destructor(0x003e3c1d)
Destructor(0x003e3c1c)
계속하려면 아무 키나 누르십시오 . . .

아 그렇군. ^^


반응형
반응형

new 실패에 따른 프로세스 종료원인을 찾다가 좋은 정보를 찾았습니다.

블로깅...


출처 : http://kuaaan.tistory.com/123




동적 메모리를 다음과 같이 사용하였습니다. 어디가 틀렸을까요?

  1. LPINT   lpInt = NULL;  
  2.   
  3. lpInt = (LPINT)malloc(sizeof(INT));  
  4. *lpInt = 4;  
  5.   
  6. printf("Value : %d\r\n", *lpInt);  
  7.   
  8. free(lpInt);  

동적 메모리를 할당한 후 정상적으로 할당되지 않은 경우에 대한 예외처리가 되지 않았군요. ^^
좀더 꼼꼼한 분이라면 다음과 같이 코딩하시겠지요.
  1. LPINT   lpInt = NULL;  
  2.   
  3. lpInt = (LPINT)malloc(sizeof(INT));  
  4.   
  5. if (lpInt == NULL)  
  6. {  
  7.     printf("Fail to alloc memory!!\r\n");  
  8.     return FALSE;  
  9. }  
  10.   
  11. *lpInt = 4;  
  12.   
  13. printf("Value : %d\r\n", *lpInt);  
  14.   
  15. free(lpInt);  
위와 같이 코딩하면 메모리 할당에 실패한 경우 "Fail to alloc memory!!"라는 에러메시지를 표시하고 프로그램은 종료하게 됩니다.


그렇다면 malloc 대신 new를 사용하는 다음의 코드는 어떨까요?
많은 분들이 사용하시는 코드입니다만... 이렇게 하면 동적 메모리 할당이 실패한 경우에 대해 올바르게 Exception Handling이 가능할까요?
  1. LPINT   lpInt = NULL;  
  2. INT nTotalBytes = 0, nAllocByte = 10000000;  
  3.   
  4. while(TRUE)  
  5. {         
  6.     lpInt = NULL;  
  7.   
  8.     lpInt = new INT[nAllocByte];  
  9.     nTotalBytes += nAllocByte * sizeof(INT);  
  10.   
  11.     if (lpInt == NULL)  
  12.     {  
  13.         printf("Fail to alloc memory!!\r\n");  
  14.         break;  
  15.     }  
  16.   
  17.     printf("Alloc Success!! (%d)\r\n", nTotalBytes);  
  18. }  
  19.   
  20. // blah~ blah~  

결론부터 얘기하자면 위와 같이 포인터가 NULL인지 체크하는 방식으로는 new 연산자에 대한 예외처리를 할 수 없습니다.


위와 같이 프로그램은 에러창을 내뱉고 죽어버립니다. 죽는 부분에도 보면 "Fail to alloc memory!!" 라는 메시지는 보이지 않습니다. 말하자면, 예외 처리 루틴을 타지 않은 것이지요.

new 연산자 관련된 MSDN 을 검색해보면 다음과 같은 내용이 있습니다.

말하자면, new 연산자가 메모리 할당에 실패했을 경우, C++ 스탠다드에 따라 std::bad_alloc Exception을 throw한다는 의미입니다. exception이 throw되었기 때문에 넘겨받은 포인터가 NULL인지 체크하는 부분까지 진행되지도 않고 프로그램이 종료된 것입니다.



음. 그렇다면 다음과 같이 코딩하면 메모리 할당 예외처리가 가능하겠군요.
  1. try  
  2. {  
  3.     LPINT   lpInt = NULL;  
  4.     INT nTotalBytes = 0, nAllocByte = 10000000;  
  5.   
  6.     while(TRUE)  
  7.     {         
  8.         lpInt = NULL;  
  9.   
  10.         lpInt = new INT[nAllocByte];  
  11.         nTotalBytes += nAllocByte * sizeof(INT);  
  12.   
  13.         printf("Alloc Success!! (%d)\r\n", nTotalBytes);  
  14.     }  
  15. }  
  16. catch ( exception e )  
  17. {  
  18.     printf("%s\r\n", e.what( ));  
  19. }  

코드를 위와 같이 수정하고 실행시키면 다음과 같이 동작하게 됩니다.

종료되기 직전 부분을 보면 제대로 Exception Handling이 되었다는 것을 알 수 있습니다.

그런데, 동적메모리 할당할 때마다 이와 같이 try ~ catch를 해주려면 너무 귀찮죠. 성능 문제로 try ~ catch를 사용하시지 않는 경우도 있구요. 더 좋은 방법은 "new handler"를 등록해주는 것입니다.


MSDN을 좀 더 검색해보면 "new handler"에 관한 내용이 나와 있습니다.

If the attempt is successful, the function returns a pointer to the allocated storage. Otherwise, the function calls the designated new handler. If the called function returns, the loop repeats. The loop terminates when an attempt to allocate the requested storage is successful or when a called function does not return.

The required behavior of a new handler is to perform one of the following operations:

  • Make more storage available for allocation and then return.

  • Call either abort or exit(int).

  • Throw an object of type bad_alloc.

The default behavior of a new handler is to throw an object of type bad_alloc. A null pointer designates the default new handler.

The order and contiguity of storage allocated by successive calls to operator new(size_t) is unspecified, as are the initial values stored there.


위의 내용을 요약해보면 다음과 같습니다.

1. new 연산자가 메모리 할당에 실패한 경우 "new handler"로 지정된 함수가 호출된다. 이 함수가 리턴한 다음에 메모리 할당이 실패한 시점부터 계속 실행된다.

2. "new handler" 는 다음의 세가지 작업 중 한가지를 수행해야 합니다.
1) 메모리를 확보한 후 return한다.
2) 프로세스를 종료시킨다.
3) bad_alloc 을 throw한다.

3. Default "New Handler"는 bad_alloc 을 throw 한다.

음, new 연산자가 메모리 할당에 실패했을 때 bad_alloc이라는 exception이 throw 되는데, 이것은 사실은 Default로 등록된 "new handler"에서 하는 일이라는 것을 알 수 있네요.

그렇다면, 이 내가 원하는 함수를 "new handler"로 등록하려면 어떻게 해야 할까요??
이런 용도로 사용되는 set_new_handler 라는 API가 있습니다.

set_new_handler 를 사용해 다음과 같이 new handler를 지정할 수 있습니다.
  1. void __cdecl MyNewHandler( )  
  2. {  
  3.    printf("Fail to Alloc Memory \r\n");  
  4. //   throw bad_alloc();  
  5.    ExitProcess(FALSE);  
  6.    return;  
  7. }  
  8.   
  9. int _tmain()  
  10. {  
  11.     set_new_handler (MyNewHandler);  
  12.   
  13.     LPINT   lpInt = NULL;  
  14.     INT nTotalBytes = 0, nAllocByte = 10000000;  
  15.   
  16.     while(TRUE)  
  17.     {         
  18.         lpInt = NULL;  
  19.       
  20.         lpInt = new INT[nAllocByte];  
  21.         nTotalBytes += nAllocByte * sizeof(INT);  
  22.   
  23.         printf("Alloc Success!! (%d)\r\n", nTotalBytes);  
  24.     }  
  25.   
  26.     // blah~ blah~  
  27. }  

결과는 다음과 같습니다.


제대로 Handler 가 호출되었다는 것을 알 수 있습니다.

그렇다면 이 Handler에서는 어떤 작업을 해주어야 할까요?

이 Handler가 return되면 실패했던 new 작업을 재시도합니다. 이때 만약 다시 실패한다면 new handler가 다시 호출되지요. 따라서 new handler에서 메모리부족을 해결하지 않고 return해버린다면 무한루프에 빠지게 됩니다.

그렇다면 new handler에서 메모리를 확보하는 것이 가능한가? 사실은 불가능합니다. 메모리가 부족하다는 것은 실제로 시스템 가상메모리가 부족하거나 아니면 Application에서 Memory Leak이 발생하고 있다는 의미가 되는데, 일개 Exception Handler에서 맘대로 시스템 가상메모리를 확보할 수도 없고, Leak된 메모리를 쫓아가서 메모리해제를 해 줄 수도 없는 노릇이죠. (만약 그게 가능하다면 처음부터 Leak이 발생하지도 않았겠죠. ^^)

제 생각에는 이 예외처리자는 그냥 로깅을 남기고 예외창 없이 조용히 죽게 만드는 정도의 작업 외에는 실제로 할 수 있는 일은 없을 것 같습니다.
혹시 다른 생각이 있으신 분은 알려주세요. :)

※ 이 글에서 쓰인 샘플코드는 MSDN의 코드를 참고하였습니다. :)


-----------------------------------------------------------------------------------------------------------------
출처 : http://cafe.naver.com/totalprogramming/34

보통 C++ 개발자중에 상당수가 C언어를 접했을 것이다.

간혹가다보면^^ C++개발자들이 실수를 하는데,

바로 new연산자를 사용함에 있다.

 

char* buf;

buf = new char[100];

if(NULL == buf){

      return FALSE;

}

 

이런식으로 사용하고 예외 처리를 하는데, 여기에는 문제점이 있다.

new연산자는 heap 메모리가 부족할 경우에는 NULL을 리턴하지 않는다.

할당을 실패할 경우에는 예외가 발생되어, if(NULL == buf)이 구문이 수행되지 않는다.

NULL체크 방식은 과거의 malloc을 사용했을 경우의 처리인 것이다.

C++에서는 이런 예외처리를 하기 위해 아래와 같이 #include <new>에 있는 bad_alloc객체를 이용해서

예외처리를 하고, NULL체크를 할수 있는 방식도 제공해준다.

 

 

#include <new>
#include <iostream>
using namespace std;

class BigClass {
public:
   BigClass() {};
   ~BigClass(){}

#ifdef _WIN64
      double BigArray[0x0fffffff];
#else
      double BigArray[0x0fffffff];
#endif
};

int main() {
   try {
      BigClass * p = new BigClass;
   }

   catch( bad_alloc a) {
      const char * temp = a.what();
      cout << temp << endl;
      cout << "Threw a bad_alloc exception" << endl;
   }

   BigClass * q = new(nothrow) BigClass;

   if ( q == NULL )
      cout << "Returned a NULL pointer" << endl;

   try {
      BigClass * r[3] = {new BigClass, new BigClass, new BigClass};
   }

   catch( bad_alloc a) {
      const char * temp = a.what();
      cout << temp << endl;
      cout << "Threw a bad_alloc exception" << endl;
   }
}



반응형
반응형
출처 : 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메가에서 프로그램이 메모리 할당에 실패했던 문제가 해소되었다.



반응형
반응형

Using static and shared libraries across platforms

I produced hereafter some information about shared libraries on different systems. However, this information is probably very sparse on details and may even not be up-to-date. Actually, keeping track of changes is nearly impossible.
The definitive information usually comes from the operating system docs. (e.g. HP's "HP-UX Linker and Libraries User's Guide", Sun's "Linker and Libraries Guide", SGI's "MIPSpro Compiling and Performance Tuning Guide", IBM's "AIX Linking and Loading Mechanisms", etc.), where there is often advice on the best options for performance.
GNU libtool offers an abstraction layer to shared library management.


Feedback is welcome.


Adapted from:
Cross platform development, Using Shared Libraries across Platforms, Shah, Amal ; Xiao, Hong, C/C++ Users JournalMay 1998, Volume 16 Number 5

Shared and static libraries information
LinuxSolarisHP-UXCompaq (Digital) Tru64AIXSGIWin32MacOS XVMSOS/390
Version[kernel 2.x, GCC 2.95.x and later][2.8][11][4.x][4.3 and later][Irix 6.5][NT 4][10.x][unmaintained][unmaintained]
1compiler flag (position independent code)-fPIC-KPIC, -Kpic+z/+Zxxxxxxxx-KPIC (default)xxxx-fno-commonxxxx-DLL
2ashared library creation flag-shared-G-b-shared-bM:SRE-sharedlink /DLLcc -bundle, -dynamiclib
libtool -dynamic
/SHARExxxx
2bshared library creation (C++)g++ -fPIC -shared -oCC -G -oaCC -b -ocxx -shared -oxlC -G (or -qmkshrobj)
obsolete:/usr/vacpp/bin/makeC++SharedLib -G -o
(was in /usr/ibmcxx/bin or/usr/lpp/xlC/bin/)
CC -shared -oCL -LD -Fexxx.DLL??
libtool -dynamic
????
2cstatic archiver (C++)arCC -xar -oarararCC -ar -oLIB (avoid link /lib that creates __impl symbols)??
libtool -static
????
3alibrary name(ld option) -soname name-h name(ld option) +h name(ld option) -soname namexxxx(ld option) -soname name/OUT:name-compatibility_version, -current_version/SHARE=xxxx
3bfile extension.so.so.sl.so.so (or .a).so.DLL.dylib.EXE??
4executable link options-Bdynamic
-Lpath -lname
-Bdynamic
-Lpath -lname
-a,shared
-Lpath -name
-no_archive
-Lpath -lname
-brtl
-bdynamic
-Lpath -lname
-Bdynamic,
-Lpath -lname
Controlled by .lib files??xxxxfilename/SHAREABLE
5aruntime path specification-rpath <path>-R <pathlist>-Wl,+b <pathlist> -Wl,+s-rpath <path>-blibpath:<path>
(by default, it is set to the arguments of -L)
-rpath <path>/LIBPATH:-install_name <path>xxxxxxxx
5bDoes not build the path for shared libraries into the executabledefault-norunpathchatr +b disable <file>default-blibpath:/usr/lib:/libdefault????????
6controlling symbolsusing a script file (see "info ld")-z defs/ nodefs/ muldefs+v[no] shlibunsats-expect [error] _unresolvedxxxx-ignore[no] _unresolved/FORCE: MULTIPLE [UNRESOLVED]??xxxxxxxx
LinuxSolarisHP-UXCompaq (Digital) Tru64AIXSGIWin32MacOS XVMSOS/390
7exports file/link option
(see notes)
using a script file (see "info ld")using a script file (see "man ld")+e,symname-exported_symbol.exp-exported_symbol
-exports_file filename
.def/__declspec(dllexport)-exported_symbols_list/SYMBOL_TABLE=(...).x file/
#pragma export()
8hiding symbolsusing a script file: VERSION command (see "Version Script" section in "info ld")using a script file (see "man ld") (see this article)-h symname-hidden_symbol, -hiddenxxxx-hidden_symbol,
-hiddens_file filename
using a .def file-unexported_symbols_listxxxxxxxx
9runtime library pathLD_LIBRARY_PATHLD_LIBRARY_PATH
LD_LIBRARY_PATH_64
SHLIB_PATH
LD_LIBRARY_PATH (64 bits)
LD_LIBRARY_PATHLIBPATHLD_LIBRARY_PATH
LD_LIBRARYN32_PATH
LD_LIBRARY64_PATH
. and then PATHDYLD_LIBRARY_PATH
DYLD_FALLBACK_LIBRARY_PATH
SYS$SHARELIBPATH
10symbol binding-Bsymbolic-Bsymbolic-Bsymbolic /immediate /deferredxxxxxxxx-Bsymbolicxxxx??xxxxxxxx
11runtime debugging(c.f. man ld.so)
LD_BIND_NOW
LD_TRACE_LOADED_OBJECTS
LD_DEBUG=help
ltrace
(c.f. man ld.so.1)
LD_BIND_NOW
LD_DEBUG
ld -D help
(c.f. man dld.sl)
_HP_DLDOPTS
(c.f. man loader)
LD_BIND_NOW
_RLD_ARGS
LDR_CNTRL(c.f. man rld)
LD_BIND_NOW
_RLD_PATH, _RLD_ARGS
xxxxDYLD_BIND_AT_LAUNCH
DYLD_PRINT_LIBRARIES
DYLD_PREBIND_DEBUG
xxxxxxxx
12runtime preloadLD_PRELOADLD_PRELOADLD_PRELOAD (probably HP-UX >= 11)_RLD_LIST "xxx.so:DEFAULT"xxxx_RLD_LIST "xxx.so:DEFAULT"??DYLD_INSERT_LIBRARIES????
13loaderld.sold.sodld.slloaderxxxxrldxxxxdyldxxxxxxxx
14runtime performancexxxxxxxxfastbind tool-quickstart_infoxxxx-quickstart_info/DELAYLOADxxxxxxxxxxxx
LinuxSolarisHP-UXCompaq (Digital) Tru64AIXSGIWin32MacOS XVMSOS/390
15versioningusing a script file: VERSION command (see "info ld")using a script file (see "man ld")
-M mapfile
xxxxxxxxxxxx-set_version/-exact_version/
-ignore_version
/VERSION:major.minor??/GSMATCH=xxxx
16entry pointsxxxxxxxxxxxxxxxxxxxxxxxxDllMainxxxxxxxxxxxx
17dynamic loading /
dynamic symbol access
dlopen / dlsymdlopen / dlsymshl_load / shl_findsym
(64 bits) dlopen / dlsym
dlopen / dlsymloadquery/loadbind
(AIX 4.2) dlopen / dlsym
dlopen / dlsymLoadLibrary / GetProcAddress"man 3 dyld"lib$find_image_symboldllload / dllqueryfn/ dllqueryvar
18utilitiesldd, ldconfig, objdump, ltrace, readelfldd, elfdump, pvs, dumpstabs (compilers V.6), crle (Solaris>=8)chatr
odump
ldd, elfdump (HP-UX >= 11)
odump -Dldump -H
ldd (in AIX tools)
elfdump -Dl
pldd
ldd (IRIX >= 6.5)
DUMPBIN, depends, EXEHDR, link -dumpotoolANALYSE/IMAGExxxx
19documentationman: ld, ld.so, ldd
info: ld, gcc, binutil
HOWTO: ELF-HOWTO, GCC-HOWTO
man: ld, ld.so.1, ldd, pvsman: ld, dld.sl, chatrman: ld, loader, odumpman: ld, dumpman: dso, ld, rld, elfdump, lddMSDNman: ld, libtool, dyld, otool????
LinuxSolarisHP-UXCompaq (Digital) Tru64AIXSGIWin32MacOS XVMSOS/390

Notes:


Acknowledgments

Juan Altmayer Pizzorno, Wolfgang Haefelinger, Per Losenborg, Anil E. Sahukar, Andrew Stalewski, Pirasenna Velandai Thiyagarajan, Nathan Stratton Treadway, Stephan Weber, Bo Xie

반응형
반응형
  1. prstat -s rss

    '-s' sorts prstat output by rss column (see man page for other columns). Also try '-a' option for a per user accumulation.

  2. ps -eo pid,pmem,vsz,rss,comm | sort -rnk2 | head

    Top 10 RAM consumers. '-o pmem' displays percentage of resident memory i.e. RAM used by process.

  3. ls -lh /proc/{pid}/as

    Easy way to show total address space (vsz) of a process. Useful in combination with pgrep to accumulate by user, pattern, ... e.g.:

    for pid in `pgrep -U webserver`; do ls -lh /proc/$pid/as; done


반응형
반응형

UNIX 및 Linux 운영 체제에서 ulimit 값 설정

UNIX 또는 Linux 운영 체제에서 적절한 ulimit 값을 설정하면 IBM® Cognos® Business Intelligence가 수행하는 방식에 영향을 미칠 수 있습니다.

예를 들어, Linux 운영 체제에서는 스택 ulimit 설정이 원인이 되어 발생하는 문제점에는 대형 보고서를 처리할 때 BIBusTKServerMain의 비정상적으로 높은 메모리 사용량 또는 BIBusTKServerMain 오류가 포함됩니다.

  • Linux 운영 체제에서 32비트 보고서 서비스를 사용 중인 경우 보고서는 실패할 수 있습니다.
  • Linux 운영 체제에서 64비트 보고서 서비스를 사용 중인 경우 실행 중인 보고서 또는 유휴 BIBusTKServerMain 프로세스가 사용 가능한 모든 RAM을 사용할 수 있습니다.

반면 UNIX 운영 체제에서는 스택 ulimit 설정이 너무 낮은 경우에 문제가 발생할 수 있습니다.

스택 ulimit 설정을 올바르게 설정하면 이러한 문제점을 방지할 수 있습니다.

새 설치에 권장되는 ulimit 설정은 다음과 같습니다.

IBM AIX®
  • CPU 시간(초): ulimit -t unlimited
  • 파일 크기(블록): ulimit -f unlimited
  • 최대 메모리 크기(KB): ulimit -m unlimited
  • 최대 사용자 프로세스: ulimit -u unlimited
  • 열린 파일 수: ulimit -n 8192(최소값)
  • 스택 크기(KB): ulimit -s 8192(최소값)
  • 가상 메모리(KB): ulimit -v unlimited
Sun Solaris
  • CPU 시간(초): ulimit -t unlimited
  • 파일 크기(블록): ulimit -f unlimited
  • 최대 사용자 프로세스: ulimit -u unlimited
  • 메모리(KB): ulimit -m unlimited
  • 열린 파일 수: ulimit -n 8192(최소값)
  • 스택 크기(KB): ulimit -s 8192(최소값)
  • 가상 메모리(KB): ulimit -v unlimited
HP-UX
  • CPU 시간(초): ulimit -t unlimited
  • 파일 크기(블록): ulimit -f unlimited
  • 메모리(KB): ulimit -m unlimited
  • 파일 수(디스크립터): ulimit -n 8192(최소값)
  • 스택 크기(KB): ulimit -s 8192(최소값)
Linux(x 및 z)
  • CPU 시간(초): ulimit -t unlimited
  • 파일 크기(블록): ulimit -f unlimited
  • 최대 메모리 크기(KB): ulimit -m unlimited
  • 최대 사용자 프로세스: ulimit -u unlimited
  • 열린 파일 수: ulimit -n 8192(최소값)
  • 스택 크기(KB): ulimit -s unlimited
  • 가상 메모리(KB): ulimit -v unlimited
참고: 애플리케이션의 수명 주기 동안 이러한 설정을 환경에 맞게 조정해야 할 수 있습니다.


반응형
반응형

출처 : http://no1rogue.blog.me/30097158983



* 메모리 맵 - mmap() <파일 혹은 디바이스를 메모리와 대응>

; 파일(리눅스에서는 디바이스도 파일로 처리하므로 디바이스도 메모리 맵으로 연결 가능)을 처리하기 위해서는 보통 저수준으로는 파일 디스크립터를 이용하고, 고수준으로 접근하기 위해서는 파일 구조체 포인터를 이용하여 접근하게 된다. 하지만 이런 방식을 이용하면 버퍼를 거쳐서 실제 입출력을 하게된다. 하지만 mmap()을 이용하여 메모리 맵 방식으로 파일을 연결하게 되면 버퍼를 이용하는 것이 아니라 '페이지(page)'를 이용하여 데이터 처리가 가능해진다. 상대적으로 크기가 작은 버퍼에 비해 보통 4KB의 크기를 가지는 페이지를 이용하면 처리 가능한 크기와 처리 속도가 향상된다. 그렇기 때문에 데이터 크기가 크거나 빠른 처리를 해야하는 경우 메모리 맵 방식을 종종 사용하게된다. 메모리 맵을 사용하면 처리 속도가 빨라지는 예가 바로 처리하는 데이터가 큰 동영상을 볼 때이다. 그리고 실제 실행 파일도 윈도우든 리눅스든 실행 할 때 페이지로 분할되므로 메모리 맵 방식으로 매핑된다. 대표적으로 코드 영역은 데이터의 변경이 없기 때문에 메모리 맵을 이용해 맵핑하면 처리 속도는 물론이고 메모리 낭비도 없다. 

 

 

* 특징

1. 생성된 메모리 맵을 포인터를 이용하여 쉽게 사용 가능하다.

2. 파일로 연결하여 사용시 메모리-파일 사이의 동기화가 편하다.

3. IPC(프로세스간 통신)로 활용 가능하다.

4. 대용량의 데이터를 사용할 시 성능이 향상된다.

 

* 주의점

- 메모리 맵은 바로 파일의 처리하는게 아니라 가상 메모리로 활용되는 페이지에 맵핑하는 방식이다. 그러므로 파일과 해당 메모리 맵이 된 페이지가 다른 공간이다. 그러므로 커널에 의해 여유 시간에 동기화(둘의 데이터가 같아지는..)가 될 때까지 서로 다른 데이터를 가질 수 있다. 그러므로 동기화에 대한 주의를 할 필요가 있다. <개발자가 직접 커널에 동기화를 명령 할 수 있는 함수도 있다. - fsync()>

 IPC로 사용 할 때에도 프로세스간 동기화에 대한 주의도 필요하다.


* 2가지 방식

1. 공유 메모리 맵 방식 (Shred Memory-Map)

; 메모리 맵 변경 시 원본 파일과 데이터가 동기화가 되는 방식

2. 복사 메모리 맵 방식 (Private Memory-Map)

; 처음 메모리 맵에 매핑 될때 파일의 내용을 읽어와서 복사하고 그 이후 동기화 하지 않는 방식.

 

 

* 메모리 맵 생성 함수 - mmap()

 

void* mmap(void *state, size_t length, int prot, int flags, int fd, ott_t offset);

 

- void *state

; 할당받기 원하는 메모리 주소. 보통 0을 써서 커널이 적합한 공간을 임의로 할당해 주소를 받을 수 있고, 직접 입력하여 사용해도된다. 하지만 직접 입력하는 경우 해당 시스템의 페이지 (배수)단위로 주소 값을 설정해줘야 한다.

 

- size_t length

; 메모리 맵을 할 크기. 바이트 단위로 설정한다.

 

- int prot

; 메모리 보호 메커니즘. 플래그 형식이므로 비트 연산으로 복수 속성으로 지정 가능하다.

 + PROT_EXEC; 해당 페이지 실행 가능.

 + PROT_READ; 해당 페이지 읽기 가능.

 + PROT_WRITE; 해당 페이지 쓰기 가능.

 + PROT_NONE; 해당 페이지 접근 불가.

 => 매핑할 파일 디스크립터와 속성이 같아야한다.

 

- int flags

 + MAP_SHARED; 공유 메모리 맵 방식.

 + MAP_PRIVATE; 복사 메모리 맵 방식.

 + MAP_FIXED ; 메모리 시작 번지 지정시 사용.

 =>MAP_SHARED/MAP_PRIVATE 둘 중에 한개만 지정해야된다.

 

- int fd

 ; 메모리 맵 방식을 사용할 파일 디스크립터.(파일 혹은 디바이스)

 

- ott_t offset

 ; 해당 파일 디스크립터에서 메모리 맵을 시작할 오프셋 값.



p style="margin-right: 0px; margin-left: 0px; padding: 0px; line-height: 20px; color: rgb(72, 72, 72); text-align: justify; ">+ return value

; 메모리 맵핑이 이루어진 가상 메모리 주소. 실패시 MAP_FAILED가 발생하고 errno에 해당 상황에 대한 값이 설정된다.

 

 

* 메모리 맵 해제 - munmap()

; 메모리 맵을 사용하고 자원을 해제 할 때 사용한다.

 

int munmap(void *start, size_t length);

 

- void *start

; 메모리 맵핑이 시작된 주소. mmap()의 반환 값을 넣으면된다.

 

- size_t length

; 메모리 맵을 한 길이. mmap() 사용시 size_t length 인자와 크기를 주면된다.

 

+ return value

;성공 0, 실패 -1

 

 

* 메모리 맵과 파일의 동기화 - fsync()

; 메모리 맵에 데이터를 갱신해도 바로 파일과 동기화가 이루어지는 것은 아니다. 커널이 여유 있을 때 동기화를 수행한다. 그러므로 개발자가 직접 동기화를 보장하고 싶을 때 사용한다. 그리고 munmap()을 하여 메모리 맵을 해제 할때에도 동기화를 해주면 데이터가 보장된다.

 

int msync(void *start, size_t length, int flags);

 

- void *start

; mmap()를 통해 리턴 받은 메모리 맵의 시작 주소.

 

-  size_t length

; 동기화를 할 길이. 시작 주소로 부터 길이를 지정하면 된다.

 

- int flags

 + MS_ASYNC

 ; 비동기 방식. 동기화(Memory->File)하라는 명령만 내리고 결과에 관계 없이 바로 리턴.

   그렇기 때문에 동기화가 된 건지 알수 없다.

 + MS_SYNC

 ; 동기 방식. 동기화(Memory->File)가 될때까지 블럭 상태로 대기한다.

 + MS_INVALIDATE

 ; 현재 메모리 맵을 무효화하고 파일의 데이터로 갱신. 즉 File->Memory

 

 

===================================================================================

       ...

#define MMAP_FULENAME "test_mmap"

#define MMAP_SIZE 64

       ...

int main()

{

     int fd;

     char *p_mmap;      //메모리 맵으로 사용할 데이터 타입

       ...

     fd = open(MMAP_FILENAME, O_RDWR|O_CREAT, 0664);

       ...

     p_mmap = (char*)mmap((void*)0, MMAP_SIZE, PROT_READ|PROT_WRITE,

                                                                     MAP_SHARED, fd, 0);

     //공유 메모리 방식을 사용한다. 읽기/쓰기 가능

       ...

     //memcpy(); 등으로 메모리 맵 데이터 갱신.

       ...

     msync(p_mmap, MAP_SIZE, MS_SYNC);

       ...

     munmap(p_mmap);

     return 0;

}

  

=> 메모리 맵 할 파일 이름만 같으면 IPC도 된다.


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

출처 : http://hsnote.tistory.com/141


윈도우의 경우는 아래의 자료를 참고.




[메모리 매핑파일]


HANDLE CreateFileMapping(HANDLE hFile,    // (1)
   LPSECURITY_ATTRIBUTES lpAttributes, //(2)
   DWORD flProtect,  // (3)
   DWORD dwMaximumSizeHigh,  // (4)
   DWORD dwMaxImumSizeLow,  // (5)
   LPCTSTR lpName   //(6)
   );


위의 함수가 매모리매핑 파일을 만드는 함수이다..

위의 함수 사용시 매모리맵파일이 생성은 되지만 실제로 매모리에 연결되어 있진않다. 

연결을 하려면 MapViewOfFile 이라는 함수를 써야지 그 때부터 메모리에 연결이 된다.

일단위 함수의 설명을 들어보자

 

목적 및 하는 일 : MMF라는 커널 객체를 만들고 그 핸들을 리턴한다.
                         메모리매핑파일을 만들수있는 기본정보들을 갖고 있는 커널객체를 만들고 그 핸들을 리턴한다.


인자설명 : 
 (1) hFile  : CreateFile 함수로 해당파일을 열고 리턴받은 값.. (CreaqteFile 의 리턴값  파일핸들) 파일핸들을 인자로 넘겨준다.. , (어떤파일을 파일매핑할건지 정하는거다.)
 
 (2) lpAttributes : 솔직히 잘 모르겠는데 .. 보통 이값은 NULL로 줬다. (아시는 분은 좀 알려주세여^^)

 (3) flProtect : 읽기 전용으로 할건지 읽기 쓰기를 할건지 설정하는 옵션이다. ex) PAGE_READONLY, PAGE_READWRITE 등등

 (3) dwMaximumSizeHigh : 매핑할 범위를 지정하는 상위 4바이트 (용량이 작은 범위라면 이곳에 0을 주고 그 다음 인자에 파일크기 및 원하는 범위를 지정한다.)
 
 (4) dwMaximumSizeLow : 매핑할 범위 지정하는 하위 4바이트

 (5) lpName : 파일매핑 객체이기 때문에 객체에 이름을 부여할때 쓴다. 보통   NULL을 주고 이름을 붙이도 다른곳에서 참조할때는 이름을 문자열로 이름을 지정한다.


사용예제 ) CreateFileMapping(hSource, NULL, PAGE_READONLY, 0, dwFileSize, NULL);
 
 CreateFileMapping(hTarget, NULL, PAGE_READWRITE, 0, dwFileSize, NULL);


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


LPVOID MapViewOfFile(HANDLE hFileMappingObject, // (1)
   DWORD dwDesiredAccess,  // (2)
   DWORD dwFileOffsetHigh,  //(3)
   DWORD dwFileOffsetLow,   // (4)
   SIZE_T dwNumberOfBytesToMap   // (5)
  );

목적 및 하는 일 : CreateFileMapping 함수로 만든 MMF 객체를 대상으로 실제 메모리번지에 연결을 하여 메모리 매핑파일을 만든다.
  메모리 매핑파일 만들고 그 메모리의 시작번지를 리턴한다.


인자설명 :
 (1) hFileMappingObject : CreateFileMapping 함수로 리턴받은 핸들값을 인자로 준다.

 (2) dwDesireAccess : 접근권한을 설정하는 것으로 FILE_MAP_READ, FILE_MAP,WRITE 등으로 옵션을 준다.

 (3) dwFileOffsetHigh :  메모리 주소가 연결될 크기 상위 4바이트

 (4) dwFileOffsetLow : 메모리 주소가 연결될 크기 하위 4바이트

 (5) dwNumberOfBytesToMap : 오프셋으로 부터 원하는 크기를 정한다.

사용예제 ) MapViewOfFile(hMapSource, FILE_MAP_READ, 0, dwAs, dwLen);

 MapViewOfFile(hMapTarget, FILE_MAP_WRITE, 0, dwAs, dwLen);


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

해당함수들을 사용후에는 해제 해주어야 하는데

CreateFileMapping 함수 같은 경우 파일 핸들을 리턴함으로

CloseHandle(리턴값); 으로 해제하고

MapViewOfFile 함수 같은 경우는 메모리 주소를 리턴함으로

UnmapViewOfFile(리턴값); 으로 해제한다.

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

반응형
반응형

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

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      -      -



반응형
반응형

===================================================================================================


[gcc 컴파일]


1) gcc 파일명(*.c) : Default로 out 파일이 생성된다. (ex a.out)

2) gcc -c 파일명(*.c) : 오브젝트 파일을 생성한다.

3) gcc -c 오브젝트_파일명(*.o) 파일명(*.c)

   gcc -o 실행파일명(*.out) 오브젝트_파일명(*.o)


4) gcc -o 실행파일 파일명(*.c) : 실행 파일을 만든다. (3번을 한줄로...)


===================================================================================================


[gcc 옵션]


1. -Wall 옵션 : 모든 모호한 코딩에 대해서 경고를 보내는 옵션

2. -W 옵션 : 합법적이지만 모호한 코딩에 대해서 경고를 보내는 옵션

3. -W -Wall 옵션 : 아주 사소한 모호성에 대해서도 경고가 발생

4. O2 옵션 : 최적화 레벨 2로 설정. (대부분의 최적화를 시도)

5. -E 옵션 : 전처리 과정의 결과를 화면에 보이는 옵션 

             (전처리과정 중 발생한 오류를 검증)

    ※ enhanced Tip: --save-temps 옵션 


6. -S 옵션 : cc1으로 전처리된 파일을 어셈블리 파일로 

             컴파일까지만 수행하고 멈춘다. (*.s)


7. -c 옵션 : as에 의한 어셈블까지만 수행하고 링크는 수행하지 않는다.

8. -v 옵션 : gcc가 컴파일을 어떤 식으로 수행하는지를 화면에 출력한다.

9. --save-temps 옵션 : 컴파일 과정에서 생성되는 중간 파일인 

                       전처리 파일(*.i)과 어셈블리 파일(*.s)을 지우지 않고,

                       현재 디렉토리에 저장한다. (오류 분석에 사용)


===================================================================================================


[cpp0 옵션]

: 소스내에서 사용된 헤더 파일과 define 매크로와 관련된 옵션들이다.

  전처리 과정에서 오류가 발생한다면 cpp0 옵션들을 점검해야 한다.


1) -l 옵션 : 전처리 과정에서 헤더 파일을 탐색하는 기본 디렉토리를 추가할 때 사용하는 옵션

2) -include 옵션 : 헤더 파일을 소스내에 추가할 때 사용한다.

3) -D[매크로] 옵션 : 매크로를 외부에서 define 할 때 사용한다.

4) -D[매크로]=[매크로 값] 옵션 : 소스 내에 #define [매크로] [매크로 값] 옵션을 추가한 것과 

                                 동일하다.


5) -U[매크로] 옵션 : -D와 반대로 소스 파일 내에 #undef[매크로] 옵션을 추가한 것과 

                     동일하다.


6) -M / -MM 옵션 : -M 옵션 - make를 위한 소스 파일의 모든 종속 항목을 출력

                   -MM 옵션 - 기본 include 디렉토리에 있는 헤더 파일은 빼고 종속 항목을

                              출력한다.


7) -nostdinc 옵션 : 디폴트 include 디렉토리(usr/include)에서 헤더 파일을 탐색하지 않고,

                    -l 옵션으로 추가한 디렉토리에서만 헤더 파일을 찾는다.


8) -C 옵션 : -E 옵션과 함께 사용하며, 전처리 과정에서 주석을 제거하지 않는다.

9) -Wp,[옵션들] 옵션 : 만약 cpp0와 gcc의 옵션이 같은 것으로 중복되면 gcc 옵션으로 

                       해석되므로... gcc의 해석을 거치지 않고 바로 cpp0 옵션으로 전달하고 

                       싶을 때 사용한다.         


===================================================================================================


[cc1 옵션]

: "C언어 옵션, 경고 옵션, 최적화 옵션, 디버깅 옵션"의 4가지 종류

  "경고 수위 조절 or 최적화 수위 조절"을 하고 싶을 때 사용한다.


1. C언어 옵션 : C언어 종류와 표준에 관련된 옵션

   1) -ansi 옵션 : ANSI C 표준에 부합하는 소스를 작성하고자 할 때 사용하는 옵션

   2) -std=[C 표준들] 옵션 : 기타 다른 표준들을 지정하고자 할 때 사용한다.

   3) -traditional 옵션 : 오래된 Traditional C 문법으로 문법을 검사한다.

   4) -fno -asm 옵션 : gnu89 문법을 바탕으로 asm, inline, typeof 키워드를 사용하지 않기를

                       원할 때 사용한다.

     


2. 경고 옵션 : cc1의 옵션을 조정하여 경고 수위를 조절할 수 있다.

   1) -W / -Wall 옵션 (gcc 옵션 참고)

   2) -w(소문자) 옵션 : 모든 경고 메시지를 제거한다.

   3) -Werror 옵션 : 모든 경고를 컴파일을 중단하는 오류로 취급한다.

                     (경고가 하나만 나와도 컴파일이 중단된다.)


   4) -pedantic 옵션 : ANSI C89 표준에서 요구하는 모든 경고 메시지를 표시한다.

   5) -pedantic-errors 옵션 : ANSI C89 표준에서 요구하는 모든 오류 메시지를 표시한다.

   6) -Wtraditional 옵션 : 소스가 ANSI C와 K&R C 간에 서로 다른 결과를 가져올 수 있는

                           부분이 있다면 경고한다.


3. 최적화 옵션 : ⓐ 실행 파일의 크기를 줄여 메모리와 하드디스크의 사이즈를 절약 (큰 의미 X)

                 ⓑ 실행 파일의 크기를 줄여 실행 속도를 향상시키는 것.

   1) -O0 옵션 : 최적화를 수행하지 않는다.

   2) -O1 옵션 : -O0보다는 조금 낫다. 

   3) -O2 옵션 : 가장 많이 사용하는 옵션. 일반 응용 프로그램이나 커널을 컴파일 할 때 사용

                 (거의 대부분의 최적화를 수행한다.)

   4) -O3 옵션 : 가장 높은 레벨의 최적화. 모든 함수를 인라인 함수와 같이 취급한다.               

                 (Call 인스트럭션은 사용 X. but, 되도록이면 사용하지 않는 것이 좋다. 

                   → 너무나 많은 소스의 변경이 가해지기 때문에 왜곡이 발생할 위험이 있다.)

   5) -O5 옵션 : 사이즈 최적화를 실행한다. (공간이 협소한 곳에서 사용 - 임베디드 시스템)


4. 디버깅 옵션

   1) -g 옵션 : gdb에게 제공하는 정보를 바이너리에 삽입한다.

                (-g 옵션을 사용하지 않고 gdb로 디버깅하면, 역어셈 → 어셈블리 코드로만 디버깅 가능)


   2) -pg 옵션 : 프로파일을 위한 코드를 삽입한다. 

                 (-pg 옵션으로 컴파일 → gmon.out(프로파일 정보) → gprof로 gmon.out 파일 분석)



===================================================================================================


[as의 옵션]

: gcc는 as의 옵션에 대해서는 알지 못한다. -Wa,[as 옵션들] 형식으로 gcc를 거치지 않고 

  바로 전달해야 한다. -Wa, -al, -as와 같은 형식으로 사용하면 as에게 -al -as 옵션이 같이 전해진다.


-Wa,[as 옵션들]

1) -al 옵션 : 어셈블된 인스트럭션을 보인다.

2) -as 옵션 : 정의된 심볼을 보인다.

3) -l[패스] 옵션 : include 디렉토리를 지정한다. 어셈블리 소스 내에서 사용된 include 지정자가 

                   지정하는 헤더파일을 찾고자 할 때 사용한다.

4) -W / --no-warn : 경고 메시지를 출력하지 않는다.

5) -march=[아키텍처 문자열] : 해당 어셈블리


===================================================================================================


[collect2 / ld 옵션]

: 링크 옵션


1) -L[라이브러리 디렉토리] 옵션 : 라이브러리를 찾을 디렉토리를 지정한다.

2) -l 옵션 : 같이 링크할 라이브러리를 지정한다.

3) -shared 옵션 : 공유 라이브러리와 정적 라이브러리가 같이 있을 경우, 공유 라이브러리를 우선하여

                  링크한다. (아무 옵션을 주지 않아도 공유 라이브러리를 우선으로 링크한다.)


4) -static 옵션 : 정적 라이브러리와 공유 라이브러리가 같이 있다면, 정적 라이브러리를 우선하여

                  링크한다. (속도는 빠르지만 파일 사이즈가 커진다는 점 고려할 것!)


5) -nostdlib 옵션 : 링크시에 표준 C 라이브러리를 사용하지 않는다. 

                    (OS, 부트로더와 같은 프로그램을 컴파일 할 때 사용)


6) -nostartfiles 옵션 : crt1.o 등과 같은 start up 파일을 링크하지 않는다.

                    (OS, 부트로더와 같은 프로그램을 컴파일 할 때 사용)


7) -Wl,[링크 옵션들] 옵션 : gcc를 거치지 않고 바로 링크에게 옵션을 정해주고자 할 때 사용한다.

                            (사용법은 -Wa와 동일한다.)

   

   < 유용한 링크 옵션들 >

   ① -s 옵션 : 실행 파일에서 심볼 테이블을 제거

   ② -x 옵션 : 출력 파일에서 로컬 심볼 제거

   ③ -n 옵션 : 텍스트 영역을 읽기 전용으로 만듬

   ④ -r 옵션 : 추후 링크가 가능하게 오브젝트를 만듬

   ⑤ -e [name] 옵션 :  시작 심볼을 name 심볼로 사용 (default 시작심볼 : _start 심볼)

   ⑥ -M 옵션 : 심볼들의 정보를 자세하게 출력

   ⑦ oformat [format] 옵션 : 주어진 형식의 오브젝트 파일을 생성


===================================================================================================




출처 : http://lvzuufx.blogspot.kr/2014/09/gnu-make-gcc-auto-dependency-makefile.html





Autotools, CMake, qmake 같은 빌드 도구나 Open Watcom 의 wmake 같은 경우에는 자체적으로 auto-dependency 를 지원하거나 이를 위한 지시자를 제공한다. 하지만 GNU Make 의 경우에는 이러한 기능을 자체적으로 지원하지도 않고, 이를 위한 지시자를 제공하지도 않는다.

하지만, 다행히도 gcc 를 이용해서 이 기능을 구현할 수 있다. 우선 이에 필요한 gcc 의 기능부터 살펴보자. 

-M 옵션 : 해당 소스 파일의 의존성을 GNU Make 의존성 규칙에 맞추어 출력한다. 시스템 헤더 파일들도 포함된다.

예를 들어, 다음과 같은 hello.c 를 생각해보자.

1
2
3
4
5
6
7
8
9
// hello.c
#include <stdio.h>

int main( void )
{
    printf("Hello, world\n");

    return 0;
}



  • gcc -M hello.c


                    이를 실행한 결과는 이렇다.

                    • hello.o: hello.c f:/lang/gcc/usr/include/stdio.h \
                    •   f:/lang/gcc/usr/include/sys/cdefs.h \
                    •   f:/lang/gcc/usr/include/sys/gnu/cdefs.h \
                    •   f:/lang/gcc/usr/include/features.h f:/lang/gcc/usr/include/sys/_types.h \
                    •   f:/lang/gcc/usr/include/machine/_types.h \
                    •   f:/lang/gcc/usr/include/386/_types.h


                    -MM 옵션 : -M 옵션과 비슷한데, 시스템 헤더 파일은 제외한다.

                    • gcc -MM hello.c 


                    다음은 실행 결과이다.

                    •  hello.o: hello.c


                     -MP 옵션 : -M 또는 -MM 옵션과 함께 쓰일 때, 헤더 파일들에 대한 phony 타겟을 만든다. 이는 헤더 파일이 지워졌을 때, 오류가 발생하는 것을 방지한다.

                    •  gcc -M -MP hello.c


                    다음은 실행 결과이다.

                    •  hello.o: hello.c f:/lang/gcc/usr/include/stdio.h \
                    •   f:/lang/gcc/usr/include/sys/cdefs.h \
                    •   f:/lang/gcc/usr/include/sys/gnu/cdefs.h \
                    •   f:/lang/gcc/usr/include/features.h f:/lang/gcc/usr/include/sys/_types.h \
                    •   f:/lang/gcc/usr/include/machine/_types.h \
                    •   f:/lang/gcc/usr/include/386/_types.h
                    • f:/lang/gcc/usr/include/stdio.h:
                    • f:/lang/gcc/usr/include/sys/cdefs.h:
                    • f:/lang/gcc/usr/include/sys/gnu/cdefs.h:
                    • f:/lang/gcc/usr/include/features.h:
                    • f:/lang/gcc/usr/include/sys/_types.h:
                    • f:/lang/gcc/usr/include/machine/_types.h:
                    • f:/lang/gcc/usr/include/386/_types.h: 


                    -MT 옵션 : -M 또는 -MM 옵션과 함께 쓰일 때, 타겟의 이름을 바꾼다.

                    • gcc -M -MT hello_MT.o hello.c


                    다음은 실행 결과이다.

                    • hello_MT.o: hello.c f:/lang/gcc/usr/include/stdio.h \
                    •   f:/lang/gcc/usr/include/sys/cdefs.h \
                    •   f:/lang/gcc/usr/include/sys/gnu/cdefs.h \
                    •   f:/lang/gcc/usr/include/features.h f:/lang/gcc/usr/include/sys/_types.h \
                    •   f:/lang/gcc/usr/include/machine/_types.h \
                    •   f:/lang/gcc/usr/include/386/_types.h


                    -MF 옵션 : -M 또는 -MM 옵션과 함께 쓰일 때, 출력 결과를 해당 장치 또는 파일로 보낸다.

                    • gcc -M -MF hello.d hello.c


                    이 때 실행 결과는 표준 출력 장치에 나타나는 것이 아니라 hello.d 라는 파일에 저장된다.

                    바로 이 옵션들을 통해서 auto-dependecy Makefile 파일을 만들 수 있다. 문제는 이 내용을 Makefile 파일에서 어떻게 활용할 것인가이다.

                    의존성 파일부터 만들어 보자. 의존성 파일을 만들기 위한 기본적인 형태는 다음과 같다.

                    • hello.d : hello.c
                    •     gcc -M -MP -MF $@ $<


                    이제는 이렇게 만들어진 의존성 파일을 포함시켜야 한다. GNU Make는 이를 위해 include 지시자를 지원한다.

                    • include hello.d


                    이때 hello.d 가 없다면 주어진 생성 규칙을 통해서 새로이 만들거나 갱신한다. 그럼에도 불구하고 hello.d 를 만들 수 없다면, GNU Make 는 오류를 보고하고, 중지한다.

                    마지막으로 실행 파일의 의존성 규칙을 추가해주면 된다.

                    •  hello.exe : hello.o


                    물론 다음과 같은 기본적인 내용이 Makefile 앞 부분에 더 추가되어야 한다.

                    • .SUFFIXES : .c .o .exe
                    •  
                    • .PHONY : all
                    •  
                    • all : hello.exe


                    완성된 Makefile 의 모습은 이렇다.

                    1
                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11
                    12
                    13
                    .SUFFIXES : .c .o .exe

                    .PHONY : all

                    all : hello.exe

                    hello.d : hello.c
                        gcc -M -MP -MF $@ $<

                    include hello.d

                    hello.exe : hello.o
                        gcc -o $@ $<



                    이제 make 를 실행하면, hello.c 자체가 수정되거나 hello.c 가 포함하는 헤더 파일이 수정되면 새롭게 빌드된다.

                    그런데 문제는 hello.d 파일 자체는 한 번 만들어지면 hello.c 가 수정되지 않는 이상, 다시 갱신되지 않는다. 왜냐하면 hello.d 파일에 대한 의존성은 hello.c 밖에 없기 때문이다. 이 문제는 hello.d 의 의존성을 hello.o 의 의존성과 동일하게 만들어주면 된다. 위 8번째 줄을 아래와 같이 바꾸자.

                    • gcc -M -MP -MT "$(@:.d=.o) $@" -MF $@ $<


                    GNU Make 의 다중 대상 기능을 이용한 것으로. 타겟이 "hello.o" 에서 "hello.o hello.d" 로 된다.

                    GNU Make 를 실행하다보면 hello.d 가 지워진 경우에,  다음과 같은 오류 메세지가 출력된다.

                    • Makefile:10: hello.d: No such file or directory


                    이 오류 메세지가 나오더라도 중단되지는 않지만, 뭔가 꺼림칙하다. 어떻게 없앨 수 없을까 ? 바로 -include 를 쓰면 된다.

                    이 예제의 경우에는 소스 파일이 하나에 불과해서 이 정도이지만, 소스 파일이 여러 개일 경우에는 해당 소스 파일마다 일일이 추가해줘야 한다. 그리고 다른 프로젝트에 쓰기에도 수정해야 할 것이 많다. 이 얼마나 불편한가 ? 이를 개선해 보자.

                    우리가 고려할 것은 실행 파일과, 소스 파일이다. 다른 모든 것들은 이들로부터 변형될 수 있다. 이들을 위한 변수를 도입하자. PROGNAME 과 SRCS 에 실행파일과 소스 파일을 담자.

                    • PROGNAME := hello.exe
                    • SRCS := hello.c


                    이제 의존성 파일 변수와 실행 파일을 만들기 위한 목적 파일 변수를 도입하자.

                    • PROGNAME_DEPS := $(SRCS:.c=.o)
                    • DEPS := $(SRCS:.c=.d)


                    이 내용들을 반영하면 위 Makefile 은 다음과 같이 쓰여질 수 있다.

                    1
                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11
                    12
                    13
                    14
                    15
                    16
                    17
                    18
                    19
                    PROGRAM := hello.exe
                    SRCS := hello.c

                    PROGRAM_DEPS := $(SRCS:.c=.o)
                    DEPS := $(SRCS:.c=.d)

                    .SUFFIXES : .c .o .exe

                    .PHONY : all

                    all : $(PROGRAM)

                    $(PROGRAM) : $(PROGRAM_DEPS)
                         gcc -o $@ $^

                    %.d : %.c
                         gcc -M -MP -MT "$(@:.d=.o) $@" -MF $@ $<

                    -include $(DEPS)



                    위 내용을 보면 특정 이름 대신에 변수를 사용한 것 외에도 몇 가지 달라진 점이 있는데, 하나는 16번째 줄에 있는 암묵적 규칙이고, 14번째 줄에 있는 $^ 이다. 암묵적 규칙은 여러개의 파일에 대해 동일한 규칙을  적용하기 위한 것이고, $^ 은 모든 의존 파일들을 뜻한다. 반면에 $< 은 첫번째 의존 파일을 뜻한다.
                    이렇게 해 두면, 다른 프로젝트에 적용을 한다든지 또는 소스가 변경되었다든지 할 때, PROGRAM 과 SRCS 만 바꾸어주면 된다. 소스 파일을 더 추가하고 싶다면 빈 칸을 사이에 두고 파일 이름을 적어주면 된다. 예를 들어 hello.c 외에 world.c 가 추가되었다면 2번째 줄을 이렇게 바꾸면 된다.

                    • SRCS := hello.c world.c


                    이외에도 여러가지 컴파일 플래그나 링커 플래그, 컴파일러나 링커를 위한 여러 변수들을 도입하면 훨씬 더 유연한 Makefile 이 될 것이다.

                    그리고 기회가 된다면 추후에 여러 개의 실행 파일과 DLL 등을 한꺼번에 빌드할 수 있는 Makefile 에 대해서도 글을 쓰도록 하겠다. 



                    반응형
                    반응형

                    출처 : http://moonsungju.tistory.com/32



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

                    SUN Studio 12 버전 별로 정리해보았습니다. 다들 알고 있으시겠죠?? 모르시는 분들을 위해~ㅋㅋㅋㅋ

                    Solaris 10u10 기준이며, OS release 따라 약간 다를 수도 있습니다. 이 부분은 다들 알고 계시기 때문에 PASS~

                    해당 설치 방법은 제가 전에 On-site 때 실행했던 방법이며, 혹시 다른 방법으로 설치하시는 분이 있다면 그 방법으로 하시면 됩니다참고만 하시면 될 듯 싶네요.

                     

                    1.     현재까지 나온 Sun Studio 12

                    l  SunStudio 12

                    l  SunStudio 12.1

                    l  SunStudio 12.2

                    l  SunStudio 12.3

                     

                    2.     압축 풀기

                    bzcat download_directory/[File Name]-[OS]-[PLATFORM]-[FORMAT]-ML.tar.bz2 | /bin/tar -xf -

                    ex) bzcat SolarisStudio12.3-solaris-sparc-pkg.tar.bz2| /bin/tar -xf -

                     

                    3.     설치/삭제 옵션

                    SunStudio Version

                    NON-GUI 실행 옵션

                    SunStudio 12

                    설치) nodisplay

                    삭제) java -cp . uninstall_Sun_Studio_12 nodisplay

                         uninstaller

                    SunStudio 12.1

                    설치) --non-interactive-accept-license --create-symlinks --tempdir /tmp

                    삭제) uninstall.sh --non-interactive (삭제 시 설치 디렉토리도 삭제하면 좋겠죠?)

                    SunStudio 12.2

                    설치) --non-interactive --create-symlinks --tempdir /tmp

                    삭제) uninstall.sh --non-interactive (삭제 시 설치 디렉토리도 삭제하면 좋겠죠?)

                    SunStudio 12.3

                     

                    4.     C로 컴파일 예제

                    #include <stdio.h>

                    int main(){

                    printf("Moonsungju, world!\n");

                    return 0;

                    }

                    컴파일링 하는 방법은 다들 아시죠? cc를 통해 진행하시면 됩니다굳이 여기까지 테스트는 안 하셔도 되나 그래도 심심풀이로 하시고 싶으신 분~~~ 각자의 소스코드로 진행하시면 됩니다. 위에 코드는 가장 많이 테스트 하시는 hello.c 코드 입니다. 그냥 moonsungju로 바꾼 것 외에 다른 수정사항은 없습니다.(gcc도 동일)







                    1.패치실행

                    2.스튜디오실행




                    output-device=virtual-console

                    input-device=virtual-console


                    eeprom "output-device=screen"

                    eeprom "input-device=keyboard"



                    /usr/dt/bin/dtlogin start


                    /usr/dt/bin/dtconfig -e

                    반응형
                    반응형

                    1. 출처 : http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/System_management/ZFS

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


                    1 ZFS

                    유닉스의 파일 시스템을 대체하기 위해서 SUN에서 개발한 파일 시스템으로 Solaris 10에 소개된다. 기능을 보면 알겠지만 단순한 파일 시스템으로 보기는 힘들다. 모든 잡다한 관리기능까지를 포함한 볼륨메니저로 봐야 한다. 예컨데 파일 시스템과 Logical Volume manager, snapshots, copy-on-write clones, continuous integrity checking, automatic repaire, 등 무슨 기능일지도 모를 것 같은 다양한 기능들을 가지고 있는 확장된 파일 시스템이다. ZFS를 써본 사람들은 지상 최대의 파일 시스템이라는 찬사를 보낸다. 정말 그러하다.

                    나는 Cloud 환경에서 신뢰성과 확장성, 성능과 관리성까지 두루 갖춘 만능 File System을 찾아보자라는 목적으로 살펴보게 됐다.

                    ZFS의 기능을 정리했다.
                    1. Data Integrigy 다른 파일 시스템과 구분되는 가장 큰 특징이다. 디스크 상의 유저 데이터를 보호준다. bit rot, cosmic radiation, current spikes, bugs in disk firmware, ghost writes 등으로 부터 데이터를 보호해 준다. 물론 Ext, XFS, JFS, ReiserFS, NTFS 등도 유저 데이터를 보호하기 위한 기능을 가지고 있기는 하지만, ZFS는 이들 보다 탁월한 성능을 보여준다.
                    2. Storage Pool LVM과 마찬가지로 하나 이상의 장치를 통합해서 관리할 수 있다. 이 논리적인 Storage Pool을 zpools라고 하며, block device 처럼 작동한다. 블럭 장치들은 다양한 레벨로 조합할 수 있습니다. non-redundantly (RAID 0과 비슷), mirror ( RAID 1과 비슷 ), RAID-Z (RAID-5와 비슷), RAID-Z2 (RAID-6와 비슷) 등등이다.
                    3. Capacity : ZFS는 128-bit 파일 시스템으로 용량에는 제약기 없다고 보면 되겠다. 페타바이트급 파일시스템이라고 하는 이유가 있다.
                      • 2^48 개의 독립된 디렉토리를 다룰 수 있다.
                      • 파일의 최대크기는 16 exabytes ( 16 X 10^18)
                      • zpool의 최대 크기는 256 zettabytes (2^78)
                      • 시스템에서 zpools의 갯수는 2^64
                      • zpools에서 파일 시스템의 갯수 2^64

                    2 Linux와 ZFS

                    Linux에 ZFS를 이식하기 위한 노력이 진행 중이다. 이식은 두 가지 방향으로 이루어지고 있다.
                    1. native ZFS
                      리눅스 커널이 ZFS를 지원하도록 하는 프로젝트
                    2. zfs-fuse
                      fuse를 이용해서 ZFS를 지원하도록 하는 프로젝트
                    아직까지는 Linux에서 마음놓고 사용할 만한 수준이 아닌 것 간다. zfs-fuse 같은 경우에는 성능에 문제가 상당히 있어서 zfs란 이런 거구나를 체험하기 위한 수준 정도에서나 사용할 수 있을 것 같다. . Native ZFS는 눈여겨 볼만하다. 꾸준히 개발하고 있는 것 같기는 한데, 언제쯤 1.0이 되서 믿고 쓸만한 날이 올지 모르겠다. 1년전에 0.6.x 버전이었는데, 지금(2013년 9월)도 0.6.x 버전이다.

                    2.1 zfs-fuse

                    1. apt-get install zfs-fuse
                    2. zpoll create mypool /dev/sdb /dev/sdc /dev/sdd /dev/sde
                    3. zpool status mypool
                    4. zfs create mypool/testzfs
                    5. FS 성능 측정 : Bonnie++

                    3 Solaris와 ZFS

                    3.1 opensolaris 설치

                    솔라리스는 ZFS를 기본 파일 시스템으로 하고 있다. 이렇게 된거 x86기반의 opensolaris를 설치해서 ZFS를 경험해 보기로 했다. VirtualBox를 이용 해서 가상으로 올렸다.
                    • hypervisor : VirtualBox VirtualBox 와 opensolaris 모두 Oracle에서 개발하고 있으니, 궁합이 잘 맞을 거란 생각이 든다.
                    • OpenSolaris
                    설치는 윈도우보다 간단하다. 설치 과정은 생략.

                    솔라리스를 마지막으로 써본게 아마 9년전 쯤인것 같다. 2002년이던가 ? 당시만 해도 상당히 투박한(하지만 왠지 멋져 보이긴 했음) CDE 화면이었는데, 지금은 gnome이 뜬다. 예쁘다.

                    보낸 사람 Linux

                    3.2 zpool

                    논리적 볼륨 관리자의 핵심은 장치를 아우르는 하나의 pool을 만드는 거다. 이 pool을 zpool이라고 부른다.

                    테스트를 위해서 SATA 2G x 2 장치를 준비했다. 리눅스에서 하던 것처럼 fdisk -l로 장치를 확인하려고 했더니, 내가 원하는 그 fdisk가 아니다. format으로 장치를 확인할 수 있다.
                    # format
                    AVAILABLE DISK SELECTIONS:
                           0. c7d0 <DEFAULT cyl 2085 alt 2 hd 255 sec 63>
                              /pci@0,0/pci-ide@1,1/ide@0/cmdk@0,0
                           1. c9t0d0 <ATA-VBOX HARDDISK-1.0-2.00GB>
                              /pci@0,0/pci8086,2829@d/disk@0,0
                           2. c9t1d0 <ATA-VBOX HARDDISK-1.0-2.00GB>
                              /pci@0,0/pci8086,2829@d/disk@1,0
                    

                    c9t0d0, c9t1d0을 tank라는 이름의 zpool로 묶기로 했다.
                    # zpool create tank c9t0d0 c9t1d0
                    

                    제대로 만들어 졌는지 확인.
                    # zpool list
                    NAME    SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
                    rpool  15.9G  3.80G  12.1G    23%  ONLINE  -
                    tank   3.97G   232K  3.97G     0%  ONLINE  -
                    

                    zfs로 파일 시스템에 대한 상세 정보를 확인.
                    # zfs list
                    NAME                         USED  AVAIL  REFER  MOUNTPOINT
                    rpool                       4.16G  11.5G  77.5K  /rpool
                    rpool/ROOT                  3.16G  11.5G    19K  legacy
                    rpool/ROOT/opensolaris      3.16G  11.5G  3.02G  /
                    rpool/dump                   511M  11.5G   511M  -
                    rpool/export                5.04M  11.5G    21K  /export
                    rpool/export/home           5.02M  11.5G    21K  /export/home
                    rpool/export/home/yundream     5M  11.5G     5M  /export/home/yundream
                    rpool/swap                   512M  11.8G   137M  -
                    tank                        74.5K  3.91G    19K  /tank
                    

                    zfs는 디렉토리 형태로 pool을 관리할 수 있다. tank 밑에 music, movie, source 3개의 파일 시스템을 만들어 봤다.
                    # zfs create tank/music
                    # zfs create tank/movie
                    # zfs create tank/source
                    # zfs list
                    NAME                         USED  AVAIL  REFER  MOUNTPOINT
                    ...
                    tank                         154K  3.91G    23K  /tank
                    tank/movie                    19K  3.91G    19K  /tank/movie
                    tank/music                    19K  3.91G    19K  /tank/music
                    tank/source                   19K  3.91G    19K  /tank/source
                    
                    3개의 파일 시스템이 추가로 만들어지긴 했지만 volume을 모두 공유해서 사용하고 있다. 내 목적은 각 파일 시스템 별로 쿼터를 정하는 거다. /tank/movie를 1G를 사용하도록 쿼터를 할당했다.
                    # zfs set quota=1g tank/movie
                    # zfs list | grep tank
                    tank                         154K  3.91G    23K  /tank
                    tank/movie                    19K  1024M    19K  /tank/movie
                    tank/music                    19K  3.91G    19K  /tank/music
                    tank/source                   19K  3.91G    19K  /tank/source
                    
                    # df -h /tank/movie
                    Filesystem            Size  Used Avail Use% Mounted on
                    tank/movie            1.0G   19K  1.0G   1% /tank/movie
                    

                    3.3 mirror, RAIDZ, RAIDZ2

                    ZFS는 mirror와 RAIDZ, RAIDZ2 3가지 RAID 레벨을 지원한다. 10G SATA Disk 6개를 추가해서 각 모드별로 테스트를 진행했다.

                    RAIDZ와 RAIDZ2는 각각 RAID 5와 RAID 6와 매우 유사하다. 즉
                    • RAIDZ : RAID 5 처럼 블럭 기반 striped 와 하나의 분산 parity 블럭을 가진다.
                    • RAIDZ2 : RAID 6 처럼 블럭 기반 striped 와 두개의 분산 parity 블럭을 가진다.


                    4 Native ZFS on Linux

                    • Native ZFS on Linux : 앞으로 오픈 솔라리스 대신 리눅스를 이용해서 zfs를 테스트할 계획이다.

                    5 Nexenta

                    Nexenta는 opensolaris 기반의 NAS/SAN어플라이언스 제품이다. 기업환경에서 ZFS를 이용해서 안정적으로 스토리지 시스템을 구성할 수 있도록 HA(High Availability cluster), Namespace Cluster, CLI및 GUI(웹 기반의) 인터페이스를 제공한다.

                    6 History

                    1. 작성일 : 2011년 9월 6일
                    2. 수정이력
                      1. 작성 : 2011/9/6
                      2. 2013-08-31 : 문장을 다듬었음. 링크 추가


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


                    zfs 파일 시스템의 관련 블로그들의 대부분은 

                    spl-0.6.0-rc6.tar.gz, zfs-0.6.0-rc6.tar.gz를 가이드했지만 내가 이 블로그를 쓰는 시점은 0.6.3을 받았다. 버전별로 리눅스 커널 지원이 다르다.

                    관련 패키지 정보는 ZFS 관련 공식 사이트인 아래 링크에 들어가서 받도록 하자.


                    http://zfsonlinux.org/


                     


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

                    2. 출처 : http://blog.lovetonight.net/m/post/164


                    ZFS on Centos6

                    마성민 | 2013/04/19 11:37 | Linux 앱으로 보기

                    약 30TB 정도의 데이터 백업을 위해 백업 서버를 한대 구성하고 XFS로 포맷하고 데이터를 저장..

                    파일 개수가 약 1억개 정도 되다보니.. 데이터를 백업 하는 과정에서 계속 XFS 파티션이 깨지는 현상이 발생..

                    거기다 설상가상으로 서버이전이다 뭐다 해서 용량이 갑자기 10TB가 추가되어버린..

                    ㅠ_ㅠ 아.. 서버 재구성해야 하나.. 했는데..

                     

                    이번기회에 ZFS로 가보자 하고 결정..

                    아래 내용은 Onenote에 정리해둔 내용을 옮겨적음..

                     

                    [기본환경]

                    • OS : CentOS release 6.3 (Final) 64Bit
                    • Kernel : 2.6.32-279.19.1.el6.x86_64

                     

                    [설치]

                    • Linux 시스템에서 ZFS 사용하기 위해서는 Native ZFS 이용하는 방법과 ZFS-FUSE 이용하는 방법이 있으며, 각각의 방법에 따라 ZFS 버전이 달라질 있습니다.

                     

                    1. 먼저 ZFS 구성을 위해 기본적으로 필요한 항목들을 설치 합니다.

                    Shell > yum install kernel-devel zlib-devel libuuid-devel libblkid-devel libselinux-devel parted lsscsi

                    Native ZFS Kernel 모듈 방식으로 동작 하기 때문에 위와 같이 kernel-devel 반드시 설치해 주어야 합니다.

                     

                    1. ZFS패키지인 SPL ZFS 패키지를 다운로드 합니다.

                    다운로드는 http://www.zfsonlinux.org 에서 받을 있습니다.

                     

                    1. 다운로드한 패키지의 압축을 해제 설치를 진행 합니다.

                    # spl install

                    Shell > tar xvfz spl-0.6.0-rc13.tar.gz

                    Shell > cd spl-0.6.0-rc13

                    Shell > ./configure && make rpm

                    Shell > rpm -Uvh *.x86_64.rpm

                    Shell > cd ..

                     

                    # zfs install

                    Shell > tar xvfz zfs-0.6.0-rc13.tar.gz

                    Shell > cd zfs-0.6.0-rc13

                    Shell > ./configure && make rpm

                    Shell> rpm -Uvh *.x86_64.rpm

                    Shell > cd ..

                     

                    1. 설치된 zfs 커널 모듈을 인식시켜 줍니다.

                    Shell > modprobe zfs

                    Shell > lsmod | grep -i zfs

                     

                    1. ZFS Spool 생성 합니다.

                    여기서 ZFS Spool 만들때 단일 디스크를 사용할 것인지 아니면 여러 개의 단일 디스크를 소프트웨어 레이드 방식으로 구성 것인지를 결정 있습니다. ZFS Spool 생성할 때에는 zpool 명령어를 사용하며, 해당 명령어에는 다양한 기능들이 포함되어 있으므로 자세한 내용은 공식 Document 참조하시기 바랍니다.

                    아래에서는 단일 디스크와 2 디스크를 미러링 하는 방법, 그리고 4 이상의 디스크를 Raid5 구성하는 방법을 설명 하겠습니다.

                    # EX : zpool [명령어] [옵션] spool

                    # CREATE EX : zpool create [-f|-n] [-o property=value] [-m mountpoint] pool vdev

                     

                    # /dev/sdb 디스크를 backup 스풀로 생성하며, compress option 기본설정 하도록 한다.

                    Shell > zpool create -o compress=on backup disk /dev/sdb

                     

                    # /dev/sdb 디스크와 /dev/sdc 디스크를 Backup 스풀로 생성하며, Raid1 구성 Compress option 설정 하도록 한다.

                    Shell > zpool create -o compress=on backup mirror /dev/sdb /dev/sdc

                     

                    # /dev/sd[b-f] 디스크( 5) 4개를 Raid5 (Parity Disk 1)구성하고 나머지 1개의 디스크는 Hot Spare 구성을 Backup 스풀을 구성하고 /backup_spool 이라는 디렉토리에 마운트 되도록 한다.

                    Shell > zpool create -m /backup_spool backup raidz1 /dev/sdb /dev/sdc /dev/sdd /dev/sde spare /dev/sdf

                     

                    1. ZFS Spool ZFS 파일 시스템을 생성 합니다.

                    ZFS Spool 공간을 이용하여 파일시스템을 생성할 있으며, 각각의 파일시스템은 Spool 적용된 property Option 상속하게 됩니다.

                    # EX : zfs [명령어] [옵션]

                    # CREATE EX : zfs create [-p] [-o] filesystem

                     

                    # backup 스풀의 공간을 이용하여 maildata 라는 파일시스템을 생성하고 자동 압축되지 않도록 구성 한다.

                    Shell > zfs create -o compress=off backup/maildata

                     

                    # Backup 스풀의 공간을 이용하여 mysql 라는 파일시스템을 생성하고 자동압축되지 않으며, /data/mysql 마운트 되도록 한다.

                    Shell > zfs create -o compress=off -o mountpoint=/data/mysql backup/mysql

                     

                    # Backup 스풀의 공간을 이용하여 user 라는 파일시스템을 생성하고 자동압축되며, 500GB 쿼터를 설정하고 /home/user 디렉토리에 마운트 되도록 한다.

                    Shell > zfs create -o compress=on -o mountpoint=/home/user -o quota=500GB backup/user

                     

                    ZFS로 구성한 후 Compression 옵션 덕분에 실제 8TB 정도 되는 데이터는 5.6TB 정도로 압축되어 저장되었다는 후문이...

                     

                    ZFS 사랑해요~!


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






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

                    출처 : https://github.com/zfsonlinux/pkg-zfs/wiki/HOWTO-install-Ubuntu-to-a-Native-ZFS-Root-Filesystem


                    HOWTO install Ubuntu to a Native ZFS Root Filesystem


                    Note: These instructions were originally created for older version of Ubuntu (12.04). Some required resource (e.g. grub ppa) is not available on newer versions, thus can lead to errors. If you use Ubuntu 14.04 or newer, see this page instead, which also allows things like raidz root, boot from snapshot, zfs-only setup (no need for separate /boot/grub), and lz4 compression.


                    These instructions are for Ubuntu. The procedure for Debian, Mint, or other distributions in the DEB family is similar but not identical.

                    System Requirements

                    • 64-bit Ubuntu Live CD. (Not the alternate installer, and not the 32-bit installer!)
                    • AMD64 or EM64T compatible computer. (ie: x86-64)
                    • 8GB disk storage available.
                    • 2GB memory minimum.

                    Computers that have less than 2GB of memory run ZFS slowly. 4GB of memory is recommended for normal performance in basic workloads. 16GB of memory is the recommended minimum for deduplication. Enabling deduplication is a permanent change that cannot be easily reverted.

                    Recommended Version

                    • Ubuntu 12.04 Precise Pangolin
                    • spl-0.6.3
                    • zfs-0.6.3

                    Step 1: Prepare The Install Environment

                    1.1 Start the Ubuntu LiveCD and open a terminal at the desktop.

                    1.2 Input these commands at the terminal prompt:

                    $ sudo -i
                    # apt-add-repository --yes ppa:zfs-native/stable
                    # apt-get update
                    # apt-get install debootstrap spl-dkms zfs-dkms ubuntu-zfs
                    

                    1.3 Check that the ZFS filesystem is installed and available:

                    # modprobe zfs
                    # dmesg | grep ZFS:
                    ZFS: Loaded module v0.6.3-2~trusty, ZFS pool version 5000, ZFS filesystem version 5
                    

                    Step 2: Disk Partitioning

                    This tutorial intentionally recommends MBR partitioning. GPT can be used instead, but beware of UEFI firmware bugs.

                    2.1 Run your favorite disk partitioner, like parted or cfdisk, on the primary storage device. /dev/disk/by-id/scsi-SATA_disk1 is the example device used in this document.

                    2.2 Create a small MBR primary partition of at least 8 megabytes. 256mb may be more realistic, unless space is tight. /dev/disk/by-id/scsi-SATA_disk1-part1 is the example boot partition used in this document.

                    2.3 On this first small partition, set type=BE and enable the bootable flag.

                    2.4 Create a large partition of at least 4 gigabytes. /dev/disk/by-id/scsi-SATA_disk1-part2 is the example system partition used in this document.

                    2.5 On this second large partition, set type=BF and disable the bootable flag.

                    The partition table should look like this:

                    # fdisk -l /dev/disk/by-id/scsi-SATA_disk1
                    
                    Disk /dev/sda: 10.7 GB, 10737418240 bytes
                    255 heads, 63 sectors/track, 1305 cylinders
                    Units = cylinders of 16065 * 512 = 8225280 bytes
                    Sector size (logical/physical): 512 bytes / 512 bytes
                    I/O size (minimum/optimal): 512 bytes / 512 bytes
                    Disk identifier: 0x00000000
                    
                    Device    Boot      Start         End      Blocks   Id  System
                    /dev/sda1    *          1           1        8001   be  Solaris boot
                    /dev/sda2               2        1305    10474380   bf  Solaris
                    

                    Remember: Substitute scsi-SATA_disk1-part1 and scsi-SATA_disk1-part2 appropriately below.

                    Hints:

                    • Are you doing this in a virtual machine? Is something in /dev/disk/by-id missing? Go read the troubleshooting section.
                    • Recent GRUB releases assume that the /boot/grub/grubenv file is writable by the stage2 module. Until GRUB gets a ZFS write enhancement, the GRUB modules should be installed to a separate filesystem in a separate partition that is grub-writable.
                    • If /boot/grub is in the ZFS filesystem, then GRUB will fail to boot with this message: error: sparse file not allowed. If you absolutely want only one filesystem, then remove the call to recordfail() in each grub.cfg menu stanza, and edit the /etc/grub.d/10_linux file to make the change permanent.
                    • Alternatively, if /boot/grub is in the ZFS filesystem you can comment each line with the text save_env in the file /etc/grub.d/00_header and run update-grub.

                    Step 3: Disk Formatting

                    3.1 Format the small boot partition created by Step 2.2 as a filesystem that has stage1 GRUB support like this:

                    # mke2fs -m 0 -L /boot/grub -j /dev/disk/by-id/scsi-SATA_disk1-part1
                    

                    3.2 Create the root pool on the larger partition:

                    # zpool create -o ashift=9 rpool /dev/disk/by-id/scsi-SATA_disk1-part2
                    

                    Always use the long /dev/disk/by-id/* aliases with ZFS. Using the /dev/sd* device nodes directly can cause sporadic import failures, especially on systems that have more than one storage pool.

                    Warning: The grub2-1.99 package currently published in the PPA for Precise does not reliably handle a 4k block size, which is ashift=12.

                    Hints:

                    • # ls -la /dev/disk/by-id will list the aliases.
                    • The root pool can be a mirror. For example, zpool create -o ashift=9 rpool mirror /dev/disk/by-id/scsi-SATA_disk1-part2 /dev/disk/by-id/scsi-SATA_disk2-part2. Remember that the version and ashift matter for any pool that GRUB must read, and that these things are difficult to change after pool creation.
                    • If you are using a mirror with a separate boot partition as described above, don't forget to edit the grub.cfg file on the second HD partition so that the "root=" partition refers to that partition on the second HD also; otherwise, if you lose the first disk, you won't be able to boot from the second because the kernel will keep trying to mount the root partition from the first disk.
                    • The pool name is arbitrary. On systems that can automatically install to ZFS, the root pool is named "rpool" by default. Note that system recovery is easier if you choose a unique name instead of "rpool". Anything except "rpool" or "tank", like the hostname, would be a good choice.
                    • If you want to create a mirror but only have one disk available now you can create the mirror using a sparse file as the second member then immediately off-line it so the mirror is in degraded mode. Later you can add another drive to the spool and ZFS will automatically sync them. The sparse file won't take up more than a few KB so it can be bigger than your running system. Just make sure to off-line the sparse file before writing to the pool.

                    3.2.1 Create a sparse file at least as big as the larger partition on your HDD:

                    # truncate -s 11g /tmp/sparsefile
                    

                    3.2.2 Instead of the command in section 3.2 use this to create the mirror:

                    # zpool create -o ashift=9 rpool mirror /dev/disk/by-id/scsi-SATA_disk1-part2 /tmp/sparsefile
                    

                    3.2.3 Offline the sparse file. You can delete it after this if you want.

                    # zpool offline rpool /tmp/sparsefile
                    

                    3.2.4 Verify that the pool was created and is now degraded.

                    # zpool list
                    NAME       SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
                    rpool     10.5G   188K  10.5G     0%  1.00x  DEGRADED  -
                    

                    3.3 Create a "ROOT" filesystem in the root pool:

                    # zfs create rpool/ROOT
                    

                    3.4 Create a descendant filesystem for the Ubuntu system:

                    # zfs create rpool/ROOT/ubuntu-1
                    

                    On Solaris systems, the root filesystem is cloned and the suffix is incremented for major system changes through pkg image-update or beadm. Similar functionality for APT is possible but currently unimplemented.

                    3.5 Dismount all ZFS filesystems.

                    # zfs umount -a
                    

                    3.6 Set the mountpoint property on the root filesystem:

                    # zfs set mountpoint=/ rpool/ROOT/ubuntu-1
                    

                    3.7 Set the bootfs property on the root pool.

                    # zpool set bootfs=rpool/ROOT/ubuntu-1 rpool
                    

                    The boot loader uses these two properties to find and start the operating system. These property names are not arbitrary.

                    Hint: Putting rpool=MyPool or bootfs=MyPool/ROOT/system-1 on the kernel command line overrides the ZFS properties.

                    3.9 Export the pool:

                    # zpool export rpool
                    

                    Don't skip this step. The system is put into an inconsistent state if this command fails or if you reboot at this point.

                    Step 4: System Installation

                    Remember: Substitute "rpool" for the name chosen in Step 3.2.

                    4.1 Import the pool:

                    # zpool import -d /dev/disk/by-id -R /mnt rpool
                    

                    If this fails with "cannot import 'rpool': no such pool available", you can try import the pool without the device name eg:

                        # zpool import -R /mnt rpool
                    

                    4.2 Mount the small boot filesystem for GRUB that was created in step 3.1:

                    # mkdir -p /mnt/boot/grub
                    # mount /dev/disk/by-id/scsi-SATA_disk1-part1 /mnt/boot/grub
                    

                    4.4 Install the minimal system:

                    # debootstrap trusty /mnt
                    

                    The debootstrap command leaves the new system in an unconfigured state. In Step 5, we will only do the minimum amount of configuration necessary to make the new system runnable.

                    Step 5: System Configuration

                    5.1 Copy these files from the LiveCD environment to the new system:

                    # cp /etc/hostname /mnt/etc/
                    # cp /etc/hosts /mnt/etc/
                    

                    5.2 The /mnt/etc/fstab file should be empty except for a comment. Add this line to the /mnt/etc/fstab file:

                    /dev/disk/by-id/scsi-SATA_disk1-part1  /boot/grub  auto  defaults  0  1
                    

                    The regular Ubuntu desktop installer may add dev, proc, sys, or tmp lines to the /etc/fstab file, but such entries are redundant on a system that has a /lib/init/fstab file. Add them now if you want them.

                    5.3 Edit the /mnt/etc/network/interfaces file so that it contains something like this:

                    # interfaces(5) file used by ifup(8) and ifdown(8)
                    auto lo
                    iface lo inet loopback
                    
                    auto eth0
                    iface eth0 inet dhcp
                    

                    Customize this file if the new system is not a DHCP client on the LAN.

                    5.4 Make virtual filesystems in the LiveCD environment visible to the new system and chroot into it:

                    # mount --bind /dev  /mnt/dev
                    # mount --bind /proc /mnt/proc
                    # mount --bind /sys  /mnt/sys
                    # chroot /mnt /bin/bash --login
                    

                    5.5 Install PPA support in the chroot environment like this:

                    # locale-gen en_US.UTF-8
                    # apt-get update
                    # apt-get install ubuntu-minimal software-properties-common
                    

                    Even if you prefer a non-English system language, always ensure that en_US.UTF-8 is available. The ubuntu-minimal package is required to use ZoL as packaged in the PPA.

                    5.6 Install ZFS in the chroot environment for the new system:

                    # apt-add-repository --yes ppa:zfs-native/stable
                    # apt-add-repository --yes ppa:zfs-native/grub
                    # apt-get update
                    # apt-get install --no-install-recommends linux-image-generic linux-headers-generic
                    # apt-get install ubuntu-zfs
                    # apt-get install grub2-common grub-pc
                    # apt-get install zfs-initramfs
                    # apt-get dist-upgrade
                    

                    Warning: This is the second time that you must wait for the SPL and ZFS modules to compile. Do not try to skip this step by copying anything from the host environment into the chroot environment.

                    Note: This should install a kernel package and its headers, a patched mountall and dkms packages. Double-check that you are getting these packages from the PPA if you are deviating from these instructions in any way.

                    Choose /dev/disk/by-id/scsi-SATA_disk1 if prompted to install the MBR loader.

                    Ignore warnings that are caused by the chroot environment like:

                    • Can not write log, openpty() failed (/dev/pts not mounted?)
                    • df: Warning: cannot read table of mounted file systems
                    • mtab is not present at /etc/mtab.

                    5.7 Set a root password on the new system:

                    # passwd root
                    

                    Hint: If you want the ubuntu-desktop package, then install it after the first reboot. If you install it now, then it will start several process that must be manually stopped before dismount.

                    Step 6: GRUB Installation

                    Remember: All of Step 6 depends on Step 5.4 and must happen inside the chroot environment.

                    6.1 Verify that the ZFS root filesystem is recognized by GRUB:

                    # grub-probe /
                    zfs
                    

                    And that the ZFS modules for GRUB are installed:

                    # ls /boot/grub/zfs*
                    /boot/grub/zfs.mod  /boot/grub/zfsinfo.mod
                    

                    Note that after Ubuntu 13, these are now in /boot/grub/i386/pc/zfs*

                    # ls /boot/grub/i386-pc/zfs*
                    /boot/grub/i386-pc/zfs.mod  /boot/grub/i386-pc/zfsinfo.mod
                    

                    Otherwise, check the troubleshooting notes for GRUB below.

                    6.2 Refresh the initrd files:

                    # update-initramfs -c -k all
                    update-initramfs: Generating /boot/initrd.img-3.2.0-40-generic
                    

                    6.3 Update the boot configuration file:

                    # update-grub
                    Generating grub.cfg ...
                    Found linux image: /boot/vmlinuz-3.2.0-40-generic
                    Found initrd image: /boot/initrd.img-3.2.0-40-generic
                    done
                    

                    Verify that boot=zfs appears in the boot configuration file:

                    # grep boot=zfs /boot/grub/grub.cfg
                    linux /ROOT/ubuntu-1/@/boot/vmlinuz-3.2.0-40-generic root=/dev/sda2 ro boot=zfs $bootfs quiet splash $vt_handoff
                    linux /ROOT/ubuntu-1/@/boot/vmlinuz-3.2.0-40-generic root=/dev/sda2 ro single nomodeset boot=zfs $bootfs
                    

                    6.4 Install the boot loader to the MBR like this:

                    # grub-install $(readlink -f /dev/disk/by-id/scsi-SATA_disk1)
                    Installation finished. No error reported.
                    

                    Do not reboot the computer until you get exactly that result message. Note that you are installing the loader to the whole disk, not a partition.

                    Note: The readlink is required because recent GRUB releases do not dereference symlinks.

                    Step 7: Cleanup and First Reboot

                    7.1 Exit from the chroot environment back to the LiveCD environment:

                    # exit
                    

                    7.2 Run these commands in the LiveCD environment to dismount all filesystems:

                    # umount /mnt/boot/grub
                    # umount /mnt/dev
                    # umount /mnt/proc
                    # umount /mnt/sys
                    # zfs umount -a
                    # zpool export rpool
                    

                    The zpool export command must succeed without being forced or the new system will fail to start.

                    7.3 We're done!

                    # reboot
                    

                    Caveats and Known Problems

                    This is an experimental system configuration.

                    This document was first published in 2010 to demonstrate that the lzfs implementation made ZoL 0.5 feature complete. Upstream integration efforts began in 2012, and it will be at least a few more years before this kind of configuration is even minimally supported.

                    Gentoo, and its derivatives, are the only Linux distributions that are currently mainlining support for a ZoL root filesystem.

                    zpool.cache inconsistencies cause random pool import failures.

                    The /etc/zfs/zpool.cache file embedded in the initrd for each kernel image must be the same as the /etc/zfs/zpool.cache file in the regular system. Run update-initramfs -c -k all after any /sbin/zpool command changes the /etc/zfs/zpool.cache file.

                    Pools do not show up in /etc/zfs/zpool.cache when imported with the -R flag.

                    This will be a recurring problem until issue zfsonlinux/zfs#330 is resolved.

                    Every upgrade can break the system.

                    Ubuntu systems remove old dkms modules before installing new dkms modules. If the system crashes or restarts during a ZoL module upgrade, which is a failure window of several minutes, then the system becomes unbootable and must be rescued.

                    This will be a recurring problem until issue zfsonlinux/pkg-zfs#12 is resolved.

                    When doing an upgrade remotely an extra precaution would be to use screen, this way if you get disconnected your installation will not get interrupted.

                    Troubleshooting

                    (i) MPT2SAS

                    Most problem reports for this tutorial involve mpt2sas hardware that does slow asynchronous drive initialization, like some IBM M1015 or OEM-branded cards that have been flashed to the reference LSI firmware.

                    The basic problem is that disks on these controllers are not visible to the Linux kernel until after the regular system is started, and ZoL does not hotplug pool members. See https://github.com/zfsonlinux/zfs/issues/330.

                    Most LSI cards are perfectly compatible with ZoL, but there is no known fix if your card has this glitch. Please use different equipment until the mpt2sas incompatibility is diagnosed and fixed, or donate an affected part if you want solution sooner.

                    (ii) Areca

                    Systems that require the arcsas blob driver should add it to the /etc/initramfs-tools/modules file and run update-initramfs -c -k all.

                    Upgrade or downgrade the Areca driver if something like RIP: 0010:[<ffffffff8101b316>] [<ffffffff8101b316>] native_read_tsc+0x6/0x20 appears anywhere in kernel log. ZoL is unstable on systems that emit this error message.

                    (iii) GRUB Installation

                    Verify that the PPA for the ZFS enhanced GRUB is installed:

                    # apt-add-repository ppa:zfs-native/grub
                    # apt-get update
                    

                    Reinstall the zfs-grub package, which is an alias for a patched grub-common package:

                    # apt-get install --reinstall zfs-grub
                    

                    Afterwards, this should happen:

                    # apt-cache search zfs-grub
                    grub-common - GRand Unified Bootloader (common files)
                    
                    # apt-cache show zfs-grub
                    N: Can't select versions from package 'zfs-grub' as it is purely virtual
                    N: No packages found
                    
                    # apt-cache policy grub-common zfs-grub
                    grub-common:
                     Installed: 1.99-21ubuntu3.9+zfs1~precise1
                     Candidate: 1.99-21ubuntu3.9+zfs1~precise1
                     Version table:
                    *** 1.99-21ubuntu3.9+zfs1~precise1 0
                          1001 http://ppa.launchpad.net/zfs-native/grub/ubuntu/precise/main amd64 Packages
                           100 /var/lib/dpkg/status
                        1.99-21ubuntu3 0
                          1001 http://us.archive.ubuntu.com/ubuntu/ precise/main amd64 Packages
                    zfs-grub:
                     Installed: (none)
                     Candidate: (none)
                     Version table:
                    

                    For safety, grub modules are never updated by the packaging system after initial installation. Manually refresh them by doing this:

                    # cp /usr/lib/grub/i386-pc/*.mod /boot/grub/
                    

                    If the problem persists, then open a bug report and attach the entire output of those apt-get commands.

                    Packages in the GRUB PPA are compiled against the stable PPA. Systems that run the daily PPA may experience failures if the ZoL library interface changes.

                    Note that GRUB does not currently dereference symbolic links in a ZFS filesystem, so you cannot use the /vmlinux or /initrd.img symlinks as GRUB command arguments.

                    (iv) GRUB does not support ZFS Compression

                    If the /boot hierarchy is in ZFS, then that pool should not be compressed. The grub packages for Ubuntu are usually incapable of loading a kernel image or initrd from a compressed dataset.

                    (v) VMware

                    • Set disk.EnableUUID = "TRUE" in the vmx file or vsphere configuration. Doing this ensures that /dev/disk aliases are created in the guest.

                    (vi) QEMU/KVM/XEN

                    • In the /etc/default/grub file, enable the GRUB_TERMINAL=console line and remove the splash option from the GRUB_CMDLINE_LINUX_DEFAULT line. Plymouth can cause boot errors in these virtual environments that are difficult to diagnose.

                    • Set a unique serial number on each virtual disk. (eg: -drive if=none,id=disk1,file=disk1.qcow2,serial=1234567890)

                    (vii) Kernel Parameters

                    The zfs-initramfs package requires that boot=zfs always be on the kernel command line. If the boot=zfs parameter is not set, then the init process skips the ZFS routine entirely. This behavior is for safety; it makes the casual installation of the zfs-initramfs package unlikely to break a working system.

                    ZFS properties can be overridden on the the kernel command line with rpool and bootfs arguments. For example, at the GRUB prompt:

                    linux /ROOT/ubuntu-1/@/boot/vmlinuz-3.0.0-15-generic boot=zfs rpool=AltPool bootfs=AltPool/ROOT/foobar-3

                    (viii) System Recovery

                    If the system randomly fails to import the root filesystem pool, then do this at the initramfs recovery prompt:

                    # zpool export rpool
                    : now export all other pools too
                    # zpool import -d /dev/disk/by-id -f -N rpool
                    : now import all other pools too
                    # mount -t zfs -o zfsutil rpool/ROOT/ubuntu-1 /root
                    : do not mount any other filesystem
                    # cp /etc/zfs/zpool.cache /root/etc/zfs/zpool.cache
                    # exit
                    

                    This refreshes the /etc/zfs/zpool.cache file. The zpool command emits spurious error messages regarding missing or corrupt vdevs if the zpool.cache file is stale or otherwise incorrect.



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

                    출처 : http://www.oracle.com/technetwork/articles/servers-storage-admin/howto-build-openstack-zfs-2248817.html



                    About OpenStack in Oracle Solaris 11

                    Want to comment on this article? Post the link on Facebook's OTN Garage page.  Have a similar article to share? Bring it up on Facebook or Twitter and let's discuss.

                    OpenStack, a popular open source project that provides cloud management infrastructure, is integrated into Oracle Solaris 11.2. OpenStack storage features include Cinder for block storage access (see Figure 1) and Swift for object storage that also provides redundancy and replication.

                    ZFS, a file system that integrates volume management features, provides a simple interface for managing large amounts data. It has a robust set of data services and also supports a variety of storage protocols.

                    Cinder provisions a ZFS block device or a volume for your project (or tenant) instances. An Oracle Solaris Kernel Zone or a non-global zone is created and deployed for each project instance. After you create a deployable image of the zone and launch an instance of the zone image, Cinder allocates a ZFS volume to contain the instance's image as the guest's root device.

                    Oracle Solaris 11.2 provides additional Cinder drivers to provision the following devices:

                    • iSCSI targets from a pool on a Cinder volume node
                    • FC LUNs as block devices
                    • iSCSI targets from an Oracle ZFS Storage Appliance

                    However, using these features is beyond the scope of this article.

                    A good way to get started with OpenStack is to run a small, all-in-one configuration where all OpenStack services are enabled, along with the Cinder volume service on the same system node, and to use ZFS as the back-end storage.

                    ZFS provides robust redundancy and doesn't need any special software or hardware arrays to provide data redundancy. ZFS is simple to configure and manage.

                    This article describes cloud storage practices for deploying a cloud infrastructure environment on Oracle Solaris and using Cinder to provide block storage devices as ZFS volumes on the same system.

                    This article does not describe how to set up OpenStack. For information on setting up OpenStack, see "Getting Started with OpenStack on Oracle Solaris 11.2."

                    Figure 1. Diagram of OpenStack Cinder Block Storage Service

                    Figure 1. Diagram of OpenStack Cinder Block Storage Service

                    OpenStack Block Storage Prerequisites and Deployment Process

                    The prerequisites require that Oracle Solaris 11.2 OpenStack already be running on a single SPARC or x86 system as the compute node that runs the primary OpenStack services and has multiple local or SAN-based devices.

                    The components of the configuration include the following:

                    • Compute node (Nova): The system node where zones for tenant or project instances are managed, but zones are not installed as part of the process described in this article. The Cinder volume service runs on this node as well.
                    • Volume service (Cinder): The location where the Cinder volume service allocates ZFS volumes for tenant or project instances, which is customized in this article.
                    • User authorization (Keystone): Both admin and tenant user names and passwords must already have been created and can be provided to Keystone, the authentication service.

                    The following general steps describe how to customize a single system that runs OpenStack services and runs the Cinder volume service to deploy ZFS volumes. Data redundancy is configured and ZFS compression and encryption can also be added in this configuration.

                    The remaining sections of this article describe these steps in detail.

                    Create the ZFS Components

                    Oracle Solaris runs on a ZFS storage pool that is typically called rpool. This usually small pool is not an ideal environment for hosting a cloud infrastructure, because it contains the Oracle Solaris components that run the system.

                    A general recommendation is to keep your root pool (rpool) small and host your application, user, and cloud data in a separate pool. Mirrored pool configurations perform best for most workloads.

                    The following steps describe how to configure the components shown in Figure 2: a mirrored ZFS storage pool (tank), the primary file system (cinder), and the ZFS volumes that will contain the tenant (or project) cloud instances.

                    Figure 2. A Mirrored ZFS Storage Pool with File System Components

                    Figure 2. A Mirrored ZFS Storage Pool with File System Components

                    1. Create a separate, mirrored ZFS storage pool that provides data redundancy and also configures two spares.

                      The following example creates a mirrored storage pool called tank that contains two pairs of mirrored disks and two spare disks:

                      # zpool create tank mirror c0t5000C500335F4C7Fd0 \
                      c0t5000C500335F7DABd0 mirror c0t5000C500335FC6F3d0 \
                      c0t5000C500336084C3d0 spare c0t5000C500335E2F03d0 \
                      c0t50015179594B6F52d0
                      

                      Size the mirrored storage pool according to your estimated cloud data needs. You can always add another mirrored pair of devices to your mirrored ZFS storage pool if you need more space.

                      For more information about ZFS administration syntax, see Managing ZFS File Systems in Oracle Solaris 11.2.

                      Review your pool's current status:

                      # zpool status tank
                      

                      Identify the pool's raw available space:

                      # zpool list tank
                      
                    2. Create a ZFS file system:

                      Note: If you want to use encryption to secure your cloud data, encryption must be enabled (as described below) when the ZFS file system is created. For more information about ZFS encryption and other encryption key methods besides being prompted for a passphrase, see see Managing ZFS File Systems in Oracle Solaris 11.2.

                      # zfs create tank/cinder
                      

                      Review the actual available space that is available to your file system:

                      # zfs list -r tank/cinder
                      

                      Frequently review the space available for your ZFS volumes by monitoring the USED space and the AVAIL space.

                      If you want to conserve disk space, enable compression on the tank/cinder file system. ZFS volumes that are allocated for project instances are automatically compressed.

                      # zfs set compression=on tank/cinder
                      

                      If you want to secure your cloud data, consider enabling encryption.

                      # zfs create -o encryption=on tank/cinder
                      Enter passphrase for 'tank/cinder': xxxxxxxx
                      Enter again: xxxxxxxx
                      

                    Customize the Cinder Storage Location

                    1. Modify the zfs_volume_base parameter in /etc/cinder/cinder.conf to identify an alternate pool/file-system.

                      For example, change this line:

                      # zfs_volume_base = rpool/cinder 
                      

                      To this:

                      # zfs_volume_base = tank/cinder
                      
                    2. Refresh the Cinder volume services:

                      # svcadm restart svc:/application/openstack/cinder/cinder-volume:setup
                      # svcadm restart svc:/application/openstack/cinder/cinder-volume:default
                      

                    Test Your Cinder Configuration

                    1. Set the authentication environment variables:

                      Cinder expects the following Keystone authorization parameters to be presented as options on the command line, or you can set them as environment variables.

                      # export OS_AUTH_URL=http://localhost:5000/v2.0 
                      # export OS_USERNAME=admin-user-name 
                      # export OS_PASSWORD=password 
                      # export OS_TENANT_NAME=tenant-user-name 
                      
                    2. Create a 1-GB test volume:

                      # cinder create --display_name test 1
                      +---------------------+--------------------------------------+
                      |       Property      |                Value                 |
                      +---------------------+--------------------------------------+
                      |     attachments     |                  []                  |
                      |  availability_zone  |                 nova                 |
                      |       bootable      |                false                 |
                      |      created_at     |      2014-07-17T20:19:33.423744      |
                      | display_description |                 None                 |
                      |     display_name    |                 test                 |
                      |          id         | 258d80e9-2ef3-eab8-fbea-96a4d176360d |
                      |       metadata      |                  {}                  |
                      |         size        |                  1                   |
                      |     snapshot_id     |                 None                 |
                      |     source_volid    |                 None                 |
                      |        status       |               creating               |
                      |     volume_type     |                 None                 |
                      +---------------------+--------------------------------------+
                      
                    3. After you create a Cinder volume, confirm that it is created and the space is consumed:

                      # zfs list -r tank/cinder
                      NAME                             USED  AVAIL REFER MOUNTPOINT
                      tank/cinder                      1.03G 547G  31K  /tank/cinder
                      tank/cinder/volume-258d80e9-...  1.03G  546G 16K  -
                      

                      You can also confirm that the volume is visible from OpenStack's Horizon interface. When you launch a project instance through Horizon, a new Cinder volume is created automatically, so you can remove the test volume from the Horizon->volume menu by using the Delete Volume feature.

                    (Optional) Perform Additional Cinder Configuration Customization

                    The following are additional customizations you can do:

                    • Monitor your ZFS pool for disk failures by setting up smtp-notify alert notifications.
                    • Use ZFS snapshots to replicate ZFS volumes.
                    • Create a separate archive pool with ZFS compression enabled to reduce the storage footprint when archiving tenant data.

                    For more information, see Managing ZFS File Systems in Oracle Solaris 11.2.

                    Summary

                    A redundant ZFS storage pool that is serving Cinder volumes for OpenStack can be hosted on any local or SAN storage to provide cloud data protection. You can also apply robust data services, such as encryption for data security or compression for data reduction, to your cloud storage.

                    See Also

                    The ZFS blog.



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




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

                    출처 : https://wiki.archlinux.org/index.php/Installing_Arch_Linux_on_ZFS


                    Installing ZFS on a CentOS 6 Linux server

                    As most of my long term readers know I am a huge Solaris fan. How can’t you love an Operating System that comes with ZFS, DTrace, Zones, FMA and Network Virtualization amongst other things? I use Linux during my day job, and I’ve been hoping for quite some time that Oracle would port one or more of these technologies to Linux. Well the first salvo has been fired, though it wasn’t from Oracle. It comes by way of the ZFS on Linux project, which is an in-kernel implementation of ZFS (this project is different from the FUSE ZFS port).

                    I had some free time this weekend to play around with ZFS on Linux, and my initial impressions are quite positive. The port on Linux is based on the latest version of ZFS that is part of OpenSolaris (version 28), so things like snapshots, de-duplication, improved performance and ZFS send and recv are available out of the box. There are a few missing items, but from what I can tell from the documentation there is plenty more coming.

                    The ZFS file system for Linux comes as source code, which you build into loadable kernel modules (this is how they get around the license incompatibilities). The implementation also contains the userland utilities (zfs, zpool, etc.) most Solaris admins are used to, and they act just like their Solaris counterparts! Nice!

                    My testing occurred on a CentOS 6 machine, specifically 6.2:

                    $ cat /etc/redhat-release
                    CentOS release 6.2 (Final)

                    The build process is quite easy. Prior to compiling source code you will need to install a few dependencies:

                    $ yum install kernel-devel zlib-devel libuuid-devel libblkid-devel libselinux-devel parted lsscsi

                    Once these are installed you can retrieve and build spl and zfs packages:

                    $ wget http://github.com/downloads/zfsonlinux/spl/spl-0.6.0-rc6.tar.gz

                    $ tar xfvz spl-0.6.0-rc6.tar.gz && cd spl*6

                    $ ./configure && make rpm

                    $ rpm -Uvh *.x86_64.rpm

                    Preparing...                ########################################### [100%]
                       1:spl-modules-devel      ########################################### [ 33%]
                       2:spl-modules            ########################################### [ 67%]
                       3:spl                    ########################################### [100%]
                    

                    $ wget http://github.com/downloads/zfsonlinux/zfs/zfs-0.6.0-rc6.tar.gz

                    $ tar xfvz zfs-0.6.0-rc6.tar.gz && cd zfs*6

                    $ ./configure && make rpm

                    $ rpm -Uvh *.x86_64.rpm

                    Preparing...                ########################################### [100%]
                       1:zfs-test               ########################################### [ 17%]
                       2:zfs-modules-devel      ########################################### [ 33%]
                       3:zfs-modules            ########################################### [ 50%]
                       4:zfs-dracut             ########################################### [ 67%]
                       5:zfs-devel              ########################################### [ 83%]
                       6:zfs                    ########################################### [100%]
                    

                    If everything went as planned you now have the ZFS kernel modules and userland utilities installed! To begin using ZFS you will first need to load the kernel modules with modprobe:

                    $ modprobe zfs

                    To verify the module loaded you can tail /var/log/messages:

                    Feb 12 17:54:27 centos6 kernel: SPL: Loaded module v0.6.0, using hostid 0x00000000
                    Feb 12 17:54:27 centos6 kernel: zunicode: module license 'CDDL' taints kernel.
                    Feb 12 17:54:27 centos6 kernel: Disabling lock debugging due to kernel taint
                    Feb 12 17:54:27 centos6 kernel: ZFS: Loaded module v0.6.0, ZFS pool version 28, ZFS filesystem version 5
                    

                    And run lsmod to verify they are there:

                    $ lsmod | grep -i zfs

                    zfs                  1038053  0 
                    zcommon                42478  1 zfs
                    znvpair                47487  2 zfs,zcommon
                    zavl                    6925  1 zfs
                    zunicode              323120  1 zfs
                    spl                   210887  5 zfs,zcommon,znvpair,zavl,zunicode
                    

                    To create our first pool we can use the zpool utilities create option:

                    $ zpool create mysqlpool mirror sdb sdc

                    The example above created a mirrored pool out of the sdb and sdc block devices. We can see this layout in the output of `zpool status`:

                    $ zpool status -v

                      pool: mysqlpool
                     state: ONLINE
                     scan: none requested
                    config:
                    
                    	NAME        STATE     READ WRITE CKSUM
                    	mysqlpool   ONLINE       0     0     0
                    	  mirror-0  ONLINE       0     0     0
                    	    sdb     ONLINE       0     0     0
                    	    sdc     ONLINE       0     0     0
                    
                    errors: No known data errors
                    

                    Awesome! Since we are at pool version 28 lets disable atime updates and enable compression and deduplication:

                    $ zfs set compression=on mysqlpool

                    $ zfs set dedup=on mysqlpool

                    $ zfs set atime=off mysqlpool

                    For a somewhat real world test, I stopped one of my MySQL slaves, mounted the pool on /var/lib/mysql, synchronized the previous data over to the ZFS file system and then started MySQL. No errors to report, and MySQL is working just fine. Next up, I trash one side of the mirror and verified that resilvering works:

                    $ dd if=/dev/zero of=/dev/sdb

                    $ zpool scrub mysqlpool

                    I let this run for a few minutes then ran `zpool status` to verify the scrub fixed everything:

                    $ zpool status -v

                      pool: mysqlpool
                     state: ONLINE
                    status: One or more devices has experienced an unrecoverable error.  An
                    	attempt was made to correct the error.  Applications are unaffected.
                    action: Determine if the device needs to be replaced, and clear the errors
                    	using 'zpool clear' or replace the device with 'zpool replace'.
                       see: http://www.sun.com/msg/ZFS-8000-9P
                     scan: scrub repaired 966K in 0h0m with 0 errors on Sun Feb 12 18:54:51 2012
                    config:
                    
                    	NAME        STATE     READ WRITE CKSUM
                    	mysqlpool   ONLINE       0     0     0
                    	  mirror-0  ONLINE       0     0     0
                    	    sdb     ONLINE       0     0   175
                    	    sdc     ONLINE       0     0     0
                    

                    I beat on the pool pretty good and didn’t encounter any hangs or kernel oopses. The file systems port is still in its infancy, so I won’t be trusting it with production data quite yet. Hopefully it will mature in the coming months, and if we’re lucky maybe one of the major distributions will begin including it! That would be killer!!



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


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

                    출처 : http://prefetch.net/blog/index.php/2012/02/13/installing-zfs-on-a-centos-6-linux-server/



                    Installing Arch Linux on ZFS


                    This article details the steps required to install Arch Linux onto a root ZFS filesystem. This article supplements the Beginners' guide.

                    Installation

                    See ZFS#Installation for installing the ZFS packages. If installing Arch Linux onto ZFS from the archiso, it would be easier to use the demz-repo-archiso repository.

                    Embedding archzfs into archiso

                    See ZFS article.

                    Partition the destination drive

                    Review Beginners' guide#Prepare_the_storage_drive for information on determining the partition table type to use for ZFS. ZFS supports GPT and MBR partition tables.

                    ZFS manages its own partitions, so only a basic partition table scheme is required. The partition that will contain the ZFS filesystem should be of the type bf00, or "Solaris Root".

                    Partition scheme

                    Here is an example, using MBR, of a basic partition scheme that could be employed for your ZFS root setup:

                    Part     Size   Type
                    ----     ----   -------------------------
                       1     512M   Ext boot partition (8300)
                       2     XXXG   Solaris Root (bf00)
                    

                    Here is an example using GPT. The BIOS boot partition contains the bootloader.

                    Part     Size   Type
                    ----     ----   -------------------------
                       1       2M   BIOS boot partition (ef02)
                       1     512M   Ext boot partition (8300)
                       2     XXXG   Solaris Root (bf00)
                    

                    An additional partition may be required depending on your hardware and chosen bootloader. Consult Beginners' guide#Install_and_configure_a_bootloader for more info.

                    Tip: Bootloaders with support for ZFS are described in #Install and configure the bootloader.
                    Warning: Several GRUB bugs (bug #42861, zfsonlinux/grub/issues/5) prevent or complicate installing it on ZFS partitions, use of a separate boot partition is recommended

                    Format the destination disk

                    Format the boot partition as well as any other system partitions. Do not do anything to the Solaris partition nor to the BIOS boot partition. ZFS will manage the first, and your bootloader the second.

                    Setup the ZFS filesystem

                    First, make sure the ZFS modules are loaded,

                    # modprobe zfs
                    

                    Create the root zpool

                    # zpool create zroot /dev/disk/by-id/id-to-partition
                    
                    Warning: Always use id names when working with ZFS, otherwise import errors will occur.

                    Create necessary filesystems

                    If so desired, sub-filesystem mount points such as /home and /root can be created with the following commands:

                    # zfs create zroot/home -o mountpoint=/home
                    # zfs create zroot/root -o mountpoint=/root
                    

                    Note that if you want to use other datasets for system directories (/var or /etc included) your system will not boot unless they are listed in /etc/fstab! We will address that at the appropriate time in this tutorial.

                    Swap partition

                    See ZFS#Swap volume.

                    Configure the root filesystem

                    First, set the mount point of the root filesystem:

                    # zfs set mountpoint=/ zroot
                    

                    and optionally, any sub-filesystems:

                    # zfs set mountpoint=/home zroot/home
                    # zfs set mountpoint=/root zroot/root
                    

                    and if you have seperate datasets for system directories (ie /var or /usr)

                    # zfs set mountpoint=legacy zroot/usr
                    # zfs set mountpoint=legacy zroot/var
                    

                    and put them in /etc/fstab

                    /etc/fstab
                    # <file system>        <dir>         <type>    <options>             <dump> <pass>
                    zroot/usr              /usr          zfs       defaults,noatime      0      0
                    zroot/var              /var          zfs       defaults,noatime      0      0

                    Set the bootfs property on the descendant root filesystem so the boot loader knows where to find the operating system.

                    # zpool set bootfs=zroot zroot
                    

                    Export the pool,

                    # zpool export zroot
                    
                    Warning: Do not skip this, otherwise you will be required to use -f when importing your pools. This unloads the imported pool.
                    Note: This might fail if you added a swap partition above. Need to turn it off with the swapoff command.

                    Finally, re-import the pool,

                    # zpool import -d /dev/disk/by-id -R /mnt zroot
                    
                    Note: -d is not the actual device id, but the /dev/by-id directory containing the symbolic links.

                    If there is an error in this step, you can export the pool to redo the command. The ZFS filesystem is now ready to use.

                    Be sure to bring the zpool.cache file into your new system. This is required later for the ZFS daemon to start.

                    # cp /etc/zfs/zpool.cache /mnt/etc/zfs/zpool.cache
                    

                    if you don't have /etc/zfs/zpool.cache, create it:

                    # zpool set cachefile=/etc/zfs/zpool.cache zroot
                    

                    Install and configure Arch Linux

                    Follow the following steps using the Beginners' guide. It will be noted where special consideration must be taken for ZFSonLinux.

                    • First mount any boot or system partitions using the mount command.
                    • Install the base system.
                    • The procedure described in Beginners' guide#Generate an fstab is usually overkill for ZFS. ZFS usually auto mounts its own partitions, so we do not need ZFS partitions in fstab file, unless the user made datasets of system directories. To generate the fstab for filesystems, use:
                    # genfstab -U -p /mnt | grep boot >> /mnt/etc/fstab
                    
                    • Edit the /etc/fstab:
                    Note:
                    • If you chose to create datasets for system directories, keep them in this fstab! Comment out the lines for the '/, /root, and /home mountpoints, rather than deleting them. You may need those UUIDs later if something goes wrong.
                    • Anyone who just stuck with the guide's directions can delete everything except for the swap file and the boot/EFI partition. It seems convention to replace the swap's uuid with /dev/zvol/zroot/swap.
                    • When creating the initial ramdisk, first edit /etc/mkinitcpio.conf and add zfs before filesystems. Also, move keyboard hook before zfs so you can type in console if something goes wrong. You may also remove fsck (if you are not using Ext3 or Ext4). Your HOOKS line should look something like this:
                    HOOKS="base udev autodetect modconf block keyboard zfs filesystems"
                    
                    • Regenerate the initramfs with the command:
                    # mkinitcpio -p linux
                    

                    Install and configure the bootloader

                    For BIOS motherboards

                    Follow GRUB#BIOS_systems_2 to install GRUB onto your disk. grub-mkconfig does not properly detect the ZFS filesystem, so it is necessary to edit grub.cfg manually:

                    /boot/grub/grub.cfg
                    set timeout=2
                    set default=0
                    
                    # (0) Arch Linux
                    menuentry "Arch Linux" {
                        set root=(hd0,msdos1)
                        linux /vmlinuz-linux zfs=zroot rw
                        initrd /initramfs-linux.img
                    }
                    

                    if you did not create a separate /boot participation, kernel and initrd paths have to be in the following format:

                     /dataset/@/actual/path  
                    

                    Example:

                       linux /@/boot/vmlinuz-linux zfs=zroot rw
                       initrd /@/boot/initramfs-linux.img
                    

                    For UEFI motherboards

                    Use EFISTUB and rEFInd for the UEFI boot loader. See Beginners' guide#For UEFI motherboards. The kernel parameters in refind_linux.conf for ZFS should include zfs=bootfs or zfs=zroot so the system can boot from ZFS. The root and rootfstype parameters are not needed.

                    Unmount and restart

                    We are almost done!

                    # exit
                    # umount /mnt/boot
                    # zfs umount -a
                    # zpool export zroot
                    

                    Now reboot.

                    Warning: If you do not properly export the zpool, the pool will refuse to import in the ramdisk environment and you will be stuck at the busybox terminal.

                    After the first boot

                    If everything went fine up to this point, your system will boot. Once. For your system to be able to reboot without issues, you need to enable the zfs.target to auto mount the pools and set the hostid.

                    For each pool you want automatically mounted execute:

                    # zpool set cachefile=/etc/zfs/zpool.cache <pool>
                    

                    Enable the target with systemd:

                    # systemctl enable zfs.target
                    

                    When running ZFS on root, the machine's hostid will not be available at the time of mounting the root filesystem. There are two solutions to this. You can either place your spl hostid in the kernel parameters in your boot loader. For example, adding spl.spl_hostid=0x00bab10c, to get your number use the hostid command.

                    The other, and suggested, solution is to make sure that there is a hostid in /etc/hostid, and then regenerate the initramfs image. Which will copy the hostid into the initramfs image. To do write the hostid file safely you need to use a small C program:

                    #include <stdio.h>
                    #include <errno.h>
                    #include <unistd.h>
                    
                    int main() {
                        int res;
                        res = sethostid(gethostid());
                        if (res != 0) {
                            switch (errno) {
                                case EACCES:
                                fprintf(stderr, "Error! No permission to write the"
                                             " file used to store the host ID.\n"
                                             "Are you root?\n");
                                break;
                                case EPERM:
                                fprintf(stderr, "Error! The calling process's effective"
                                                " user or group ID is not the same as"
                                                " its corresponding real ID.\n");
                                break;
                                default:
                                fprintf(stderr, "Unknown error.\n");
                            }
                            return 1;
                        }
                        return 0;
                    }
                    

                    Copy it, save it as writehostid.c and compile it with gcc -o writehostid writehostid.c, finally execute it and regenerate the initramfs image:

                    # ./writehostid
                    # mkinitcpio -p linux
                    

                    You can now delete the two files writehostid.c and writehostid. Your system should work and reboot properly now. 


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





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

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



                    오랫동안 사용하던 E450이 문제가 있어서 수리를 하면서, 그동안 사용하던 solaris9를 solaris10으로 다시 설치했다. disksuit로 구성을 하려다가 오래전에 본 비디오가 생각나서 zfs로 구성을 해 보기로 했다.

                    개념은 굉장히 간단하며, 사용방법 또한 metadb를 구성하는 것보다 간단하다. 하지만, 아직 확실한 개념 정립이 되지 않아서…

                    사용하는 디스크는 모두 6개로, 9GB 3개와 18GB 3개다. 9GB 1개는 OS를 설치했고, 나머지는 모두 사용하지 않는 상태다. 디스크는 아래와 같다

                    bash-3.00# format
                    Searching for disks…done
                    AVAILABLE DISK SELECTIONS:
                    0. c0t0d0 <SUN9.0G cyl 4924 alt 2 hd 27 sec 133>
                    /pci@1f,4000/scsi@3/sd@0,0
                    1. c0t1d0 <FUJITSU-MAE3091L SUN9.0G-0706-8.43GB>
                    /pci@1f,4000/scsi@3/sd@1,0
                    2. c0t2d0 <IBM-DDRS39130SUN9.0G-S98E-8.43GB>
                    /pci@1f,4000/scsi@3/sd@2,0
                    3. c2t0d0 <FUJITSU-MAG3182L SUN18G-1111-16.87GB>
                    /pci@1f,4000/scsi@4/sd@0,0
                    4. c3t2d0 <SEAGATE-ST318203LSUN18G-034A-16.87GB>
                    /pci@1f,4000/scsi@4,1/sd@2,0
                    5. c3t3d0 <SEAGATE-ST318203LC-0002-16.96GB>
                    /pci@1f,4000/scsi@4,1/sd@3,0
                    Specify disk (enter its number):

                    먼저, zpool을 사용하여 디스크 풀(이름은 fox_pool로 했다)을 만든다. (18GB 짜리 3개)

                    #zpool create fox_pool c2t0d0 c3t2d0 c3t3d0

                    #zpool list
                    NAME                    SIZE    USED   AVAIL    CAP  HEALTH     ALTROOT
                    fox_pool               58.8G    102K   58.7G     0%  ONLINE     -

                    9GB 디스크를 하나 더 추가했다.

                     #zpool add -f fox_pool c0t2d0

                    예전의 disk suit이 디스크 size에 민감했던 반면에, zfs는 디스크 size가 달라도 잘 추가가 된다.  상태를 확인해보면,

                    # zpool status
                    pool: fox_pool
                    state: ONLINE
                    scrub: none requested
                    config:

                    NAME        STATE     READ WRITE CKSUM
                    fox_pool    ONLINE       0     0     0
                    c2t0d0    ONLINE       0     0     0
                    c3t2d0    ONLINE       0     0     0
                    c3t3d0    ONLINE       0     0     0
                    c0t2d0    ONLINE       0     0     0

                    errors: No known data errors

                    이렇게  pool을 생성하면 /에 pool이름이 자동으로 마운트되어 사용가능한 상태가 된다. 이게 영 맘에 안들어서 zpool destroy로 만든 pool을 삭제하고 다시 생성했다(마운트하는 방법을 몰라서… ;ㅡㅡ)

                    #zpool create -f -m /export/home fox_pool c2t0d0 c3t2d0 c3t3d0 c0t2d0

                    그런데, 이것이 굳이 이럴 필요가 있는것인지 알 수가 없다. 왜냐하면, zfs 로  /export/home 에 zfs를 마운트할 수 있기 때문이다. 즉, 하나의 디스크 풀을 각기 다른 디렉토리에 마운트 할 수 있는것 같다. 그래서 oracle 프로그램용으로 zfs를 생성해서 마운트 해보았다.

                     #zfs create fox_pool/oracle mount /oracle  —> error

                    #zfs create fox_pool/oracle

                    # zfs list
                    NAME              USED  AVAIL  REFER  MOUNTPOINT
                    fox_pool          130K  57.8G    31K  /export/home
                    fox_pool/oracle  24.5K  57.8G  24.5K  /export/home/oracle

                    생성은 잘 되었지만, 문제가 있다. 나는 oracle을 /에 마운트 하고 싶은 것이다.

                    # zfs destroy fox_pool/oracle
                    # zfs list
                    NAME       USED  AVAIL  REFER  MOUNTPOINT
                    fox_pool  99.5K  57.8G    30K  /export/home

                    그래서 삭제를 해 버렸다.

                    여기서 어떻게 해야할지 모르겠다……   자, 답을 알아냈다

                    #zfs create fox_pool/oracle
                    #zfs set mountpoint=/oracle   fox_pool/oracle

                    마운트 포인트를 변경하니 해결이 된다.

                    자, 여기서, 일부러 에러를 유발하여 복구시켜보았다.

                    #dd if=/dev/urandom of=/dev/c3t3d0s0 bs=1024 count=10000

                    s0는 디스크들의 정보가 기록되는 슬라이스로 보이는데, 이곳을 쓰레기 값으로 채워넣은 것이다.

                    #zpool scrub fox_pool

                    이 에러는 복구가 되지 않았다. 사실 내가 원하는것은 이것이 아니었다. 그 후 여러번의 시행 착오를 거쳐서 알아낸 것은, zpool 생성시 어떤 옵션도 주지 않으면 디스크들이 stripe 로 묶이는 것이며, mirror 옵션을 주던가 아니면 가장 중요한, raidz 옵션을 주는 것이다.  사실 내가 원하던 것은 Raid5 였다.  mirror도 좋지만, 디스크 두개중 한개밖에 사용할 수 없으니까.

                    아무튼, Raid-Z 로 디스크를 구성했다. Raid5와 다른점은 디스크 두개로도 구성이 가능하다는 점이다. 사실 이 경우는 mirror와 별 차이가 없는것 같다.

                    # zpool create fox_pool raidz c2t0d0 c3t2d0
                    # zpool status
                    pool: fox_pool
                    state: ONLINE
                    scrub: none requested
                    config:

                    NAME        STATE     READ WRITE CKSUM
                    fox_pool    ONLINE       0     0     0
                    raidz1    ONLINE       0     0     0
                    c2t0d0  ONLINE       0     0     0
                    c3t2d0  ONLINE       0     0     0

                    errors: No known data errors
                    # df -h

                    fox_pool                16G    24K    16G     1%    /fox_pool

                    # zpool list
                    NAME                    SIZE    USED   AVAIL    CAP  HEALTH     ALTROOT
                    fox_pool               33.5G    178K   33.5G     0%  ONLINE     -

                    두 개의 디스크에 다시 에러를 유발시킨다. 여기서는 두번째 디스크 c3t2d0s0에 쓰레기값을 넣었다.

                    # zpool scrub fox_pool
                    # zpool status
                    pool: fox_pool
                    state: ONLINE
                    status: One or more devices has experienced an unrecoverable error.  An
                    attempt was made to correct the error.  Applications are unaffected.
                    action: Determine if the device needs to be replaced, and clear the errors
                    using ‘zpool clear’ or replace the device with ‘zpool replace’.
                    see: http://www.sun.com/msg/ZFS-8000-9P
                    scrub: scrub completed with 0 errors on Tue May 27 22:00:49 2008
                    config:

                    NAME        STATE     READ WRITE CKSUM
                    fox_pool    ONLINE       0     0     0
                    raidz1    ONLINE       0     0     0
                    c2t0d0  ONLINE       0     0     0
                    c3t2d0  ONLINE       0     0    27

                    errors: No known data errors

                    에러를 수정하는 방법에는 두가지가 있다. clear나 replace하는 방법이다. 나는 디스크가 하나 더 있기때문에, replace했다.

                    #zpool replace fox_pool c3t2d0 c3t3d0
                    # zpool status
                    pool: fox_pool
                    state: ONLINE
                    scrub: resilver completed with 0 errors on Tue May 27 22:02:22 2008
                    config:

                    NAME           STATE     READ WRITE CKSUM
                    fox_pool       ONLINE       0     0     0
                    raidz1       ONLINE       0     0     0
                    c2t0d0     ONLINE       0     0     0
                    replacing  ONLINE       0     0     0
                    c3t2d0   ONLINE       0     0    27
                    c3t3d0   ONLINE       0     0     0

                    errors: No known data errors

                    잠시후 확인해보면 디스크가 바뀌어 있는것을 확인 할 수 있다.

                     zpool status
                    pool: fox_pool
                    state: ONLINE
                    scrub: scrub completed with 0 errors on Tue May 27 22:09:20 2008
                    config:

                    NAME        STATE     READ WRITE CKSUM
                    fox_pool    ONLINE       0     0     0
                    raidz1    ONLINE       0     0     0
                    c2t0d0  ONLINE       0     0     0
                    c3t3d0  ONLINE       0     0     0

                    errors: No known data errors

                     

                    fox_pool에 남은 c3t2d0를 추가하기 위하여 zpool add명령을 사용했다.

                    결과는 별로다. 디스크가 raidz로 추가되는 것이 아니라, 기존의 raidz1과 stripe로 묶여버린 것이다. 물론, raidz 옵션을 추가할때 넣어봤지만, 이경우역시 작동되지 않았다.

                    # zpool status
                    pool: fox_pool
                    state: ONLINE
                    scrub: none requested
                    config:

                    NAME        STATE     READ WRITE CKSUM
                    fox_pool    ONLINE       0     0     0
                    raidz1    ONLINE       0     0     0
                    c2t0d0  ONLINE       0     0     0
                    c3t3d0  ONLINE       0     0     0
                    c3t2d0    ONLINE       0     0     0

                    errors: No known data errors

                    그래서 다시 디스크 세개로 fox_pool을 생성하였으며, 역시 에러를 유발한 후 테스트 하였다.

                    # zpool scrub fox_pool
                    # zpool status
                    pool: fox_pool
                    state: ONLINE
                    status: One or more devices has experienced an unrecoverable error.  An
                    attempt was made to correct the error.  Applications are unaffected.
                    action: Determine if the device needs to be replaced, and clear the errors
                    using ‘zpool clear’ or replace the device with ‘zpool replace’.
                    see: http://www.sun.com/msg/ZFS-8000-9P
                    scrub: scrub completed with 0 errors on Tue May 27 21:44:42 2008
                    config:

                    NAME        STATE     READ WRITE CKSUM
                    fox_pool    ONLINE       0     0     0
                    raidz1    ONLINE       0     0     0
                    c2t0d0  ONLINE       0     0     0
                    c3t2d0  ONLINE       0     0     0
                    c3t3d0  ONLINE       0     0    38

                    errors: No known data errors

                    같은방식으로 에러를 유발했다. c3t3d0의 체크섬이 38이다. 이것은 아래 명령으로 수정가능하다.

                    bash-3.00# zpool clear fox_pool c3t3d0
                    bash-3.00# zpool status
                    pool: fox_pool
                    state: ONLINE
                    scrub: scrub completed with 0 errors on Tue May 27 21:44:42 2008
                    config:

                    NAME        STATE     READ WRITE CKSUM
                    fox_pool    ONLINE       0     0     0
                    raidz1    ONLINE       0     0     0
                    c2t0d0  ONLINE       0     0     0
                    c3t2d0  ONLINE       0     0     0
                    c3t3d0  ONLINE       0     0     0

                    errors: No known data errors

                    다음은 snapshot을 만들어 보았다. snapshot은 만드는 시점의 데이타를 한번만 반영하는것 같다. 말 그대로 스냅샷을 수행하던 시점의 백업을 만드는 것 같다.

                    fox_pool에 zfs로 화일시스템을 만들고 세개의 화일(test.txt, last.txt, words)을 생성했다.  그리고 스냅샷을 만들었다.

                    # ls -al
                    total 576
                    drwxr-xr-x   2 root     sys            5 May 27 22:26 .
                    drwxr-xr-x   3 root     sys            3 May 27 22:25 ..
                    -rw-r–r–   1 root     root        7105 May 27 22:26 last.txt
                    -rw-r–r–   1 root     root       16566 May 27 22:26 test.txt
                    -r–r–r–   1 root     root      206663 May 27 22:26 words

                    # zfs snapshot fox_pool/home@snap1
                    bash-3.00# zfs list
                    NAME                  USED  AVAIL  REFER  MOUNTPOINT
                    fox_pool              424K  33.1G  35.3K  /fox_pool
                    fox_pool/home         316K  33.1G   316K  /fox_pool/home
                    fox_pool/home@snap1      0      –   316K  –

                    # rm words
                    # ls -al
                    total 58
                    drwxr-xr-x   2 root     sys            4 May 27 22:37 .
                    drwxr-xr-x   3 root     sys            3 May 27 22:25 ..
                    -rw-r–r–   1 root     root        7105 May 27 22:26 last.txt
                    -rw-r–r–   1 root     root       16566 May 27 22:26 test.txt
                    bash-3.00# zfs snapshot fox_pool/home@snap2
                    bash-3.00# zfs list
                    NAME                  USED  AVAIL  REFER  MOUNTPOINT
                    fox_pool              467K  33.1G  35.3K  /fox_pool
                    fox_pool/home         348K  33.1G  57.9K  /fox_pool/home
                    fox_pool/home@snap1   290K      –   316K  –
                    fox_pool/home@snap2      0      –  57.9K  -

                    스냅샷은 /fox_pool/home/.zfs/snapshot/snap1 과, /fox_pool/home/.zfs/snapshot/snap2에 각각 저장되어 있다.

                    # pwd
                    /fox_pool/home/.zfs/snapshot/snap2
                    # ls
                    last.txt  test.txt
                    # cd ../snap2
                    # ls
                    last.txt  test.txt

                    snap1로 롤백을 해보았다.

                    # zfs rollback fox_pool/home@snap1
                    cannot rollback to ‘fox_pool/home@snap1′: more recent snapshots exist
                    use ‘-r’ to force deletion of the following snapshots:
                    fox_pool/home@snap2
                    # zfs rollback -r fox_pool/home@snap1
                    cannot unmount ‘/fox_pool/home': Device busy
                    bash-3.00# pwd
                    /fox_pool/home
                    # ls
                    # cd ..
                    # zfs rollback -r fox_pool/home@snap1
                    # cd home
                    # ls
                    last.txt  test.txt  words

                    이때, 나중에 만든 snap2는 snap1이 만들어지던 시점에는 존재하지않았기때문에, 지워져 버렸다.. :-( 그래서 경고메시지가 나왔었군…

                    암튼, 스냅샷은 디스크를 차지하고 있으므로, 필요가 없으면 제거해준다.

                    #zfs  destroy fox_pool/home@snap1

                    스냅샷이 저장되는 디렉토리 .zfs 는 ls -al로는 확인이 되지 않았지만, 그 이후는 확인이 가능했다. 아울러, 필요한 화일을 직접 복사하는것도 가능했다.

                    여기까지 사용해본 소감은, 참 편리하다는거. newfs도 필요없고, 마운트도 필요없고. 생성속도 또한 빠르다. disksuit을 사용해야할 이유를 더 이상 찾을 수가 없다.(물론, solaris10이 아니라면 선택의 여지가 없겠지만…)

                    마지막으로 참고사이트 : http://docs.sun.com/app/docs/doc/819-5461?l=en  너무 늦게 발견 ;ㅡㅡ




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



                    반응형

                    'OS > LINUX Common' 카테고리의 다른 글

                    리눅스 프로세스별 메모리 사용량 확인  (0) 2015.09.02
                    리눅스 LVM 생성  (0) 2015.08.20
                    tmpfs 설정하는 방법  (0) 2014.04.16
                    GNU tar의 특이성 , 체크섬 오류  (0) 2013.07.09
                    리눅스 vsftpd 설치 / 설정.  (0) 2011.10.14
                    반응형


                    1) 출처 : http://linuxro-textcube.blogspot.kr/2010/01/vmware%EC%97%90-%EC%84%A4%EC%B9%98%EB%90%9C-linux%EC%9D%98-%EB%94%94%EC%8A%A4%ED%81%AC-%EC%9A%A9%EB%9F%89-%ED%82%A4%EC%9A%B0%EA%B8%B0lvm.html



                    VMWare에 설치된 linux의 디스크 용량 키우기(LVM)

                    2년전에 VMWare에 설치하여 지금껏 사용해 오던 리눅스 가상머신의 하드디스크 용량이 이제 거의 남아 있지 않게 되었다. 주로 개발용으로 사용할 목적으로 리눅스 가상머신을 만들고, 또 처음 설치할 당시에는 이 정도 용량이면 충분하겠지 했는데, 의외로 오랜 기간 동안 가상머신이 망가지지 않고 지금까지 개발환경으로 사용해 온 것이다. 이제 처음 할당했던 디스크가 거의 다 사용되어 하드 디스크의 확장이 필요하다. 실제 컴퓨터의 경우 하드디스크 용량을 늘리고 싶으면 하드디스크를 새로 구매해서 장착하고 파티션 잡고, 포멧해서 마운트 하는 과정을 거친다. VMWare상의 가상머신에서도 비슷한 과정으로 디스크 용량을 늘려준다.


                    VMWare에 배포판 리눅스를 설치하면 대부분 LVM타입으로 디스크가 설정된다. 따라서 본 포스트에서는 VMWare상에서 디스크의 파티션이 LVM으로 설정된 경우 디스크 용량을 늘리는 방법을 살펴본다.

                    VMWare에 설치된 리눅스의 디스크 용량을 늘리는 작업의 순서는 다음과 같다.

                     

                    1)  용량을 늘리고자 하는 가상머신에 장착된 하드디스크의 용량을 키워준다.

                    2)  Guest OS인 리눅스를 부팅한다.

                    3)  fdisk 유틸을 이용해서 PV(Physical Volume)를 설정한다.

                    4)  VG(Volume Group)를 확장한다

                    5)  LV(Logical Volume) 늘리기.

                    6)  파일 시스템을 조정한다.

                     

                      각 단계를 살펴보자. 기존에 20GBytes의 하드디스크 용량을 할당해서 설치한 리눅스에 20GBytes의 용량을 늘려 줘서 총 40GBytes의 용량을 가진 리눅스 시스템으로 업그레이드 해본다. 참고로 설치되어 있는 리눅스는 Fedora8이고, 하드디스크는 20GBytes, LVM(Logical Volume Manager) 으로 관리되고 있다.


                    1. 가상머신상의 하드디스크 늘리기


                      가상머신에 설치되어 있는 20GBytes 짜리 하드디스크를 40GBytes 짜리 하드디스크로 용량을 늘려 준다. 가상머신의 하드디스크 용량 확장은 vmware-vdiskmanager.exe 라는 유틸을 이용한다. vmware-vdiskmanager.exe VMWare 설치시 기본 설치되는 유틸리티이며C:\Program Files\VMware\VMware Workstation에 있다. 콘솔창에서 다음과 같이 명령을 수행한다. 여기서 "Other Linux 2.6.x kernel.vmdk"는 설치되어 있는 Fedora8의 가상머신 이미지 이다. –x 옵션은 가상디스크의 용량을 지정된 크기만큼 늘리라는 명령이다. 여기서는 40Gb를 지정해 줬기 때문에 가상디스크의 크기가 40GBytes로 확장되게 된다.

                     

                    “C:\Program Files\VMware\VMware Workstation\vmware- vdiskmanager.exe” -x 40Gb "Other Linux 2.6.x kernel.vmdk"

                     
                      하드디스크 증설에는 시간이 꽤 걸린다. 마치 컴퓨터 전원을 내리고, 드라이버로
                    나사 풀고, 하드디스크 끼워 넣는 시간 만큼은 걸리는 것 같다.(시간이 꽤 걸린다.)  

                    2. 이제 하드디스크를 증설했으면 리눅스를 부팅한다.

                      가상머신을 부팅해서 디스크 사용량과 디스크 관리 타입을 확인해 보니, 다음 그림과 같다. 디스크는 거의 다 사용해서 이제 남은 용량이 658Mb정도 이고, VolGroup00-LogVol00 “/” (Root)에 마운트 되어 있으며, 파일 시스템은 ext3 타입이다.



                    3. PV(Physical Volume)를 생성한다.

                     

                      /dev/sda3에 파티션을 만들기 위해서는 디바이스 노드 파일이 있어야 하므로, 미리 있는지 확인해 보고 없으면 만들어 준다. 살펴 봤더니, 없어서 다음과 같이 디바이스 노드를 만들어 주고, 소유권을 root:disk로 변경해 주었다.

                     

                    mknod /dev/sda3 b 8 3

                    chown root:disk /dev/sda3


                      fdisk를 이용해서 늘어난 디스크의 크기와 각 파티션별 디스크 타입을 확인해 보면 다음 그림과 같다. 기존에 20GBytes였는데, 42.9GBytes로 늘어 났고, /dev/sda2 Linux LVM 타입으로 파티션이 설정되어 있으며, 확장된20GBytes의 디스크 용량은 아직 파티션으로는 잡혀 있지 않은 상태임을 알 수 있다. 그림에서 처럼 새로운 파티션을 Primary partition 3로 추가 하고, 파티션 타입을 LinuxLVM타입(8e)으로 설정해 준다.



                     파티션을 만들고 나서는 반드시 재부팅을 해 줘야 한다.

                     

                    시스템 재부팅 후 /dev/sda3 PV(Physical Volume)를 생성해 준다.

                    pvcreate /dev/sda3

                     PV 생성 명령의 수행 화면은 다음과 같다.


                    4. VG(Volume Group) 확장


                      다음 명령을 수행하여 VG를 확장한다.

                    vgextend VolGroup00 /dev/sda3


                      위의 명령은 VolGroup00 dev/sda3를 추가하라는 명령이다. pvscan명령을 이용하여 /dev/sda3VolGroup00에 제대로 추가되었는지 확인한다. vgdisplay VolGroup00 명령을 이용해 Volume group 00의 내용을 보면 다음과 같다.


                    5. LV(Logical Volume) 늘리기.

                     

                      LV의 확장은 lvextend 명령을 이용하여 수행한다. 기존의 LV에 새로 추가된 20GBytesPV를 확장하자.

                    lvextend –L +20g /dev/VolGroup00/LogVol00


                     

                    6. 파일 시스템 크기 조정

                     

                      다음 명령어를 이용하여 변경된 LV를 파일 시스템에 반영한다.

                    resize2fs /dev/VolGroup00/LogVol00

                     

                      이제 하드디스크의 용량을 확인해 보면, 새로 추가한 20GBytes의 용량이 새로 확보되었음을 알 수 있다.

                     

                      지금까지 VMWare에 설치된 리눅스의 디스크 파티션 타입이 LVM으로 설정되어 있는 경우 디스크 용량을 확장하는 방법에 대해 간략히 살펴 보았으며, 쉽게 확장할 수 있음을 알 수 있다.


                     

                    참조)

                       1. vmware-vdiskmanager 사용법
                        2. LVM 소개

                        3. Logical Volume Manager(Linux)









                    2) 출처 : http://blueray21.tistory.com/31

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



                    1. 시스템 디스크 용량 확인 및 LVM(Logical Volume Manager) 설정 내용 확인

                    1.1 df

                    [root@centos ~]# df -k
                    Filesystem           1K-blocks      Used Available Use% Mounted on /dev/mapper/vg_centos-lv_root
                                          18102140  15189340   1993248  89% /
                    tmpfs                   515440    258020    257420  51% /dev/shm
                    /dev/sda1               495844     31202    439042   7% /boot

                    • /dev/mapper/vg_centos-lv_root가 18G 중 현재 용량 89% 사용 중
                    1.2 fdisk

                    [root@centos ~]# fdisk /dev/sda

                    WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
                             switch off the mode (command 'c') and change display units to
                             sectors (command 'u').

                    Command (m for help): p

                    Disk /dev/sda: 21.5 GB, 21474836480 bytes
                    255 heads, 63 sectors/track, 2610 cylinders
                    Units = cylinders of 16065 * 512 = 8225280 bytes
                    Sector size (logical/physical): 512 bytes / 512 bytes
                    I/O size (minimum/optimal): 512 bytes / 512 bytes
                    Disk identifier: 0x000644ee

                       Device Boot      Start         End      Blocks   Id  System
                    /dev/sda1   *           1          64      512000   83  Linux
                    Partition 1 does not end on cylinder boundary.
                    /dev/sda2              64        2611    20458496   8e  Linux LVM

                    Command (m for help): q

                    • /dev/sda 디스크 전체 용량은 21.5 G 
                    • p : print the partition table

                    1.3 pvscan

                    [root@centos ~]# pvscan
                      PV /dev/sda2   VG vg_centos   lvm2 [19.51 GiB / 0    free]
                      Total: 1 [19.51 GiB] / in use: 1 [19.51 GiB] / in no VG: 0 [0   ]

                    • Physical Volume Name : /dev/sda2
                    • Volume Group Name : vg_centos

                    1.4 pvdisplay

                    [root@centos ~]# pvdisplay
                      --- Physical volume ---
                      PV Name               /dev/sda2
                      VG Name               vg_centos
                      PV Size               19.51 GiB / not usable 3.00 MiB
                      Allocatable           yes (but full)
                      PE Size               4.00 MiB
                      Total PE              4994
                      Free PE               0
                      Allocated PE          4994
                      PV UUID               LwySgs-zNx3-auDL-l5h0-hzCU-OXiC-iihaws

                    1.5 lvdisplay

                    [root@centos ~]# lvdisplay
                      --- Logical volume ---
                      LV Name                /dev/vg_centos/lv_root
                      VG Name                vg_centos
                      LV UUID                zhE2Ty-1NPU-QrAT-x7H9-65mY-tC3D-L2YJXt
                      LV Write Access        read/write
                      LV Status              available
                      # open                 1
                      LV Size                17.54 GiB
                      Current LE             4490
                      Segments               1
                      Allocation             inherit
                      Read ahead sectors     auto
                      - currently set to     256
                      Block device           253:0

                      --- Logical volume ---
                      LV Name                /dev/vg_centos/lv_swap
                      VG Name                vg_centos
                      LV UUID                DWSUev-UlpF-O4Zf-lpu5-G6uo-fpDY-14yxU5
                      LV Write Access        read/write
                      LV Status              available
                      # open                 1
                      LV Size                1.97 GiB
                      Current LE             504
                      Segments               1
                      Allocation             inherit
                      Read ahead sectors     auto
                      - currently set to     256
                      Block device           253:0

                    • LV_NAME : /dev/vg_centos/lv_root
                    1.6 vgdisplay

                    [root@centos ~]# vgdisplay
                      --- Volume group ---
                      VG Name               vg_centos
                      System ID     
                      Format                lvm2
                      Metadata Areas        1
                      Metadata Sequence No  3
                      VG Access             read/write
                      VG Status             resizable
                      MAX LV                0
                      Cur LV                2
                      Open LV               2
                      Max PV                0
                      Cur PV                1
                      Act PV                1
                      VG Size               19.51 GiB
                      PE Size               4.00 MiB
                      Total PE              4994
                      Alloc PE / Size       4994 / 19.51 GiB
                      Free  PE / Size       0 / 0   
                      VG UUID               NoIptA-3L3H-VRXx-rNo8-3HJy-2niS-2sxPZh

                    • Free PE가 0

                    2. VMWare에서 디스크 용량 늘이기

                    2.1 VMWare Disk 파일 확인

                    2.2 vmware-vdiskmanager.exe 실행

                    • 시스템 Shutdown 및 VMWare 종료

                    cd "C:\Program Files\VMware\VMware Workstation"
                    vmware-vdiskmanager.exe -x 30GB -t 1 "C:\vmware\centos\CentOS.vmdk"

                    • - x : 추가하고 싶은 용량이 아니라 늘이고 나서의 디스크 전체 용량
                    • - t : virtual disk type
                    •   Disk types:
                    •       0                   : single growable virtual disk
                    •       1                   : growable virtual disk split in 2GB files
                    •       2                   : preallocated virtual disk      
                    •       3                   : preallocated virtual disk split in 2GB files
                    •       4                   : preallocated ESX-type virtual disk
                    •       5                   : compressed disk optimized for streaming
                    •       6                   : thin provisioned virtual disk - ESX 3.x and above

                    2.3 늘어난 용량 VMWare에서 확인

                    • VMWare 재 실행


                    3. CentOS 시스템에서 용량 늘이기

                    3.1 늘어난 DISK 용량 확인 - fdisk

                    [root@centos ~]# fdisk /dev/sda

                    WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
                             switch off the mode (command 'c') and change display units to
                             sectors (command 'u').

                    Command (m for help): p

                    Disk /dev/sda: 32.2 GB, 32212254720 bytes
                    255 heads, 63 sectors/track, 3916 cylinders
                    Units = cylinders of 16065 * 512 = 8225280 bytes
                    Sector size (logical/physical): 512 bytes / 512 bytes
                    I/O size (minimum/optimal): 512 bytes / 512 bytes
                    Disk identifier: 0x000644ee

                       Device Boot      Start         End      Blocks   Id  System
                    /dev/sda1   *           1          64      512000   83  Linux
                    Partition 1 does not end on cylinder boundary.
                    /dev/sda2              64        2611    20458496   8e  Linux LVM

                    • /dev/sda 디스크 전체 용량이 32.2 G 로 증가
                    3.2 파티션 생성 - fdisk

                    Command (m for help): n
                    Command action
                       e   extended
                       p   primary partition (1-4)
                    p
                    Partition number (1-4): 3
                    First cylinder (2611-3916, default 2611): 
                    Using default value 2611
                    Last cylinder, +cylinders or +size{K,M,G} (2611-3916, default 3916): 
                    Using default value 3916

                    Command (m for help): p

                    Disk /dev/sda: 32.2 GB, 32212254720 bytes
                    255 heads, 63 sectors/track, 3916 cylinders
                    Units = cylinders of 16065 * 512 = 8225280 bytes
                    Sector size (logical/physical): 512 bytes / 512 bytes
                    I/O size (minimum/optimal): 512 bytes / 512 bytes
                    Disk identifier: 0x000644ee

                       Device Boot      Start         End      Blocks   Id  System
                    /dev/sda1   *           1          64      512000   83  Linux
                    Partition 1 does not end on cylinder boundary.
                    /dev/sda2              64        2611    20458496   8e  Linux LVM
                    /dev/sda3            2611        3916    10483750   83  Linux

                    Command (m for help): t
                    Partition number (1-4): 3
                    Hex code (type L to list codes): 8e
                    Changed system type of partition 3 to 8e (Linux LVM)

                    Command (m for help): w
                    The partition table has been altered!

                    Calling ioctl() to re-read partition table.

                    WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
                    The kernel still uses the old table. The new table will be used at
                    the next reboot or after you run partprobe(8) or kpartx(8)
                    Syncing disks.
                    [root@centos ~]# shutdown -r now

                    • 작업 후 재부팅

                    3.3 Pysical Volume  생성 - pvcreate

                    [root@centos ~]# pvscan
                      PV /dev/sda2   VG vg_centos   lvm2 [19.51 GiB / 0    free]
                      Total: 1 [19.51 GiB] / in use: 1 [19.51 GiB] / in no VG: 0 [0   ]  
                    [root@centos ~]# 
                    pvcreate /dev/sda3
                    [root@centos ~]# pvscan
                      PV /dev/sda2   VG vg_centos   lvm2 [19.51 GiB / 0    free]
                      PV /dev/sda3                      lvm2 [10.00 GiB]
                      Total: 2 [29.51 GiB] / in use: 1 [19.51 GiB] / in no VG: 1 [10.00 GiB]
                    [root@centos ~]# pvdisplay
                      --- Physical volume ---
                      PV Name               /dev/sda2
                      VG Name               vg_centos
                      PV Size               19.51 GiB / not usable 3.00 MiB
                      Allocatable           yes (but full)
                      PE Size               4.00 MiB
                      Total PE              4994
                      Free PE               0
                      Allocated PE          4994
                      PV UUID               LwySgs-zNx3-auDL-l5h0-hzCU-OXiC-iihaws

                      "/dev/sda3" is a new physical volume of "10.00 GiB"
                      --- NEW Physical volume ---

                      PV Name               /dev/sda3
                      VG Name               
                      PV Size               10.00 GiB
                      Allocatable           No
                      PE Size               0
                      Total PE              0
                      Free PE               0
                      Allocated PE          0
                      PV UUID               arlrZ3-JGKi-1meJ-blcj-AaVj-QNTH-84RcQy

                    3.4 Volume Group 확장 - vgextend

                    • vgextend VG_NAME PV_NAME
                    • VG_NAME과 PV_NMAE은 위 1.3 pvscan에서 확인

                    [root@centos ~]# vgextend vg_centos /dev/sda3
                      Volume group "vg_centos" successfully extended
                    [root@centos ~]# vgdisplay
                      --- Volume group ---
                      VG Name               vg_centos
                      System ID     
                      Format                lvm2
                      Metadata Areas        2
                      Metadata Sequence No  4
                      VG Access             read/write
                      VG Status             resizable
                      MAX LV                0
                      Cur LV                2
                      Open LV               2
                      Max PV                0
                      Cur PV                2
                      Act PV                2
                      VG Size               29.50 GiB
                      PE Size               4.00 MiB
                      Total PE              7553
                      Alloc PE / Size       4994 / 19.51 GiB
                      Free  PE / Size       2559 / 10.00 GiB   
                      VG UUID               NoIptA-3L3H-VRXx-rNo8-3HJy-2niS-2sxPZh

                    • Free PE 생김

                    3.5 물리적인 파티션 용량 증가

                    • lvextend LV_NAME -l +LogicalExtentsNumber
                    • LV_NAME은 위 1.5 lvdisplay에서 확인
                    • LogicalExtentsNumber은 위 3.4 vgdisplay에서 Free PE 크기 내에서

                    [root@centos ~]# lvextend /dev/vg_centos/lv_root -l +2559
                      Extending logical volume lv_root to 27.54 GiB
                      Logical volume lv_root successfully resized
                    [root@centos ~]# vgdisplay
                      --- Volume group ---
                      VG Name               vg_centos
                      System ID     
                      Format                lvm2
                      Metadata Areas        2
                      Metadata Sequence No  5
                      VG Access             read/write
                      VG Status             resizable
                      MAX LV                0
                      Cur LV                2
                      Open LV               2
                      Max PV                0
                      Cur PV                2
                      Act PV                2
                      VG Size               29.50 GiB
                      PE Size               4.00 MiB
                      Total PE              7553
                      Alloc PE / Size       7553 / 29.50 GiB
                      Free  PE / Size       0 / 0 GiB   
                      VG UUID               NoIptA-3L3H-VRXx-rNo8-3HJy-2niS-2sxPZh

                    • Free PE가 다시 0으로 되고 Alloc PE가 늘어남
                    3.6 파일시스템 반영 - resize

                    [root@centos ~]# resize2fs /dev/vg_centos/lv_root
                    resize2fs 1.41.12 (17-May-2010)
                    Filesystem at /dev/vg_centos/lv_root is mounted on /; on-line resizing required

                    old desc_blocks = 2, new_desc_blocks = 2
                    Performing an on-line resize of /dev/vg_centos/lv_root to 7218176 (4k) blocks.

                    The filesystem on /dev/vg_centos/lv_root is now 7218176 blocks long.

                    [root@centos ~]# 
                    df -k
                    Filesystem           1K-blocks      Used Available Use% Mounted on
                    /dev/mapper/vg_centos-lv_root
                                          28419964  15189140  11791824  57% /
                    tmpfs                   515440    258032    257408  51% /dev/shm
                    /dev/sda1               495844     31202    439042   7% /boot



                    해당 에러가 발생하면 resize2fs 가 아니라 다르게 진행.
                    resize2fs 1.42.9 (28-Dec-2013)
                    resize2fs: Bad magic number in super-block while trying to open /dev/mapper/centos-root
                    Couldn't find valid filesystem superblock.

                    xfs_growfs /dev/vg_centos/lv_root


                    반응형
                    반응형

                    Note: These instructions were originally created for older version of Ubuntu (12.04). Some required resource (e.g. grub ppa) is not available on newer versions, thus can lead to errors. If you use Ubuntu 14.04 or newer, see this page instead, which also allows things like raidz root, boot from snapshot, zfs-only setup (no need for separate /boot/grub), and lz4 compression.


                    These instructions are for Ubuntu. The procedure for Debian, Mint, or other distributions in the DEB family is similar but not identical.

                    System Requirements

                    • 64-bit Ubuntu Live CD. (Not the alternate installer, and not the 32-bit installer!)
                    • AMD64 or EM64T compatible computer. (ie: x86-64)
                    • 8GB disk storage available.
                    • 2GB memory minimum.

                    Computers that have less than 2GB of memory run ZFS slowly. 4GB of memory is recommended for normal performance in basic workloads. 16GB of memory is the recommended minimum for deduplication. Enabling deduplication is a permanent change that cannot be easily reverted.

                    Recommended Version

                    • Ubuntu 12.04 Precise Pangolin
                    • spl-0.6.3
                    • zfs-0.6.3

                    Step 1: Prepare The Install Environment

                    1.1 Start the Ubuntu LiveCD and open a terminal at the desktop.

                    1.2 Input these commands at the terminal prompt:

                    $ sudo -i
                    # apt-add-repository --yes ppa:zfs-native/stable
                    # apt-get update
                    # apt-get install debootstrap spl-dkms zfs-dkms ubuntu-zfs
                    

                    1.3 Check that the ZFS filesystem is installed and available:

                    # modprobe zfs
                    # dmesg | grep ZFS:
                    ZFS: Loaded module v0.6.3-2~trusty, ZFS pool version 5000, ZFS filesystem version 5
                    

                    Step 2: Disk Partitioning

                    This tutorial intentionally recommends MBR partitioning. GPT can be used instead, but beware of UEFI firmware bugs.

                    2.1 Run your favorite disk partitioner, like parted or cfdisk, on the primary storage device. /dev/disk/by-id/scsi-SATA_disk1 is the example device used in this document.

                    2.2 Create a small MBR primary partition of at least 8 megabytes. 256mb may be more realistic, unless space is tight. /dev/disk/by-id/scsi-SATA_disk1-part1 is the example boot partition used in this document.

                    2.3 On this first small partition, set type=BE and enable the bootable flag.

                    2.4 Create a large partition of at least 4 gigabytes. /dev/disk/by-id/scsi-SATA_disk1-part2 is the example system partition used in this document.

                    2.5 On this second large partition, set type=BF and disable the bootable flag.

                    The partition table should look like this:

                    # fdisk -l /dev/disk/by-id/scsi-SATA_disk1
                    
                    Disk /dev/sda: 10.7 GB, 10737418240 bytes
                    255 heads, 63 sectors/track, 1305 cylinders
                    Units = cylinders of 16065 * 512 = 8225280 bytes
                    Sector size (logical/physical): 512 bytes / 512 bytes
                    I/O size (minimum/optimal): 512 bytes / 512 bytes
                    Disk identifier: 0x00000000
                    
                    Device    Boot      Start         End      Blocks   Id  System
                    /dev/sda1    *          1           1        8001   be  Solaris boot
                    /dev/sda2               2        1305    10474380   bf  Solaris
                    

                    Remember: Substitute scsi-SATA_disk1-part1 and scsi-SATA_disk1-part2 appropriately below.

                    Hints:

                    • Are you doing this in a virtual machine? Is something in /dev/disk/by-id missing? Go read the troubleshooting section.
                    • Recent GRUB releases assume that the /boot/grub/grubenv file is writable by the stage2 module. Until GRUB gets a ZFS write enhancement, the GRUB modules should be installed to a separate filesystem in a separate partition that is grub-writable.
                    • If /boot/grub is in the ZFS filesystem, then GRUB will fail to boot with this message: error: sparse file not allowed. If you absolutely want only one filesystem, then remove the call to recordfail() in each grub.cfg menu stanza, and edit the /etc/grub.d/10_linux file to make the change permanent.
                    • Alternatively, if /boot/grub is in the ZFS filesystem you can comment each line with the text save_env in the file /etc/grub.d/00_header and run update-grub.

                    Step 3: Disk Formatting

                    3.1 Format the small boot partition created by Step 2.2 as a filesystem that has stage1 GRUB support like this:

                    # mke2fs -m 0 -L /boot/grub -j /dev/disk/by-id/scsi-SATA_disk1-part1
                    

                    3.2 Create the root pool on the larger partition:

                    # zpool create -o ashift=9 rpool /dev/disk/by-id/scsi-SATA_disk1-part2
                    

                    Always use the long /dev/disk/by-id/* aliases with ZFS. Using the /dev/sd* device nodes directly can cause sporadic import failures, especially on systems that have more than one storage pool.

                    Warning: The grub2-1.99 package currently published in the PPA for Precise does not reliably handle a 4k block size, which is ashift=12.

                    Hints:

                    • # ls -la /dev/disk/by-id will list the aliases.
                    • The root pool can be a mirror. For example, zpool create -o ashift=9 rpool mirror /dev/disk/by-id/scsi-SATA_disk1-part2 /dev/disk/by-id/scsi-SATA_disk2-part2. Remember that the version and ashift matter for any pool that GRUB must read, and that these things are difficult to change after pool creation.
                    • If you are using a mirror with a separate boot partition as described above, don't forget to edit the grub.cfg file on the second HD partition so that the "root=" partition refers to that partition on the second HD also; otherwise, if you lose the first disk, you won't be able to boot from the second because the kernel will keep trying to mount the root partition from the first disk.
                    • The pool name is arbitrary. On systems that can automatically install to ZFS, the root pool is named "rpool" by default. Note that system recovery is easier if you choose a unique name instead of "rpool". Anything except "rpool" or "tank", like the hostname, would be a good choice.
                    • If you want to create a mirror but only have one disk available now you can create the mirror using a sparse file as the second member then immediately off-line it so the mirror is in degraded mode. Later you can add another drive to the spool and ZFS will automatically sync them. The sparse file won't take up more than a few KB so it can be bigger than your running system. Just make sure to off-line the sparse file before writing to the pool.

                    3.2.1 Create a sparse file at least as big as the larger partition on your HDD:

                    # truncate -s 11g /tmp/sparsefile
                    

                    3.2.2 Instead of the command in section 3.2 use this to create the mirror:

                    # zpool create -o ashift=9 rpool mirror /dev/disk/by-id/scsi-SATA_disk1-part2 /tmp/sparsefile
                    

                    3.2.3 Offline the sparse file. You can delete it after this if you want.

                    # zpool offline rpool /tmp/sparsefile
                    

                    3.2.4 Verify that the pool was created and is now degraded.

                    # zpool list
                    NAME       SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
                    rpool     10.5G   188K  10.5G     0%  1.00x  DEGRADED  -
                    

                    3.3 Create a "ROOT" filesystem in the root pool:

                    # zfs create rpool/ROOT
                    

                    3.4 Create a descendant filesystem for the Ubuntu system:

                    # zfs create rpool/ROOT/ubuntu-1
                    

                    On Solaris systems, the root filesystem is cloned and the suffix is incremented for major system changes through pkg image-update or beadm. Similar functionality for APT is possible but currently unimplemented.

                    3.5 Dismount all ZFS filesystems.

                    # zfs umount -a
                    

                    3.6 Set the mountpoint property on the root filesystem:

                    # zfs set mountpoint=/ rpool/ROOT/ubuntu-1
                    

                    3.7 Set the bootfs property on the root pool.

                    # zpool set bootfs=rpool/ROOT/ubuntu-1 rpool
                    

                    The boot loader uses these two properties to find and start the operating system. These property names are not arbitrary.

                    Hint: Putting rpool=MyPool or bootfs=MyPool/ROOT/system-1 on the kernel command line overrides the ZFS properties.

                    3.9 Export the pool:

                    # zpool export rpool
                    

                    Don't skip this step. The system is put into an inconsistent state if this command fails or if you reboot at this point.

                    Step 4: System Installation

                    Remember: Substitute "rpool" for the name chosen in Step 3.2.

                    4.1 Import the pool:

                    # zpool import -d /dev/disk/by-id -R /mnt rpool
                    

                    If this fails with "cannot import 'rpool': no such pool available", you can try import the pool without the device name eg:

                        # zpool import -R /mnt rpool
                    

                    4.2 Mount the small boot filesystem for GRUB that was created in step 3.1:

                    # mkdir -p /mnt/boot/grub
                    # mount /dev/disk/by-id/scsi-SATA_disk1-part1 /mnt/boot/grub
                    

                    4.4 Install the minimal system:

                    # debootstrap trusty /mnt
                    

                    The debootstrap command leaves the new system in an unconfigured state. In Step 5, we will only do the minimum amount of configuration necessary to make the new system runnable.

                    Step 5: System Configuration

                    5.1 Copy these files from the LiveCD environment to the new system:

                    # cp /etc/hostname /mnt/etc/
                    # cp /etc/hosts /mnt/etc/
                    

                    5.2 The /mnt/etc/fstab file should be empty except for a comment. Add this line to the /mnt/etc/fstab file:

                    /dev/disk/by-id/scsi-SATA_disk1-part1  /boot/grub  auto  defaults  0  1
                    

                    The regular Ubuntu desktop installer may add dev, proc, sys, or tmp lines to the /etc/fstab file, but such entries are redundant on a system that has a /lib/init/fstab file. Add them now if you want them.

                    5.3 Edit the /mnt/etc/network/interfaces file so that it contains something like this:

                    # interfaces(5) file used by ifup(8) and ifdown(8)
                    auto lo
                    iface lo inet loopback
                    
                    auto eth0
                    iface eth0 inet dhcp
                    

                    Customize this file if the new system is not a DHCP client on the LAN.

                    5.4 Make virtual filesystems in the LiveCD environment visible to the new system and chroot into it:

                    # mount --bind /dev  /mnt/dev
                    # mount --bind /proc /mnt/proc
                    # mount --bind /sys  /mnt/sys
                    # chroot /mnt /bin/bash --login
                    

                    5.5 Install PPA support in the chroot environment like this:

                    # locale-gen en_US.UTF-8
                    # apt-get update
                    # apt-get install ubuntu-minimal software-properties-common
                    

                    Even if you prefer a non-English system language, always ensure that en_US.UTF-8 is available. The ubuntu-minimal package is required to use ZoL as packaged in the PPA.

                    5.6 Install ZFS in the chroot environment for the new system:

                    # apt-add-repository --yes ppa:zfs-native/stable
                    # apt-add-repository --yes ppa:zfs-native/grub
                    # apt-get update
                    # apt-get install --no-install-recommends linux-image-generic linux-headers-generic
                    # apt-get install ubuntu-zfs
                    # apt-get install grub2-common grub-pc
                    # apt-get install zfs-initramfs
                    # apt-get dist-upgrade
                    

                    Warning: This is the second time that you must wait for the SPL and ZFS modules to compile. Do not try to skip this step by copying anything from the host environment into the chroot environment.

                    Note: This should install a kernel package and its headers, a patched mountall and dkms packages. Double-check that you are getting these packages from the PPA if you are deviating from these instructions in any way.

                    Choose /dev/disk/by-id/scsi-SATA_disk1 if prompted to install the MBR loader.

                    Ignore warnings that are caused by the chroot environment like:

                    • Can not write log, openpty() failed (/dev/pts not mounted?)
                    • df: Warning: cannot read table of mounted file systems
                    • mtab is not present at /etc/mtab.

                    5.7 Set a root password on the new system:

                    # passwd root
                    

                    Hint: If you want the ubuntu-desktop package, then install it after the first reboot. If you install it now, then it will start several process that must be manually stopped before dismount.

                    Step 6: GRUB Installation

                    Remember: All of Step 6 depends on Step 5.4 and must happen inside the chroot environment.

                    6.1 Verify that the ZFS root filesystem is recognized by GRUB:

                    # grub-probe /
                    zfs
                    

                    And that the ZFS modules for GRUB are installed:

                    # ls /boot/grub/zfs*
                    /boot/grub/zfs.mod  /boot/grub/zfsinfo.mod
                    

                    Note that after Ubuntu 13, these are now in /boot/grub/i386/pc/zfs*

                    # ls /boot/grub/i386-pc/zfs*
                    /boot/grub/i386-pc/zfs.mod  /boot/grub/i386-pc/zfsinfo.mod
                    

                    Otherwise, check the troubleshooting notes for GRUB below.

                    6.2 Refresh the initrd files:

                    # update-initramfs -c -k all
                    update-initramfs: Generating /boot/initrd.img-3.2.0-40-generic
                    

                    6.3 Update the boot configuration file:

                    # update-grub
                    Generating grub.cfg ...
                    Found linux image: /boot/vmlinuz-3.2.0-40-generic
                    Found initrd image: /boot/initrd.img-3.2.0-40-generic
                    done
                    

                    Verify that boot=zfs appears in the boot configuration file:

                    # grep boot=zfs /boot/grub/grub.cfg
                    linux /ROOT/ubuntu-1/@/boot/vmlinuz-3.2.0-40-generic root=/dev/sda2 ro boot=zfs $bootfs quiet splash $vt_handoff
                    linux /ROOT/ubuntu-1/@/boot/vmlinuz-3.2.0-40-generic root=/dev/sda2 ro single nomodeset boot=zfs $bootfs
                    

                    6.4 Install the boot loader to the MBR like this:

                    # grub-install $(readlink -f /dev/disk/by-id/scsi-SATA_disk1)
                    Installation finished. No error reported.
                    

                    Do not reboot the computer until you get exactly that result message. Note that you are installing the loader to the whole disk, not a partition.

                    Note: The readlink is required because recent GRUB releases do not dereference symlinks.

                    Step 7: Cleanup and First Reboot

                    7.1 Exit from the chroot environment back to the LiveCD environment:

                    # exit
                    

                    7.2 Run these commands in the LiveCD environment to dismount all filesystems:

                    # umount /mnt/boot/grub
                    # umount /mnt/dev
                    # umount /mnt/proc
                    # umount /mnt/sys
                    # zfs umount -a
                    # zpool export rpool
                    

                    The zpool export command must succeed without being forced or the new system will fail to start.

                    7.3 We're done!

                    # reboot
                    

                    Caveats and Known Problems

                    This is an experimental system configuration.

                    This document was first published in 2010 to demonstrate that the lzfs implementation made ZoL 0.5 feature complete. Upstream integration efforts began in 2012, and it will be at least a few more years before this kind of configuration is even minimally supported.

                    Gentoo, and its derivatives, are the only Linux distributions that are currently mainlining support for a ZoL root filesystem.

                    zpool.cache inconsistencies cause random pool import failures.

                    The /etc/zfs/zpool.cache file embedded in the initrd for each kernel image must be the same as the /etc/zfs/zpool.cache file in the regular system. Run update-initramfs -c -k all after any /sbin/zpool command changes the /etc/zfs/zpool.cache file.

                    Pools do not show up in /etc/zfs/zpool.cache when imported with the -R flag.

                    This will be a recurring problem until issue zfsonlinux/zfs#330 is resolved.

                    Every upgrade can break the system.

                    Ubuntu systems remove old dkms modules before installing new dkms modules. If the system crashes or restarts during a ZoL module upgrade, which is a failure window of several minutes, then the system becomes unbootable and must be rescued.

                    This will be a recurring problem until issue zfsonlinux/pkg-zfs#12 is resolved.

                    When doing an upgrade remotely an extra precaution would be to use screen, this way if you get disconnected your installation will not get interrupted.

                    Troubleshooting

                    (i) MPT2SAS

                    Most problem reports for this tutorial involve mpt2sas hardware that does slow asynchronous drive initialization, like some IBM M1015 or OEM-branded cards that have been flashed to the reference LSI firmware.

                    The basic problem is that disks on these controllers are not visible to the Linux kernel until after the regular system is started, and ZoL does not hotplug pool members. See https://github.com/zfsonlinux/zfs/issues/330.

                    Most LSI cards are perfectly compatible with ZoL, but there is no known fix if your card has this glitch. Please use different equipment until the mpt2sas incompatibility is diagnosed and fixed, or donate an affected part if you want solution sooner.

                    (ii) Areca

                    Systems that require the arcsas blob driver should add it to the /etc/initramfs-tools/modules file and run update-initramfs -c -k all.

                    Upgrade or downgrade the Areca driver if something like RIP: 0010:[<ffffffff8101b316>] [<ffffffff8101b316>] native_read_tsc+0x6/0x20 appears anywhere in kernel log. ZoL is unstable on systems that emit this error message.

                    (iii) GRUB Installation

                    Verify that the PPA for the ZFS enhanced GRUB is installed:

                    # apt-add-repository ppa:zfs-native/grub
                    # apt-get update
                    

                    Reinstall the zfs-grub package, which is an alias for a patched grub-common package:

                    # apt-get install --reinstall zfs-grub
                    

                    Afterwards, this should happen:

                    # apt-cache search zfs-grub
                    grub-common - GRand Unified Bootloader (common files)
                    
                    # apt-cache show zfs-grub
                    N: Can't select versions from package 'zfs-grub' as it is purely virtual
                    N: No packages found
                    
                    # apt-cache policy grub-common zfs-grub
                    grub-common:
                     Installed: 1.99-21ubuntu3.9+zfs1~precise1
                     Candidate: 1.99-21ubuntu3.9+zfs1~precise1
                     Version table:
                    *** 1.99-21ubuntu3.9+zfs1~precise1 0
                          1001 http://ppa.launchpad.net/zfs-native/grub/ubuntu/precise/main amd64 Packages
                           100 /var/lib/dpkg/status
                        1.99-21ubuntu3 0
                          1001 http://us.archive.ubuntu.com/ubuntu/ precise/main amd64 Packages
                    zfs-grub:
                     Installed: (none)
                     Candidate: (none)
                     Version table:
                    

                    For safety, grub modules are never updated by the packaging system after initial installation. Manually refresh them by doing this:

                    # cp /usr/lib/grub/i386-pc/*.mod /boot/grub/
                    

                    If the problem persists, then open a bug report and attach the entire output of those apt-get commands.

                    Packages in the GRUB PPA are compiled against the stable PPA. Systems that run the daily PPA may experience failures if the ZoL library interface changes.

                    Note that GRUB does not currently dereference symbolic links in a ZFS filesystem, so you cannot use the /vmlinux or /initrd.img symlinks as GRUB command arguments.

                    (iv) GRUB does not support ZFS Compression

                    If the /boot hierarchy is in ZFS, then that pool should not be compressed. The grub packages for Ubuntu are usually incapable of loading a kernel image or initrd from a compressed dataset.

                    (v) VMware

                    • Set disk.EnableUUID = "TRUE" in the vmx file or vsphere configuration. Doing this ensures that /dev/disk aliases are created in the guest.

                    (vi) QEMU/KVM/XEN

                    • In the /etc/default/grub file, enable the GRUB_TERMINAL=console line and remove the splash option from the GRUB_CMDLINE_LINUX_DEFAULT line. Plymouth can cause boot errors in these virtual environments that are difficult to diagnose.

                    • Set a unique serial number on each virtual disk. (eg: -drive if=none,id=disk1,file=disk1.qcow2,serial=1234567890)

                    (vii) Kernel Parameters

                    The zfs-initramfs package requires that boot=zfs always be on the kernel command line. If the boot=zfs parameter is not set, then the init process skips the ZFS routine entirely. This behavior is for safety; it makes the casual installation of the zfs-initramfs package unlikely to break a working system.

                    ZFS properties can be overridden on the the kernel command line with rpool and bootfs arguments. For example, at the GRUB prompt:

                    linux /ROOT/ubuntu-1/@/boot/vmlinuz-3.0.0-15-generic boot=zfs rpool=AltPool bootfs=AltPool/ROOT/foobar-3

                    (viii) System Recovery

                    If the system randomly fails to import the root filesystem pool, then do this at the initramfs recovery prompt:

                    # zpool export rpool
                    : now export all other pools too
                    # zpool import -d /dev/disk/by-id -f -N rpool
                    : now import all other pools too
                    # mount -t zfs -o zfsutil rpool/ROOT/ubuntu-1 /root
                    : do not mount any other filesystem
                    # cp /etc/zfs/zpool.cache /root/etc/zfs/zpool.cache
                    # exit
                    

                    This refreshes the /etc/zfs/zpool.cache file. The zpool command emits spurious error messages regarding missing or corrupt vdevs if the zpool.cache file is stale or otherwise incorrect.

                    반응형
                    반응형

                    출처 : http://ngee.tistory.com/83



                    안녕하세요.


                    리눅스에서 파일 검색을 하기 위한 명령어 find를 소개합니당.


                    리눅스 상에서 주로 개발을 하는 저로써는 매우 자주 사용하는 명령어 인데요.


                    간단하니깐 !! 바로 !! 명령어 들어갑니당.



                    명령어 : find 파일 찾을 위치 지정 -name 찾을 파일 이름

                        ex  : find ./ -name aaa.txt


                    위에 ex를 설명해드리면 ./(현재 폴더 부터, 하위 폴더 포함) aaa.txt 파일을 찾아줘!!! 입니다.





                    다음으로 파일 내부 문자열을 검색하는 명령어 grep 입니다.


                    사실 grep은 여러군데서 사용하고 있는 것이기 때문에, 파일 내부 문자열 검색만을 위해서 쓰이고 있지는 않습니다.


                    grep의 man을 보시면 -print lines matching a pattern 으로 나와있어요.


                    이번 포스팅에서는 grep을 통해서 파일 내부의 문자열을 검색해서, 찾고자 하는 문자열과 동일한 문자열을 가진


                    파일을 찾아주는 것으로 


                    명령어 : grep -r "찾을 문자열" ./*

                         ex : grep -r "aaa" ./*

                            

                    위의 ex를 설명드리면 ./(현재 폴더 아래 모든 파일에서) aaa라는 문자열이 있는지 찾아라!! 단 하위 디렉토리 모두에서(-r) 입니다.


                    간단하죠? ^ ^ 

                    반응형

                    + Recent posts