그럴 때는 $(info xxx) 을 사용하면 된다.
예를 들어,
mk 파일에
TEST_VALUE="Branden"
이 있다면, 이 TEST_VALUE 값을 찍으려면 mk 파일에 다음과 같이 해주면 된다.
TEST_VALUE="Branden"
$(info $(TEST_VALUE))
이렇게 하면 Branden 이 찍히게 되는 것이다.
드디어 2012년 새해가 밝았다. 음력 설이 오늘이다. 난 이제 36살이 되었고, 아직 뭔가 이루어 놓은 것은 없다는 생각이 많이 든다.
물론 난 특정한 날에 별로 의미를 많이 두는 편이 아니라서, 이번 구정이라고 새로운 출발이다, 뭐다 하는 그런 것을 하지는 않겠지만, 왠지 이번 해에는 뭔가 내가 큰일을 해낼것 같은 느낌이 강하게 든다.
이 새벽에 음악을 들으며, 그리고 많은 생각을 하면서 조용하게 날이 밝기를 기다리는 이 느낌이 좋다.
2012년에는 정말 최선을 다해서 살 수 있도록 다시 나를 다잡아보자.
상철아 진지해져라. 그리고 진심을 다해라!
먼저 이 책을 읽고 느낀 것은, 이 책은 감동적이다 라는 것이다.
무엇이 감동인고 하니, 정치에 전혀 관심이 없었던 나에게도 와~ 정치판이 이렇구나 하는 생각을 들게 했다는 것이다.
사실 얼마전 우연찮게 SBS 에서하는 힐링캠프에 박근혜, 문재인이 나온 것을 본적이 있다. 그러면서 어 뭔가 현재의 정치판을 이해할 필요가 있다고 생각이 들어서 (그리고 누가 한번쯤 읽어봄으로써 요즘 정치판이 돌아가는 상황을 정리하는 것도 괜찮지 않냐는 권유(?) 에 의해서) 이 책을 선택하게 되었다.
일단 김어준이라는 사람에 대해서 굉장한 호기심이 생겼다. 어떻게 이런 것을 다 알고 있을까? 물론 많은 관심을 갖으면 가능하다고 할 수 있겠지만, 이렇게 용감하게 자신의 생각을 책으로 펴내기까지는 쉽지 않았으리나는 생각이 든다.
보수든 진보든 암튼 현세대를 살아가는 우리에게는 꼭 한번은 읽어봐야 할 책임에는 틀림없는 것 같다.
아~~주 오래전에 조금 읽다가 이상하게 눈에 정말로 안들어와서 그만둔 책을 다시 읽었다.
난 왜 이 책이 베스트셀러인지 잘 이해가 안된다.
물론 남녀의 연애감정을 아주 깊숙히 파고 들어서 책을 읽다가 보면, "아하 정말 그러네" 라고 탄식을 지르게 하기도 하지만, 이 책은 뭐랄까 나에게는 조금 무겁게 다가왔다.
그래서 책을 정말 무슨 의무감에 의해서 어쩔 수 없이 다 읽었다는 느낌을 벗어버릴 수 없었다.
암튼 나에게는 잘 안맞는 책이다. 물론 연애감정의 깊숙한 내면까지 숙고하기를 원하는 사람이라면 읽어도 좋을 책인 것만은 틀림없는 것 같다.

아오~ 요즘 이 노래에 완전 빠져버렸당 ㅠㅠ
노래가 넘 신나고... 어린애들의 풋풋한 사람이 느껴지기도... (16살에 이런 느낌이면 너무 이른가? ^^).
You know you love me
I know you care
Just shout whenever
And I'll be there
You want my love
You want my heart
And we would never ever
ever be apart
Are we an item
Girl quit playin'
We're just friends
What are you sayin'
Said there's another
look right in my eyes
My first love broke my heart
for the first time
And I was like
Baby baby baby
Baby baby baby
Baby baby baby
I thought you'd
always be mine mine
Baby baby baby
Baby baby baby
Baby baby baby
I thought you'd always be mine
Oh oh For you
I would have done whatever
And I just can't believe
we ain't together
And I got the play cool
couse I'm losin' you
I'll buy you anything
I'll buy you anytring
Cause I'm in pieces
Baby fix me
And just shake me till you
wake me from this bad dream
I'm goin down down down
And I just can't believe
my first love
won't be around And I'm like
Baby baby baby
Baby baby baby
Baby baby baby
I thought you'd
always be mine mine
Baby baby baby
Baby baby baby
Baby baby baby
I thought you'd
always be mine mine
I'm 16
And I thought that you'd be mine
I used to tweet you and text you
And call you and hit you on
Facebook all the time
what now you're gone
So far along
that I cant even find you
You know that feeling
When you leave your love
And it's right behind you
Can't believe that you
did me wrong
We were on iChat all night long
Listening to our favorite song
She was wrong
I am gone
I thought I loved her
Never put no one above her
Yeah she was my lover
But now onto another like
Baby baby baby
Baby baby baby
Baby baby baby
I thought you'd
always be mine mine
Baby baby baby
Baby baby baby
Baby baby baby
I though you'd
always be mine mine
Yeah yeah yeah
Yeah yeah yeah
Yeah yeah yeah
Yeah yeah yeah
Yeah yeah yeah
Now I'm all gone gone gone
I'm gone
안드로이드는 부팅을 하면서 init.rc 에서 mediaserver 를 실행합니다. 이 mediaserver 는 Main_mediaserver.cpp 이므로 이 파일을 보면 다음과 같은 부분이 있습니다.
AudioFlinger::instantiate();
즉 audioflinger 을 instance 화 하겠다고 하면서 여기서 audioflinger service 를 생성하고 있습니다. Gingerbread (GB 라 함) 이전 안드로이드는 AudioFlinger::instantiate() 이것이 AudioFlinger.cpp 에 선언이 되어 있지만, GB 이후부터는 BinderService 에서 template 으로 이 부분을 처리하고 있습니다.
좀 더 살펴보면, AudioFlinger.h 에 다음과 같은 부분이 있습니다.
#include <binder/BinderService.h>
class AudioFlinger:
public BinderService<AudioFlinger>,
public BnAudioFlinger
{
위에서 나와있는 코드와 같이 AudioFlinger 는 결국은 BinderService, BnAudioFlinger 를 상속받아서 사용되고 있는 것을 알 수 있습니다. 그리고 BinderService.h 에 가보면 우리가 찾고 있던 instantiate() 가 다음과 같이 정의되어 있습니다.
template<typename SERVICE>
class BinderService
{
public:
static status_t publish() {
sp<IServiceManager> sm(defaultServiceManager());
return sm->addService(String16(SERVICE::getServiceName()), new SERVICE());
}
static void publishAndJoinThreadPool() {
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SERVICE::getServiceName()), new SERVICE());
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
static void instantiate() { publish(); }
static status_t shutdown() {
return NO_ERROR;
}
};
즉 h 파일에서 함수 원형이 다 들어 있는 꼴로 되어 있습니다. 왜냐하면 BinderService 는 template 형식으로 사용되어서 이렇게 한 것 같습니다.
따라서 AudioFlinger::instantiate() 는 결국은 AudioFlinger 가 상속받은 BinderService 의 publish() 가 호출되는 것이 됩니다.
이 publish 함수를 보면,
static status_t publish() {
sp<IServiceManager> sm(defaultServiceManager());
return sm->addService(String16(SERVICE::getServiceName()), new SERVICE());
}
이렇게 되어 있는데, 현재 AudioFlinger 에서 호출된 것이라서 위 코드는 결국은 다음과 같이 호출된 것과 같은 것이 됩니다 (즉, SERVICE 부분이 AudioFlinger 로 되는 것입니다).
static status_t publish() {
sp<IServiceManager> sm(defaultServiceManager());
return sm->addService(String16(AudioFlinger::getServiceName()), new AudioFlinger());
}
위 코드가 중요한 것은 new AudioFlinger() 에서 AudioFlinger 의 instance 를 생성하고, addService 를 통해서 ServiceManager 에 AudioFlinger 를 등록시킴으로써 AudioFlinger 의 binder 가 등록이 된다는 것입니다.
참고로 위 내용은 AudioFlinger 에서 onFirstRef() 함수가 안불리는 문제 때문에 추척한 것인데 (이것은 binding 이 되면 자동으로 호출되도록 되어 있음), 이것을 추적하기 위해서는 new AudioFlinger() 에서 AudioFlinger 쪽 생성자를 계속 추적해서 들어가보면 IAudioFlinger 를 통해서 BnInterface<IAudioFlinger> 를 통한 후 BpInterface 의 상속자인 BpRefBase 가 되고 이것의 생성자인 Binder.cpp 에 있는 BpRefBase() 에서 mRemote->incStrong(this); 가 호출되어 이 incStrong() 안에서 const_cast<RefBase*>(this)->onFirstRef(); 로 AudioFlinger::onFirstRef() 가 호출되는 것입니다.
위에서 언급한 Binder 구조에 대해서는 제가 인터넷에서 찾은 문서를 같이 첨부로 보내드립니다. 참조하시면 저의 난해한 이야기를 좀 더 수월하게 이해하실 수 있을 것입니다. ^^;
혹 잘못된 내용이 있으면 바로 알려주시면 감사하겠습니다. 제 짧은 소견이 안드로이드 바다를 이해하는데 조금이라도 도움이 되길 바라며....
이상입니다.
첨부파일 : How_Android_IPC_system_works.pdf
최근 덧글