pow( ) - 거듭제곱 함수 구현하기(정수 기반)

by Blogger 하얀쿠아
2017. 12. 21. 13:57 소프트웨어 Note/C

개요

C언어의 수학 함수 중, 거듭제곱을 구하는 pow( )라는 함수가 있다.

예를들어, 2의 10승을 계산하고 싶다면, pow(2.0, 10.0); 형태로 사용하는 함수이다.

이 함수는 math.h 헤더를 include하면 사용할 수 있는 함수이다.


#include <math.h>

double pow(double x, double y);

x : 거듭제곱의 밑수

y : 거듭제곱의 지수


그런데 이렇게 거듭제곱을 계산하는 함수를 직접 구현해야 하는 경우가 있었다.

매우 큰 수의 거듭제곱을 계산하면서 중간중간에 주어진 특정 값으로 mod 연산(나눗셈 후 나머지 값을 취하여 반환하는 연산)을 해야 하는 알고리즘 풀이 문제였다.


문제 조건 상, pow( )를 직접 사용하면 연산속도가 느려지는 상황이라 직접 구현을 시도해 보았다.



my_pow( ) 직접 구현하기


내가 필요한 것은 math.h 에서 제공하는 함수와는 달리, 밑과 지수가 큰 정수(unsigned long long 타입)이면 충분했다.

아래와 같이 구현했다.

편의상 위에서 언급한 mod 연산 부분은 제외하였다.

또한, 항상 exp >= 1 이고 base >= 1 이라고 가정하였다.


unsigned long long my_pow(unsigned long long base, int exp)
{
    unsigned long long res = 1;
    while (exp)
    {
        if (exp & 1)
            res *= base;
        exp >>= 1;
        base *= base;
    }

    return res;
}


설명

조금만 찾아보면 알겠지만, '제곱에 의한 지수법(?)' 표준 방법이라고 한다.

그러나 이것은 모든 지수 값에 대해 작동하는 일반적인 방법으로 할 수있는 최선의 방법 일 수는 있지만 특정 지수 값에 대해서는 더 적은 곱셈으로도 계산 가능한 더 빠른 해결방법이 존재할 수 있다. 즉, 항상 최적의 해결방법은 아니라는 것이다.


예를들면 x의 15승 (x ^ 15) 를 생각해보자.


x^15 = (x^7)*(x^7)*x 

x^7 = (x^3)*(x^3)*x 

x^3 = x*x*x


위의 구현방법으로는 총 6번의 곱셈을 해야 계산결과를 얻게된다.


그러나, 'Addition-Chain exponentiation[각주:1]' 방법을 사용하면 5번의 곱셈으로 결과를 얻을 수 있다.


n*n = n^2

n^2*n = n^3

n^3*n^3 = n^6

n^6*n^6 = n^12

n^12*n^3 = n^15




사용 예

아래와 같이 사용하면 된다.

// 2^3
pow(2,3); // 8

// 5^5
pow(5,5); // 3125


  1. https://en.wikipedia.org/wiki/Addition-chain_exponentiation [본문으로]
이 댓글을 비밀 댓글로

[네트워크/C reference] Special IPv6 주소 검사 매크로

by Blogger 하얀쿠아
2017. 12. 14. 02:25 소프트웨어 Note/C

개요


IPv6 주소 체계에서는 'Special IPv6 addresses' 라고 부르는, 미리 정의된 특별한 주소들이 있다.

미리 정의된 비트 패턴(bit pattern) 으로 각 주소의 역할을 구분한다.


최근들어 C언어로 네트워크 프로그래밍을 하면서 IPv6 주소를 다루게 되는 경우가 발생하곤 하는데, 이 주소가 특정 Special IPv6 address 인지 아닌지를 확인 해야 하는 경우가 있었다. 

그래서 조금 찾아보니, 이런 경우 유용하게 사용 할 수 있는 매크로 함수가 C의 표준 라이브러리인 glibc 의 netinet/in.h 헤더에 정의가 되어 있었다.


이번 포스팅에서는 이들 매크로 함수들을 간단히 소개한다.


특수 IPv6 주소(Special IPv6 Address) 검사 매크로 함수

IEEE Std 1003.1, 2004 Edition 에는, <netinet/in.h> 헤더는 아래와 같은 매크로들을 정의해야 한다고 권고하고 있다.

이 각각의 매크로들은 인자로 하나의 const struct in6_addr * type을 받으며, 인자의 IPv6 주소가 special IPv6 addresses 인지 아닌지를 검사하고 int type으로 참인 경우 1 / 거짓인 경우 0을 반환하는 기능을 한다.


아래 내용중, 실제 정의 내용은 glibc/inet/netinet/in.h 에서 발췌했다. 정확한 버전은 기억나지 않는다. 

변경될 만한 성격의 것이 아니라 버전마다 다를 가능성은 적지만, 단언하긴 어려우며 확인이 필요하다.



IN6_IS_ADDR_UNSPECIFIED(addr)

정의되지 않은 주소(Unspecified address) 여부를 검사한다.

정의되지 않은 주소이면 1을 반환한다.

정의되지 않은 주소가 아니면 0을 반환한다.


참고로 IPv6에서 정의되지 않은 주소는 ::/128 이다.


헤더파일에는 아래와 같이 정의되어 있다.


#ifdef __GNUC__
# define IN6_IS_ADDR_UNSPECIFIED(a) \
  (__extension__                                                              \
   ({ const struct in6_addr *__a = (const struct in6_addr *) (a);              \
      __a->__in6_u.__u6_addr32[0] == 0                                              \
      && __a->__in6_u.__u6_addr32[1] == 0                                      \
      && __a->__in6_u.__u6_addr32[2] == 0                                      \
      && __a->__in6_u.__u6_addr32[3] == 0; }))
#else
# define IN6_IS_ADDR_UNSPECIFIED(a) \
        (((const uint32_t *) (a))[0] == 0                                      \
         && ((const uint32_t *) (a))[1] == 0                                      \
         && ((const uint32_t *) (a))[2] == 0                                      \
         && ((const uint32_t *) (a))[3] == 0)

#endif





IN6_IS_ADDR_LOOPBACK(addr)

local host로의 루프백 주소(Loopback address) 여부를 검사한다.

루프백 주소이면 1을 반환한다.

루프백 주소가 아니면 0을 반환한다.


참고로 IPv6에서 루프백 주소는 ::1/128 이다. IPv4의 127.0.0.1과 같은 역할을 한다.


헤더파일에는 아래와 같이 정의되어 있다.


#ifdef __GNUC__
# define IN6_IS_ADDR_LOOPBACK(a) \
  (__extension__                                                              \
   ({ const struct in6_addr *__a = (const struct in6_addr *) (a);              \
      __a->__in6_u.__u6_addr32[0] == 0                                              \
      && __a->__in6_u.__u6_addr32[1] == 0                                      \
      && __a->__in6_u.__u6_addr32[2] == 0                                      \
      && __a->__in6_u.__u6_addr32[3] == htonl (1); }))
#else
# define IN6_IS_ADDR_LOOPBACK(a) \
        (((const uint32_t *) (a))[0] == 0                                      \
         && ((const uint32_t *) (a))[1] == 0                                      \
         && ((const uint32_t *) (a))[2] == 0                                      \
         && ((const uint32_t *) (a))[3] == htonl (1))
#endif



IN6_IS_ADDR_MULTICAST(addr)

멀티캐스트 주소 (Multicast address) 여부를 검사한다.

멀티캐스트 주소이면 1을 반환한다.

멀티캐스트 주소가 아니면 0을 반환한다.


IPv6 에서 멀티캐스트 주소라고 하면, ff0X:: 로 시작하는 주소이다. 여기서 X는 16 진수 값으로 예약되어 있으므로 멀티캐스트 그룹에 할당하면 안된다. 이 예약에 대해서는 IANA (Internet Assigned Numbers Authority)가 관리한다. 현재까지는, 이 X의 값으로 scope를 구분한다.

현재는 0, 1, 2, 3, 5, 6, 7, 8, e, f 가 사용되고 있는데, 이중.. 1 (interface-local), 2 (link-local), 5 (site-local)를 의미한다. 다른 값들도 특정한 의미가 있다.


간단히 예를 들어보면, ff02::2 는 link-local의 모든 라우터를 지칭하는 주소이고, ff01::2 는 interface-local의 모든 라우터를 지칭하는 주소이며, ff05::2는 site-local의 모든 라우터를 지칭하는 주소인 식이다.

이에 대해서는 별도의 포스팅으로 한번 더 다뤄보겠다.


헤더파일에는 이 매크로를 아래와 같이 정의하고 있다.


#define IN6_IS_ADDR_MULTICAST(a) (((const uint8_t *) (a))[0] == 0xff)





IN6_IS_ADDR_LINKLOCAL(addr)

유니캐스트 링크로컬 주소(Unicast link-local address) 여부를 검사한다.

유니캐스트 링크로컬 주소이면  1을 반환한다.

유니캐스트 링크로컬 주소가 아니면 0을 반환한다.


헤더파일에는 아래와 같이 정의하고 있다.


#ifdef __GNUC__
# define IN6_IS_ADDR_LINKLOCAL(a) \
  (__extension__                                                              \
   ({ const struct in6_addr *__a = (const struct in6_addr *) (a);              \
      (__a->__in6_u.__u6_addr32[0] & htonl (0xffc00000)) == htonl (0xfe800000); }))
#else
# define IN6_IS_ADDR_LINKLOCAL(a) \
        ((((const uint32_t *) (a))[0] & htonl (0xffc00000))                      \
         == htonl (0xfe800000))
#endif




IN6_IS_ADDR_SITELOCAL(addr)

유니캐스트 사이트 로컬 주소(Unicast site-local address) 여부를 검사한다.

유니캐스트 사이트 로컬 주소이면  1을 반환한다.

유니캐스트 사이트 로컬 주소가 아니면 0을 반환한다.


헤더파일에는 아래와 같이 정의되어 있다.


#ifdef __GNUC__
# define IN6_IS_ADDR_SITELOCAL(a) \
  (__extension__                                                              \
   ({ const struct in6_addr *__a = (const struct in6_addr *) (a);              \
      (__a->__in6_u.__u6_addr32[0] & htonl (0xffc00000)) == htonl (0xfec00000); }))
#else
# define IN6_IS_ADDR_SITELOCAL(a) \
        ((((const uint32_t *) (a))[0] & htonl (0xffc00000))                      \
         == htonl (0xfec00000))
#endif




IN6_IS_ADDR_V4MAPPED(addr)

IPv4 매핑된 주소(IPv4 mapped address) 여부를 검사한다.

참고로 IPv4 mapped address는 prefix가 ::ffff:0:0/96 이고, 범위는 ::ffff:0.0.0.0부터 ::ffff:255.255.255.255 까지 이다.

이 매크로는, 인자 addr이 이에 해당하는 지를 검사하여 결과를 반환한다.


헤더파일에는 아래와 같이 정의되어 있다.


#ifdef __GNUC__
# define IN6_IS_ADDR_V4MAPPED(a) \
  (__extension__                                                              \
   ({ const struct in6_addr *__a = (const struct in6_addr *) (a);              \
      __a->__in6_u.__u6_addr32[0] == 0                                              \
      && __a->__in6_u.__u6_addr32[1] == 0                                      \
      && __a->__in6_u.__u6_addr32[2] == htonl (0xffff); }))
#else
# define IN6_IS_ADDR_V4MAPPED(a) \
        ((((const uint32_t *) (a))[0] == 0)                                      \
         && (((const uint32_t *) (a))[1] == 0)                                      \
         && (((const uint32_t *) (a))[2] == htonl (0xffff)))
#endif


IN6_IS_ADDR_V4COMPAT(addr)

IPv4 호환 주소(IPv4-compatible address) 여부를 검사한다.

참고로 IPv4-compatible address의 prefix는 ::/96 이다. 그러나 이 주소 prefix는 deprecated 되었음을 기억하자.


이 매크로는 헤더파일에 아래와 같이 정의되어 있다.


#ifdef __GNUC__
# define IN6_IS_ADDR_V4COMPAT(a) \
  (__extension__                                                              \
   ({ const struct in6_addr *__a = (const struct in6_addr *) (a);              \
      __a->__in6_u.__u6_addr32[0] == 0                                              \
      && __a->__in6_u.__u6_addr32[1] == 0                                      \
      && __a->__in6_u.__u6_addr32[2] == 0                                      \
      && ntohl (__a->__in6_u.__u6_addr32[3]) > 1; }))
#else
# define IN6_IS_ADDR_V4COMPAT(a) \
        ((((const uint32_t *) (a))[0] == 0)                                      \
         && (((const uint32_t *) (a))[1] == 0)                                      \
         && (((const uint32_t *) (a))[2] == 0)                                      \
         && (ntohl (((const uint32_t *) (a))[3]) > 1))
#endif



IN6_IS_ADDR_MC_NODELOCAL

멀티캐스트 노드 로컬 주소 (Multicast node-local address) 여부를 검사한다.


이 매크로는 헤더파일에 아래와 같이 정의되어 있다.


#define IN6_IS_ADDR_MC_NODELOCAL(a) \
        (IN6_IS_ADDR_MULTICAST(a)                                              \
         && ((((const uint8_t *) (a))[1] & 0xf) == 0x1))




IN6_IS_ADDR_MC_LINKLOCAL


멀티캐스트 링크 로컬 주소 (Multicast link-local address) 여부를 검사한다.


이 매크로는 헤더파일에 아래와 같이 정의되어 있다.


#define IN6_IS_ADDR_MC_LINKLOCAL(a) \
        (IN6_IS_ADDR_MULTICAST(a)                                              \
         && ((((const uint8_t *) (a))[1] & 0xf) == 0x2))




IN6_IS_ADDR_MC_SITELOCAL

멀티캐스트 사이트-로컬 주소(Multicast site-local address) 여부를 검사한다.


멀티캐스트 사이트-로컬 주소이면 1을 반환한다.

멀티캐스트 사이트-로컬 주소가 아니면 0을 반환한다.


헤더파일에는 아래와 같이 정의되어 있다.


#define IN6_IS_ADDR_MC_SITELOCAL(a) \
        (IN6_IS_ADDR_MULTICAST(a)                                              \
         && ((((const uint8_t *) (a))[1] & 0xf) == 0x5))



IN6_IS_ADDR_MC_ORGLOCAL

멀티캐스트 organization-local 주소(Multicast organization-local address) 여부를 검사한다.


참고로 organization-local 주소의 prefix는 ffx8::/16 이고, IPv4의 239.192.0.0/14 와 동일하다.

헤더파일에는 아래와 같이 정의되어 있다.


#define IN6_IS_ADDR_MC_ORGLOCAL(a) \
        (IN6_IS_ADDR_MULTICAST(a)                                              \
         && ((((const uint8_t *) (a))[1] & 0xf) == 0x8))



IN6_IS_ADDR_MC_GLOBAL

멀티캐스트 글로벌 주소(Multicast global address) 여부를 검사한다. 

멀티캐스트 글로벌 주소이면 1을 반환한다.

멀티캐스트 글로벌 주소가 아니면 0을 반환한다.


헤더파일에는 아래와 같이 정의되어 있다.



#define IN6_IS_ADDR_MC_GLOBAL(a) \
        (IN6_IS_ADDR_MULTICAST(a)                                              \
         && ((((const uint8_t *) (a))[1] & 0xf) == 0xe))



참조 - 예약된 IPv6 주소(Reserved IPv6 address)

Special IPv6 address와 같이 볼 것이 있는데, Reserved IPv6 address 이다. IPv6 주소 체계에서 특수 목적으로 예약된 몇몇 주소들인데, 아래 wiki의 표와 같다.


https://en.wikipedia.org/wiki/Reserved_IP_addresses#IPv6

이 댓글을 비밀 댓글로

[우분투 16.04] 32bit library를 64 bit 우분투 16.04에 설치하는 방법

by Blogger 하얀쿠아
2017. 12. 13. 21:03 소프트웨어 Note/Linux

개요

우분투라는 운영체제는 32 bit CPU용 버전과 64 bit CPU용 버전이 제공된다.

그런데 종종, 32bit 용으로 빌드 된 실행파일을 64 bit 용 우분투에서 실행시켜야 하는 경우가 있다.

그리고 우분투 12.04 LTS의 64bit 버전에서는 꼼수로써, ia32-libs 라는 패키지를 제공해서, 32bit용 실행파일을 실행 시킬 수 있도록 했었다.


그러나 우분투 16.04 에서는 ia32-libs 패키지가 deprecated 처리가 되었다.

그 이유는 MultiArch를 사용하도록 유도하기 위해서 인 듯 싶다.


하지만 방법이 있다.

아래와 같은 순서로 MultiArch를 설치하고, 32 bit 용 실행파일을 우분투 16.04 의 64bit 버전 에서 실행되도록 할 수 있다.



i386 아키텍쳐 활성화 하기


root 권한으로 아래 명령을 통해 i386 아키텍쳐를 활성화 시킨다.


$ sudo dpkg --add-architecture i386
$ sudo apt-get update



32-bit 라이브러리 설치하기


root 권한으로 아래 명령을 통해 32-bit 라이브러리를 설치한다.


$ apt-get install libc6:i386 libstdc++6:i386


설치 과정의 console 로그

아래와 같이 설치가 진행된다.

참고 바란다.


$ sudo apt-get install libc6:i386 libstdc++6:i386
Reading package lists... Done
Building dependency tree      
Reading state information... Done
The following additional packages will be installed:
  cpp-5 g++-5 gcc-5 gcc-5-base gcc-5-base:i386 gcc-6-base:i386 libasan2 libatomic1 libc-dev-bin libc6 libc6-dbg libc6-dev libcc1-0 libcilkrts5 libgcc-5-dev libgcc1:i386 libgomp1 libitm1 liblsan0 libmpx0 libquadmath0 libstdc++-5-dev
  libstdc++6 libtsan0 libubsan0
Suggested packages:
  gcc-5-locales g++-5-multilib gcc-5-doc libstdc++6-5-dbg gcc-5-multilib libgcc1-dbg libgomp1-dbg libitm1-dbg libatomic1-dbg libasan2-dbg liblsan0-dbg libtsan0-dbg libubsan0-dbg libcilkrts5-dbg libmpx0-dbg libquadmath0-dbg
  glibc-doc glibc-doc:i386 locales:i386 libstdc++-5-doc
The following NEW packages will be installed:
  gcc-5-base:i386 gcc-6-base:i386 libc6:i386 libgcc1:i386 libstdc++6:i386
The following packages will be upgraded:
  cpp-5 g++-5 gcc-5 gcc-5-base libasan2 libatomic1 libc-dev-bin libc6 libc6-dbg libc6-dev libcc1-0 libcilkrts5 libgcc-5-dev libgomp1 libitm1 liblsan0 libmpx0 libquadmath0 libstdc++-5-dev libstdc++6 libtsan0 libubsan0
22 upgraded, 5 newly installed, 0 to remove and 424 not upgraded.
Need to get 41.1 MB of archives.
After this operation, 12.1 MB of additional disk space will be used.
Do you want to continue? [Y/n] y
Get:1 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libc6-dbg amd64 2.23-0ubuntu9 [3,683 kB]
Get:2 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libc6-dev amd64 2.23-0ubuntu9 [2,082 kB]
Get:3 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libc-dev-bin amd64 2.23-0ubuntu9 [68.6 kB]
Get:4 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libc6 amd64 2.23-0ubuntu9 [2,586 kB]
Get:5 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libcc1-0 amd64 5.4.0-6ubuntu1~16.04.5 [38.8 kB]
Get:6 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libgomp1 amd64 5.4.0-6ubuntu1~16.04.5 [55.1 kB]
Get:7 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libitm1 amd64 5.4.0-6ubuntu1~16.04.5 [27.4 kB]
Get:8 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libatomic1 amd64 5.4.0-6ubuntu1~16.04.5 [8,920 B]
Get:9 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libasan2 amd64 5.4.0-6ubuntu1~16.04.5 [264 kB]
Get:10 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 liblsan0 amd64 5.4.0-6ubuntu1~16.04.5 [105 kB]
Get:11 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libtsan0 amd64 5.4.0-6ubuntu1~16.04.5 [244 kB]
Get:12 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libubsan0 amd64 5.4.0-6ubuntu1~16.04.5 [95.3 kB]
Get:13 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libcilkrts5 amd64 5.4.0-6ubuntu1~16.04.5 [40.1 kB]
Get:14 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libmpx0 amd64 5.4.0-6ubuntu1~16.04.5 [9,786 B]
Get:15 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libquadmath0 amd64 5.4.0-6ubuntu1~16.04.5 [131 kB]
Get:16 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 g++-5 amd64 5.4.0-6ubuntu1~16.04.5 [8,435 kB]
Get:17 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libstdc++-5-dev amd64 5.4.0-6ubuntu1~16.04.5 [1,430 kB]
Get:18 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libgcc-5-dev amd64 5.4.0-6ubuntu1~16.04.5 [2,226 kB]
Get:19 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 gcc-5 amd64 5.4.0-6ubuntu1~16.04.5 [8,638 kB]
Get:20 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 cpp-5 amd64 5.4.0-6ubuntu1~16.04.5 [7,786 kB]
Get:21 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 gcc-5-base amd64 5.4.0-6ubuntu1~16.04.5 [17.1 kB]
Get:22 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libstdc++6 amd64 5.4.0-6ubuntu1~16.04.5 [393 kB]
Get:23 http://kr.archive.ubuntu.com/ubuntu xenial/main i386 gcc-6-base i386 6.0.1-0ubuntu1 [14.3 kB]
Get:24 http://kr.archive.ubuntu.com/ubuntu xenial/main i386 libgcc1 i386 1:6.0.1-0ubuntu1 [46.8 kB]
Get:25 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main i386 libc6 i386 2.23-0ubuntu9 [2,269 kB]
Get:26 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main i386 gcc-5-base i386 5.4.0-6ubuntu1~16.04.5 [17.1 kB]                                                                                                                   
Get:27 http://kr.archive.ubuntu.com/ubuntu xenial-updates/main i386 libstdc++6 i386 5.4.0-6ubuntu1~16.04.5 [418 kB]                                                                                                                    
Fetched 41.1 MB in 6s (6,517 kB/s)                                                                                                                                                                                                     
Preconfiguring packages ...
(Reading database ... 195047 files and directories currently installed.)
Preparing to unpack .../libc6-dbg_2.23-0ubuntu9_amd64.deb ...
Unpacking libc6-dbg:amd64 (2.23-0ubuntu9) over (2.23-0ubuntu5) ...
Preparing to unpack .../libc6-dev_2.23-0ubuntu9_amd64.deb ...
Unpacking libc6-dev:amd64 (2.23-0ubuntu9) over (2.23-0ubuntu5) ...
Preparing to unpack .../libc-dev-bin_2.23-0ubuntu9_amd64.deb ...
Unpacking libc-dev-bin (2.23-0ubuntu9) over (2.23-0ubuntu5) ...
Preparing to unpack .../libc6_2.23-0ubuntu9_amd64.deb ...
Unpacking libc6:amd64 (2.23-0ubuntu9) over (2.23-0ubuntu5) ...
Selecting previously unselected package libc6:i386.
Preparing to unpack .../libc6_2.23-0ubuntu9_i386.deb ...
Unpacking libc6:i386 (2.23-0ubuntu9) ...
Setting up libc6:amd64 (2.23-0ubuntu9) ...
Processing triggers for libc-bin (2.23-0ubuntu5) ...
Processing triggers for man-db (2.7.5-1) ...
Selecting previously unselected package libgcc1:i386.
(Reading database ... 195351 files and directories currently installed.)
Preparing to unpack .../libgcc1_1%3a6.0.1-0ubuntu1_i386.deb ...
Unpacking libgcc1:i386 (1:6.0.1-0ubuntu1) ...
Selecting previously unselected package gcc-6-base:i386.
Preparing to unpack .../gcc-6-base_6.0.1-0ubuntu1_i386.deb ...
Unpacking gcc-6-base:i386 (6.0.1-0ubuntu1) ...
Processing triggers for libc-bin (2.23-0ubuntu5) ...
Setting up gcc-6-base:i386 (6.0.1-0ubuntu1) ...
Setting up libgcc1:i386 (1:6.0.1-0ubuntu1) ...
Setting up libc6:i386 (2.23-0ubuntu9) ...
Processing triggers for libc-bin (2.23-0ubuntu5) ...
(Reading database ... 195356 files and directories currently installed.)
Preparing to unpack .../libcc1-0_5.4.0-6ubuntu1~16.04.5_amd64.deb ...
Unpacking libcc1-0:amd64 (5.4.0-6ubuntu1~16.04.5) over (5.4.0-6ubuntu1~16.04.4) ...
Preparing to unpack .../libgomp1_5.4.0-6ubuntu1~16.04.5_amd64.deb ...
Unpacking libgomp1:amd64 (5.4.0-6ubuntu1~16.04.5) over (5.4.0-6ubuntu1~16.04.4) ...
Preparing to unpack .../libitm1_5.4.0-6ubuntu1~16.04.5_amd64.deb ...
Unpacking libitm1:amd64 (5.4.0-6ubuntu1~16.04.5) over (5.4.0-6ubuntu1~16.04.4) ...
Preparing to unpack .../libatomic1_5.4.0-6ubuntu1~16.04.5_amd64.deb ...
Unpacking libatomic1:amd64 (5.4.0-6ubuntu1~16.04.5) over (5.4.0-6ubuntu1~16.04.4) ...
Preparing to unpack .../libasan2_5.4.0-6ubuntu1~16.04.5_amd64.deb ...
Unpacking libasan2:amd64 (5.4.0-6ubuntu1~16.04.5) over (5.4.0-6ubuntu1~16.04.4) ...
Preparing to unpack .../liblsan0_5.4.0-6ubuntu1~16.04.5_amd64.deb ...
Unpacking liblsan0:amd64 (5.4.0-6ubuntu1~16.04.5) over (5.4.0-6ubuntu1~16.04.4) ...
Preparing to unpack .../libtsan0_5.4.0-6ubuntu1~16.04.5_amd64.deb ...
Unpacking libtsan0:amd64 (5.4.0-6ubuntu1~16.04.5) over (5.4.0-6ubuntu1~16.04.4) ...
Preparing to unpack .../libubsan0_5.4.0-6ubuntu1~16.04.5_amd64.deb ...
Unpacking libubsan0:amd64 (5.4.0-6ubuntu1~16.04.5) over (5.4.0-6ubuntu1~16.04.4) ...
Preparing to unpack .../libcilkrts5_5.4.0-6ubuntu1~16.04.5_amd64.deb ...
Unpacking libcilkrts5:amd64 (5.4.0-6ubuntu1~16.04.5) over (5.4.0-6ubuntu1~16.04.4) ...
Preparing to unpack .../libmpx0_5.4.0-6ubuntu1~16.04.5_amd64.deb ...
Unpacking libmpx0:amd64 (5.4.0-6ubuntu1~16.04.5) over (5.4.0-6ubuntu1~16.04.4) ...
Preparing to unpack .../libquadmath0_5.4.0-6ubuntu1~16.04.5_amd64.deb ...
Unpacking libquadmath0:amd64 (5.4.0-6ubuntu1~16.04.5) over (5.4.0-6ubuntu1~16.04.4) ...
Preparing to unpack .../g++-5_5.4.0-6ubuntu1~16.04.5_amd64.deb ...
Unpacking g++-5 (5.4.0-6ubuntu1~16.04.5) over (5.4.0-6ubuntu1~16.04.4) ...
Preparing to unpack .../libstdc++-5-dev_5.4.0-6ubuntu1~16.04.5_amd64.deb ...
Unpacking libstdc++-5-dev:amd64 (5.4.0-6ubuntu1~16.04.5) over (5.4.0-6ubuntu1~16.04.4) ...
Preparing to unpack .../libgcc-5-dev_5.4.0-6ubuntu1~16.04.5_amd64.deb ...
Unpacking libgcc-5-dev:amd64 (5.4.0-6ubuntu1~16.04.5) over (5.4.0-6ubuntu1~16.04.4) ...
Preparing to unpack .../gcc-5_5.4.0-6ubuntu1~16.04.5_amd64.deb ...
Unpacking gcc-5 (5.4.0-6ubuntu1~16.04.5) over (5.4.0-6ubuntu1~16.04.4) ...
Preparing to unpack .../cpp-5_5.4.0-6ubuntu1~16.04.5_amd64.deb ...
Unpacking cpp-5 (5.4.0-6ubuntu1~16.04.5) over (5.4.0-6ubuntu1~16.04.4) ...
Preparing to unpack .../gcc-5-base_5.4.0-6ubuntu1~16.04.5_amd64.deb ...
Unpacking gcc-5-base:amd64 (5.4.0-6ubuntu1~16.04.5) over (5.4.0-6ubuntu1~16.04.4) ...
Selecting previously unselected package gcc-5-base:i386.
Preparing to unpack .../gcc-5-base_5.4.0-6ubuntu1~16.04.5_i386.deb ...
Unpacking gcc-5-base:i386 (5.4.0-6ubuntu1~16.04.5) ...
Processing triggers for libc-bin (2.23-0ubuntu5) ...
Processing triggers for man-db (2.7.5-1) ...
Setting up gcc-5-base:amd64 (5.4.0-6ubuntu1~16.04.5) ...
Setting up gcc-5-base:i386 (5.4.0-6ubuntu1~16.04.5) ...
(Reading database ... 195359 files and directories currently installed.)
Preparing to unpack .../libstdc++6_5.4.0-6ubuntu1~16.04.5_amd64.deb ...
Unpacking libstdc++6:amd64 (5.4.0-6ubuntu1~16.04.5) over (5.4.0-6ubuntu1~16.04.4) ...
Selecting previously unselected package libstdc++6:i386.
Preparing to unpack .../libstdc++6_5.4.0-6ubuntu1~16.04.5_i386.deb ...
Unpacking libstdc++6:i386 (5.4.0-6ubuntu1~16.04.5) ...
Processing triggers for libc-bin (2.23-0ubuntu5) ...
Setting up libstdc++6:amd64 (5.4.0-6ubuntu1~16.04.5) ...
Setting up libstdc++6:i386 (5.4.0-6ubuntu1~16.04.5) ...
Setting up libc6-dbg:amd64 (2.23-0ubuntu9) ...
Setting up libc-dev-bin (2.23-0ubuntu9) ...
Setting up libc6-dev:amd64 (2.23-0ubuntu9) ...
Setting up libcc1-0:amd64 (5.4.0-6ubuntu1~16.04.5) ...
Setting up libgomp1:amd64 (5.4.0-6ubuntu1~16.04.5) ...
Setting up libitm1:amd64 (5.4.0-6ubuntu1~16.04.5) ...
Setting up libatomic1:amd64 (5.4.0-6ubuntu1~16.04.5) ...
Setting up libasan2:amd64 (5.4.0-6ubuntu1~16.04.5) ...
Setting up liblsan0:amd64 (5.4.0-6ubuntu1~16.04.5) ...
Setting up libtsan0:amd64 (5.4.0-6ubuntu1~16.04.5) ...
Setting up libubsan0:amd64 (5.4.0-6ubuntu1~16.04.5) ...
Setting up libcilkrts5:amd64 (5.4.0-6ubuntu1~16.04.5) ...
Setting up libmpx0:amd64 (5.4.0-6ubuntu1~16.04.5) ...
Setting up libquadmath0:amd64 (5.4.0-6ubuntu1~16.04.5) ...
Setting up cpp-5 (5.4.0-6ubuntu1~16.04.5) ...
Setting up libgcc-5-dev:amd64 (5.4.0-6ubuntu1~16.04.5) ...
Setting up gcc-5 (5.4.0-6ubuntu1~16.04.5) ...
Setting up libstdc++-5-dev:amd64 (5.4.0-6ubuntu1~16.04.5) ...
Setting up g++-5 (5.4.0-6ubuntu1~16.04.5) ...
Processing triggers for libc-bin (2.23-0ubuntu5) ...


결론

64bit 버전의 우분투 16.04(Ubuntu 16.04) 에서 32bit executable file을 실행하고자 하는 경우가 있는데,

기존 우분투 12.04(Ubuntu 12.04)에서 사용하던 패키지인 ia32-libs 를 설치하기는 어렵다.

대신 libc6:i386libstdc++6:i386, 이렇게 두개의 패키지를 설치함으로써 원하는 바를 달성할 수 있다.

이 댓글을 비밀 댓글로

shell prompt에 git branch 이름 표시 / 색상으로 status 표시

by Blogger 하얀쿠아
2017. 11. 23. 01:10 소프트웨어 Note/Linux

git 기본 사용시 불편한 점

여러 소스코드 형상관리 툴 중 git을 주로 사용하는데, linux shell prompt에서 사용하다 보면, 불편한 경우가 있다.

아래 두가지 경우였다.


1. 현재 git directory의 branch가 어디인지?

2. 현재 git directory의 변경사항이 있는지?


기본 상태에서...

1번의 경우는, 'git branch' 라고 명령을 입력해야 확인 가능하다.

2번의 경우는 'git status' 라고 명령을 입력해야 확인 가능하다.


이게 은근 귀찮다.

그래서 shell prompt에서 git directory로 진입을 하면 branch명을 표시하고, 해당 branch명을 다시 status에 따라 녹색/빨간색으로 표시하도록 하고자 한다.



.bashrc 파일 수정


HOME directory의 '.bashrc' 파일에 몇가지 추가 및 수정을 하면 된다.
c_cyan=`tput setaf 6`
c_red=`tput setaf 1`
c_green=`tput setaf 2`
c_sgr0=`tput sgr0`

parse_git_branch ()
{
   if git rev-parse --git-dir >/dev/null 2>&1
   then
      gitver=$(git branch 2>/dev/null| sed -n '/^\*/s/^\* //p')
   else
      return 0
   fi
   echo -e $gitver
}

branch_color ()
{
   if git rev-parse --git-dir >/dev/null 2>&1
   then
      color=""
      if git diff --quiet 2>/dev/null >&2
      then
         color="${c_green}"
      else
         color=${c_red}
      fi
   else
      return 0
   fi
   echo -ne $color
}

.... 중략 ....

if [ "$color_prompt" = yes ]; then
    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
#    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\[${c_sgr0}\] (\[$(branch_color)\]$(parse_git_branch)\[${c_sgr0}\])\$ '
fi



붉게 표시한 부분이 실제 shell prompt에 git branch 이름과 색상을 결정하고 표시하는 부분이다.


branch_color( ), parse_git_branch( ) 는 새로 추가한 함수이다. 

c_cyan, c_red, c_green, c_sgr0 는 새로 추가한 변수이고, 색상을 결정한다.


작업하면서 헷갈릴 수 있는데, PS1가 shell prompt에 표시되는 내용을 결정한다.


\u : 사용자명 

\h : 호스트명

\W : 현재 디랙토리

\w : 현재 경로


이렇게 나타내게 된다. 이외에도 있을 것 같은데, 나는 더이상 필요없어서 알아보진 않았다. 각자 자신의 입맛에 맛게 수정하면 될 것 같다.

PS1에서 branch_color와 parse_git_branch함수를 호출하도록 하여, git 저장소를 사용하는 디렉토리이면 현재의 브랜치명을 표시하고, 수정내용이 있으면 빨간색으로 표시하며 그외에는 녹색으로 표시하도록 하는 내용 이다.


수정 한 뒤, 적용이 잘 되었는지 확인하려면, terminal을 닫은 후 다시 실행 하던가, 아래 커맨드로 .bashrc의 변경된 내용을 현재 terminal에 적용하면 된다.


source ~/.bashrc


적용된 모습

적용 되면 아래와 같이 동작한다.



아무런 수정사항이 없는 경우, 녹색으로 branch 이름이 표시된다.



뭔가 diff가 있는 경우, 빨간색으로 branch 이름이 표시된다.





이 댓글을 비밀 댓글로
    • 나그네
    • 2018.03.18 00:49
    긋입니다.. 잘적용됩니다.
    • dd
    • 2020.12.31 14:40
    에러 개많네

[우분투 16.04] 부팅시 프로그램을 자동으로 시작하도록 설정하는 방법 (How to add auto startup applications in Ubuntu 16.04)

by Blogger 하얀쿠아
2017. 11. 12. 02:09 소프트웨어 Note/Linux

프로그램 자동실행 이유

우분투 16.04 이 설치된 PC를 켤때 synergy client를 자동으로 실행되도록 하고 싶다.

지금은 우분투 PC가 켜지면, shell prompt를 띄우고, 명령어를 직접 입력해서 synergy client를 실행시켜 synergy server PC에 연결되도록 수동으로 사용하고 있다.


이 과정이 번거롭기 때문에, 자동화 하고자 한다.


참고로 synergy는 서로다른 2대 이상의 PC를 연결시켜서, 한쌍의 키보드와 마우스를 이용해 연결된 PC 모두를 제어하도록 도와주는 프로그램이다.

본 포스팅에서 설명하고자 하는 것은, 우분투 16.04 PC가 synergy client가 되고, 그외의 PC (윈도우 혹은 Mac 혹은 또다른 우분투)가 synergy server가 되는 상황이다.


auto startup 설정 방법

STEP 1: 프로그램을 실행시키기 위한 커맨드라인 명령어 찾기

우선, 시작 목록에 프로그램을 추가하기 위해서는, 해당 프로그램이 시작되는 명령어를 알아야 한다.


synergy의 경우, synergyc 가 client이다.

--help 옵션을 통해 지원하는 옵션들을 살펴보자.


jeon@Jeon-PC:~$ synergyc --help
Usage: synergyc [--yscroll ] [--display ] [--no-xinitthreads] [--daemon|--no-daemon] [--name ] [--restart|--no-restart] [--debug ] 

Connect to a synergy mouse/keyboard sharing server.

  -d, --debug       filter out log messages with priority below level.
                             level may be: FATAL, ERROR, WARNING, NOTE, INFO,
                             DEBUG, DEBUG1, DEBUG2.
  -n, --name  use screen-name instead the hostname to identify
                             this screen in the configuration.
  -1, --no-restart         do not try to restart on failure.
*     --restart            restart the server automatically if it fails.
  -l  --log          write log messages to file.
      --no-tray            disable the system tray icon.
      --enable-drag-drop   enable file drag & drop.
      --enable-crypto      enable the crypto (ssl) plugin.
      --display   connect to the X server at 
      --no-xinitthreads    do not call XInitThreads()
  -f, --no-daemon          run in the foreground.
*     --daemon             run as a daemon.
      --yscroll     defines the vertical scrolling delta, which is
                             120 by default.
  -h, --help               display this help and exit.
      --version            display version information and exit.

* marks defaults.

The server address is of the form: [][:].  The hostname
must be the address or hostname of the server.  The port overrides the
default port, 24800.

synergyc: a server address or name is required
Try `synergyc --help' for more information.


살펴보니, daemon으로 실행하고, debug level로 DEBUG 정도 줘서 로그좀 남기도록 하면 될 것 같아 보인다.

최종적으로 아래 명령으로 자동 실행 시키기로 결정했다.


/usr/bin/synergyc --daemon --debug DEBUG --name Jeon-PC 192.168.1.121:24800

Jeon-PC 부분은 본인이 사용하려는 'screen name' 을 입력하면 된다.

192.168.1.121 부분은 본인이 연결하려는 synergy server의 IP address를 입력하면 된다.

24800 부분은 본인이 연결하려는 synergy server의 Port number를 입력하면된다.



STEP 2: 시작 프로그램 설정하기

step1 에서 결정한 시작시킬 명령어를 입력할 차례이다.


Dash 메뉴에서 'Startup Applications' 를 찾아서 실행한다. Dash 메뉴는 '윈도우 키' 를 누르거나, sidebar에서 우분투 아이콘 버튼을 누르면 나오는 검색 윈도우를 말한다.




실행된 이후, '추가(Add)' 버튼을 누른 뒤, '명령어(Command)' 부분에 위에서 결정했던 명령어를 복사/붙여넣는다.

이름(Name)과 설명(Commnet) 부분은 아무것이나 입력하고 싶은것을 넣을 수 있다.




모두 입력했으면, '저장(Save)'을 누른 뒤, 입력한 항목이 생겼는지 확인한다.




다음번 우분투 PC를 재시작하게되면, synergy client 프로그램이 자동으로 실행되어, 설정한 IP주소의 synergy server로 연결되는 것을 확인 할 수 있다.


명령어로 확인 방법

이렇게 우분투의 GUI로 추가한 자동 시작 프로그램은 shell terminal 상에서도 확인이 가능하다.


[HOME]/.config/autostart 아래에서 확인해 보면, 추가한 항목이 존재함을 알 수 있다.


jeon@Jeon-PC:~/.config/autostart$ cat synergyc.desktop 
[Desktop Entry]
Type=Application
Exec=\s/usr/bin/synergyc --daemon --debug DEBUG --name Jeon-PC 192.168.1.121:24800
Hidden=false
NoDisplay=false
X-GNOME-Autostart-enabled=true
Name[en_US]=Synergy
Name=Synergy
Comment[en_US]=Keyboard & Mouse Sharing
Comment=Keyboard & Mouse Sharing


이 댓글을 비밀 댓글로

[네트워크/C reference] inet_pton 함수

by Blogger 하얀쿠아
2017. 11. 12. 01:07 소프트웨어 Note/C

기능 요약 (Summary)

inet_pton( ) 함수는 사람이 알아보기 쉬운 텍스트(human-readable text)형태의 IPv4 와 IPv6 주소를 binary 형태로 변환 하는 기능을 한다.



헤더 (Header files)

이 함수를 사용하려면 다음 헤더파일을 포함시킨다.


#include <arpa/inet.h>


API 원형 (API Prototype)

3개의 파라미터를 가지는 함수이다.

int inet_pton(int af, const char *src, void *dst);

af [input] -  address family를 지정한다. src의 문자열이 IPv4 주소를 나타내는지, IPv6 주소를 나타내는지를 함수에 알린다.

src [input] - 문자열 형태의 IP주소를 넣는다.

dst : [output] - src를 binary형태로 변환 후 복사된 메모리의 포인터이다.


설명 (Description)

이 함수는 af의 address family가 가리키는 네트워크 주소 구조체에 src의 문자열 값을 변환 한 후, 이 네트워크 주소 구조체를 dst에 복사한다.

af는 반드시 AF_INET 혹은 AF_INET6 둘 중 하나여야 한다.

dst는 network byte order로 작성된다.


언급했듯이 현재는 IPv4 및 IPv6를 의미하는 아래 2개의 address family들만 지원된다.


AF_INET

src이 가리키는 문자열은 IPv4 네트워크 주소이고, 점으로 자리를 구분하는 10진수 주소 형태이다.

"ddd.ddd.ddd.ddd" 와 같은 형태이고, ddd 자리에 0~255 범위의 10진수가 온다.

그 주소는 in_addr 구조체로 변환 된 후, 4byte크기를 가지는 dst로 복사된다. 

참고로 in_addr 구조체는 크기가 4byte 이다.



AF_INET6

src이 가리키는 문자열은 IPv6 네트워크 주소이다.

그 주소는 in6_addr 구조체로 변환된 후 16byte크기를 가지는 dst로 복사된다.

src에 넣을 수 있는 IPv6 주소 표현방식은 IPv4 주소 표현 방식에 비해 다양한데, 아래와 같은 규칙을 따른다.


IPv6 주소 표현 규칙

1. 우선시 되는 형태는 x:x:x:x:x:x:x:x 이다. 

각각의 x 는 16진수 문자이며 16bit 값을 표현하므로, 최대 4자리가 될 수 있다.

또한 x와 x 는 콜론으로 구분되며, 전체 8개로 구성된다.


2. 연속되는 0 값들은 :: 로 축약해서 표현하는 방법이 사용된다. 

단, 하나의 주소표현에서 :: 는 단 한번만 등장할 수 있다.

예를 들면, IPv6의 loopback 주소는 0:0:0:0:0:0:0:1 인데, 이걸 간단히 ::1 로 축약해서 표현 할 수 있다.

또한, wildcard 주소인 모든 값이 0으로 구성된 주소는, :: 라고 쓸 수 있다.


3. 대체 유형은  IPv4-mapped IPv6주소를 표현하는데 유용하다. 이 형태는 x:x:x:x:x:x:d.d.d.d 와 같이 쓰인다.

처음 앞의 6개 x 들은 주소의 최상위 비트 6개를 정의한다. (96 bit)

그리고 나머지 d들은 최하위 32bit에 점으로 구분하는 10진수 표기법을 정의한다.

예를 들면 ::FFFF:204.152.189.116 이러한 주소다.



더 자세한 IPv6 주소 표현방법을 알고 싶다면, RFC 2373 을 참고하기 바란다.


반환값 (Return value)

inet_pton( )은 성공시 1을 반환한다.

즉, 1이 return되면 네트워크 주소가 성공적으로 변환되었음을 의미한다.


0 이 반환되는 경우는 src의 문자열이 나타내는 네트워크 주소가, af에 명시된 address family의 유효한 값이 아닌 경우이다.

-1 이 반환되는 경우는 af가 적절한 address family값이 아닌 경우이다. 이때는 errno이 EAFNOSUPPORT 값으로 설정된다.


준수사항

POSIX.1-2001, POSIX.1-2008.  



알아둘 내용

inet_aton( ) 및 inet_addr( )와는 달리, inet_pton( )은 IPv6주소를 지원한다. 


반면에, inet_pton( )은 점 3개와 10진수 표현법의 (dotted-decimal notation) IPv4주소만 받아들인다. 

inet_aton( )및 inet_addr( )은 좀더 일반적인 표현법인 'numbers-and-dots notation' 에 대해서도 받아들인다.


'numbers-and-dots notation'는 이와 같다.

hexadecimal and octal number formats, and formats that don't require all four bytes to be explicitly written.  


알려진 버그

AF_INET6은 IPv4주소를 인식하지 못한다. 

대신에 명시적으로 IPv4-mapped IPv6 주소가 반드시 src에 넣어져야 한다.


같이 볼 함수들

getnameinfo( )

getaddrinfo( )

inet_ntop( )


이 댓글을 비밀 댓글로

[네트워크/C reference] inet_ntop 함수

by Blogger 하얀쿠아
2017. 11. 2. 02:16 소프트웨어 Note/C

기능 요약 (Summary)

inet_ntop - IPv4 와 IPv6 주소를 binary 형태에서 사람이 알아보기 쉬운 텍스트(human-readable text)형태로 전환해준다.



헤더 (Header files)

  #include <arpa/inet.h>


API 원형 (API Prototype)

const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);



설명 (Description)

이 함수는 네트워크 주소 구조체인 src를 캐릭터 문자열 dst로 변환해주는 함수이다. 네트워크 주소는 IPv4 혹은 IPv6 가 될 수 있으며, 'address family'를 의미하는 af 를 참고하여 src를 해석하게 된다. 결과가 저장되는 dst는 반드시 NULL 포인터가 아니어야 한다. 즉, 메모리 공간이 할당된 포인터 이어야 한다는 뜻.


이 API를 호출하는 쪽에서는 dst 버퍼의 크기를 size 를 통해 지정한다.


inet_ntop( )는 다양한 address family를 지원하기 위해 inet_ntoa( ) 함수를 확장한다.

그래서 inet_ntoa( )는 현재 deprecated 되도록 고려되고 있다.


af 는 현재 아래의 address family들을 사용 할 수 있도록 지원된다.


AF_INET

src 는 struct in_addr (network byte order임) 구조체를 가리킨다. 

이것은 IPv4 네트워크 주소로 변환 될 것이고, 'dotted-decimal format' 이라고 불리는 형태의 주소, 즉, "ddd.ddd.ddd.ddd" 과 같은 형태가 될 것이다.

버퍼 dst 는 반드시 메모리가 할당되어야 하며, 그 크기는 최소한 INET_ADDRSTRLEN 크기만큼의 바이트 수는 되어야 한다.


AF_INET6

src 는 struct in6_addr (network byte order임) 구조체를 가리킨다.

이것은 IPv6 네트워크 주소로 변환될 것이다. 변환된 문자열의 형태는 해당 IPv6 주소를 나타내기에 가장 적절한 형태가 될 것이다. 

즉, 생략가능한 부분은 연속으로 콜론 2개를 찍은 형태의 단축형 결과를 얻게 된다는 것이다. 

버퍼 dst 는 반드시 메모리가 할당되어야 하며, 그 크기는 최소한 INET6_ADDRSTRLEN 크기만큼의 바이트 수는 되어야 한다.



반환값 (Return value)

성공하면, inet_ntop( ) 는 dst 를 가리키는 포인터를 반환한다.

만약 에러가 있었다면, NULL이 반환되고, errno 에 에러와 관련된 값이 설정된다.




오류 값 (Errors)

EAFNOSUPPORT

af 가 유효한 address family가 아님.


ENOSPC 

변환된 주소 문자열이 size에 의해 주어진 크기를 초과하게 됨.



준수사항

POSIX.1-2001, POSIX.1-2008.  

RFC 2553 에서는 이 함수 원형의 마지막 인자인 size를 size_t로 정의하고 있음을 알아둘 것.

많은 시스템이 RFC2553를 따른다. Glibc 2.0와 2.1 버전은 size_t 이지만, 2.2 및 이후 버전은 socklen_t 이다.



같이 볼 함수들

getnameinfo( )

getaddrinfo( )

inet_pton( )



이 댓글을 비밀 댓글로

TCP Flags: PSH 그리고 URG

by Blogger 하얀쿠아
2017. 9. 29. 00:34 소프트웨어 Note/Network Technology

개요

TCP헤더를 들여다 보면, 1비트 짜리 플래그가 몇개 있다. 1비트로는 0 아니면 1 만을 나타낼 수 있기 때문에, 플래그는 태생적으로 boolean type 이다.
이 플래그들은 TCP연결을 통하는 데이터의 흐름을 조절 및 제어 하기 위해 사용된다고 알려져 있다.

RFC 3168 에 의해 혼잡 통지(Congestion Notification)을 위해 추가된 CWR 그리고 ECE 플래그를 제외하고나면, 총 6개의 TCP 제어 플래그가 남는다.
일단 CWR과 ECE는 논외로 하자.

TCP 기본 헤더 포맷


Data Offset 다음을 보면, 6개의 플래그, URG, ACK, PSH, RST, SYN, FIN 이 보인다.

그 중, 아래 4개는 TCP연결의 설정(establish), 유지 관리(management) 및 분리(tear-down)를 제어하는 용도이다. 아마  패킷 분석좀 해본 경험이 있다면 이미 익숙 한 플래그 일 것이다.


  • SYN - 연결을 시작한다
  • ACK - 수신 된 데이터를 확인한다
  • FIN - 연결을 닫는다
  • RST - 오류에 대한 응답으로 연결을 중단한다


나머지 두개의 플래그 PSH (Push)와 URG (Urgent)가 있는데, 이 둘의 역할이 종종 헷갈린다.

눈치 챘는가? 이 두개 플래그의 역할, 그것이 바로 오늘 쓸 포스팅의 주제다.



PSH 플래그

PSH 플래그의 기능을 이해하려면 우선 TCP가 데이터를 버퍼링하는 방법을 이해해야 한다. 


기본적인 이야기 부터 해보자. TCP는 OSI Layer 4에서 동작한다. 그것은 패킷 기반 통신의 복잡성을 감추고, 들어온 데이터를 읽어내거나, 혹은, 내보낼 데이터를 쓸 수 있는 간단한 소켓 인터페이스를 상위 Layer에 제공한다. 그리고 TCP는 응용 프로그램(OSI Layer 7)이 언제든지 이 소켓으로부터 읽거나 쓸 수 있도록 버퍼를 제공한다. 버퍼는 TCP 연결 양쪽(송신자와 수신자)의 들어오고 나가는 양쪽 방향 모두에서 구현된다. 말이 헷갈린다면 간단히 생각하자. 송신자의 TCP도 read buffer, write buffer 를 가지고, 수신자의 TCP도 read buffer, write buffer를 가진다.


아래 다이어그램은 송신 전에 송신자가 데이터를 버퍼링하는 방법과 수신자가 수신 시 데이터를 버퍼링하는 방법을 보여준다.





MSS (Maximum Segment Size)를 초과하는 데이터 보낼때를 상상해 보라. 예를 들면 큰 파일 전송 같은 것 말이다. 버퍼는 이런 큰 데이터를 보다 효율적으로 전송할 수 있게 해주는 역할을 한다. 그러나 데이터를 가능한 한 빨리 전송해야 하는 실시간 응용 프로그램을 처리 할 때는 큰 버퍼가 좋지 않다. 예를 들어 TCP가 패킷을 보내기 전에 패킷의 버퍼를 데이터가 가득 채울때까지 기다리다가 전송한다면.. 텔넷 세션에 어떤 일이 발생하는지 생각해보라. 첫 번째 패킷이 원격 장치로 전송되게 하려면 그 전에 먼저 문자 타이핑을 1000자 넘게 해야할 것이다. 이럴땐 별로 유용해 보이지 않는다. 


만약 텔넷의 예가 어렵다면, 카카오톡이나 채팅 프로그램 같은걸 상상해 보면 된다. 짧은 메세지 몇글자 보내려 하는데, TCP버퍼가 가득 찰때까지 기다렸다가 전달된다면? 답답할 것이다.


바로 이것이 PSH 플래그가 필요한 경우다.

응용프로그램(Application Layer) 에서는 소켓에  "Push"하는 옵션을 사용하여 데이터를 쓸 수있다. 이 옵션은  추가 데이터가 버퍼에 들어갈 때까지 기다리지 않고 즉시 데이터를 내보낸다. 이 경우 송신 TCP 패킷의 PSH 플래그가 1로 설정된다. 연결의 반대편인 '수신측' 종단에서는 PSH 플래그가 설정된 패킷을 수신하면 TCP세그먼트를 응용프로그램에 즉시 전달하도록 동작한다. PSH 플래그가 없다면 수신측에서도 버퍼에 일정량의 데이터가 모일때까지 기다렸다가 응용프로그램에 전달할 것이다.


설명이 어렵고 이해가 안된다면 아래 요약만 일단 기억하자

TCP의 push 기능은 다음 두 가지를 수행한다.

  • 송신측에서의 PSH 기능: 호스트의 응용프로그램(Application Layer)은 '이 데이터는 버퍼에 쌓지 말고 즉시 보내라' 고 TCP Layer에 알리는 역할을 한다.
  • 수신측에서의 PSH 기능: '이 데이터는 버퍼에 쌓지 말고 즉시 응용프로그램(Application Layer) 에 올려야 되겠군' 하고 수신측 호스트의 TCP Layer가 인식하게 하는 역할을 한다.


아래 패킷 캡쳐 예를 보자.

패킷 #36은 HTTP GET 요청인데, PSH 플래그를 사용하는 예를 볼 수 있다. 이 HTTP 요청에는 PSH 플래그가 설정되어 클라이언트에 추가 할 데이터가 더 이상 없고 요청이 애플리케이션 (이 경우 웹서버 데몬)에 즉시 전송되어야 함을 나타낸다. 다시 말하면, PSH 플래그는 송신기가 더 이상 송신 할 데이터가 없다는 것을 수신기에 알리기 위해 사용된다 (현재로서는).



HTTP.cap





앞서 언급 했듯이, PSH 플래그는 TCP를 통한 실시간 통신을 용이하게하기 위해 사용된다. 관심이 있다면 한가지 실험을 해보면 좋을것 같다. 텔넷의 패킷을 캡쳐해서 wireshark로 살펴보길 바란다. 텔넷 세션의 패킷 캡처는 텔넷 데이터를 전송하는 모든 패킷이 키 누름이 TCP에 의해 버퍼링되는 것을 방지하기 위해 PSH 플래그를 1로 설정되어 있음을 보여줄 것이다.



URG 플래그

URG 플래그는 이름 그대로 긴급(Urgent) 하다는 의미를 표시한다. 이 플래그는 수신측에게 '네가 현재 받은 TCP 세그먼트에 포함된 데이터는 긴급한 데이터야. 우선 처리되도록 우선순위를 높게 주길 바래' 쯤의 의미를 알리는 역할이다. 이때, 수신측 호스트의 TCP stack은 TCP 헤더의 16비트 필드인 'Urgent Pointer'를 측정하게 된다. Urgent Pointer는 '긴급한 정도'를 나타낸다. 얼마나 긴급한지 말이다.





URG 플래그는 현대의 프로토콜에서는 많이 사용되지 않는다. 왜냐하면 이 플래그의 사용이 더이상 추천되지 않기(RFC 6093) 때문이다. 아주 휘귀하다. 그러나 운 좋게도 이전에 언급 했던 텔넷의 패킷 캡처에서 URG 플래그의 예를 볼 수 있다. 


cm4116_telnet.cap





수신측 입장에서 패킷 #86에서 전송 된 0xFF 문자는 패킷 #70 의 텔넷 명령 0xF2 (242)보다 앞서서 전달된다. RFC 854[각주:1]에 따라, 이 명령은 TCP URG 플래그가 설정된 상태로 보내야한다. 패킷 #86의 긴급 포인터는 세그먼트의 첫 번째 바이트 (이 경우 전체 세그먼트)가 긴급 데이터로 간주되어야 함을 나타낸다.


이것은 URG 플래그의 가장 훌륭한 예는 아니겠지만, 현실에서의 여러 캡처를 아무리 살펴봐도 실제 사용되는 다른 예를 거의 찾아볼 수가 없었다.


TCP의 PSH 및 URG 기능에 대한 더욱 자세한 내용은 온라인 TCP/IP 가이드를 참조하길 바란다.


  1. RFC 854는 TELNET PROTOCOL SPECIFICATION 에 대한 내용이다. 다음 주소에서 확인할 수 있다. https://tools.ietf.org/html/rfc854 [본문으로]

'소프트웨어 Note > Network Technology' 카테고리의 다른 글

TCP Flags: PSH 그리고 URG  (1) 2017.09.29
무선 LAN, Wi-Fi 이야기  (0) 2017.02.08
이 댓글을 비밀 댓글로
    • 우주고래
    • 2019.12.18 17:39
    안녕하세요. 정리가 정말 잘 되어있어서 URL 공유 할게요. 감사합니다!