# shutdown -k now : 시스템 종료 경고만 출력

# shutdown now : 유지보수(싱글유저)모드로 들어감

*  runlevel
 0 : 시스템 종료
 1 : 유지보수(싱글유저)모드
 6 : 시스템 재시작

시스템을 종료하기 위해서는 runlevel 0으로 들어가야 함.
shutdown 시 -h 옵션을 주지 않으면 기본값으로 runlevel 1(유지보수모드)로 전환됨

---------------------------
--시스템 종료
---------------------------
# shutdown -h now
# init 0
# poweroff
# halt

---------------------------
-- 시스템 재시작
---------------------------
# shutdown -r now
# init 6
# reboot


sys/time.h에 있는 매크로 이용

# define timeradd(a, b, result)                           \
  do {                                        \
    (result)->tv_sec = (a)->tv_sec + (b)->tv_sec;                 \
    (result)->tv_usec = (a)->tv_usec + (b)->tv_usec;                  \
    if ((result)->tv_usec >= 1000000)                         \
      {                                       \
    ++(result)->tv_sec;                           \
    (result)->tv_usec -= 1000000;                         \
      }                                       \
  } while (0)
# define timersub(a, b, result)                           \
  do {                                        \
    (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;                 \
    (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;                  \
    if ((result)->tv_usec < 0) {                          \
      --(result)->tv_sec;                             \
      (result)->tv_usec += 1000000;                       \
    }                                         \
  } while (0)
 

출처 : http://sthyun.tistory.com/entry/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%ED%95%A8%EC%88%98%EC%9D%98-BlockingNon-Blocking-IO-%EB%8F%99%EC%9E%91

1. 입력함수: read, readv, recv, recvfrom, recvmsg

Blocking TCP 소켓인 경우, 소켓수신버퍼에 수신된 데이터가 없으면, 프로세스는 sleep한다. 데이터가 도착하면 (그것이 충분한 크기가 아닐지라도) 프로세스는 깨어난다. 원하는 크기만큼 도착할때까지 기다리려면, while로 계속 받아 붙이던가, 아니면, MSG_WAITALL 플래그를 이용한다.

UDP 소켓인 경우, 소켓수신버퍼가 비어 있으면, 프로세스는 sleep한다. UDP패킷이 도착하면, 프로세스는 깨어난다.

Nonblocking 소켓의 경우, 수신버퍼가 비어 있는 경우, 에러 EWOULDBLOCK 으로 바로 리턴한다.

 

2. 출력함수: write, writev, send, sendto, sendmsg

Blocking TCP 소켓의 경우, 출력함수는 어플리케이션의 데이터를 커널의 소켓전송버퍼에 복사한다. 만약 소켓전송버퍼에 공간이 없으면, 프로세스는 sleep한다.

Nonblocking TCP 소켓의 경우, 소켓전송버퍼에 공간이 없는 경우, 에러 EWOULDBLOCK으로 바로 리턴한다. 만약 소켓전송버퍼에 약간의 공간이 있는 경우, 복사가능한 공간을 바이트로 리턴한다.

UDP소켓은 실제로 소켓 전송 버퍼가 없다. 즉, 호출 즉시 UDP/IP스택으로 전달하므로, block되지 않는다.

 

3. accept 함수

Blocking 소켓인 경우, 새로운 연결이 없으면, 프로세스는 sleep한다.

Nonblocking 소켓의 경우, 새로운 연결이 없으면, 에러 EWOULDBLOCK으로 리턴한다.

 

4. connect 함수

Blocking TCP 소켓의 경우, 실제 연결이 될 때까지, 즉 SYN에 대한 ACK을 받을때까지 block되어 있는다.

NonBlocking TCP 소켓의 경우, 에러 EINPROGRESS로 리턴한다. (같은 호스트의 경우에는 바로 정상 연결이 이루어 질 수 있다)

UDP 소켓의 경우 connect는 가상의 연결을 만드는 것이라서 바로 리턴한다.

 

(참고: UNIX Network Programming, vol.1, 2nd edition, Ch.15)

 

5. close()

1. Connect 관련 Test

Ÿ 정상적인 경우의 Connect

내용

정상적으로 Connect가 이루어지는 경우, Connect 호출 후, 접속 완료까지 소요되는 시간

방법

Connect 호출 전, 호출 후의 시간을 측정하여 표시한다.

결과

호출 전 시간과 호출 호의 시간이 동일하게 표시됨

Window의 Timer의 유효치 이내의 시간으로 접속

결과분석

 

Ÿ Server Process가 없는 경우의 Connect

내용

연결할 IP에 대한 Computer가 켜져 있으나, Server Process가 없는 경우, Connect Fail의 형태

방법

Server Process를 실행하지 않고 Connect 시도

결과

1, 2초 후에 Connect Fail 발생

결과분석

연결할 Computer에서 Bind된 Port가 없음을 알 수 있으므로 Timeout은 발생하지 않고, 일정 시간내에 Connect Fail이 발생함

Ÿ 연결대상 Computer가 없는 경우의 Connect

내용

연결할 IP에 대한 Computer가 존재하지 않거나 꺼져 있는 경우, Connect Fail의 형태

방법

없는 IP에 대한 Connect 시도

결과

20여초 후에 Connect Fail 발생

결과분석

Timeout 될 때까지 IP를 찾음

 

2. Send/Receive 관련 Test

Ÿ Network Cable을 제거한 즉시 Send

내용

Network Cable을 제거한 즉시 Send를 하는 경우에 대한 결과

방법

Socket 연결 후, Network Cable을 제거한 즉시 Send 시킴

결과

Send가 성공함

 

[Non Blocking Mode]

Socket Close 메시지가 발생할 때까지 성공

[Blocking Mode]

Socket Close 메시지가 발생할 때까지 첫 Send는 성공, 두번째부터는 실패함

 

연결이 끊긴 것을 감지할 때까지는 성공함

7초 정도가 지난 후, 연결 끊김을 감지함

상대방의 Network Cable을 제거하였을 경우에는 약 3분 정도의 시간이 지난 후, 연결 끊김을 감지함

결과분석

Network Cable을 제거하더라도 한동안 Process는 그것을 인식하지 못함

Send는 TCP/IP 하부 레벨에 데이터 전송이 처리되면 성공으로 간주하는 것으로 판단됨

Ÿ Network Cable을 제거한 즉시 다시 연결 후 Send

내용

Network Cable을 제거한 즉시, 다시 Cable을 연결하여 Send 성공여부를 Test

Receive 측 Data Receive 성공여부도 함께 Test

방법

Network Cable을 제거 후, Close를 감지하기 전에 다시 연결하여 Send, Receive의 성공여부를 Test함

결과

Send, Receive 모두 성공

결과분석

Close를 감지하기 전에 다시 Cable을 연결하면, 연결은 유지됨

Ÿ Network Cable을 제거 후, 다시 연결하는 시간을 변화하여 Send

내용

Network Cable 제거 후, 다시 연결하는 시간을 변화시켜 위의 Test를 반복하여 성공여부를 확인

방법

Network Cable 제거 후, 다시 연결하는 시간을 변화시켜 위의 Test를 반복하여 성공여부를 확인

결과

Close를 감지하기 전에 다시 연결하면 Send, Receive 모두 성공

결과분석

 

Ÿ Send 후, Receive를 호출하지 않은 경우

내용

Data를 Send하고 Receive 측에서 Receive 함수를 호출하지 않는 경우, Timeout 발생여부와 Timeout 발생시간을 확인

방법

Data를 Send하고 Receive측에서 Receive 함수를 호출하지 않음

결과

Timeout이 발생하지 않음

결과분석

 

Ÿ Send, Receive Message 발생 수 소규모 데이터

내용

비교적 작은 크기의 데이터(수십 byte 내외)를 아주 빠르게 Send를 여러 번 호출하는 경우, Receive 측에 Receive Message의 발생과 실제 Receive한 Data의 크기를 확인

- Send 수와 Receive Message 발생 수를 비교검사

- Send한 Data 크기와 Receive한 Data 크기 비교

- Receive 시에 실제 Send한 Data보다 수배의 크기의 Buffer로 Receive한 경우와 Send한 Data의 크기와 동일한 크기의 Buffer로 Receive하는 경우의 비교

방법

100 Byte 크기의 Data를 10번 Send함

결과

Ÿ Receive Buffer 크기가 1024 byte인 경우

-       Receive Message 2번 발생

-       첫번째는 100 byte를, 두번째는 900 byte를 Receive 함

Ÿ Receive Buffer 크기가 100 byte인 경우

-       Receive Message는 10번 발생

-       모두 100 byte 씩 Receive함

결과분석

작은 크기의 데이터를 빠르게 연속적으로 전송하는 경우, Network 하부 Layer에서 몇 개의 데이터를 묶어서 한꺼번에 전송하게 된다. 따라서 Send한 Data와 실제 전송되는 Data 크기는 달라질 수 있으며, Send한 수와 Receive Message의 발생 또한 다를 가능성이 있다.

하지만 두번째 Test 결과로 봤을 때, Socket의 내부적인 Buffer에서 Receive Buffer로 Data를 읽어 들일 때, 내부 Buffer를 모두 비울때까지 Receive Message를 자체적으로 발생시키는 것으로 예상된다.

Ÿ Send, Receive Message 발생 수 대규모 데이터

내용

비교적 큰 크기의 데이터(수십 Kbyte 이상)를 Send 하는 경우, Receive 측에 Receive Message의 발생과 실제 Receive한 Data의 크기를 확인

방법

다양한 크기의 Data를 10번 Send 함

결과

- 50Kbyte 크기의 Data일 경우, Receive Message 33번 발생. 한번에 약 1.7Kbyte 수신

- 10Kbyte 크기의 Data일 경우, Receive Message 14번 발생. 한번에 받는 양이 일정하지 않음

- 100Kbyte 크기의 Data일 경우, Receive Message 63번 발생. 한번에 약 17Kbyte 수신

결과분석

한번에 큰 크기의 데이터를 Send하는 경우, Receive 측에서 Receive Message가 발생한 시점에 모든 데이터가 전송되지 않는다. 따라서 Receive Message 발생 시점에 Receive 함수를 호출하면 호출 시점까지 전송된 데이터만을 읽어들이게 된다. 그 이후 전송되는 데이터들은 별도의 Message가 다시 발생하며, 모든 데이터가 Receive될 때까지 Receive Message가 발생한다.

따라서 대용량 Data를 Receive하는 경우에는 데이터의 길이에 대한 정보를 미리 받아서 그 데이터가 모두 도착할때까지 읽도록 하여야 완전한 데이터를 수신할 수 있다.

Receive Message의 발생은 Receive Buffer의 크기와 한번의 Receive Message에 대해서 호출되는 Receive 함수의 수에 따라 그 발생횟수는 달라질 수 있다.

 


3. Close 관련 Test

Ÿ Close Message 발생 Test

내용

각 상황에 따른 Close Message의 발생여부 검사

-       Process를 비정상적으로 강제 Kill 시킨 경우

-       Computer의 전원이 꺼진 경우

-       Network Cable을 제거한 경우

-       Network Cable을 제거한 후 다시 연결하고 접속을 해제하는 경우

-       Network Cable을 제거한 후 Prcess를 종료하고 다시 Cable을 연결하는 경우

방법

 

결과

-       작업관리자에서 Process를 종료하였을 경우 Close Message 발생함

-       Network Cable을 제거한 경우 자신의 Cable 제거시 7초정도, 상대방 Cable 제거시 3분 정도 후에 Cloase Message 발생

-       Network Cable 제거 후 Close Message가 발생하기 전에 다시 연결하여 접속을 해제하는 경우, 정상적으로 Close Message 발생

-       Network Cable을 제거한 후 Process를 종료하고 다시 Cable을 연결하는 경우, Close Message 발생하지 않음

결과분석

 

 



출처 : http://www.cyberciti.biz/faq/yum-downloadonly-plugin/

----------------------------------------
방법1 : yum-downloadonly plugin 이용
----------------------------------------
[a] --downloadonly : don't update, just download a rpm file
[b] --downloaddir=/path/to/dir : specifies an alternate directory to store packages such as /tmp

1) plugin 설치
# yum install yum-downloadonly

2) 다운로드
# yum install httpd -y --downloadonly
# yum update httpd -y --downloadonly
-> 다운로드 디렉토리 : /var/cache/yum/base/packages
                                /var/cache/yum/updates/packages

3) 지정한 디렉토리로 패키지 다운로드
# yum install httpd -y --downloadonly --downloaddir=/opt
# yum update httpd -y --downloadonly --downloaddir=/opt
-> 다운로드 디렉토리 : /opt

----------------------------------------
방법2 :  yum-utils.noarch 패키지 이용
----------------------------------------
1) 설치
# yum -y install yum-utils.noarch

2) rpm 다운로드
# yumdownloader httpd
-> 다운로드 디렉토리 : 현재 디렉토리


----------------------------------------
rpm 설치
----------------------------------------
rpm은 기본적으로 확장자가 .rpm으로 끝나는 패키지를 설치하고 제거하는 기능을 합니다.
물론 이외에도 수없이 많은 기능과 옵션이 존재합니다만 그리 자주 사용되지는 않습니다.

X Winodw용 rpm 패키지 관리자가 있기는 하지만 모두 콘솔용 rpm을 응용하고 있기 때문에
rpm 관리자는 꼭 알아두셔야 합니다.

가장 기본적으로 버전과 도움말을 보겠습니다.

> rpm --version
RPM 버전 - 4.4.2
...

> rpm --help
사용법: rpm [옵션...]
...

빼기(-) 기호가 2개입니다.

다음은 rpm의 기본 옵션입니다.

설치 옵션: -i 또는 -U   (install, upgrade)
제거 옵션: -e             (erase)
질의 옵션: -q             (query)
기타: -v              (정보 표시)
       -h              (진행상태 표시)
       --force        (강제설치)
       --nodeps     (의존성 무시)

자 그럼 패키지를 설치해 보겠습니다.

패키지 install과 upgrade가 있는데 upgrade를 사용하면 먼저 install되어 있는지
확인하므로 upgrade만 사용하셔도 됩니다.

> rpm -Uvh kaffeine-0.8.2-2.i386.rpm

그러면 설치정보를 함께 표시하면서 진행 상황을 "#####..."게 표시해 줍니다.
항상 이렇게 많이 쓰니 외워 두시면 편리합니다.

내 컴퓨터에 설치된 rpm이 ㅤㅁㅕㅈ 개일까요?
질의 옵션을 사용하여 설치된 패키지를 볼 수 있습니다.

> rpm -qa

실로 엄청나게 많습니다. (중간에 멈추려면 Ctrl-C입니다.)
수세는 설치를 전부 rpm으로 하기 때문에 이것을 다 보기란 불가능합니다.

내가 원하는 패키지가 rpm으로 설치되어 있는지 알아보고 싶다면 다음과 같이 표현합니다.

> rpm -qa | grep kaffeine
kaffeine-0.8.2-2

kaffeine이 설치되어 있다면 위와 같이 버전도 함께 출력됩니다.
(파이프라인은 자주 사용되므로 익숙해지셔야 합니다.)

kaffeine이 설치되어 있지 않다면 아무것도 표시하지 않습니다.

이제 kaffeine을 삭제해 보겠습니다. (정말 지우시면 YaST로 다시 깔아야 합니다.)

삭제는 다음과 같이 -e 옵션을 사용합니다. 

> rpm -e kaffeine-0.8.2-2

아무 출력이 없다면 성공적으로 삭제된 것입니다.
GUI처럼 보기 좋지는 않지만 기능은 더 막강합니다.

다음에 프로그램 설치할 때 꼭 이용해 보세요.


귀속년도 : 2010
코드번호 : 749609
 귀속년도 2010
 기준경비율코드 749609
 중분류명 사업지원 서비스업
 세분류명 그외 기타 사업지원 서비스업
 세세분류명 그외 기타 분류안된 사업지원 서비스업
 업태명 N. 사업시설관리 및 사업지원서비스업
 자가율 적용여부 Y
 단순경비율(기본율) 86.4
 기준경비율 20.1
 적용범위및 기준 ?타인의 의뢰에 의하여 당사자 일방이 어느일을 완성할 것을 약정하고 그 일의 결과에 따라 대가를 받는 사업 ?기계조립, 고정, 배치, 시설개체서비스, 대형탱크 조립설치 등 달리 분류되지 않은 도급업


귀속년도 : 2010 코드번호 : 721000
 귀속년도 2010
 기준경비율코드 721000
 중분류명 컴퓨터 프로그래밍, 시스템 통합 및 관리업
 세분류명 컴퓨터시스템 통합 자문, 구축 및 관리업
 세세분류명 컴퓨터시스템 통합 자문 및 구축 서비스업,컴퓨터시설 관리업
 업태명 J. 출판, 영상, 방송통신 및 정보서비스업
 자가율 적용여부 Y
 단순경비율(기본율) 75
 기준경비율 31.6
 적용범위및 기준 ?컴퓨터 유형, 배치, 시스템 및 관련 소프트웨어의 적용 등에 관한 설계?자문 활동을 영위하는 업 ?고객의 컴퓨터시스템을 관리하는 산업활동 (부수적으로 관련 소프트웨어의 설계 및 보완이 관리과정에서 이루어 질 수 있음)


귀속년도 : 2010 코드번호 : 722000
 귀속년도 2010
 기준경비율코드 722000
 중분류명 컴퓨터 프로그래밍, 시스템 통합 및 관리업
 세분류명 시스템·응용 소프트웨어 개발 및 공급업
 세세분류명 응용소프트웨어 개발 및 공급업,시스템? 소프트웨어 개발 및 공급업
 업태명 J. 출판, 영상, 방송통신 및 정보서비스업
 자가율 적용여부 Y
 단순경비율(기본율) 72.5
 기준경비율 26.4
 적용범위및 기준 ?컴퓨터프로그램 번역, 임대, 공급 *컴퓨터 조립생산(→300100) ?범용성 및 주문형 컴퓨터소프트웨어에 관하여 자문, 제작 및 공급을 수행하는 산업활동 ?시스템 및 운영?응용 소프트웨어 제작 ?게임소프트웨어 제작(제작한 게임소프트웨어를 인터넷으로 제공하는 사업체 포함) ?웹디자인(프로그래밍 수반)



1. df -Th

2. file -s /dev/sda1

CHIP_COUNT=`cat /proc/cpuinfo | grep "physical id" | sort -u | wc -l`; CHIP_CORES=`cat /proc/cpuinfo | grep "siblings" | tail -1 | cut -d: -f2`; echo "CPU: $CHIP_COUNT chips x $CHIP_CORES cores"

출처 : http://kukuta.tistory.com/35


Read/Write Lock(이하 rwlock)의 기본적인 생각은 아래와 같이 간단하다.

  * Read 작업은 값을 변경하지 않으니 몇개가 붙어도 동기화에 문제가 생기지 않는다.
  * Write 작업은 값을 변경 할 수도 있으니, 하나의 크리티컬 섹션에 하나만 붙어야 한다.
  * Read 작업은 끼리는 여러개가 하나의 크리티컬 섹션에 접근 가능하나, Read하는 것을 도중에 바꾸면 안된다.

 

 위의 세 가지 사항 정도만 제외 한다면 rwlock은 mutex랑 비슷하다. 개념도 비슷하고, 사용법도 비슷하고, 하는
일도 비슷하다.

 rwlock의 장점은 read 작업에 있어서 여러개의 쓰레드가 서로 블록킹 하는 일이 없어 괜한 오버헤드를 가지고 오
지 않고, 단점은
그 특성상 read작업이 많다면 거기에 눌려 write 오퍼레이션은 뒤로 밀리기 마련이다.
 
 write lock을 걸려고 하는 쓰레드가 자원을 못 받아 말라 죽는
시나리오를 만들어 보자.

 1) 1번 쓰레드가 A라는 공유 자원을 참조 하려고 한다.
   *
아직 아무런 lock이 걸려 있지 않으므로 커널은 lock을 허락한다.
 2) 2번 쓰레드가 A라는 공유 자원을 변경 하려고 한다.
   * 변경이라는 것은 wrtie lock을 걸어야 하는데 아직 read 작업이 있으므로 write를 잠시 멈춘다.
     
하지만 그 사이에 다른 read 작업이 또 들어 온다. read 작업은 공유가 되므로 커널은 뒤 늦게 온 read 작업을
     크리티컬섹션 안으로 넣어 버린다. 이런 현상의 반복으로 write를 요청하는 thread는 굶어 죽는 경우가 발생
     해 버릴수 있다.(현실적으로는 이런 경우를 대비하여 만들었 겠지만, 그래도 rwlockmodify작업보
    다는 read가 더 많은 곳에 사용하는 것이 가장  이상적이다
.)


#include <pthread.h>
int pthread_rwlock_init(pthread_rwlock_t *restrict    rwlock, const pthread_rwlockattr_t    *restrict attr);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);


 API가 상당히 직관적이다. mutex같은 것들과 마찬가지로 pthread_rwlock_t 객체를 사용하기 이전에
pthread_rwlock_init으로 객체르르 초기화 해주고, 사용이 끝나고 커널에 반환 해야 할 경우에는 pthread_rwlock_destroy로 객체를 해제해 준다.

 read 작업을 하는 경우에는 pthread_rwlock_rdlock을 호출 하고, write작업을 할경우에는
pthread_rwlock_wrlock을 호출 하면 된다. 그리고 어떠한 read 작업이든, write작업이든 lock을 풀어 줄때는
pthread_rwlock_unlock을 호출 한다. read작업을 다른 말로 shared 작업, 즉 공유가 가능한 작업이라고 하는데 구현상 그 갯수에 제한을 두고 있다.
 
 
Single Unix
계열에서는 아래와 같은 함수를 지원한다..

#include <pthread.h>

int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

  try라는 이름과 같이 단시 시도를 할 뿐이다. 만일 lock을 잡을 수 없는 상황이라면 바로 리턴을 한다. 리턴 값은
lock를 잡을 경우에는 0을 리턴하고, 그렇지 못하다면 EBUSY를 리턴한다.

 아래의 예제 코드는 두개의 read lock과 하나의 write lock을 사용한다. 하나의 read lock을 걸고 다른 read lock
를 걸었을 경우 과연 예상대로 lock이 잡히는지 안잡히는지, 그리고 read lock가 걸려 있는 상태에서 write lock는 과연 대기 상태에 있는지를 알아 보고자 하는 코드다.

예제 코드 닫기

#include <pthread.h>
#include <iostream>
#include <unistd.h>

pthread_rwlock_t g_rwLock;
int g_share = 0;

void* thr_readLock(void* arg) {
 int ret = pthread_rwlock_rdlock(&g_rwLock);
 if(ret == 0) {
  std::cout << "try to read lock successfully complete!!" << std::endl;
 }
 sleep(3);
 pthread_rwlock_unlock(&g_rwLock);
 std::cout << "unlock the read lock" << std::endl;
}

void* thr_writeLock(void* arg) {
 int ret = pthread_rwlock_wrlock(&g_rwLock);
 if(ret == 0) {
  std::cout << "try to write lock successfully complete!!" << std::endl;
 }
 pthread_rwlock_unlock(&g_rwLock);
 std::cout << "unlock the write lock" << std::endl;
}

int main() {
 int ret = 0;
 ret = pthread_rwlock_init(&g_rwLock, NULL);
 if(ret != 0) {
  std::cout << strerror(ret) << std::endl;
  exit(1);
 }
 
 pthread_t readThr[2];
 pthread_t writeThr;

 ret = pthread_create(&readThr[0], NULL, thr_readLock, NULL);
 if(ret != 0) {
  std::cout << strerror(ret) << std::endl;
  exit(1);
 }
 ret = pthread_create(&readThr[1], NULL, thr_readLock, NULL);
 if(ret != 0) {
  std::cout << strerror(ret) << std::endl;
  exit(1);
 }
 ret = pthread_create(&writeThr, NULL, thr_writeLock, NULL);
 if(ret != 0) {
  std::cout << strerror(ret) << std::endl;
  exit(1);
 }
 
 sleep(10);
 pthread_rwlock_destroy(&g_rwLock);
}

+ Recent posts