달려라 강기사

이건 일반적으로 얘기하는 SMS 보내기와는 좀 다릅니다. 일반적으로는 SMS를 중간 업체를 통해 또는 직접 이동통신사에 컨택하여 API나 기타 접근 인터페이스를 제공받아서 처리하고 있지요. 대량으로 보내는 경우라면 이게 맞습니다. 하지만 회사 내부에서만 쓸 때 예를 들어 관리 목적으로 잠시 잠시 사용하는 경우라면 대략 난감이죠. 배보다 배꼽이 더 크니까요. 그런 경우 이런 방법을 사용하면 유용하게 사용할 수 있습니다.

일단 코드부터....

 위 코드는 proof of concept 용으로 아주 간단하게 짠거라 실제 쓰시기에는 코드를 약간 수정해야 합니다. 하지만 어떻게 하는 건지 정도는 아실 수 있으리라 생각합니다. 제가 해보니 잘 되더군요. 눈치빠른 분은 이미 아시겠지만, 이건 휴대폰을 모뎀처럼 인식한 후에 특정 모뎀 명령을 보내어 처리하는 방법입니다. 예전 모뎀 세대들은 AT 라는 명령어보자마자 눈치 채셨을 겁니다.

문제는 휴대폰 연결방법인데 요새는 USB 연결 방법은 다 아실테니 이건 스킵하고 CreateFile 에 여는 COM 포트가 무엇인가 문제입니다. 이건 아래 그림처럼 확인하시면 됩니다.

사용자 삽입 이미지

제 휴대폰을 제 노트북에 연결했을 경우인데 젤 위에 보면 COM5 라고 보시시죠? LGE CDMA USB 라고도 보이시고요 저겁니다. 이렇게 하면 테스트해보실 수 있을 겁니다. 아 참 안되는 모델도 있다고 하더군요. 이런 경우는 ㅎㅎㅎ 대략 좌절이겠군요. 그리고 너무 많이 테스트는 하지 마세요. 문자 요금 그대로 나갑니다. 휴대폰으로 안했다 뿐이지 문자로 나간다는 건 똑같으니까요. ^^

아 프로그램도 하나 만들어볼까 했는데, 생각 외로 쓸 일이 많이 없어 아직은 안 만들었습니다. 쓸 일이 자주 생긴다면 Ruby로 하나 만들어볼 작정입니다 ^^:

ps. 안되면 얘기해주세요. 제 컴에서는 되었습니다만...안되면 대략 좌절이지만요.^^
Posted by 강기사

아래 그램을 보면 정말 웃음이 나온다. 어찌 저리 핵심을 간결하게 표현했나 싶다.

결국 하나의 목표에 대하여 서로 잘못이해하여 삽질을 하게 된다는거다.

역시나.. 커뮤니케이션의 중요성을 잘 나타내 주고 있는 한가지 예라 볼 수 있겠군.

 
사용자 삽입 이미지
 
Posted by 강기사

Reentrant

Software 2007/06/13 14:37

Introduction

  • pthread 를 이용한다면 한번쯤 Reentrant function 에 대하여 들어보았을 것이다. 간단하게 Reentrant 에 대해서 적어본다.

Detailed Description

  • reentrant function이 중요하게 되는 경우는 signal handler에서 사용가능하느냐와 multi-thread 환경에서 입니다. 어떤 function이 전역변수를 사용하거나 static 변수를 사용한다고 할때, 한 process가 이 function에 진입하여 실행중에 signal이 발생하고 signal handler에서 다시 이 function에 진입한다면 예기치 않은 결과를 얻을 수 있습니다. 마찬가지로 동일 process의 서로다른 thread가 같은 function에 진입하는 경우도 문제가 될 수 있습니다. 그래서 reentrant function은 (1)전역변수 사용안함 (2)static 변수 사용안함 (3)stack 변수만 사용 으로 보장됩니다. 조금 다른 개념으로 thread-safe function이라는 개념도 있는데, 이는 reentrant function이거나 그렇지 않은 경우라면 mutex등을 사용하여 전역변수에 대한 동시접근을 막아서 multi-thread 환경에서 안전함을 보장합니다. thread-safe function이지만 reentrant function이 아닌 경우라면 signal handler에서의 사용은 금지됩니다.

int no_reentrant_counter( int increment) 
{ 
    static my_counter=0; 
    my_counter= mycounter + increment; 
    return my_counter; 
} 

int reentrant_counter(int current, int increment) 
{ 
    return current; 
} 

함수 내부 변수를 스태틱으로 사용하면 (또는 외부에 전역변수로 사용하면) 사실 편리할 때가 많습니다. 
하지만 여러 함수에서 동시에 부르는 (스케줄링에 따라 말이죠) 상황이면 결과가 틀릴 수가 있습니다. 

예를 들면 쓰레드 프로그램에서 no_reentrant_counter(1)을 두부분이 사용한다 치면 
한부분에서 호출하고 우연히 함수콜 한 다음에 블럭 되어버려서 
다른 부분에서 호출하는 부분으로 넘어갈 수도 있습니다. 
그당시 my_counter가 10이었다면 
(1)번 (2)번이 부른다 치면 
* (1) -> no_reentrant 호출 
* my_counter= mycounter + 1; 수행도중 
>> mycounter+1=11로 계산했고 막 mycounter에 11을 넣으려다 블럭됨
 (한줄에 썼지만 몇단계로 나뉘어 실행되죠. 값 읽어오고, 계산하고, 결과 저장하고) 
@ (2) -> no_reentrant 호출하였음 
@ 아직 my_counter를 11로 못 바꾼 상태이므로 10이었던 것으로 계산해서 
@ my_counter= 10+1; ===>11 
@ my_counter <=11 후 리턴 
* (1)로 다시 돌아가서 
* 아까 하던 일 마저하기 (my_counter에 11 넣기) 
결국 최종값은 11이 되죠. 두번 호출했으니 12가 되어야 하는데 말이죠. 
그래서 쓰레드 돌리며 값을 바꾸는 것과 같이 동기화가 필요한 데에서는 
reentrant함수를 사용해야 합니다. 

ps. 사실 예로 든게 아주 적절하진 않습니다. reentrant_counter도 저렇게는 
써봤자 mutex나 semaphore를 써야 되지만.. 어쨌든 reentrant하지 않으면 
결과 값이 이상해 지는 경우도 있구나 하고 생각하시면 됩니다. 
꼭 reentrant 해야 하는 함수로 printf가 있죠. 여러 곳에서 동시에 
호출하는 데 내부 스태틱 변수 같은 것을 쓴다 치면.. 대란이 일어나겠죠.
  • thread-safe function 은 말 그대로 multi-thread환경에서 여러 thread가 동시에 동일 함수에 진입했을 때 안전한 function 입니다. 저번에도 말씀드렸듯이 thread-safe function은 reentrant function 이거나, reentrant function이 아니라면 mutex 등으로 전역변수에의 동시 접근을 막아서 여러 thread가 동일 함수에 동시에 진입했을때 안전함을 보장하는 function 입니다. reentrant function은 내부적으로도 동기화를 위한 locking처리 자체를 하지 않습니다. 동기화 할 필요가 없도록 function을 설계하는 것이지요. 하지만 어쩔수 없이 전역변수를 사용해야 하는 function이 있을 수 있겠지요? 이런 function이라면 여러 thread가 동시에 접근하는 경우에 대비해 전역변수를 사용하는 code 부분을 mutex 등으로 막아서 여러 thread가 동시에 function에 진입할 수는 있으나 동시에 전역변수에 접근하지는 못하도록 합니다. 이런 경우 동일 process/thread context에서 signal이 발생하여 signalhandler에서 이 함수에 다시 진입한다면 dead lock 이 발생할 수 있습니다. 그렇기 때문에 reentrant 하지 않은 thread-safe function은 signal handler에서 사용하지 않습니다. 결국 어떤 function이 reentrant function 이라면 당연히 thread-safe function입니다. 하지만 모든 thread-safe function이 reentrant function 인 것은 아닙니다.
  • 부언하여 -D_REENTRANT 를 제가 아는 한도에서 설명드리자면, 선언이 되면, 대개의 구현에서.. include 할 때, _r 계열 함수의 선언을 열어 주는(?) 것과 기존 함수 혹은 변수를 reentrant 계열로 재정의해주게 됩니다. 즉, 함수가 두 벌이 존재하고, -D_REENTRANT 에 따라 link 되는 것이 달라지게 됩니다. 그리고, 대개의 구현에서 내부에 static 값이 있는 경우에 대해 pthread_key_create 시리즈 함수를 사용하여 thread 만의 데이터를 핸들링하도록 합니다.
  • 그렇다면 -D_REENTRANT 을 선언해 주어야 하는 것일까? 혹자는 쓰레드 라이브러리를 사용하게 되면 -D_REENTRANT 가 자동 선언된다고 하는데 아닌 것 같기도 하고..???

Reference

Posted by 강기사

int형과 float형은 둘 다 4바이트로 자료형의 크기가 같은데 실제로 표현될 수 있는 값은 왜 그렇게 큰 차이가 나는 것일까?

int, float 자료형의 bit구조를 알기전까지는 위와 같은 의문을 가진바가 있었다.

그 의문은 컴퓨터구조라는 과목을 배우면서 해결되었다.

더불어, 부동소수점 형이 의외로 신뢰할 수 없는 결과를 나을 수 있다는 것도..


int 형     -2,147,483,648  ~  2,147,483,647     ( 2-31 ~ 231-1 )

float형   3.4E-38 ~ 3.4E+38                   ( 3.4*10-38 ~ 3.4*1038 )


int형이 42억 남짓한 수를 표현할 수 있는 반면,

float형은 무려 0 이 38개나 붙는 어마어마한 수를 표현할 수 있다.

     ( 조 단위까지 가더라도 0 은 고작 12개일 뿐이다. )


위에서도 언급했다시피 똑같은 4바이트(32비트)로 표현가능한 수의 범위가 차이나는 이유는 무엇일까?

그 이유는 두 자료형을 구성하는 비트 구조가 다른데서 기인한다.


int형은 구조가 단순하다.

4바이트를 비트형태로 보면 아래와 같다.


 31  30 29 28 27 .......                                                     .........2  1  0 bit

1

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1


int형의 범위는 아래와 같이 구해진다.


    (1*231) + (1*230) + (1*229) + ...... + (1*21) + (1*20)


이와 같이 이진수 <-> 십진수 변환법과 똑기에 2-31 ~ 231-1 까지 표현가능하다.


하지만 float형은 다르다.


 31 30 29 28 .. 25 24 23  22 21 20 ......                                   .........2  1  0 bit

1

1 1 1 1 1 1 1 1 

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

부호   지수비트(8bit)                           유효자리비트(23bit)

비트


float 형의 범위는 아래와 같이 구해진다.


    (-1)부호비트 * (1 + 유효자리) * 2(지수-127)


부호비트 - 부호를 결정하는 비트

유효자리 - 소수점 이하의 수를 표현

지 수     - 2n 에서 n을 표현


부호비트(1bit) + 지수(8bit) + 유효자리(23bit)로 구성되어 있고, 이와같이 숫자를 표현하는 비트구조 자체가 서로 차이를 보임으로 인해 int형과 float형은 4byte 의 크기를 지니더라도 실제 표현가능한 값에는 상당한 차이가 있음을 알았다.

부동소수점에 대해 조금 더 알아보자.

더 큰 수를 표현할 수 있다고 해서 float형이 더 좋은 것일까?   그것은 아니다.

분명히 단점도 존재한다. 그것은 이전 글에서 언급한 정밀도의 한계를 가진다는 것이다.

int형은 있는 그대로의 비트를 보여주면 되기 때문에 100%의 정확도를 가지며, 그에 비해 float형은 아주 큰 수를 표현할 수 있지만 그 수가 유효자리비트로 표현할 수 있는 한계를 넘어가버리게 되면 근사치를 취하게 된다. 실제로 값을 짤라먹는다는 말이다.

컴퓨터의 계산은 100% 믿을 수 있어야 하는데 이처럼 그 값을 제대로 표현하지 못하게 되면 어찌 될까.

아주 큰 수에서 이러한 경우가 발생하기 때문에 보통은 신경 쓰지 않아도 되지만 그것조차 고려를 해야한다면

해결 방법으로는 double 형을 쓰는 것이 있다.


double         1.7E-308 ~ 1.7E+308         ( 1.7*10-308 ~ 1.7*10308 )

long double    3.4E-4932 ~ 3.4E+4932         ( 3.4*10-4932 ~ 1.7*104932 )


 31  30 29 28 .......       22 21 20   19 18 17 ....                        ......   2  1  0 bit

1

1 1 1 1 1 1 1 1 1 1 1

 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

부호   지수비트(11bit)                           유효자리비트(20bit)

비트


1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

                           유효자리비트(30bit)


double형은 8바이트(64비트)로 표현하기 때문에 float보다 훨씬 크며, 유효자리비트 또한 커서 정밀도 역시 높아지게 된다. 그렇다면 많은 비트를 할당해서 더 큰 수와 더 정확한 정밀도를 제공한다고 해서 float형에서 발생했던 오류가 사라지는 것인가?


아니다.  여전히 존재한다.  단지, 그러한 경우가 발생할 확률이 줄어들도록 더욱 더 많은 비트를 할당 할 뿐...


다만, 이러한 경우가 발생할 것을 예측하여, 프로그래머가 예방하는 길만이 최선의 방법일 것이다.

알아두자. 아주 크거나 아주 작은 부동소수점 수는 무조건 믿으면 안된다는 것을...

지금까지 언급한 내용은 IEEE745 표준에서 나온 것으로 부동소수점 연산을 하는 기계에서 다루어지는 부분이다.

 float, double, long double 의 값들은 특정한 기계에 대한 것이며 기계에 따라 다를 수 있다. < C++을 이용한 프로그래밍, 사이텍미디어 >

Posted by 강기사
식사나 쇼핑 등 일상적인 것에서부터 진학ㆍ취직ㆍ연애ㆍ결혼ㆍ전직ㆍ유학 등 중대한 결정을 내려야 할 때 오래 망설이는 사람은 주위 사람을 피곤하게 하고 일에 지장을 초래한다.
 이런 사람은 자신의 우유부단한 성격에 저항감을 느끼면서도 선뜻 결정을 못 내린다. 심리학에서는 이런 상태를 '갈등 상태'라고 한다.
 갈등 상태에는 두 회사에 합격하고도 어느 회사에 가야 할지 결정을 내리지 못하는 것처럼, 두 가지 좋은 일 가운데 어느 것을 선택해야 할지 몰라 망설이는 '(+)(+) 갈등', 일도 싫지만 백수로 지내는 것도 싫은, 두 가지 좋지 못한 일 가운데 어느 것도 선택하기 싫은 '(-)(-) 갈등'이 있다. 또 월급은 많긴 하지만 일의 내용이 마음에 안 드는 것처럼, 한 가지 일에 득과 실이 있어 선택의 기로에 서는 '(+)(-) 갈등'도 있다. 이러한 갈등으로 욕구불만 상태에 빠지게 되면 자기뿐만 아니라 주위 사람에게도 괴로움을 끼친다.
 어떤 사람은 실패에 대한 막연한 두려움 때문에 결단을 재촉받아도 '어떻게 할까, 어떻게 하지.' 하면서 미루기만 한다. 일이 저절로 풀려나가기를 바라면서 우물쭈물 시간을 끌기도 한다.
 그러면 왜 이런 타입은 결단을 못 내리는가? 자신감이 부족하여 실패를 두려워하기 때문이다. 마음 한구석에 '그냥 둬도 일이 저절로 풀리겠지' 하는 생각과, '다른 사람의 결정에 따르면 나에게는 책임이 없는 것 아냐.' 하는 생각으로 결단을 미루는 것이다.
 이런 타입의 심층 심리에는 자신의 무능력을 다른 사람에게 드러내고 싶지 않다는 생각으로 꽉 차 있다. 또 결단을 잘못 내리면 다른 사람의 노여움을 사서 책망받을지도 모른다는 공포심으로 가득 차 있다.
 또 이런 타입의 기분에는 아직도 유아성(幼兒性)이 그대로 남아 있다. 이런 사람은 갖고 싶은 것을 모두 사주고, 하고 싶은 것을 모두 허용한 부모의 방임적 양육 태도로 인하여 결단의 훈련을 겪을 기회가 없었다. 우리는 살아가는 동안 버려야 할 때는 버려야 하고 포기해야 할 때는 포기할 수 있는 결단이 요구된다. 그런 점에서 양자택일이 결단 가운데 가장 어려운 결정이 된다. '예스냐, 노냐?' '이쪽으로 가야 하나, 저쪽으로 가야 하나?'가 가장 선택하기 어려운 결정이다. 'OX' 문제를 틀리고 가장 아쉬워하는 이유가 바로 여기에 있다.

- 인간관계 명품의 법칙 中 -

Posted by 강기사