Implementing a New Manet Unicast Routing Protocol in NS2 Version 0.2 번역판-2

4.3.2 command()

코드의 다음 조각은 조금 더 복잡하다. 그것은 우리의 에이전트가 에이전트 클래스로부터 물려받는 command() 방법의 구현으로 구성된다.

protoname/protoname.cc

1: int

2: Protoname::command(int argc, const char*const* argv) {

3: if (argc == 2) {

4: if (strcasecmp(argv[1], “start”) == 0) {

5: pkt_timer_.resched(0.0);

6: return TCL_OK;

7: }

8: else if (strcasecmp(argv[1], “print_rtable”) == 0) {

9: if (logtarget_ != 0) {

10: sprintf(logtarget_->pt_->buffer(), “P %f _%d_ Routing Table”,

11: CURRENT_TIME,

12: ra_addr());

13: logtarget_->pt_->dump();

14: rtable_.print(logtarget_);

15: }

16: else {

17: fprintf(stdout, “%f _%d_ If you want to print this routing table ”

18: “you must create a trace file in your tcl script”,

19: CURRENT_TIME,

20: ra_addr());

21: }

22: return TCL_OK;

23: }

24: }

25: else if (argc == 3) {

26: // Obtains corresponding dmux to carry packets to upper layers

27: if (strcmp(argv[1], “port-dmux”) == 0) {

28: dmux_ = (PortClassifier*)TclObject::lookup(argv[2]);

29: if (dmux_ == 0) {

30: fprintf(stderr, “%s: %s lookup of %s failedn”,

31: __FILE__,

32: argv[1],

33: argv[2]);

34: return TCL_ERROR;

35: }

36: return TCL_OK;

37: }

38: // Obtains corresponding tracer

39: else if (strcmp(argv[1], “log-target”) == 0 ||

40: strcmp(argv[1], “tracetarget”) == 0) {

41: logtarget_ = (Trace*)TclObject::lookup(argv[2]);

42: if (logtarget_ == 0)

43: return TCL_ERROR;

44: return TCL_OK;

45: }

46: }

47: // Pass the command to the base class

48: return Agent::command(argc, argv);

49: }

argv[0]은 선포되는 방법 (항상 “cmd”, 3장 [2]를 보라)의 이름을 포함하고, argv[1]은 요청되는 동작이며, argv[2..argc-1]은 통과되었던 인수들의 나머지이다. 이런 함수 내에서 우리가 Tcl로부터 접근하기 쉽게 만들기를 원하는 임의의 다른 동작뿐만 아니라 몇 가지 의무적인 동작들을 코드해야 한다. 한 예로써 우리는 라우팅 표의 내용들을 트레이스 파일로 덤프하는 print_rtable로 불리는 동작을 코드할 것이다.

우리는 네가 그것들을 어떻게 처리하는 지 볼 수 있도록, 2개 또는 3개의 인수들을 가진 경우들에서만 우리의 코드의 초점을 맞춘다. 각각의 경우는 TCL_OK (만약 모든 것이 괜찮으면) 또는 TCL_ERROR (만약 임의의 에러가 발생되었다면) 둘 중의 하나를 되돌려주면서 그것의 실행을 끝내야 한다.

줄들 4-7은 우리가 항상 구현해야 하는 의무적인 명령어를 기술한다: start. 이런 명령어의 예상되는 행동은 그것의 실행을 시작하기 위한 에이전트를 구성하는 것이다. 우리의 경우에서 그것은 자신의 패킷 전송 타이머를 시작한다. 우리는 라우팅 에이전트가 자신의 동작을 시작하기 위해서 수행해야 하는 모든 요구되는 행동들을 여기에서 구현해야 한다.

줄들 8-23은 우리의 print_rtable 명령어를 구현한다. 우리는 logtarget_이 초기화되는 지를 첫 번째로 체크한다. (줄 9) 그리고 나서 우리는 줄들 10-13에 보여지는 것처럼 표를 트레이스 파일 안으로 덤프한다. 코드의 이런 조각을 이해하기 위해서 네가 trace/trace.h 헤더 파일을 조사하는 것은 유용할 것이다. 트레이스 클래스가 정의되는 곳이 있다. 그것은 BaseTrace 클래스의 pt_와 관계가 있다. 이런 마지막 클래스는 출력이 버퍼되는 변수를 얻기 위해 사용되는 buffer()와 그 버퍼에서 출력 파일로 쏟아져 나오기 위해 사용되는 dump() 함수들 각각 구현한다. 마지막으로, 줄 14는 자신 소유의 내용을 트레이스 파일 안에 쓰기 위한 우리의 라우팅 표의 print() 함수를 호출한다. 아래의 TCL 코드는 시뮬레이션 스크립트로부터 정해진 시간에 print_rtable 동작을 실행하는 법을 보여준다. ns_시뮬레이터의 인스턴스를 포함하고 node_ns_에 의해서 생성된 노드임을 가정한다. 우리는 인수로써 255를 통과시키는 중인데 왜냐하면 이것은 라우팅 에이전트가 부착되는 포트의 숫자이기 때문이다.

simulation.tcl

1: $ns_ at 15.0 “[$node_ agent 255] print_rtable”

구현하기 위한 또 다른 의무적인 명령어는 port-dmux이다. 그것의 구현은 줄들 27-37에서 제공된다. [2]의 3장에서 설명되는 것처럼, NS는 그것의 이름이 주어지는 그것들 각각에 빠른 접속을 제공하기 위해서 해시 표 안에 모든 콤파일된 오브젝트 (C++ 오브젝트)에 대한 참조를 저장한다. 우리는 그것의 이름이 주어지는 포트분류자 오브젝트를 획득하기 위해서 줄 28에서 그 편의를 이용한다.

유사하게, 그것의 이름이 주어지는 트레이스 오브젝트를 단순히 획득하는 tracetarget (우리는 게다가 그것이 log-target으로 불려지도록 허락한다는 것을 주목해라)이라 불리는 또 다른 의무적인 동작이 있다.

만약 우리가 요청되는 명령어를 처리하는 법을 알지 못한다면, 우리가 줄 48에서 실행한 것처럼, 이런 책임을 기반 클래스에 위임한다.

4.3.3 recv()

다음 함수는 recv()이고 우리가 아는 것처럼 라우팅 에이전트가 패킷을 받을 때마다 언제나 선포된다. 모든 패킷common/packet.h에서 정의된 hdr_cmn이라 불리는 공통의 헤더를 가진다. 이런 헤더에 접속하기 위해서 우리 소유의 패킷 유형을 위해서 우리가 전에 정의했던 것과 같은 매크로가 있고, 우리는 그것을 줄 3에서 사용한다. 줄 4는 같은 것을 실행하지만 ip.h 안에 기술된, hdr_ip, IP 헤더를 얻기 위한 것이다.

1: void

2: Protoname::recv(Packet* p, Handler* h) {

3: struct hdr_cmn* ch = HDR_CMN(p);

4: struct hdr_ip* ih = HDR_IP(p);

5:

6: if (ih->saddr() == ra_addr()) {

7: // If there exists a loop, must drop the packet

8: if (ch->num_forwards() > 0) {

9: drop(p, DROP_RTR_ROUTE_LOOP);

10: return;

11: }

12: // else if this is a packet I am originating, must add IP header

13: else if (ch->num_forwards() == 0)

14: ch->size() += IP_HDR_LEN;

15: }

16:

17: // If it is a protoname packet, must process it

18: if (ch->ptype() == PT_PROTONAME)

19: recv_protoname_pkt(p);

20: // Otherwise, must forward the packet (unless TTL has reached zero)

21: else {

22: ih->ttl_–;

23: if (ih->ttl_ == 0) {

24: drop(p, DROP_RTR_TTL);

25: return;

26: }

27: forward_data(p);

28: }

29: }

우리가 해야 하는 첫 번째 것은 우리가 우리 자신에게 전송했던 패킷을 받는 중이 아님을 체크하는 것이다. 만약 그것이 그 경우라면, 우리가 줄들 8-11에서 실행한 것처럼, 패킷을 버려야 하고 되돌려 보내야 한다. 게다가, 만약 그 패킷이 (노드의 상위 레이어들에 의해서) 노드 내에서 발생되었다면 우리는 라우팅 프로토콜이 (바이트 단위로) 더하는 중인 그 오버헤드를 패킷의 길이에 더해야 한다. 줄들 13-14에서 보여지는 것처럼, 우리는 protoname이 IP 위에서 동작한다고 가정한다.

받아들여진 패킷이 유형 PT_PROTONAME일 때 그때 우리는 그것을 처리하기 위해서 recv_protoname_pkt()를 호출할 것이다. (줄들 18-19) 만약 TTL[3]이 0에 도달하지 않았다면, 만약 그것이 데이터 패킷이라면 그때 우리는 그것을 (만약 그것이 다른 노드로 예정된 것이라면) 전송해야 하거나 (만약 그것이 브로드캐스트 패킷이었거나 우리 자신에게로 예정되었던 것이라면) 상위 레이어들에게 그것을 전달하기 위해서 전송해야 한다. 줄들 21-28은 forward_data() 함수의 사용하는 것을 단지 기술했던 것을 실행한다.

너는 drop() 함수가 패킷을 버리기 위해서 사용된다는 것을 깨달았을 것이다. 그것의 인수들은 패킷 자체로 향하는 포인터이고 그것을 버리기 위한 이유를 주는 상수이다. 이런 상수들이 여러 개가 존재한다. 너는 파일 trace/cmu-trace.h에서 그것들을 볼 수 있다.

4.3.4 recv_protoname_pkt()

라우팅 에이전트가 protoname 패킷을 받았고, 선포되기 위한 recv_protoname_pkt()를 만들었다고 가정하자. 이런 함수의 구현은 구체적인 프로토콜에 따라서 많이 변할 것이지만, 우리는 다음 예제에서 일반적인 설계를 볼 수 있다.

줄들 3-4는 평소대로 IP 헤더와 protoname 패킷 헤더를 얻는다. 그 후에 우리는 줄들 8-9에서 소스와 목적지 포트들이 RT_PORT임을 확인한다. 이 상수는 common/packet.h안에 정의되고 그것은 255와 같다. 이 포트는 라우팅 에이전트를 붙이기 위해서 예약된다.

그 후에, protoname 패킷은 우리의 라우팅 프로토콜의 규격에 따라서 처리되어야 한다.

마지막으로 우리는 줄 14에서 우리가 실행한 것처럼 자원들을 해제해야 한다.

1: void

2: Protoname::recv_protoname_pkt(Packet* p) {

3: struct hdr_ip* ih = HDR_IP(p);

4: struct hdr_protoname_pkt* ph = HDR_PROTONAME_PKT(p);

5:

6: // All routing messages are sent from and to port RT_PORT,

7: // so we check it.

8: assert(ih->sport() == RT_PORT);

9: assert(ih->dport() == RT_PORT);

10:

11: /* … processing of protoname packet … */

12:

13: // Release resources

14: Packet::free(p);

15: }

4.3.5 send_protoname_pkt()

우리는 4.2절에서 우리의 맞춤 타이머가 그것이 만료가 될 때마다 send_protoname_pkt() 함수를 어떻게 호출하는 지를 보았다. 우리는 아래에 이런 함수의 견본 구현을 보여준다. 물론 각각의 프로토콜은 무언가를 다르게 요구하고 이것은 단지 예제일 뿐이다.

protoname/protoname.cc

1: void

2: Protoname::send_protoname_pkt() {

3: Packet* p = allocpkt();

4: struct hdr_cmn* ch = HDR_CMN(p);

5: struct hdr_ip* ih = HDR_IP(p);

6: struct hdr_protoname_pkt* ph = HDR_PROTONAME_PKT(p);

7:

8: ph->pkt_src() = ra_addr();

9: ph->pkt_len() = 7;

10: ph->pkt_seq_num() = seq_num_++;

11:

12: ch->ptype() = PT_PROTONAME;

15

13: ch->direction() = hdr_cmn::DOWN;

14: ch->size() = IP_HDR_LEN + ph->pkt_len();

15: ch->error() = 0;

16: ch->next_hop() = IP_BROADCAST;

17: ch->addr_type() = NS_AF_INET;

18:

19: ih->saddr() = ra_addr();

20: ih->daddr() = IP_BROADCAST;

21: ih->sport() = RT_PORT;

22: ih->dport() = RT_PORT;

23: ih->ttl() = IP_DEF_TTL;

24:

25: Scheduler::instance().schedule(target_, p, JITTER);

26: }

패킷을 보내기 위해서 우리는 첫 번째 그것을 할당할 필요가 있다. 우리는 그것을 위해서 allocpkt() 함수를 사용한다. 이 함수는 모든 에이전트들을 위해서 정의된다. 그리고 나서 우리는 평소대로 공통의, IP와 protoname 패킷 헤더들을 얻는다. (줄들 3-6) 우리의 목표는 우리가 원하는 값들로 모든 이런 헤더들을 채우는 것이다.

Protoname 패킷 헤더는 줄들 8-10에서 채워진다. 우리의 단순한 예제에서 우리는 단지 에이전트의 소스 주소, 메시지의 (바이트 단위로) 길이 그리고 시퀀스 넘버를 필요로 한다. 이런 필드들은 protoname의 패킷 규격에 완전히 의존적이다.

NS에서 공통의 헤더는 여러 개의 필드들을 가진다. 우리는 우리가 흥미가 있는 그런 것들에만 초점을 맞춘다. (줄들 12-17) 우리는 패킷 유형을 protoname 패킷으로 설정할 필요가 있다. (줄 12) 우리는 줄 13에서 패킷 방향을 또한 할당한다. 우리가 패킷을 보내는 중이기 때문에, 그것은 hdr_cmn::DOWN 상수에 의해서 의미되는, 아래로 가는 중이다. 패킷의 크기는 줄 14에서 주어진다. 그것은 바이트 단위이고 이것은 NS2 계산들을 위해 사용되는 값이다. 우리가 의도하는 것은 너의 hdr_protoname_pkt struct의 실제 크기는 문제가 되지 않는다는 것이다. 전달 딜레이와 같은 것들을 계산하기 위해서 NS2는 네가 여기 안에 넣는 값을 사용할 것이다. 공통의 헤더와 함께 계속해서, 줄 15에서 우리는 전달에서 어떤 에러를 갖지 않는다고 결정한다. 줄 16은 패킷이 보내져야 하는 쪽으로 다음 홉을 할당한다. 이것은 매우 중요한 필드이고, 우리의 프로토콜에서 그것은 IP_BROADCAST로써 설립되는데 왜냐하면 우리는 그 이웃하는 노드들 모두가 이런 제어 패킷을 받기를 원하기 때문이다. 그 상수는 common/ip.h에서 정의되고 너는 다른 매크로들을 위해서 거기서 체크할 수 있다. 우리가 채우는 그 마지막 필드는 주소 유형이다. 그것은 NS_AF_NONE, NS_AF_ILINK 또는 NS_AF_INET이 될 수 있다. (common/packet.h를 보라) 우리는 NS_AF_INET을 선택하는데 왜냐하면 우리는 인터넷 프로토콜을 구현하는 중이기 때문이다.

이제 우리는 IP 헤더의 구성을 계속한다. 그것은 줄들 19-23에서 볼 수 있는 것처럼 매우 단순하다. common/ip.h에서 정의되고 IP 패킷들을 위한 초기 TTL 값을 의미하는 IP_DEF_TTL로 불리는 새로운 상수가 있다. 그 IP 헤더는 IPv6 시뮬레이션들을 위해 사용되는 다른 필드들을 가지지만, 우리는 우리의 예제를 위해서 그것들이 필요하지 않다.

이제 우리는 패킷을 보내는 것을 단지 계속할 수 있다. 패킷들은 이벤트들이고 ([2]의 12장을 보라) 그래서 그것들은 스케쥴될 필요가 있다. 사실, 패킷을 보내는 것은 그것을 정해진 시간에서 스케쥴하는 것과 동등하다. 줄 25는 몇 개의 지터를 소개하는 패킷을 전송하는 법을 보여준다. 그 패킷 클래스는 커넥터 클래스로부터 물려받는데, 이것은 target_으로 불리는 TclObject와 관계가 있다. 이것은 그 이벤트를 처리할 것인 핸들러이고 인수로써 schedule() 함수에게로 통과된다.

4.3.6 reset_protoname_pkt_timer()

우리의 패킷 전송 타이머는 그것 자체를 다시 스케쥴하기 위한 다른 콜백 (4.2절)을 수행한다. 그것은 함수 reset_protoname_pkt_timer()에서 실행된다. 우리는 pkt_timer_가 5초 후에 기한 만료가 되도록 다시 스케쥴되는, 다음 예제에서 그것을 보여준다.

protoname/protoname.cc

1: void

2: Protoname::reset_protoname_pkt_timer() {

3: pkt_timer_.resched((double)5.0);

4: }

4.3.7 forward_date()

지금까지 우리는 protoname 패킷들에 주로 초점을 맞춰왔지만, 데이터 패킷들을 다룰 시간이다. forward_data() 함수는 패킷이 상위-레이어 에이전트들에게 배달되어야 하는지 또는 다른 노드에게 전송되어야 하는 지를 결정한다. 우리는 줄들 6-10에서 첫 번째 경우를 체크한다. 그것이 안으로 들어오는 패킷이고 목적지 주소가 노드 자체이거나 브로드캐스트라면, 그때 우리는 안으로 들어오는 패킷을 받아들이기 위해서 (만약 우리가 그것이 포트분류자 오브젝트임을 기억한다면) 노드의 dmux_를 사용한다.

만약 그렇지 않으면, 우리는 패킷을 전송해야 한다. 이것은 우리가 줄들 12-28에서 실행한 것처럼 공통의 헤더를 적당히 설정함으로써 달성된다. 만약 그 패킷이 브로드캐스트 패킷이라면, 그때 다음 홉은 적절히 채워질 것이다. 만약 아니라면, 우리는 다음 홉을 알아내기 위해서 우리의 라우팅 표를 사용한다. (줄 17) 우리의 구현은 목적지 주소로 향하는 루트가 없을 때 IP_BROADCAST를 되돌려준다. 그런 경우에서 우리는 디버그 메시지를 프린트하고 (줄들 19-22) 패킷을 버린다. (줄 23) 만약 모든 것이 괜찮다면 그때 우리는 줄 29에서 실행한 것처럼 패킷을 전송할 것이다.

protoname/protoname.cc

1: void

2: Protoname::forward_data(Packet* p) {

3: struct hdr_cmn* ch = HDR_CMN(p);

4: struct hdr_ip* ih = HDR_IP(p);

5:

6: if (ch->direction() == hdr_cmn::UP &&

7: ((u_int32_t)ih->daddr() == IP_BROADCAST || ih->daddr() == ra_addr())) {

8: dmux_->recv(p, 0.0);

9: return;

10: }

11: else {

12: ch->direction() = hdr_cmn::DOWN;

13: ch->addr_type() = NS_AF_INET;

14: if ((u_int32_t)ih->daddr() == IP_BROADCAST)

15: ch->next_hop() = IP_BROADCAST;

16: else {

17: nsaddr_t next_hop = rtable_.lookup(ih->daddr());

18: if (next_hop == IP_BROADCAST) {

19: debug(“%f: Agent %d can not forward a packet destined to %dn”,

20: CURRENT_TIME,

21: ra_addr(),

22: ih->daddr());

23: drop(p, DROP_RTR_NO_ROUTE);

24: return;

25: }

26: else

27: ch->next_hop() = next_hop;

28: }

29: Scheduler::instance().schedule(target_, p, 0.0);

30: }

31: }

Implementing a New Manet Unicast Routing Protocol in NS2 Version 0.2 번역판

Implementing a New Manet Unicast Routing Protocol in NS2 번역입니다.

수정할 내용이 있으면 바로 알려주세요.

NS2에서 새로운 Manet 유니캐스트 라우팅 프로토콜을 구현하기

1 소개

작년 동안에, 우리는 ns-유저들 메일링 리스트에서 같은 질문을 요구하는 많은 사람들을 목격해왔다. 내가 NS2에 적합한 내 소유의 프로토콜을 어떻게 개발하는가? 이 문서를 작성함으로써 우리는 NS-2.27에 적합한 manet 라우팅 프로토콜 더할 필요가 있는 그런 연구자들을 돕기를 희망한다. 우리는 우리의 문서를 유니캐스트 프로토콜에 초점을 맞춘다. 그 문서는 ns-2에서 시뮬레이션들을 수행하는 것에 그럭저럭 잘 아는 그런 사람들을 목표로 하고, 그들은 그들 소유의 프로토콜들을 구현하기 위해서 한 단계 앞으로 가기를 원한다. 이 문장에서 우리가 기술한 모든 것은 NS2의 2.27 버전과 관련이 있지만, 그것은 다른 버전들에서도 마찬가지로 유용할 것이다.

우리는 독자가 NS2 기본들을 잘 안다고 가정한다. 그것은 “Marc Greis’ Tutorial” [1]을 읽었고 적어도 대부분 이해했다는 것을 의미한다. 만약 네가 “The ns Manual” [2], 특히 3-5, 10-12, 15-16, 23, 25 그리고 29장을 또한 훑어본다면 매우 유용할 것이다. 우리는 이런 문장 처음부터 끝까지 여러 번 그것들을 언급할 것이고 네가 그것들을 읽도록 격려할 것이다. 너의 소유의 라우팅 프로토콜을 코딩하기 전에, 너는 다른 구현된 프로토콜들로 시뮬레이션들을 어떻게 수행하는 지 알아야 하고 너는 시뮬레이터를 잘 알고 편안하게 느낄 것으로 예상된다. 이것은 이 문서를 읽는 동안에 많은 오해들과 의심들을 피할 것이다.

게다가 이 tutorial은 프로그래밍에 관한 것이다. 너는 C++과 (조금) Tcl 프로그래밍에 대한 지식이 필요하다. 만약 네가 이런 프로그래밍 언어들을 충분히 경험되지 않았다면, 너는 인터넷에서 자유로이 이용 가능한 그것들에 관한 임의의 훌륭한 자원들을 첫째로 읽어야 한다.

2 시작하면서

우리는 protoname으로 불리는 새로운 manet 라우팅 프로토콜을 단계별로 구현할 예정이다. 이 프로토콜은 유용하지 않지만, 다른 라우팅 프로토콜들과 함께 몇 개의 공통점들을 가지기엔 충분히 일반적이다. 너도 알 것이기 때문에 (만약 아니라면, 우리가 말했던 것을 첫째로 읽어라!) 우리는 C++를 사용해서 라우팅 프로토콜을 구현할 예정이고 그리고 나서 우리는 Tcl 스트립트들로 시나리오들을 기술하는 시뮬레이션들을 할 것이다.

우리의 코드를 할당하기 위해서 우리는 너의 NS2 기반 디렉토리 안쪽에 protoname으로 불리는 새로운 디렉토리를 첫째로 생성할 것이다. 우리는 거기에 5 개의 파일들을 생성할 것이다:

protoname.h 이것은 (만약 있다면) 모든 필요한 타이머들이 정의될 것인 헤더 파일이고 프로토콜의 기능성을 수행하는 라우팅 에이전트이다.

protoname.cc 이 파일 안에는 모든 타이머들, 라우팅 에이전트 그리고 Tcl 후크들이 실제로 구현된다.

protoname_pkt.h 여기에는 MANET에서 노드들 사이에 교환할 필요가 있는 모든 패킷들 protoname 프로토콜이 선언된다.

protoname_rtable.h 우리 소유의 라우팅 표가 선언되는 헤더 파일

protoname_rtable.cc 라우팅 표 구현

너는 원하는 대로 너의 코드를 조직화할 수 있다. 즉, 너는 그런 이름들 또는 다른 것들과 함께 파일들을 더 또는 덜 생성할 수 있다; 그것은 단지 힌트이다. 우리의 조언은 그런 파일들을 적어도 사용하는 것이고 그것들이 필요한 만큼 더 생성하는 것이다.

이제 우리는 우리의 “물리적인” 구조 (파일들)를 가지고 있기 때문에, “논리적인” 것 (클래스들)을 계속하자. NS2에서 라우팅 프로토콜을 구현하기 위해서 너는 에이전트 클래스로부터 물려받음으로써 에이전트를 생성해야 한다. 10장 [2]의 맨 처음에서 우리는 “에이전트들은 네트워크-레이어 패킷들이 구성되거나 소비되는 엔드포인트들을 의미하고, 다양한 레이어들에서 프로토콜들의 구현 안에 사용된다”를 읽을 수 있다. 네가 이해할 수 있는 대로, 이것은 우리가 우리의 라우팅 프로토콜을 구현하기 위해서 코드를 해야할 것인 주된 클래스이다. 게다가, 이 클래스는 Tcl 인터페이스와 연계를 제공하고, 그래서 우리는 Tcl 안에 쓰여진 시뮬레이션 스크립트들을 통해서 우리의 라우팅 프로토콜을 제어할 수 있을 것이다.

우리의 라우팅 에이전트는 내부의 상태와 (항상 필요하지는 않는) 라우팅 표를 유지할 것이다. 내부의 상태는 새로운 클래스로써 또는 라우팅 에이전트 안쪽에 속성들의 집합으로써 나타낼 수 있다. 우리는 새로운 클래스, protoname_rtable로써 라우팅 표를 다룰 수 있을 것이다.

또한 우리의 새로운 프로토콜은 자신의 제어 패킷들의 형식을 의미할 것인 적어도 하나의 새로운 패킷 유형을 정의해야 한다. 우리가 말했던 대로 이런 패킷 유형들은 protoname/protoname_pkt.h에 정의된다. 그 프로토콜이 주기적으로 또는 이벤트의 발생으로부터 약간의 시간 후에 패킷들을 보낼 필요가 있을 때, 타이머 클래스에 의지하는 것은 매우 유용하다. 우리는 규칙적인 간격들에서 이런 패킷들을 보내기 위해서 우리 소유의 타이머들을 코드하는 예를 보여준다. 타이머들은 많은 다른 경우들에서도 또한 유용하다. 정해진 시간에서 지워져야 하는 내부 정보의 몇 가지 종류들을 저장할 필요가 있는 protoname을 상상해라. 가장 좋은 해결책은 그런 일을 할 수 있는 맞춤의 타이머를 생성하는 것이다. 타이머는 라우팅 표 안에서 입력의 시간수명을 명시하기 위해서 또한 사용되어야 한다. 일반적으로, 우리가 주어진 시간에서 업무를 스케쥴해야할 때는 언제나 타이머를 사용할 것이다.

세부적인 것들로 가기전에 우리가 알아야 하는 또 다른 중요한 클래스가 있다. 트레이스 클래스는 시뮬레이션 동안에 무엇이 일어 났는지에 대한 정보를 가진 로그 파일들을 쓰기 위한 기반이다.

그리고 마지막 힌트: 네가 너의 코드 안에 디버그 메시지를 프린트 하기를 원할 때, 25장 [2]에서 제안되는 것처럼 디버그() 함수를 사용하는 것은 도움이 된다. 이것은 네가 너의 시뮬레이션 스크립트들로부터 디버깅을 켜거나 끄도록 허락하고 다른 프로그래머들이 읽는 것이 쉽다.

3 패킷 유형들

이제 네가 기초들을 벌써 알기 때문에, 새로운 파일을 생성하고 그것을 protoname/protoname_pkt.h 이라고 부르자. 여기에서 우리는 우리의 새로운 패킷(들) 유형과 관련된 모든 데이터 구조들, 상수들, 매크로들을 넣을 예정이다. 다음 예제를 보자.

protoname/protoname_pkt.h

1: #ifndef __protoname_pkt_h__

2: #define __protoname_pkt_h__

3:

4: #include <packet.h>

5:

6: #define HDR_PROTONAME_PKT(p) hdr_protoname_pkt::access(p)

7:

8: struct hdr_protoname_pkt {

9:

10: nsaddr_t pkt_src_; // Node which originated this packet

11: u_int16_t pkt_len_; // Packet length (in bytes)

12: u_int8_t pkt_seq_num_; // Packet sequence number

13:

14: inline nsaddr_t& pkt_src() { return pkt_src_; }

15: inline u_int16_t& pkt_len() { return pkt_len_; }

16: inline u_int8_t& pkt_seq_num() { return pkt_seq_num_; }

17:

18: static int offset_;

19: inline static int& offset() { return offset_; }

20: inline static hdr_protoname_pkt* access(const Packet* p) {

21: return (hdr_protoname_pkt*)p->access(offset_);

22: }

23:

24: };

25:

26: #endif

줄들 8-24는 우리가 정의하는 중인 새로운 패킷 유형을 의미하는 hdr_protoname_pkt를 선언한다. 줄들 10-12에서 우리는 우리의 패킷이 가지는 3가지 처리되지 않은 속성들을 볼 수 있다. 그것들은 다음의 유형들이다:

nsaddr_t 네가 NS2에서 네트워크 주소를 선언하기를 원할 때마다 매번 너는 이 유형을 사용해야 한다.

u_int16_t 16 비트들 부호 없는 정수

u_int8_t 8 비트들 부호 없는 정수

이런 모든 유형들과 더 많은 것들은 헤더 파일 config.h 안에 정의된다. 우리는 독자가 이런 파일을 훑어보고 거기에 정의된 유형들을 사용하는 것을 격려한다. 다른 변수들과 그것들을 구별하기 위한 밑줄과 함께 끝내기로 예상되는 처리 되지 않은 속성들의 이름들은 또한 언급할 만한 가치가 있다. (25장 [2]를 보라)

줄들 14-16은 정의된 속성들을 위한 멤버 함수들이다. 이것은 의무적이지는 않지만 12장 [2]에서 제안되는 “좋은 습관”이다 (그리고 우리는 그것을 실제로 지원한다!)

줄 4는 패킷 클래스를 정의하는 파일 common/packet.h를 포함한다. (12장 [2]를 보라) 패킷들은 시뮬레이션 안에서 오브젝트들 사이에 정보를 교환하기 위해서 사용되고, 우리의 목표는 우리의 새로운 struct hdr_protoname_pkt를 그것들에 더하는 것이다. 우리의 제어 패킷들을 그렇게 하는 것은 시뮬레이션 안에서 노드들에 의해서 보내지고 받아들여 질 수 있을 것이다. 우리가 그것을 어떻게 할 수 있는가? 이런 질문에 답하기 위해서 우리는 모든 패킷 헤더들이 패킷 클래스에 의해서 어떻게 저장되는 지를 알아야 하고, 그 답은 패킷들의 필드들이 보관되는 부호 없는 케릭터들의 배열 (비트들의 가방)을 사용하는 것이다. 구체적인 패킷 헤더에 접속하기 위해서 그것이 위치되는 오프셋을 제공할 필요가 있다. 그리고 그것은 정확하게 우리가 줄들 18-22를 통해서 하는 것이다. 우리는 고정된 (모든 hdr_protoname_pkt 구조들에 공통적인) 오프셋, 그것에 접속하기 위한 하나의 멤버 함수 그리고 하나의 패킷이 주어진 hdr_protoname_pkt을 되돌려보내는 함수를 정의한다. 게다가, 줄 6에서 우리는 이런 마지막 함수를 사용하기 위한 매크로를 생성한다.

하나의 업무가 남아있다: 우리의 패킷 헤더를 Tcl 인터페이스에 묶는 것. 우리는 다음의 코드로 protoname/protoname.cc 안에 그렇게 할 것이다. 우리가 볼 수 있듯이 우리는 우리의 패킷 헤더의 오프셋을 Tcl을 통해서 접근하기 쉽게 하는 중이다.

protoname/protoname.cc

1: int protoname_pkt::offset_;

2: static class ProtonameHeaderClass : public PacketHeaderClass {

3: public:

4: ProtonameHeaderClass() : PacketHeaderClass(“PacketHeader/Protoname”,

5: sizeof(hdr_protoname_pkt)) {

6: bind_offset(&hdr_protoname_pkt::offset_);

7: }

8: } class_rtProtoProtoname_hdr;

4 라우팅 에이전트

이제 우리는 에이전트 자체의 프로그래밍을 시작한다. protoname/protoname.h 안쪽에 우리는 그것의 작업을 하는데 있어서 프로토콜을 돕도록 요구되는 속성들과 함수들을 포함하는 Protoname이라 불리는 새로운 클래스를 정의한다. 타이머들의 사용을 묘사하기 위해서 우리는 protoname이 몇 개의 제어 패킷들을 주기적으로 발산할 필요가 있는 예방의 라우팅 프로토콜임을 가정한다. 다음 코드는 그런 예제를 보여준다.

protoname/protoname.h

1: #ifndef __protoname_h__

2: #define __protoname_h__

3:

4: #include “protoname_pkt.h”

5: #include <agent.h>

6: #include <packet.h>

7: #include <trace.h>

8: #include <timer-handler.h>

9: #include <random.h>

10: #include <classifier-port.h>

11:

12: #define CURRENT_TIME Scheduler::instance().clock()

13: #define JITTER (Random::uniform()*0.5)

14:

15: class Protoname; // forward declaration

16:

17: /* Timers */

18:

19: class Protoname_PktTimer : public TimerHandler {

20: public:

21: Protoname_PktTimer(Protoname* agent) : TimerHandler() {

22: agent_ = agent;

23: }

24: protected:

25: Protoname* agent_;

7

26: virtual void expire(Event* e);

27: };

28:

29: /* Agent */

30:

31: class Protoname : public Agent {

32:

33: /* Friends */

34: friend class Protoname_PktTimer;

35:

36: /* Private members */

37: nsaddr_t ra_addr_;

38: protoname_state state_;

39: protoname_rtable rtable_;

40: int accesible_var_;

41: u_int8_t seq_num_;

42:

43: protected:

44:

45: PortClassifier* dmux_; // For passing packets up to agents.

46: Trace* logtarget_; // For logging.

47: Protoname_PktTimer pkt_timer_; // Timer for sending packets.

48:

49: inline nsaddr_t& ra_addr() { return ra_addr_; }

50: inline protoname_state& state() { return state_; }

51: inline int& accessible_var() { return accessible_var_; }

52:

53: void forward_data(Packet*);

54: void recv_protoname_pkt(Packet*);

55: void send_protoname_pkt();

56:

57: void reset_protoname_pkt_timer();

58:

59: public:

60:

61: Protoname(nsaddr_t);

62: int command(int, const char*const*);

63: void recv(Packet*, Handler*);

64:

65: };

66:

67: #endif

줄들 4-10은 우리의 에이전트에 의해서 요구되는 헤더 파일들을 포함하기 위해서 사용된다. 아래에 우리는 그것들이 무엇을 위해 유용한지를 설명한다.

protoname/protoname_pkt.h 우리의 패킷 헤더를 정의한다.

common/agent.h 에이전트 기반 클래스를 정의한다.

common/packet.h 패킷 클래스를 정의한다.

common/timer-handler.h TimerHandler 기반 클래스를 정의한다. 우리는 우리의 맞춤 타이머들을 생성하기 위해서 그것을 사용할 것이다.

trace/trace.h 시뮬레이션 결과를 트레이스 파일로 쓰기 위해 사용되는, 트레이스 클래스를 정의한다.

tools/random.h 가짜의-랜덤 숫자들을 발생시키는 데 유용한, 랜덤 클래스를 정의한다. 우리는 그것을 곧 사용할 것이다.

classifier/classifier-port.h 패킷들을 상위 레이어들에게 올려 보내기 위해서 사용되는 포트분류자 클래스를 정의한다.

줄 12는 시뮬레이터 시계 안에 현재 시간을 얻기 위한 유용한 매크로를 정의한다. 그것은 스케쥴러 클래스의 단일의 인스턴스에 접속함으로써 실행된다. 이 오브젝트는 시뮬레이션 동안에 생산된 모든 이벤트들과 시뮬레이터의 내부 시계를 관리한다. (4장 [2]을 보라)

또 다른 매크로는 줄 13에 있다. 그것은 [0-0.5] 간격 안쪽에 랜덤 숫자를 획득하기 위한 단지 쉬운 방법이다. 이것은 결국에 충돌들을 생산하고 그래서 이런 패킷들을 송신하는 시간에서 딜레이되는, 자신의 이웃들과 함께 노드의 동기화를 피하기 위해 제어 패킷들의 송신을 랜덤화하기 위해서 보통 사용된다.[1]

줄들 19-27은 주기적인 제어 패킷들을 송신하기 위한 우리의 맞춤 타이머를 선언한다. 우리의 Protoname_PktTimer 클래스는 TimerHandler로부터 물려받고 그것을 생성하는 라우팅 에이전트에 관계가 있다. 이것은 라우팅 에이전트에게 새로운 제어 패킷을 전송하고 다음 것을 스케쥴하라고 말하기 위한 콜백으로써 사용된다. 우리는 expire() 방법에 어떻게 과부하가 걸리는 지를 기술할 때, 뒤에 이것을 더 봐야 한다. 이런 콜백들을 실행하기 위해서 라우팅 에이전트는 동료 클래스로써 Protoname_PktTimer를 다룰 필요가 있다. (줄 34)

Protoname 클래스는 줄들 31-65 내에 정의된다. 그것은 자신 소유의 주소, 내부의 상태, 라우팅 표, Tcl에서 접근하기 쉬운 변수 그리고 시퀀스 넘버들을 출력 패킷들에 할당하기 위한 카운터 (줄들 37-41)를 캡슐화한다. protoname_state_는 클래스 자체 또는 그것의 작업을 하기 위해서 Protoname 클래스에 의해 요구되는 속성들의 집합일 수 있다. accessible_var_는 Tcl 스크립트들 또는 쉘 명령어들로부터 읽혀지고 쓰여지는 것으로 생각된다. 이것은 많은 상황들에서 유용한데 왜냐하면 그것은 유저들이 시뮬레이터의 재-컴파일없이 자신들의 스크립트들을 통해서 시뮬레이션 행동을 바꾸는 것을 허락하기 때문이다.

포트분류자 오브젝트는 줄 45에서 선언된다. 너는 노드의 구조를 이해하기 위해서 5장 [2]를 읽어야 한다. 거기서 노드가 주소 분류자와 포트 분류자로 어떻게 구성되는 지 너는 볼 수 있을 것이다. 첫 번째는 적절한 링크로 들어오는 패킷들을 안내하거나 그것들을 상위 레이어 에이전트에게 충당하기 위해서 그것들을 운반할 것인, 포트 분류자에게로 그것들을 통과하기 위해서 사용된다. 그것이 라우팅 에이전트가 포트 분류자를 필요로 하는 이유이다. 그것이 자신으로 예정된 데이터 패킷들을 받을 때 그것은 일치하는 에이전트에게 그것들을 주기 위해서 dmux_를 사용할 것이다.[2] 모바일 노드의 세부적인 아키텍처는 [2]의 16장에서 설명된다.

또 다른 중요한 속성은 트레이스 오브젝트이다. (줄 46을 보라) 그것은 트레이스 파일 안에 저장되기 위한 로그들을 생산하기 위해서 사용된다. 우리의 예제에서 유저가 Tcl 인터페이스에서 그것을 요청할 때마다 라우팅 표의 내용들을 쓰기 위해서 우리는 그것을 사용한다. 만약 네가 패킷들에 관해서 트레이싱 정보를 쓰는 데만 단지 관심이 있다면 이것이 필수는 아니다. 그 경우에서, 그런 로깅 함수들은 다른 위치에서 구현된다. (우리가 6절에서 봐야 할 것처럼)

줄 47은 우리의 맞춤 타이머를 선언한다. 그리고 줄들 49-51은 몇 개의 내부 속성들에 접속하기 위한 멤버 함수들이다.

줄 53에서 함수는 데이터 패킷들을 그것들의 올바른 목적지로 전송하기 위해서 사용될 것이다. 줄 54에서 함수는 제어 패킷이 받아들여질 때마다 호출될 것이고, 줄 55에서 그것은 제어 패킷을 전송하기 위해서 선포된다. 줄 57은 우리의 맞춤 타이머 기한 만료를 스케쥴하기 위해서 사용되는 함수를 선언한다.

줄들 61-63은 클래스 Protoname의 공개 함수들을 포함한다. 건설자는 라우팅 에이전트의 주소로써 사용되는 식별자를 인수로써 받는다. Protoname은 구현될 필요가 있는 두 개의 메인 함수들을 에이전트 기반 클래스로부터 물려받는다: recv()command(). recv()는 에이전트가 패킷을 받을 때마다 불려진다. 노드 자체 (실제로는 UDP 또는 TCP와 같은 상위 레이어)가 패킷을 발생하는 중이거나 다른 노드로부터 패킷을 받는 중일 때 이것은 일어날 것이다. command() 함수는 3장 [2]에서 기술된 것처럼 Tcl로부터 선포된다. 그것은 우리의 Tcl 코드로부터 몇 개의 업무를 하도록 C++ 오브젝트에게 요청하기 위한 방식이다. 한번 우리가 절 4.3을 경험하면 너는 이것을 더 이해할 것이다.

이제 너는 Protoname의 인터페이스가 어떻게 있는 지 알기 때문에, 그것의 구현을 계속할 시간이다. 다음 하위 절들은 protoname/protoname.cc 파일과 관련된다.

4.1 Tcl hooks

우리는 우리 소유의 패킷을 Tcl에 묶는 법을 3절에서 보았다. 이제 우리는 우리의 에이전트 클래스를 위해 같은 것을 할 것이다. 그 목적은 Protoname에게 Tcl로부터 예시되도록 하는 것이다. 그렇게 하기 위해서 우리는 다음의 코드에서 묘사된 것처럼 클래스 TclClass로부터 물려받아야 한다.

protoname/protoname.cc

1: static class ProtonameClass : public TclClass {

2: public:

3: ProtonameClass() : TclClass(“Agent/Protoname”) {}

4: TclObject* create(int argc, const char*const* argv) {

5: assert(argc == 5);

6: return (new Protoname((nsaddr_t)Address::instance().str2addr(argv[4])));

7: }

8: } class_rtProtoProtoname;

클래스 건설자는 줄 3에 있고 그것은 인수로써 스트링 “Agent/Protoname”을 가진 기반 클래스를 호출한다. 이것은 본문의 방법에서 이 에이전트를 위한 클래스 계층을 의미한다.

줄들 4-7에서 우리는 TclObject로써 새로운 Protoname 인스턴스를 되돌려주는 create()로 불리는 함수를 구현한다. argv는 “<오브젝트의 이름> <$self> <$클래스> <$proc> <유저 인수>” 형태이다. (더 많은 정보를 위해서 [2]의 3장을 보라) 이런 특별한 경우에서 그것은 “<오브젝트의 이름> <$self> Agent/Protoname create-shadow <id>”이다. 이것 때문에, 줄 6에서 우리는 argv[4]에서 시작되는 식별자를 가진 새로운 Protoname 오브젝트를 되돌려준다. 우리는 스트링에서 nsaddr_t 유형을 얻기 위해 주소 클래스를 사용한다.

4.2 타이머들

우리가 타이머들에 대해 protoname/protoname.cc 안에서 코드해야 하는 모두는 expire() 방법이다. 타이머들은 11장 [2]에 세부적으로 되어있다. 이것을 구현하는 것은 매우 쉬운데 왜냐하면 우리는 단지 새로운 제어 패킷을 보내고 타이머 자체를 다시 스케쥴하기를 단지 원하기 때문이다. 우리의 설계 결정들에 따라서 두 개의 업무들은 라우팅 에이전트에 의해서 실행되어야 하고, 그래서 우리는 다음의 예제에서처럼 이런 콜백들을 선포한다.

protoname/protoname.cc

1: void

2: Protoname_PktTimer::expire(Event* e) {

3: agent_->send_protoname_pkt();

4: agent_->reset_protoname_pkt_timer();

5: }

4.3 에이전트

4.3.1 건설자

건설자 구현과 함께 시작해보자. 아래 줄 1에서 볼 수 있는 것처럼, 우리는 PT_PROTONAME을 통과하는 기반 클래스를 위한 건설자를 인수로써 호출함으로써 시작한다. 이런 상수는 뒤에 정의될 것이고 그것은 이런 라우팅 에이전트에 의해서 보내지고 받아들여지는 제어 패킷들을 식별하기 위해서 사용된다. 같은 줄에서 우리는 우리의 Protoname_PktTimer 오브젝트를 생성한다.

하자마자 우리는 이제 Tcl로부터 읽혀지고 쓰여질 것인 논리 속성으로써 accessible_var_을 묶는다. 정수로써 이 변수를 묶기 위해서, 우리는 bind_bool() 대신에 bind() 함수를 사용해야 한다.

줄 3은 주어진 식별자를 라우팅 에이전트의 주소로 저장한다.

protoname/protoname.cc

1: Protoname::Protoname(nsaddr_t id) : Agent(PT_PROTONAME), pkt_timer_(this) {

2: bind_bool(“accessible_var_”, &accessible_var_);

3: ra_addr_ = id;

4: }

Tcl 스크립트들로부터 접근하는 것은 꽤 단순하다. 다음 예제는 accessible_var_의 값을 true로 설정한다.

simulation.tcl

1: Agent/Protoname set accesible_var_ true

Embedded 참고 사이트

임베디드 리눅스 관련 사이트 목록

목차

1부. 임베디드 시스템과 리눅스

1장. 임베디드 시스템

2장. 리눅스

3장. 임베디드 리눅스

4장. 실시간 운영체제

5장. 윈도우 시스템

2부. 임베디드 리눅스 개발 방법론

6장. 제품 기획 단계에서 고려할 사항

7장. 타겟 보드 선정 방법

8장. 장치 선정과 드라이버 구현

9장. 임베디드 리눅스 이식 절차

10장. 임베디드 리눅스 환경에서 응용 프로그램 개발 절차

11장. 개발 후 상용 제품을 위한 패키징

3부. 리눅스 개발 환경 구축과 이식

12장. 교차 개발 환경 구축

13장. 네트워크와 디버깅 환경 구축

14장. 부트 스트랩 로더 이식

15장. 리눅스 커널 환경 설정과 컴파일

16장. 루트 파일시스템 구축

17장. 실시간 리눅스 커널 이식

18장. 윈도우 시스템 환경 이식

19장. 부팅과 설치 확인

20장. 상용 제품을 위한 패키징

1부. 임베디드 시스템과 리눅스

1장. 임베디드 시스템

□ 『C, C++로 작성하는 임베디드 시스템 프로그래밍』, 마이클 바 저, 이석주 역, 한빛미디어, 2000

C 와 C++ 프로그래밍 언어를 사용하여 임베디드 시스템을 제작하는 방법을 기술하고 있다. 아쉽게도 이 책에 나오는 보드를 국내에서 구하기가 어렵기 때문에 본격적인 실습이 불가능하다는 단점이 있다. 하지만 임베디드 시스템에 대한 개념을 단기간에 잡기에는 적당하다.

□ 『네트워크 프린팅』, 토드 레이더마커, 매튜 개스트 저, 박재호, 이영미 역, 한빛미디어, 2001

리눅스와 유닉스를 서버로, 윈도우, 맥, 넷웨어를 클라이언트로 구성한 네트워크 환경에서 인쇄하는 방법을 기술한다. BOOTP, DHCP와 같은 네트워크 프로토콜을 사용해 프린터를 부팅하는 방법도 소개한다.

http://wombat.doc.ic.ac.uk/foldoc/index.html

FOLDOC 컴퓨터 용어 전문 사전이다.

■ http://www.linuxdevices.com/articles/AT4936596231.html

임베디드 리눅스를 탑재하고 있는 임베디드 장치를 소개하는 페이지이다. PDA를 제외한 여러 장치를 종류별로 제시하고 있다.

■ http://www.linuxdevices.com/articles/AT8728350077.html

임베디드 리눅스를 탑재했거나 탑재할 수 있는 PDA를 소개하는 페이지이다.

■ http://www.linuxdevices.com/articles/AT4313418436.html
임베디드 리눅스를 탑재할 수 있는 SOC(System-On-Chip)을 소개하는 페이지이다.

■ http://www.classicgaming.com/
고전 게임을 소개하는 페이지이다. MSX와 애플을 비롯한 각종 플랫폼을 흉내낸 애뮬레이터와 게임용 롬 이미지를 다운로드할 수 있다.

■ http://quest.arc.nasa.gov/mars/ask/about-mars-path/pathfinder_computer.txt
패스파인더에 탑재한 컴퓨터 사양을 설명하는 기사이다.

■ http://quest.arc.nasa.gov/mars/ask/about-mars-path/Assembly_language_programming_used_in_Pathfinder.txt
패스파인더 개발을 위해 사용한 어셈블리어에 대해 설명하는 기사이다.

■ http://quest.arc.nasa.gov/mars/ask/about-mars-path/Selection_of_programming_languages.txt
패스파인더 개발을 위해 사용한 프로그래밍 언어 선택과 관련한 기사이다.

■ http://www.windriver.com/customer/html/jpl.html
VxWorks를 만든 윈드리버에서 만든 제트추진연구소에 대한 기사이다.

■ http://www.iews.na.baesystems.com/space/pdf/0887.pdf
패스파인더에 탑재한 마이크로프로세서를 소개하는 기사이다.

목차

2장. 리눅스

□ 『리눅스 그냥 재미로: 우연한 혁명에 대한 이야기』, 리누스 토발즈, 데이비드 다이아몬드 저, 안진환 역, 한겨례신문사, 2001

리 누스 토발즈가 집필한 리눅스에 대한 일종의 자서전으로 리눅스 개발의 이면에 숨겨진 배경 이야기를 허심탄회하게 풀어내고 있다. 예상과는 달리 내용이 따분하지 않고 재미있기 때문에(제목을 한번 보라!) 언제 어디서나 부담 없이 읽을 수 있는 책이다.

□ 『Operating System Concepts 6th edition』, A. Silberschatz, J. Peterson, P. Galvin, John Wiley & Sons, 2001
일명 ‘공룡책’이라고 불리며 운영체제에 대한 일반 내용을 다루는 기본서이다. 운영체제라는 세계에 첫 걸음을 내딛도록 도와준다. 대학교에서 운영체제 과목 교과서로 많이 사용하고 있으며, 대학 3학년 이상 학생이 읽기에 적합하다.

□ 『리눅스 커널의 이해』, 다니엘 보베이, 마르코 체사티 저, 이 호, 심마로 역, 한빛미디어, 2001
오라일리 『Understanding the Linux Kerne』의 번역판이다. 리눅스 커널 내부를 탐험하고 싶은 사람에게 등불이 될 책으로 리눅스나 유닉스 운영체제에 대해 중급 이상의 지식을 확보한 개발자에게 적합하다.

□ 『러닝 리눅스 3판』, 매트 웰시, 라 카우프만, 칼레 딜하이머 저, 이만용 역, 한빛미디어, 2001

오 라일리 『Running Linux 3rd Edition』의 번역판이다. 리눅스를 처음 접하는 독자가 고민하면서 읽을 가치가 있는 ‘정보를 위한 정보를 담은 메타북(meta-book)’으로 리눅스라는 운영체제에 철학적으로 접근하는 구성 방식이 돋보인다. 운영체제를 전혀 모르는 완전 초보자에게는 다소 어려울 수도 있다.

□ 『오픈 소스』에릭 레이몬드 외 저, 송창훈 외 역, 한빛미디어, 2000
오 라일리 『Open Source: Voice from the Open Source Revolutions』의 번역판이다. 공개 소스와 관련한 여러 선구자들이 수필식으로 적은 글을 묶어놓은 책으로 리눅스를 비롯한 공개 소스 소프트웨어가 어떤 식으로 발전해왔으며 앞으로 어떻게 발전할지 전반적인 구도를 제시한다.

□ 『Operating Systems: Design and Implementation』 Andrew S. Tanenbaum, Prentice-Hall, 1987
타 넨바움 교수가 지은 MINIX 운영체제를 소개하는 책이다. 리누스도 이 책을 접합 후부터 스스로 운영체제를 만들 생각을 했다니까, 실제 운영체제가 어떻게 돌아가는지 구체적인 동작 원리에 관심있는 독자는 한 번씩 읽어보면 도움이 될 것이다.

■ http://www.linuxhq.com/
리눅스 커널에 대한 각종 정보를 체계적으로 정리한 본부 사이트이다. 각 커널 버전에 따라 무엇이 어떻게 변했으며, 패치가 어떻게 이뤄지는지 잘 정리하고 있다.

■ http://www.kernel.org
리눅스 커널을 배포하는 공식 사이트이다. 과거부터 현재까지 모든 리눅스 커널을 유지하고 있으므로, 이 사이트에 들러 필요한 버전을 가져오기 바란다.

■ http://www.livinginternet.com/?i/iw_unix_linux.htm
리눅스 역사를 간략하게 기술하는 사이트이다. 간결하면서도 있어야 하는 내용은 모두 자리잡고 있다.

■ http://www.li.org/linuxhistory.php
리누스 토발즈가 유즈넷(USENET)에 올린 글을 토대로 초창기 리눅스 역사를 재조명하는 사이트이다.

■ http://www.memalpha.cx/Linux/Kernel/
리눅스 커널 버전과 관련한 역사를 한눈에 살펴볼 수 있다. 각 버전별로 리눅스 커널이 정확하게 몇 월 몇 일 몇 시에 나왔는지 궁금하면 이 사이트를 방문해보기 바란다.

■ http://lwn.net/2001/features/Timeline/
2001년 한해동안 리눅스와 관련한 각종 사건을 월 단위로 정리하고 있다. 아쉽게도 1998년부터 추적할 수 있다. 연도별 시간띠를 보면서 과거에 어떤 일이 있었는지 기억을 한번 더듬어보기 바란다.

■ http://www.nwfusion.com/newsletters/linux/2001/01086735.html
아마존이 리눅스를 웹서버로 채택했다는 소식을 담은 기사이다.

■ http://www.computer.org/computer/homepage/0202/ec/
리눅스가 헐리우드에서 맹활약하는 사례를 제시하고 있다. 블록버스터 영화에서 리눅스를 어떻게 사용하는지 실례를 들어 설명하고 있다.

■ http://www.fsf.org
자유 소프트웨어 재단 홈페이지이다. GNU 프로젝트에 대한 여러 가지 내용을 담고 있다.

■ http://www.fsf.org/software/software.html
GNU에서 개발한 GPL과 LGPL을 따르는 각종 소프트웨어 목록과 기타 공개 소스 소프트웨어 목록을 제공하고 있다. 그냥 심심풀이로 훑어보기만 해도 리눅스에 얼마만큼 많은 응용 프로그램이 존재하는지 확인할 수 있다.

■ http://www.pcmag.com/article/0,2997,ss%253D1490%2526s%253D25068%2526a%253D17930,00.asp
리누스 오른팔인 알란 콕스가 커널 2.4 유지 보수를 더 이상 맡지 않는다는 기사를 담은 페이지이다.

■ http://www.marcelothewonderpenguin.com/
알란 콕스 뒤를 이은 새로운 커널 2.4 유지보수 펭귄(maintainer)인 마르첼로(Marcelo Wormsbecker Tosatti)의 신상정보를 담은 페이지이다.

■ http://www.linuxdoc.org/
리눅스 문서 프로젝트(LDP, Linux Document Project)와 관련한 결과 문서를 제공하는 홈페이지이다. 리눅스와 관련한 HOW-TO, FAQ를 위시하여 도움이 될만한 각종 문서를 체계적으로 제공한다.

■ http://www.kldp.org
리눅스 한글 문서 프로젝트 홈페이지이다. 리눅스 관련 각종 번역 문서와 창작 문서를 분류별/주제별로 제공한다. 또한 팁 게시판과 사용기도 정리해놓았다.

■ http://kldp.org/root/cathedral-bazaar/cathedral-bazaar.html#toc10
에릭 레이먼드씨가 작성한 시장과 성당을 번역한 글이다. 이 글이 인터넷에 오른 이후부터 공개 소스 소프트웨어 운동이 한층 활기를 띄게 된다.

■ http://www-903.ibm.com/developerworks/kr/index.html
IBM에서 운영하는 리눅스 개발 사이트(developerWorks 한글판)로서 리눅스와 관련한 여러 유용한 정보를 제공한다.

■ http://safari.informit.com/mainhom.asp?home
InformIT 에서 운영하는 사파리 서비스 홈페이지이다. 사파리 서비스는 구매에 앞서 책 내용을 온라인으로 검색할 수 있도록 지원하는 서비스이다. 아쉽게도 유료이다. 사파리 멤버 중 하나인 오라일리 출판사 홈페이지에서도 바로 사파리 서비스에 접근할 수 있다.

■ http://www.google.com/grphp?hl=en
유 즈넷 기사를 검색할 수 있는 구글(Google) 검색엔진 홈페이지이다. 구글에 앞서 이러한 서비스를 제공하던 데자뉴스(deja.com)시절부터 현재까지 엄청난 분량의 기사를 담고 있다. ISP에서 제공하는 뉴스그룹 서비스에 불만을 품고 있다면 반드시 한번 사용해보기 바란다.

목차

3장. 실시간 운영체제

□ 『리눅스 커널의 이해』, 다니엘 보베이, 마르코 체사티 저, 이 호, 심마로 역, 한빛미디어, 2001
오라일리 『Understanding the Linux Kernel』의 번역판이다. 리눅스 커널 내부를 탐험하고 싶은 사람에게 등불이 되어줄 책으로 리눅스나 유닉스 운영체제에 대해 중급 이상 지식을 확보한 개발자에게 적합하다.

□ 『러닝 리눅스 3판』, 매트 웰시, 라 카우프만, 칼레 딜하이머 저, 이만용 역, 한빛미디어, 2001

오 라일리 『Running Linux 3rd Edition』의 번역판이다. 리눅스를 처음 접하는 독자가 고민하면서 읽을 가치가 있는 ‘정보를 위한 정보를 담은 메타북(meta-book)’으로 리눅스라는 운영체제에 철학적으로 접근하는 구성 방식이 돋보인다. 운영체제를 전혀 모르는 완전 초보자에게는 다소 어려울 수도 있다.

□ 『오픈 소스』, 에릭 레이몬드 외 저, 송창훈 외 역, 한빛미디어, 2000
오 라일리 『Open Source: Voice from the Open Source Revolutions』의 번역판이다. 공개 소스와 관련한 여러 선구자가 에세이 형식으로 적은 글을 묶은 책으로 리눅스를 비롯한 공개 소스 소프트웨어가 어떤 식으로 발전해왔으며 앞으로 어떻게 발전할지 전반적인 구도를 제시한다.

□ 『Embedded Linux』, John Lombardo, New Riders, 2002

x86 플랫폼에서 리눅스를 최소한으로 패키징하는 방법을 기술한다. 아주 뛰어나거나 새로운 내용은 담고 있지 않지만, x86에서 임베디드 리눅스를 재미로 탑재해보려는 초보자에게는 도움을 줄 수 있다.

■ http://www.linuxdevices.com/articles/AT9888936014.html
임베디드 리눅스와 관련한 요약 가이드를 제공하는 기사이다. 여러 가지 읽을 거리에 대한 링크를 제공한다.

■ http://www.linuxdevices.com/articles/AT3620938516.html
임베디드 리눅스를 위한 요구 사항을 분석한 기사이다. PDA와 같은 특정 분야에 치우치지 않고 전반적인 흐름을 잘 짚고 있다.

■ http://www.linuxdevices.com/articles/AT9202043619.html
임베디드 리눅스에서 동작하는 여러 윈도우 시스템을 소개하는 기사이다. 윈도우 시스템을 공개 소스와 상용 제품으로 나누어 정리하였다.

■ http://www.linuxdevices.com/articles/AT2760742655.html
다양한 임베디드 리눅스 배포판을 소개한 기사이다. 공개 소스와 상업적 지원 배포판의 특징과 URL을 간략하게 정리하고 있다.

■ http://www.linuxdevices.com/files/article011/index.html
임베디드 리눅스에 대한 현재 상태(시장 상황, 향후 전망)를 제시한 기사이다. 다양한 도표와 그래프를 통해 통계 자료를 제공하므로 전략적인 결정에 참고하기 바란다.

■ http://www-903.ibm.com/developerworks/kr/linux/library/l-emb.html?dwzone=linux
리눅스가 임베디드 시장을 석권할 수 있는 이유를 제시한 기사이다.

■ http://www-903.ibm.com/developerworks/kr/linux/library/l-embl.html?dwzone=linux
임베디드 리눅스 애플리케이션에 대한 개요를 소개하는 기사이다. 임베디드 리눅스와 관련한 기본 사항을 잘 요약하고 있다.

■ http://www.uclinux.org/
임베디드 리눅스 마이크로 컨트롤러 프로젝트이다. MMU 없는 CPU에서 동작하는 리눅스에 대한 이식 작업 성과를 볼 수 있다.

■ http://www.linux-mtd.infradead.org/
리눅스를 위한 MTD(Memory Technology Device) 서브 시스템과 관련있는 각종 사항을 정리한 홈페이지이다.

■ http://www.microsoft.com/Windows/embedded/xp/evaluation/compare/notlinux.asp
임베디드 환경에서 동작하는 윈도우계열 운영체제와 리눅스계열 운영체제를 비교한 자료이다. 마이크로소프트사에서 작성했으므로 윈도우계열에 높은 점수를 주고 있다.

■ http://www.lineo.com/news_events/announcements/2001/12.20.html
마이크로소프트사에서 발표한 임베디드 윈도우 계열 운영체제와 임베디드 리눅스 계열 운영체제 비교 문건을 반박하는 내용을 담고 있다.

■ http://www.lynuxworks.com/products/whitepapers/xp-vs-linux.php3
임베디드 환경에서 동작하는 윈도우계열과 리눅스계열 운영체제를 비교한 자료이다. 리눅스웍스에서 작성했으므로 리눅스계열에 높은 점수를 주고 있다.

목차

4장. 실시간 운영체제

□ 『Operating System Concepts 6th edition』, A. Silberschatz, J. Peterson, P. Galvin, John Wiley & Sons 2001
일명 ‘공룡책’이라 불리며 운영체제에 대한 일반 내용을 다루는 기본서이다. 운영체제라는 세계에 첫 걸음을 내딛도록 도와준다. 대학에서 운영체제 과목 교재로 많이 사용하며, 대학교 3학년 이상이 읽기에 적합하다.

□ 『리눅스 커널의 이해』, 다니엘 보베이, 마르코 체사티 저, 이 호, 심마로 역, 한빛미디어 2001년
오라일리 『Understanding the Linux Kernel』의 번역판이다. 리눅스 커널 내부를 탐험하고 싶은 사람에게 등불이 되는 책으로 리눅스나 유닉스 운영체제에 대해 중급 이상의 지식을 확보한 개발자가 읽기에 적합하다.

□ 『The Design of the UNIX Operating System』, Maurice J. Bach, PTR/PH 1990
유닉스 운영체제 설계 사상을 담고 있는 가장 기본적인 바이블이다. 유닉스 내부 구조를 꿰뚫어야 할 필요성이 있다면 이 책부터 시작하기 바란다. 대학교 4학년 이상이 읽기에 적합하다.

□ 『UNIX Internals: The New Frontiers』, Uresh Vahalia, Prentice Hall 1996
앞 서 『The Design of the UNIX Operating System』이 유닉스 내부 구조에 대한 바이블이라면 이 책은 다양한 유닉스 변종에 대한 주해서로 볼 수 있다. 명쾌한 설명과 풍부한 예제는 이 책을 손에서 떼기 어렵게 만든다. 대학교 4학년 이상이 읽기에 적합하다.

■ http://dictionary.cambridge.org/
캠브리지 온라인 사전이다.

■ http://wombat.doc.ic.ac.uk/foldoc/index.html
FOLDOC 컴퓨터 용어 전문 사전이다.

■ http://research.microsoft.com/~mbj/Mars_Pathfinder/Authoritative_Account.html
화성 탐사선인 패스파인더가 문제를 일으켰던 원인과 해결책을 설명한 글이다.

■ http://qdn.qnx.com/articles/dec1200/realtime.html
실시간과 실시간 운영체제에 대한 기본 소개가 나온 글이다.

■ http://www.faqs.org/faqs/realtime-computing/faq/
실시간에 대해 자주 나오는 각종 질문을 정리한 FAQ를 제공한다.

■ http://www.linuxdevices.com/files/elecjun00/yodaiken/yodaiken.pdf
FSMLabs에서 개발한 RTLinux에 대한 발표 자료이다. 하드 실시간을 리눅스에서 어떻게 구현했는지 설계 사상이 잘 나타나 있다.

■ http://fsmlabs.com/community/
FSMLabs에서 지원하는 RTLinux 커뮤니티 사이트이다. 설치 방법, FAQ, 백서와 같은 자료가 있다.

■ http://www.aero.polimi.it/projects/rtai/
리니오에서 지원하는 RTAI 커뮤니티 사이트이다. 설치 방법, FAQ, 백서와 같은 자료가 있다.

■ http://www.mvista.com/realtime/
몬타비스타에서 개발한 실시간 리눅스 커널 패치에 대한 홈페이지이다. 실시간 리눅스 커널 패치와 관련한 여러 자료가 있다.

■ http://www.mech.kuleuven.ac.be/~bruyninc/rthowto/rtHOWTO/rtHOWTO.html
실시간과 임베디드에 대한 How-to 문서로써, 기본 내용을 간결하면서도 체계적으로 정리하고 있다.

■ http://www.wired.com/news/print/0,1294,13987,00.html
윈도우 NT를 탑재한 미해군 USS 요크타운호가 두 시간 동안 바다에서 표류할 수 밖에 없었던 원인을 분석한 기사이다.

■ http://www.pasc.org/
포직스 표준을 제정하는 PASC(Portable Application Standards Committee) 홈페이지로, 포직스에 대한 정보도 얻을 수 있다.

■ http://www.delphion.com/details?pn=US05995745__
FSMLabs에서 출원한 RTLinux 관련 특허를 설명하는 페이지이다. 세부 내용을 모두 보려면 subscription이 필요하다.

목차

5장. 윈도우 시스템

□ 『러닝 리눅스 3판』, 매트 웰시, 라 카우프만, 칼레 딜하이머 저, 이만용 역, 한빛미디어, 2001

오 라일리 『Running Linux 3rd Edition』의 번역판이다. 리눅스를 처음 접하는 독자가 고민하면서 읽을 가치가 있는 ‘정보를 위한 정보를 담은 메타북(meta-book)’으로 리눅스라는 운영체제에 철학적으로 접근하는 구성 방식이 돋보인다. 운영체제를 전혀 모르는 완전 초보자에게는 다소 어려울 수도 있다.

□ 『Introduction to the X Window System』, Oliver Jones, Prentice-Hall, 1989
X 윈도우에 대한 고전적인 입문서이다. 1989년에 나왔기 때문에 편집 스타일은 상당히 볼품없지만 내용 자체만 놓고 보면 아주 훌륭하다. 페졸드가 지은 마이크로소프트 윈도우 프로그래밍 입문서와 비견할 만하다.

□ 『X Window System 2nd Edition』, Robert W. Scheifler & James Gettys, Digital Press, 1990
X를 만든 아버지인 세이플러와 게티스가 지은 X 윈도우 시스템에 대한 바이블이다. 최신 버전에 대한 내용은 X 윈도우 패키지 내부에서 온라인 문서 형식으로 찾을 수 있다.

□ 『The X Toolkit Cookbook』, Paul E. Kimball, PTR/PH, 1995
현재 나와있는 X 윈도우 툴킷 책 중에 가장 정리가 잘되어있으며, 숨겨진 몇몇 비밀을 명쾌하게 해설하고 있다. 모티프나 아데나 위젯을 사용하는 개발자라면 누구나 한번 정도 이 책을 읽을 필요가 있다.

□ 『Volume 1: Xlib Programming Manual』, Adrian Nye, O’Reilly, 1992
오늘날의 오라일리가 존재하도록 만든 초기 역작이다. X 환경에서 프로그램을 작성하는 방법에 대해 간결 명료하게 설명하고 있다.

■ http://wombat.doc.ic.ac.uk/foldoc/index.html
FOLDOC 컴퓨터 용어 전문 사전이다.

■ http://www.linuxdevices.com/articles/AT9202043619.html
임베디드 리눅스에서 사용하는 여러 공개/상용 윈도우 시스템을 소개하는 기사이다. 윈도우 시스템을 상당히 체계적으로 정리하고 있으므로 특히 첫 단추를 꿰는 개발자에게 적당하다.

■ http://www.linuxdevices.com/articles/AT9035650492.html
임베디드 리눅스에서 X 윈도를 적용함에 있어 고려할 여러 사항을 소개하는 발표 자료이다. 다른 기사와는 달리 상당히 정량적인 방법으로 접근하고 있으므로, 비교 자료로 사용하기에 부족함이 없다.

■ http://www.linuxdevices.com/links/LK4761626139.html
마이크로 윈도우 프로젝트에 대해 간략하게 소개하는 기사이다.

■ http://www.linuxdevices.com/links/LK7730481424.html
피코구이 프로젝트에 대해 간략하게 소개하는 기사이다.

■ http://www.xfree86.org
x86, MacOS, 기타 임베디드 시스템에서 동작하는 공개소스 X 윈도우 환경을 개발하기 위해 설립한 XFree86 프로젝트 홈페이지이다. XFree86 소프트웨어를 자유롭게 다운로드할 수 있다.

■ http://www.x.org
X 컨소시움 후속인 오픈 그룹 홈페이지이다. X 윈도우 시스템 원본 소스와 각종 응용 프로그램을 자유롭게 다운로드할 수 있다.

■ http://www.rahul.net/kenton/xsites.framed.html
필자가 본 인터넷에서 가장 뛰어난 X 윈도우와 모티프 정리 사이트이다. 그야말로 주옥 같은 자료들이 실려있으므로, X 윈도나 모티프 개발자라면 필요할 때마다 이 사이트에 들러서 필요한 정보를 얻기 바란다.

■ http://www.openmotif.org/
공개용 모티프 툴킷을 다운로드할 수 있는 홈페이지이다. 이 페이지는 현재 BX라는 사용자 인터페이스 생성도구로 유명한 ICS 사에서 관리하고 있다.

■ http://www.opengroup.org/openmotif/
오픈 그룹에서 관리하는 오픈 모티프 공식 홈페이지이다. 공개용 모티프 툴킷 최신 버전을 다운로드할 수 있으며, 모티프 개발자를 위한 공간도 마련하고 있다. 임베디드 모티프에 대한 정보도 찾을 수 있다.

■ http://www.motifdeveloper.com/news/news12.html
오라일리의 모티프 프로그래밍 매뉴얼과 레퍼런스 매뉴얼을 온라인 문서로 받아볼 수 있도록 지원하는 홈페이지이다.

■ http://www.lesstif.org/
모 티프를 자유롭게 쓸 목적으로 시작한 레스티프 프로젝트 홈페이지이다. 레스티프는 라이센스에 제한이 있는 공개용 모티프와는 달리 LGPL 라이센스를 따르므로 완벽한 공개 소스 소프트웨어이다. 레스티프는 모티프와 원시 코드 단계에서 거의 99% 호환성을 유지하므로, 각종 공개 소스 소프트웨어 개발자가 즐겨 사용하는 라이브러리이기도 하다.

■ http://www.gtk.org/
Gtk+ 공식 홈페이지이다. 다양한 프로젝트에 걸친 여러 자료를 얻을 수 있으며 최신 버전 라이브러리를 다운로드할 수도 있다.

■ http://www.efalk.org/Widgets/
X에서 사용할 수 있는 각종 위젯 집합을 비교한 기사이다. 다양한 위젯 집합을 기능과 외양면에서 분석하고 있으므로, 개발에 필요한 툴킷을 선택할 때 참조하기 바란다.

■ http://www.microwindows.org/
마이크로 윈도우 공식 홈페이지이다. 원시 코드를 다운로드할 수 있으며, 각종 매뉴얼과 학습서도 얻을 수 있다.

■ http://www.fltk.org
X11, 마이크로소프트 윈도우, 마이크로 윈도우에서 쓸 수 있는 FLTK 프로젝트 공식 홈페이지이다.

■ http://tinywidgets.sourceforge.net/
마이크로 윈도우에서 쓸 수 있는 타이니 위젯 프로젝트 공식 홈페이지이다.

■ http://www.trolltech.com/
Qt와 Qt/임베디드를 만든 트롤테크 홈페이지이다.

■ http://pgui.sourceforge.net/
피코구이 공식 홈페이지이다. 각종 기사와 문서를 얻을 수 있으며, 피코구이 패키지도 다운로드할 수 있다.

목차

2부. 임베디드 리눅스 개발 방법론

6장. 제품 기획 단계에서 고려할 사항

□ 『C∙C++로 작성하는 임베디드 시스템 프로그래밍』, 마이클 바 저, 이석주 역, 한빛미디어, 2000
C 와 C++ 프로그래밍 언어를 사용해 임베디드 시스템을 제작하는 방법을 기술한다. 아쉽게도 이 책에 나오는 보드를 국내에서 구하기 어려워 본격적인 실습이 불가능하다. 하지만 임베디드 시스템에 대한 개념을 단기간에 잡기에는 적당하다.

□ 『Embedded Linux』, John Lombardo, New Riders, 2002

x86 플랫폼에서 리눅스를 최소한으로 패키징하는 방법을 기술한다. 아주 뛰어나거나 새로운 내용은 담고 있지 않지만, x86에서 임베디드 리눅스를 재미로 탑재해보려는 초보자에게는 도움을 줄 수 있다.

7장. 타겟 보드 선정 방법

□ 『C, C++로 작성하는 임베디드 시스템 프로그래밍』, 마이클 바 저, 이석주 역, 한빛미디어, 2000

C 와 C++ 프로그래밍 언어를 사용하여 임베디드 시스템을 제작하는 방법을 기술하고 있다. 아쉽게도 이 책에 나오는 보드를 국내에서 구하기가 어렵기 때문에 본격적인 실습이 불가능하다는 단점이 있다. 하지만 임베디드 시스템에 대한 개념을 단기간에 잡기에는 적당하다.

□ SWAN-II 사용자 설명서

아이트로닉스(제품에 포함)

■ http://www.linuxdevices.com/articles/AT4548672342.html
포스트-PC 시대를 도래해 임베디드 리눅스를 동작시킬 수 있는 SOC에 대해 소개하는 홈페이지이다.

■ http://www.linuxdevices.com/articles/AT4313418436.html
리눅스를 적용할 수 있는 각종 SOC(System On Chip)에 대한 정보를 모아놓은 홈페이지이다. ARM, MIPS, MPC, x86을 기반으로 각종 제품을 소개한다.

■ http://www.uclinux.org/
MMU가 없는 CPU를 위한 리눅스인 uClinux 공식 홈페이지이다.

■ http://www.advantech.com/products/PCM-5824.asp
어드밴텍에서 만든 Geode 기반 SBC(Single Board Computer)인 PCM-5824에 대한 각종 자료를 제공한다.

■ http://www.national.com/appinfo/solutions/0,2062,239,00.html
네셔날 세미컨덕터에서 만든 SOC인 Geode에 대한 각종 자료를 제공한다.

■ http://www.linuxdevices.com/products/PD7399900675.html
인텔에서 만든 SA-1110 마이크로프로세스 개발 참조 보드에 대한 간략한 정보를 제공한다.

■ http://developer.intel.com/design/pca/applicationsprocessors/manuals/index.htm
인텔에서 만든 각종 마이크로프로세스에 대한 문서를 모아놓은 홈페이지이다.

■ http://developer.intel.com/design/strong/datashts/278241.htm
인텔에서 만든 SA-1110 마이크로 프로세스에 대한 간략한 데이터시트를 제공하는 홈페이지이다.

■ http://developer.intel.com/design/strong/guides/278278.htm
인텔에서 만든 SA-1110 마이크로 프로세스 개발 참조 보드인 아사벳에 대한 각종 자료를 제공하는 홈페이지이다.

■ http://www.linfos.co.kr/htm/pro_li01.htm
린포스에서 만든 SA-1110 마이크로 프로세스 개발 참조 보드인 TBEL1110에 대한 각종 자료를 제공하는 홈페이지이다.

■ http://developer.intel.com/design/intelxscale/
인텔에서 개발한 StrongARM 후속 버전인 XScale에 대한 공식 홈페이지이다.

■ http://www.ipaqlinux.com/
StrongARM을 탑재한 PDA인 iPAQ에 리눅스를 탑재하는 데 필요한 정보와 링크를 모아놓은 홈페이지이다.

■ http://www.handhelds.org/
StrongARM을 탑재한 PDA인 iPAQ을 위한 리눅스 배포판과 설치 노하우를 모아놓은 홈페이지이다.

■ http://www.arm.com/
가장 널리 사용하는 32비트 RISC 방식 임베디드 CPU를 설계한 ARM 본사 홈페이지이다.

■ http://www.itronixit.co.kr/products_cpu_swan2.html
아이트로닉스에서 만든 MPC860 기반 SBC(Single Board Computer)인 SWAN-II에 대한 각종 자료를 제공하는 홈페이지이다.

■ http://e-www.motorola.com/webapp/sps/site/prod_summary.jsp?code=MPC860&nodeId=01M0ypBDKCb
모토로라에서 만든 파워PC 계열 SOC인 MPC860에 대한 각종 자료를 제공한다.

■ http://e-www.motorola.com/brdata/PDFDB/docs/MPC860EC.pdf
MPC860에 대한 상세 정보를 제공하는 PDF 파일이다.

■ http://e-www.motorola.com/webapp/sps/site/taxonomy.jsp?nodeId=01M0ypBDKCb
모토로라에서 파워PC 코어 기반으로 만든 MPC8xx 계열 CPU에 대한 비교 정보를 제공한다.

■ http://penguinppc.org/embedded/
파워PC를 채택한 임베디드 시스템을 위한 각종 자료를 제공한다.

■ http://www.macraigor.com/zenofbdm.pdf
BDM에 대한 멋진 소개서이다. BDM에 대한 역사와 간략한 디버깅 방법을 기술하고 있다.

■ [통계] http://www.linuxdevices.com/files/article011/sld023.html
임베디드 개발자가 향후 채택하리라 예상되는 CPU 비율을 보여주는 자료이다.

■ [통계] http://www.linuxdevices.com/files/article011/sld024.html
임베디드 개발자가 향후 채택하리라 예상되는 하드웨어 플랫폼 비율을 보여주는 자료이다.

■ [통계] http://www.linuxdevices.com/files/article011/sld025.html
임베디드 개발자가 향후 채택하리라 예상되는 주변 장치를 보여주는 자료이다.

■ [통계] http://www.linuxdevices.com/files/article011/sld026.html
임베디드 개발자가 향후 채택하리라 예상되는 운영체제를 올리기 위해 사용하는 장치를 보여주는 자료이다.

목차

8장. 장치 선정과 드라이버 구현

□ 『리눅스 장치 드라이버』, 알렉산드로 루비니 저, 김인성/류태중 역, 한빛미디어, 2000

리눅스에서 장치 드라이버를 제작하는지 방법을 구체적으로 소개한다. 리눅스 커널에 대해 어느 정도 지식이 있어야 하므로 초보자가 읽기에는 적합하지 않다. 단점은 커널 2.2에 대해서 다룬다는 점이다.

□ 『Linux Device Driver 2nd Ed』, Alessandro Rubini, O’Reilly, 2001
『리눅스 장치 드라이버』 원서 2판으로 커널 2.4를 다룬다. 인쇄 버전은 물론이고 일부 발췌가 아닌 완벽한 온라인 버전까지 나와 있으므로 큰 부담 없이 읽을 수 있다.

□ 『네트워크 프린팅』, 토드 레이더마커, 매튜 개스트 저, 박재호, 이영미 역, 한빛미디어, 2001

리눅스와 유닉스를 서버로, 윈도우, 맥, 넷웨어를 클라이언트로 구성한 네트워크 환경에서 인쇄하는 방법을 기술한다. BOOTP, DHCP와 같은 네트워크 프로토콜을 사용해 프린터를 부팅하는 방법도 소개한다.

□ 리눅스 커널 내부 /Documentation/devices.txt
리눅스에서 제공하는 각종 장치에 대한 간략한 소개와 장치 번호를 정의한 문서이다. 리눅스에서 장치 드라이버를 사용하거나 만들기 위해 반드시 참조해야 하는 표준 문서이다.

■ http://lhd.datapower.com/
리눅스에서 사용할 수 있는 각종 하드웨어 데이터베이스를 제공하는 홈페이지이다. 제품 이름이나 제품 카테고리로 검색할 수 있다.

■ http://www.tldp.org/HOWTO/Hardware-HOWTO/
리눅스 하드웨어 호환성과 관련한 HOW-TO 문서이다. 다양한 주변 장치에 대한 호환성 여부를 알려준다. 제품 이름이나 카테고리를 통한 검색은 불가능하며, 목차에서 찾아 들어가기 바란다.

■ http://www.tldp.org/HOWTO/HOWTO-INDEX/hardware.html
리눅스에서 사용할 수 있는 하드웨어에 대한 HOW-TO를 집대성한 색인을 제공하는 홈페이지이다.

■ http://www.torque.net/linux-pp.html
리눅스에서 사용할 수 있는 외장 주변 장치(PC와 병렬 포트로 통신)에 대한 링크와 제품 목록을 제공하는 홈페이지이다.

■ http://www.redhat.com/support/hardware/
가장 대표적인 배포판 회사인 레드햇을 위한 리눅스 호환 하드웨어 목록을 제공하는 홈페이지이다. 다양한 방법(제조사/카테고리/하드웨어 클래스/배포판 종류/인증 상태)으로 하드웨어를 검색할 수 있다.

■ http://www.linuxhardware.net/
리눅스 관련 각종 하드웨어와 장치 드라이버를 검색할 수 있도록 데이터베이스를 제공하는 홈페이지이다. 일반 사용자 참여로 데이터베이스를 갱신하고 있다는 사실이 흥미롭다.

■ http://www.linux-usb.org/
리눅스에 탑재한 USB 스택에 대한 정보를 제공하는 홈페이지이다. FAQ와 유용한 링크를 담고 있다.

■ ftp://ftp.compaq.com/pub/supportinformation/papers/ecg0480997_a4.pdf
OHCI와 UHCI 차이점을 설명한 문서이다. 상당히 깔끔하게 정리되어 있으므로, USB에 대한 개념을 잡는 데 도움을 받을 수 있다.

■ http://usb.cs.tum.edu/usbdoc/
리눅스에서 USB 장치 드라이버를 작성하는 방법을 설명하는 홈페이지이다.

■ http://whatis.techtarget.com/definition/0,,sid9_gci537791,00.html
I2C에 대한 사전적인 정의를 소개하는 홈페이지이다.

■ http://www.connectworld.net/cable-length.html

직렬/병렬/스카시 포트에 연결할 수 있는 케이블 길이 제한에 대해 소개하는 홈페이지이다.

■ http://www.pcisig.com/news_room/faqs
다양한 PCI 규약에 대한 질문과 응답을 싣고 있는 홈페이지이다.

■ http://pcmcia-cs.sourceforge.net/
리눅스에서 PCMCIA를 사용하는 데 필요한 각종 정보를 제공하는 홈페이지이다. 리눅스에서 PCMCIA 장치를 사용하고 싶다면 여기를 먼저 방문하기 바란다.

■ http://pcmcia-cs.sourceforge.net/ftp/doc/PCMCIA-PROG.html
리눅스에서 PCMCIA용 장치 드라이버를 개발하는 데 도움을 주는 프로그래머 가이드이다.

■ http://linux1394.sourceforge.net/hcl.php
리눅스에서 사용할 수 있는 IEEE 1394(파이어와이어) 주변 장치 목록을 제공하는 홈페이지이다.

■ http://www.skipstone.com/wizard.html
IEEE 1394와 관련한 FAQ 모음집이다.

■ http://irda.sourceforge.net/
리눅스에서 IrDA용 장치 드라이버를 설치하고 사용하는 데 도움이 되는 정보를 제공하는 홈페이지이다.

■ http://mobilix.org/ir_misc.html
리눅스에서 사용할 수 있는 IrDA 주변 장치를 소개하는 홈페이지이다. 데이터베이스 검색은 불가능하며 전체 목록이 한꺼번에 나온다.

■ http://www.lirc.org
리눅스에서 IrDA로 여러 주변 장치를 제어할 수 있는 패키지를 소개하는 홈페이지이다.

■ http://delbert.matlock.com/linux-bluetooth.htm#howto
리눅스에서 블루투스를 사용하는데 필요한 각종 정보를 제공하는 홈페이지이다. 다양한 드라이버와 문서를 싣고 있으므로 블루투스에 관심이 많은 개발자라면 반드시 여기를 방문하기 바란다.

■ http://www.microsoft.com/hwdev/bus/1394/1394tech.asp
마이크로소프트사에서 만든 IEEE1394 관련 특장점을 설명하는 홈페이지이다. 윈도우 관련 내용이 많이 있지만, 일반적인 특성을 파악하는 데 큰 무리가 없을 것이다.

■ http://www.linux-mtd.infradead.org/
리눅스를 위한 MTD(Memory Technology Device) 서브 시스템과 관련있는 각종 사항을 정리한 홈페이지이다.

목차

9장. 임베디드 리눅스 이식 절차

□ 『Embedded Linux: Hardware, Software, and Interfacing』, Dr. Craig Hollabaugh, Addison-Wesley, 2002

임베디드 리눅스에 대해 체계적으로 잘 구성된 책이다. 절반 이상이 인터페이스하는 방법에 대한 소개이므로, 일정 수준 이상의 개발자가 보기에 적당하다.

□ 『삼바 활용하기』, 로버트 에크슈타인, 데이비드 칼리어-브라운, 피터 켈리 저, 박재호/이영미 역, 한빛미디어, 2001
리 눅스나 유닉스 환경에서 네트워크로 윈도우 클라이언트에 공유 파일과 프린팅 서비스를 해주는 소프트웨어인 삼바를 소개한다. 삼바를 사용하면 네트워크로 물린 이기종 컴퓨터 사이에 자원을 쉽게 공유할 수 있으므로, 윈도우쪽으로 기울어진 개발 환경을 리눅스쪽으로 돌리는 데 도움을 줄 수 있다.

□ 『네트워크 프린팅』, 토드 레이더마커, 매튜 개스트 저, 박재호, 이영미 역, 한빛미디어, 2001

리눅스와 유닉스를 서버로, 윈도우, 맥, 넷웨어를 클라이언트로 구성한 네트워크 환경에서 인쇄하는 방법을 기술한다. BOOTP, DHCP와 같은 네트워크 프로토콜을 사용해 프린터를 부팅하는 방법도 소개한다.

□ 『러닝 리눅스 3판』, 매트 웰시, 라 카우프만, 칼레 딜하이머 저, 이만용 역, 한빛미디어, 2001

오 라일리 『Running Linux 3rd Edition』의 번역판이다. 리눅스를 처음 접하는 독자가 고민하면서 읽을 가치가 있는 ‘정보를 위한 정보를 담은 메타북(meta-book)’으로 리눅스라는 운영체제에 철학적으로 접근하는 구성 방식이 돋보인다. 운영체제를 전혀 모르는 완전 초보자에게는 다소 어려울 수도 있다.

□ 『Embedded Linux』, John Lombardo, New Riders, 2002

x86 플랫폼에서 리눅스를 최소한으로 패키징하는 방법을 기술한다. 아주 뛰어나거나 새로운 내용은 담고 있지 않지만, x86에서 임베디드 리눅스를 재미로 탑재해보려는 초보자에게는 도움을 줄 수 있다.

□ 『GNU 소프트웨어로 프로그래밍 하기』, 마이크 루키디스, 앤디 오람 저, 이기동 역, 한빛미디어, 2000

오 라일리 『Programming with GNU Software』의 번역판이다. 문서 편집기인 이맥스, C/C++ 컴파일러인 gcc, 디버거인 gdb, 컴파일 자동화 도구인 make, 소스 관리 시스템인 RCS에 대해 입문하는 병아리 개발자에게 안내자 구실을 한다. 아쉽게도 중급 개발자에게는 부적합하다.

■ http://www.aleph1.co.uk/armlinux/devboards/Assabet-HOWTO/t1.html
아사벳에 임베디드 리눅스를 이식하는 절차를 일목요연하게 정리한 HOW-TO 문서이다. 아사벳에 임베디드 리눅스를 이식해야 한다면 꼭 살펴보기 바란다.

■ http://www-2.cs.cmu.edu/~wearable/software/assabet.html
역 시 아사벳에 임베디드 리눅스를 이식하기 위해 필요한 자료를 모아놓은 홈페이지이다. 각종 링크가 이식 순서에 맞춰 잘 나와있으므로 이식 과정에서 필요한 소프트웨어를 구할 경우에 많은 도움을 받을 수 있다. 다른 홈페이지에 비해 최신 버전으로 갱신하는 속도이 빠르다는 장점이 있다.

■ http://www-2.cs.cmu.edu/~wearable/software/docs/assabet-linux-report/intel-report.html
인 텔 아사벳 참조 보드에 ARM 리눅스를 올리는 방법을 체계적으로 기술한 기술 보고서이다. 미국립 과학재단에서 발주하고 미국 카네기 멜론 대학교의 웨어러블(Wearable) 그룹에서 수행한 프로젝트 결과 보고를 위해 만든 문서이다.

■ http://www.aleph1.co.uk/armlinux/thebook.html
다 양한 ARM 임베디드 시스템에 임베디드 리눅스를 이식하는 방법을 소개하는 온라인 책이다. 원래 StrongARM을 사용한 참조 보드인 LART를 위해 만든 책이지만, 아사벳에 대해서도 충분히 참조할만한 가치가 있는 내용을 담고 있다.

■ http://penguinppc.org/embedded/howto/PowerPC-Embedded-HOWTO.html
MPC 플랫폼을 위한 교차 개발 환경 구축 방법, PPCBOOT 설치와 사용법, 부팅에 필요한 각종 설정, 패키징 관련 내용을 체계적으로 소개하는 문서이다.

■ http://developer.intel.com/design/strong/applnots/sa1100lx/sa1100lx.htm
인텔에서 만든 자료로, 아사벳을 위한 교차 참조 개발 환경을 구축하는 방법을 소개한다.

■ http://sources.redhat.com/binutils/
GNU binutils에 대한 홈페이지이다. 들어있는 프로그램과 각 프로그램 구실을 간략하게 설명한다.

■ http://www.astonlinux.com/
윈도우 환경에서 임베디드 리눅스를 개발할 수 있게 지원하는 툴인 코드메이커 개발사 홈페이지이다.

■ http://www.linux.org/docs/ldp/howto/Glibc2-HOWTO.html
glibc 버전 2를 리눅스 시스템에 설치하고 활용하는 방법/하는 HOW-TO 문서이다.

■ http://www.linuxdoc.org/HOWTO/mini/Partition/
리눅스에서 스왑 영역을 잡는 방법을 친절하게 설명하는 HOW-TO 문서이다.

■ http://kldp.org/HOWTO/html/Kernel/Kernel-HOWTO.html
리눅스에서 커널 환경을 설정하고 컴파일하는 방법을 설명하는 HOW-TO 문서이다. 2.2.x 계열 설명이므로 시대에 조금 뒤떨어졌다고 생각할 수도 있으나 기본 사항을 충분히 잘 설명하고 있다.

■ http://kldp.org/KoreanDoc/html/2.4Kernel_Compile-KLDP/2.4Kernel_Compile-KLDP.html

리눅스 커널 2.4를 환경 설정하고 컴파일하는 방법을 소개하는 HOW-TO 문서이다.

■ http://kldp.org/KoreanDoc/html/Kernel_Compile_Guide-KLDP/Kernel_Compile_Guide-KLDP.html
리눅스 커널을 컴파일하는 기본 절차를 소개하는 문서이다. 역시 커널 2.2 계열이라서 조금 낡았다는 느낌이 들지만 전반적인 감을 잡기에는 부족함이 없다.

■ http://option.kernel.pe.kr/
리눅스 커널 환경 설정 도움말을 한글로 이식하는 프로젝트를 위한 홈페이지이다. 최신 커널 버전을 꾸준히 쫓아오고 있으므로, 리눅스 커널을 설정하다 지쳐버린 사람들에게 많은 도움을 줄 수 있으리라 확신한다.

■ http://kldp.org/HOWTO/mini/html/LILO/LILO.html
실례를 들어 리눅스 표준 부트 스트랩 로더인 LILO를 어떻게 설정하는지 설명하고 있는 문서이다.

■ http://penguinppc.org/embedded/cross-compiling/
MPC용 교차 개발 환경 컴파일 방법이다. 잘못된 내용이 들어있기 때문에, 단순히 참고용으로만 활용하기 바란다

■ http://www.armlinux.org/docs/toolchain/toolchHOWTO/x183.html
ARM용 교차 개발 환경 컴파일 방법이다. 조금 잘못된 내용이 들어있기 때문에, 단순히 참고용으로만 활용하기 바란다.

■ http://www.delorie.com/gnu/docs/glibc/libc_toc.html
GNU에서 개발한 기본 라이브러리인 glibc에 대한 온라인 북이다.

■ http://sources.redhat.com/newlib/
레드햇에서 만든 glibc를 대체할 경량 기본 라이브러리인 newlib에 대한 홈페이지이다.

■ http://www.uclibc.org/
임베디드 리눅스 시스템을 위한 경량 기본 라이브러리인 uclibc에 대한 홈페이지이다.

■ http://www.fefe.de/dietlibc/
크기에 신경을 써서 만든 기본 라이브러리인 diet libc에 대한 홈페이지이다.

■ http://www.embedded.com/story/OEG20011220S0058
경량 라이브러리인 newlib에 대해 소개하는 홈페이지이다.

■ http://www.netsonic.fi/~walker/minicom.html
유닉스에서 사용할 수 있는 직렬 통신을 지원하는 터미널 흉내내기 프로그램인 minicom 홈페이지이다.

■ http://www.tldp.org/HOWTO/mini/LILO.html
가장 널리 알려진 x86용 부트 스트랩 로더인 LILO를 설명하는 미니 HOW-TO이다. LILO 환경 설정과 주의 사항을 소개한다.

■ http://www.linuxgazette.com/issue64/kohli.html
강력한 x86용 부트 스트랩 로더인 GNU GRUB를 소개하는 홈페이지이다. GRUB이 무엇인지, 설치를 어떻게 하는지, 환경 설정을 어떻게 하는지 설명한다.

■ http://www.aleph1.co.uk/armlinux/docs/ARMbooting/t1.html
ARM에서 동작하는 각종 부트 스트랩 로더를 소개하는 온라인 기사이다.

■ http://armboot.sourceforge.net/
강력한 ARM와 StrongARM용 부트 스트랩 로더인 ARMBOOT에 대해 소개하는 홈페이지이다. 여기서 원시 코드를 다운로드할 수도 있고 간단한 설명도 읽을 수 있다.

■ http://sourceforge.net/projects/blob/
SA11x0(StrongARM)용 부트 스트랩 로더인 BLOB를 소개하는 홈페이지이다. 여기서 원시 코드를 다운로드할 수도 있고 간단한 설명도 읽을 수 있다.

■ http://www.handhelds.org/z/wiki/bootldr
컴팩에서 만든 StrongARM을 사용한 PDA인 iPAQ에서 동작하는 부트 스트랩 로더인 bootldr를소개하는 홈페이지이다.

■ http://www.wearablegroup.org/software/bootldr/
iPAQ용 부트 스트랩 로더인 bootldr을 간략하게 설명하는 홈페이지이다.

■ http://ppcboot.sourceforge.net/
임베디드 파워PC를 위한 부트 스트랩 로더인 PPCBOOT를 소개하는 홈페이지이다. 프로젝트 진행에 따른 변경 사항과 간략한 설명을 한눈에 확인할 수 있다.

■ http://www.redhat.com/embedded/technologies/redboot/
다중 플랫폼을 지원하는 강력한 부트 스트랩 로더인 REDBOOT를 소개하는 홈페이지이다. 레드햇답게 문서 정리를 깔끔하게 잘 해놓았다.

■ http://tinylogin.busybox.net/
경량급이면서도 필요한 기능을 모두 갖추고 있는 임베디드 리눅스에서 동작하는 로그인 프로그램인 tinylogin 홈페이지이다.

■ http://www.busybox.net/
GNU fileutils, shellutils에 들어있는 각종 프로그램을 하나로 묶어놓은 임베디드 리눅스를 위한 맥가이버 칼(스위스 군용 칼이 정확한 표현이지만 여기서는 편의상 맥가이버 칼로 지칭한다)인 busybox 홈페이지이다.

■ http://www.wearablegroup.org/software/ramdisk/
ARM(특히 아사벳)을 위한 램디스크를 제공하는 홈페이지이다.

■ ftp://ftp.denx.de/pub/LinuxPPC/usr/src/
MPC를 위한 램디스크를 제공하는 홈페이지이다.

■ http://kpreempt.sourceforge.net/
x86, 리눅스 커널 선점 확장 프로젝트 공식 홈페이지이다.

■ http://www.ittc.ku.edu/kurt/
또 다른 x86 리눅스 커널 선점 확장 프로젝트인 KURT 공식 홈페이지이다.

■ http://www.aero.polimi.it/~rtai/
RTAI 실시간 리눅스 확장 프로젝트 공식 홈페이지이다.

■ http://www.fsmlabs.com/community/
RTLinux 커뮤니티 공식 홈페이지이다.

■ http://www.linux-fbdev.org/
리눅스 프레임 버퍼, 프레임 버퍼 장치, 관련 사이트를 체계적으로 정리한 홈페이지이다.

■ http://gtf.org/garzik/video/
리눅스 비디오 드라이버와 프레임 버퍼에 대한 링크를 체계적으로 정리한 홈페이지이다.

■ http://www.tldp.org/HOWTO/Framebuffer-HOWTO.html
리눅스 프레임 버퍼 HOW-TO 문서로, 프레임 버퍼에 대한 일반론과 플랫폼별 특성을 소개한다.

■ http://www.microwindows.org/
마이크로 윈도우 공식 홈페이지이다. 원시 코드를 다운로드할 수 있으며, 각종 매뉴얼과 학습서도 구할 수 있다.

■ http://www.xfree86.org
x86, MacOS, 기타 임베디드 시스템에서 동작하는 공개 소스 X 윈도우 환경을 개발하기 위해 설립한 XFree86 프로젝트 홈페이지이다. XFree86 소프트웨어를 자유롭게 다운로드할 수 있다.

■ http://pgui.sourceforge.net/
피코구이 공식 홈페이지이다. 각종 기사와 문서를 얻을 수 있으며, 피코구이 패키지도 다운로드할 수 있다.

목차

10장. 임베디드 환경에서 응용 프로그램 개발 절차

□ 『Rapid Development: Taming Wild Software Schedules』, Steve McConnell, Microsoft Press 1996
소프트웨어를 짧은 시간 내 성공리에 개발하는 데 필요한 각종 지식을 총 집결시켜놓은 멋진 책이다. 이론뿐만 아니라 실전에 바로 써먹을 수 있는 내용으로 가득 하다. 관리자는 물론, 일반 개발자도 필독할 가치가 있는 책이다.

□ 『Software Project Survival Guide』, Steve McConnell, Microsoft Press, 1998
소프트웨어 개발 생명 주기 동안 벌어지는 각종 활동 내역을 위험 관리라는 측면에서 이끌어내는 방법을 명쾌하게 설명한다. “Rapid Development”와 더불어 관리자와 개발자가 꼭 읽어야 하는 필독서이다.

□ 『러닝 리눅스 3판』, 매트 웰시, 라 카우프만, 칼레 딜하이머 저, 이만용 역, 한빛미디어, 2001

오 라일리 『Running Linux 3rd Edition』의 번역판이다. 리눅스를 처음 접하는 독자가 고민하면서 읽을 가치가 있는 ‘정보를 위한 정보를 담은 메타북(meta-book)’으로 리눅스라는 운영체제에 철학적으로 접근하는 구성 방식이 돋보인다. 운영체제를 전혀 모르는 완전 초보자에게는 다소 어려울 수도 있다.

□ 『GNU 소프트웨어로 프로그래밍 하기』, 마이크 루키디스, 앤디 오람 저, 이기동 역, 한빛미디어, 2000

오 라일리 『Programming with GNU Software』의 번역판이다. 문서 편집기인 이맥스, C/C++ 컴파일러인 gcc, 디버거인 gdb, 컴파일 자동화 도구인 make, 소스 관리 시스템인 RCS에 대해 입문하는 병아리 개발자에게 안내자 구실을 한다. 아쉽게도 중급 개발자에게는 부적합하다.

□ 『The UNIX Programming Environment』, Brian Kernighan, Rob Pike, Prentice-Hall, 1984
고전 중의 고전인 이 책은 유닉스에서 프로그램을 개발하는 표준적인 방법론을 간략하면서도 짜임새 있게 다룬다.

□ 『Software Tools in Pascal』, Brian Kernighan, P Plauger, Addison-Wesley, 1981
『The UNIX Programming Environment』와 더불어 유닉스 프로그래밍 철학을 이해하는 데 중요한 책이다. C의 인기에 밀린 파스칼로 모든 코드를 소개하지만 중요한 것은 형식이 아니라 철학이라는 사실을 잊지 말자.

□ 『The Unix Network Programming』, W. Richard Stevens, Prentice-Hall, 1994
유닉스에서 네트워크 프로그램을 작성하려고 마음먹은 개발자 누구나 이 책을 읽을 필요가 있다. 더 이상의 설명이 필요없는 명작이다.

□ 『Advanced Programming in the UNIX Environment』, W. Richard Stevens, Addison-Wesley, 1992
유닉스 환경에서 시스템 프로그래밍을 하는 방법을 체계적이고 자세하게 다룬 책으로 “The Unix Network Programming”과 함께 읽으면 더욱 큰 효과를 얻을 수 있다.

□ 『유닉스 시스템 프로그래밍 SVR4』, 데이비드 커리 저, 이수진/이성희 역, 한빛미디어 , 2001
시 스템 V쪽에 치우쳐 설명하고 있지만, 유닉스 시스템 호출과 각종 라이브러리 저변에 깔린 기본 원리를 충실히 다루고 있으므로 시스템 V는 물론이고 리눅스와 BSD 계열을 사용하는 시스템 소프트웨어 개발자도 이 책을 반드시 읽어야 한다.

□ 『Programming for the real world: POSIX.4』, Bill O. Galleister, O’Reilly & Associates, 1995
실시간 프로그램을 위한 C 인터페이스인 POSIX.4에 대해 상세하게 다루는 책이다. 초보자가 보기에는 내용이 조금 어렵지만 본격적인 실시간 프로그램을 위해서는 반드시 읽고 넘어가야 한다.

□ 『Pthreads Programming』, Bradford Nichols, Dick Buttlar, Jacqueline Proulx Farrell, O’Reilly, 1996
포직스 스레드(Pthreads)에 대한 이론과 실전을 다루는 책으로 Pthreads로 프로그램을 작성하는 개발자는 반드시 읽어봐야 하는 필독서이다.

□ 『Practical UNIX Programming: A Guide to Concurrency, Communication, and Multithreading』, Kay A. Robbins, Steven Robbins, Prentice-Hall, 1996
실질적인 네트워크와 시스템 프로그래밍 작성 예제를 많이 제공하는 책이다. 포직스 스레드 프로그래밍과 동기화에 대한 내용도 들어있다.

□ 『배시 셸 시작하기』, 캐머런 뉴햄, 빌 로젠블랫 저, 배창렬 역, 한빛미디어, 2001
리눅스 표준 셸인 배시 셸에 대해 기초부터 차근차근 설명하는 책이다. 배시 셸은 이런저런 소프트웨어를 합치는 결합 언어(glue language)로 사용하기 적합하므로, 임베디드 시스템 개발자라도 알아두면 편리할 때가 많다.

■ http://pauillac.inria.fr/~xleroy/linuxthreads/
리눅스를 위한 포직스 1003.1c 스레드 패키지인 LinuxThreads에 대한 소개와 각종 링크를 제공하는 홈페이지이다.

■ http://www.cvshome.org/cyclic/cyclic-pages/rcs.html
RCS에 대해 소개하는 홈페이지이다. RCS와 관련한 각종 링크를 제공하므로 여기서 시작하면 된다.

■ http://www.cvshome.org/cyclic/cyclic-pages/sccs.html
SCCS에 대해 소개하는 홈페이지이다.

■ http://www.cvshome.org/
CVS(Concurrent Versions System) 관련 공식 홈페이지이다. CVS에 대한 매뉴얼과 소프트웨어를 다운로드할 수 있다.

■ http://www.wi.leidenuniv.nl/~wichert/strace/
리눅스에서 사용할 수 있는 시스템 호출 추적 툴인 strace 공식 홈페이지이다.

■ http://freshmeat.net/projects/ltrace/?topic_id=846%2C47
리눅스에서 사용할 수 있는 동적 라이브러리 호출 감시 툴인 ltrace 공식 홈페이지이다.

■ http://www.redhat.com/software/tools/gnupro/gnupro_gdb.html#gdb
gdb 기능에 대해 간략하게 소개하고 있는 레드햇사 홈페이지이다.

■ http://gcc.gnu.org/
gcc 공식 홈페이지이다. 필요한 각종 문서와 소프트웨어를 다운로드할 수 있다.

■ http://www.linuxgazette.com/issue71/joshi.html
gcc에서 최적화 작업을 수행하는 몇 가지 방법의 주요 원리를 설명하는 홈페이지이다.

■ http://www.cs.may.ie/~jpower/Courses/se209/optim/gcc_2.html
최적화를 위한 각종 gcc 옵션을 설명하는 홈페이지이다.

■ http://www.gnu.org/manual/gprof-2.9.1/html_node/gprof_toc.html
GNU 프로파일러인 gprof 에 대한 사용 설명서이다. 한글 번역판은 http://purple.icu.ac.kr/~kimkk/guide/gprof/gprof_toc.html를 참조하기 바란다.

■ http://www710.univ-lyon1.fr/~yperret/fnccheck/doc.html
gcc에서 사용할 수 있는 신형 프로파일러인 fncdump에 대한 소개 문서이다. 한글 번역판은 http://purple.icu.ac.kr/~kimkk/guide/functioncheck/#SEC_1를 참조하기 바란다.

■ http://www.redhat.com/software/gnupro/technical/gnupro_gcc.html

gcc 프로젝트를 이끌고 있는 레드햇사에서 개발한 상용 프로그램인 GNUPro 패키지에서 제공하는 최적화 기법을 소개하는 기사이다.

목차

11장. 개발 후 상용 제품을 위한 패키징

□ 『Embedded Linux: Hardware, Software, and Interfacing』, Dr. Craig Hollabaugh, Addison-Wesley, 2002

임베디드 리눅스에 대해 체계적으로 잘 구성된 책이다. 절반 이상이 인터페이스하는 방법에 대한 소개이므로, 일정 수준 이상의 개발자가 보기에 적당하다.

□ 『Embedded Linux Devleopment: Building Embedded Linux Systems(MPC8xx)』, 교육자료, Adelinux 2001

□ 『Embedded Linux Devleopment: Building Embedded Linux Systems(StrongARM)』, 교육자료, Adelinux 2001

■ http://www-903.ibm.com/developerworks/kr/linux/library/l-fs.html,

http://www-903.ibm.com/developerworks/kr/linux/library/l-fs2.html,

http://www-903.ibm.com/developerworks/kr/linux/library/l-fs3.html,

http://www-903.ibm.com/developerworks/kr/linux/library/l-fs4.html,

http://www-903.ibm.com/developerworks/kr/linux/library/l-fs5.html,

http://www-903.ibm.com/developerworks/kr/linux/library/l-fs6.html,

http://www-903.ibm.com/developerworks/kr/linux/library/l-fs7.html,

http://www-903.ibm.com/developerworks/kr/linux/library/l-fs8.html,

http://www-903.ibm.com/developerworks/kr/linux/library/l-fs9.html,

http://www-903.ibm.com/developerworks/kr/linux/library/l-fs10.html
IBM developerWorks에서 연재한 저널링 파일시스템 특집 기사이다. 저널링 파일시스템에 대해 일목요연하게 정리하고 있으므로 읽을만한 가치가 있다.

■ http://e2fsprogs.sourceforge.net/ext2.html
EXT2 파일시스템 홈페이지이다. EXT2 파일시스템에 대한 설명과 링크를 제공한다.

■ http://www.zipworld.com.au/~akpm/linux/ext3/
EXT3 파일시스템 홈페이지이다. EXT3 파일시스템에 대한 설명과 소프트웨어, 링크를 제공한다.

■ http://www.namesys.com/
ReiserFS 파일시스템을 만든 namesys.com 홈페이지이다. ReiserFS에 대한 각종 기술 데이터를 제공한다.

■ http://www.linuxfocus.org/English/July2001/article210.shtml
신형 리눅스 램디스크 파일시스템인 ramfs를 소개하는 기사이다. 최신 커널 2.4에 대해 다룬다.

■ http://www.linuxfocus.org/English/November1999/article124.html
구형 리눅스 램디스크 사용 방법을 소개하는 기사이다. 이 문서를 역사적인 관점에서 참조하기 바란다.

■ http://developer.axis.com/software/jffs/doc/jffs.shtml
JFFS(Journaling Flash File System)을 소개하는 문서이다.

■ http://developer.axis.com/software/jffs/
JFFS 공식 홈페이지이다.

■ http://www.embeddedlinuxworks.com/articles/jffs_guide.html
JFFS 관련해 구체적인 사용법을 정리한 홈페이지이다.

■ http://sources.redhat.com/jffs2/
JFFS2 공식 홈페이지이다.

■ http://penguinppc.org/embedded/howto/root-filesystem.html
MPC에서 루트 파일시스템을 만드는 방법을 정리한 홈페이지이다.

■ http://www.linux-mtd.infradead.org/
리눅스를 위한 MTD(Memory Technology Device) 서브 시스템과 관련있는 각종 사항을 정리한 홈페이지이다.

■ http://www.aleph1.co.uk/armlinux/projects/yaffs/jffs2_and_nand.html
NAND 플래시에서 JFFS2를 사용할 때 발생하는 문제점을 소개하는 문서이다. 그런데 문서 내용에서 잘못된 부분(예: JFFS2가 배드 섹터를 처리하지 못한다. NAND 플래시를 사용할 수 없다)이 보인다.

■ http://ftp.linux.org.uk/pub/people/dwmw2/mtd/cvs/mtd/mtd-jffs-HOWTO.txt
간단한 리눅스 MTD, JFFS HOW-TO 문서이다.

■ http://ykjung99.netian.com/mtd/mtd.html
MPC860 보드에 MTD/JFFS2를 이식하는 방법을 소개하는 홈페이지이다.

■ http://myhome.naver.com/kingseft/gallery.html
임베디드 리눅스 관련 데이터를 제공하는 홈페이지이다. 데이터/게시판 메뉴에서 ‘Embedded Linux’를 선택하기 바란다.

■ http://www.linuxdevices.com/articles/AT7478621147.html
임베디드 리눅스 시스템을 위한 플래시 파일시스템에 대한 기사이다.

■ http://www.linuxhq.com/kernel/v2.4/doc/initrd.txt.html
부팅을 위한 리눅스 램디스크인 initrd 사용법을 정리한 기사이다.

■ http://kldp.org/Translations/html/Initrd-KLDP/Initrd-KLDP.html
초기 램디스크인 initrd에 대한 사용 방법을 정리한 기사이다.

■ http://www.linux.org/docs/ldp/howto/Bootdisk-HOWTO/index.html
리눅스에서 사용할 수 있는 부트 디스크를 만드는 방법을 설명하는 HOW-TO 문서이다.

■ http://www.tldp.org/HOWTO/mini/Loopback-Root-FS.html
루프백 루트 파일시스템을 만드는 방법을 설명하는 HOW-TO 문서이다.

■ http://atrak.usc.edu/~kar/mtd-jffs.html
아사벳에서 bootldr을 사용해 MTD-JFFS 파일 이미지로 부팅하는 방법을 소개하는 홈페이지이다.

■ http://www.busybox.net/
GNU fileutils, shellutils에 들어있는 각종 프로그램을 하나로 묶어놓은 임베디드 리눅스를 위한 맥가이버 칼(스위스 군용 칼이 정확한 표현이지만 여기서는 편의상 맥가이버 칼로 지칭한다)인 busybox 홈페이지이다.

■ http://tinylogin.busybox.net/
경량급이면서도 필요한 기능을 모두 갖추고 있는 임베디드 리눅스에서 동작하는 로그인 프로그램인 tinylogin 홈페이지이다.

■ http://udhcp.busybox.net/
임베디드 리눅스에서 동작하는 경량급 dhcp 서버와 클라이언트 패키지인 udhcp 홈페이지이다.

■ http://packages.debian.org/stable/base/ae.html
경량 문서 편집기인 안토니 편집기(ae) 패키지를 구할 수 있는 홈페이지이다.

■ http://packages.debian.org/unstable/base/elvis-tiny.html
경량 vi 클론인 elvis-tiny 패키지를 구할 수 있는 홈페이지이다.

목차

3부. 리눅스 개발 환경 구축과 이식

12장. 교차 개발 환경 구축

□ 『Embedded Linux: Hardware, Software, and Interfacing』, Dr. Craig Hollabaugh, Addison-Wesley, 2002

임베디드 리눅스에 대해 체계적으로 잘 구성된 책이다. 절반 이상이 인터페이스하는 방법에 대한 소개이므로, 일정 수준 이상의 개발자가 보기에 적당하다.

□ 『러닝 리눅스 3판』, 매트 웰시, 라 카우프만, 칼레 딜하이머 저, 이만용 역, 한빛미디어, 2001

오 라일리 『Running Linux 3rd Edition』의 번역판이다. 리눅스를 처음 접

VirtualBox 로 윈도우 설치하기.

1. 아래의 주소에서 ubuntuvirtualbox 의 바이너리 파일을 바탕화면으로 다운 받는다.

http://www.virtualbox.org/wiki/Downloads

2. 터미널을 실행하고 받은 파일이 있는 곳으로 가서 아래처럼 실행한다.
sudo dpkg  -i 받은파일이름
이 때, 받은 파일 이름이 VirtualBox_1.3.8_Ubuntu_dapper_i386.deb 이면
sudo dpkg  -i VirtualBox_1.3.8_Ubuntu_dapper_i386.deb
를 실행한다.
, 이 때 주의할 점은, X윈도우의 터미널에서 위의 명령을 실행할 경우,

마치 설치가 멈춘 것처럼 보일 수 있다. 이 경우 실행창의 아래부분에 보이는 자세히…’

를 클릭해 보면, <ok>를 눌러주기를 기다리고 있는 터미널 모드의 대화창이 보인다.

키보드의 tab키를 눌러 <ok>를 선택한 후 스페이스 바를 눌러 준다.
이런 식으로 설치가 진행되고 나서, 프로그램 메뉴의 시스템 도구를 열어보면,

innoTek VirtualBox 아이콘이 보인다.

3. 설치된 아이콘을 클릭하여 실행한다.

New > Next

> 이름은 ‘WinXP’등 적당히 정하고, OS TypeWindows XP로 정한 후 > Next

> 설치될 윈도우즈에게 배당할 메모리 크기를 정한다. 당연히, 자신의 컴퓨터에 설치된 메모리 크기보다 적어야 한다. > Next

> Boot Hard Disk를 만들 차례이다. 하드디스크 이미지 파일을 생성하기 위해 New단추를 누른다. 그냥 기본 설정을 사용해도 무난하므로 > Next > Next > Next > Finish를 하고 나면, Boot Hart Disk 에 방금 생성한 디스크 이미지가 보인다. > Next > Finish

이제 가상 머신이 생성된 것이 보이게 된다.
4. Windows XP 설치하기

cdrom드라이브에 Windows XP CD를 넣거나, Windows XPiso이미지를 적당한 디렉토리에 복사해 넣은 후, 방금 생성한 가상 머신의 윗 쪽의 도구상자에 보이는 Settings를 클릭한다.

CD/DVD-ROM 부분에서 Mount CD/DVD Drive를 클릭한 후, WindowsXPCD로 부터 설치하려면, Host CD/DVD Drive를 선택하고, iso이미지로 부터 설치하려면, ISO Imange File부분에서 iso 파일을 선택한다.
Audio 부분에서 Enabel Audio를 클릭한다.
대화 상자의 아래쪽에 있는 OK를 눌러 창을 닫는다.
이제 모든 준비가 되었다. Start를 누르면, 가상 머신이 작동하면…… 좋겠지만,

아직 설정해야 할 것이 남아 있다.
우선 터미널을 실행하고,

sudo usermod -G vboxusers -a 로그인아이디

를 실행하고,
sudo chmod 666 /dev/vbox/drv

를 한다.
또한

sudo gedit /etc/rc.local 를 실행하여,

맨 아랫줄의 exit 0이라고 써 있는 부분의 윗쪽에

chmod 666 /dev/vbox/drv

를 추가해 두면 로그인때마다 폴더의 권한을 재설정하여 윈도우즈의 실행에 문제가 없게 된다.
이제 가상머신을 시작하면 윈도우즈의 설치기 시작되는 것을 볼 수 있다.
5. 윈도우즈의 설치가 끝나면, 가상머신을 실행한 상태에서 마우스 커서가 윈도우즈 창에 갖히게 되는 것을 볼 수 있다. 이 때는 키보드의 오른쪽 Ctrl을 누르면, 윈도우즈 창이 실행된 채로 리눅스로 나올 수 있다. 리눅스로 나와서 실행중인 윈도우즈 가상머신창의 위쪽에 보이는 메뉴 중에서, Devices메뉴의 맨 아랫쪽에 보이는 Install Guest Additions를 클릭하면, 윈도우즈 창 안에서 프로그램이 실행되는 것이 보이게 된다. 그것을 실해하고 나면, 마우스 커서가 윈도우즈와 리눅스 사이에 자유롭게 왕래하는 것을 볼 수 있다. 또한 가상 머신이 실행된 상태에서 키보드의 오른쪽 Ctrl+G키를 누르면, 가상머신이 실행중인 창의 크기를 조절 할 때마다 가상머신에서 실행중인 윈도우즈의 해상도가 자동적으로 변화하는 것을 볼 수 있다.

VirtualBox의 실행 속도는 기대 이상으로 무척 빠르다.

다만, VirtualBox가 아직 DirectX를 지원하지 않는 이유때문에 3D게임이 실행되지는 않지만, 그외의 대부분의 작업이 가능하다.

6. 리눅스와 가상머신 사이의 파일 공유

리눅스와 가상머신의 윈도우즈 사이의 파일 공유는 VirtualBox에서 제공하는 파일 공유의 방법과

ubuntu리눅스에는 samba 데몬 서비스를 실행하고, 가상머신의 윈도우즈에서는 클라이언트로 삼바 서버에 접근하는 방법을 사용할 수 있다.

[VirtualBox의 공유기능 사용법]

VirtualBox를 종료한 후에, 터미널에서 아래 명령을 실행한다.

VBoxManage sharedfolder add “가상머신이름” -name “공유 디렉토리 이름” -hostpath “공유 디렉토리 전체 경로”

, 가상머신의 이름이 “WindowsXP”이고, 공유할 디렉토리가 /home/my_id/MyDoc이라면

VBoxManage sharedfolder add “WindowsXP” -name “MyDoc” -hostpath “/home/my_id/MyDoc”

이라고 실행하면 된다. 이 명령은 스크립트로 만들어서 리눅스가 실행될 때, 자동실행하게 하는 편이 좋다.

터미널에서 gedit AddShare 라고 실행하여 편집기를 연 후에 위의 스크립트를 그 안에 저장하고,

chmod +x 파일이름

의 명령을 실행해서 실행 권한을 부여한다.

리눅스 작업표시줄의 <시스템 메뉴> 안에 있는 <기본 설정>에서 <세션>을 실행하고, 시작 프로그램에 만든 스크립트를 추가하면,

X윈도우즈가 실행될 때마다 이 스크립트가 실행된다.

이제 가상머신의 윈도우즈를 실행하고, 시작메뉴의 실행에서 cmd 실행 시켜서 터미널이 뜨면,
net use n: \vboxsvr
공유디렉토리이름

을 친다. 위의 보기에서라면, net use n: \vboxsvrMyDoc 이라고 치면 된다.

여기에서 n: 은 드라이브 문자이므로 다른 것으로 바꿀 수 있다.

[리눅스의 삼바를 이용하여, 윈도우즈 공유를 실행하는 법]

먼저 터미널에서

sudo gedit /etc/samba/smb.conf를 실행하고,

그 안의 내용을 다 지우고 아래의 내용을 복사해 넣는다.

[global]

workgroup=WORKGROUP

encrypt password=yes

read only=no

hosts allow=10.0.

unix charset=utf-8

dos charset=utf-8

browsable=yes

[MyDoc]

comment=My Documents

path=/home/로그인아이디/Desktop /MyDoc

경로 설정은 바꿀 수 있다. 위의 설정대로 하려면, 바탕화면에 MyDoc 디렉토리를 생성해야 한다. smb.conf를 저장하고 닫은 후에 터미널에서 아래의 명령을 실행한다.

sudo apt-get install samba

를 실행하여 삼바를 설치한다. 삼바가 설치되는 동시에 서버가 실행된다.

삼바 접근 권한 설정을 위해

터미널에서 smbpasswd -a 로그인아이디

를 실행하고 비밀번호를 설정한다.

이제 가상 머신의 윈도우즈를 열고,

내 컴퓨터를 더블 클릭하고,

> 네트워크 환경 추가를 더블 크릭,

>다음 > 다음

>인터넷 또는 네트워크 주소에

\10.0.2.2MyDoc

를 입력

위에서 설정한 아이디와 비밀번호로 접속하면

리눅스의 지정한 디렉토리와 윈도우즈가 서로 연결된다.

윈도우즈에서 아무 폴더나 열고서 도구 메뉴의 네트워크 드라이브 연결을 선택하고서 드라이브를 정하고 앞서 연결한 삼바네트워크를 정해주면, 삼바로 연결된 리눅스의 디렉토리가 윈도우즈에서는 드라이브로 설정된다.

7. Windows의 백업과 복원

가상 윈도우즈가 바이러스에 걸려 복구 불가능일 때를 대비해 백업하고 복사하는 법은 간단하다.

리눅스에 로그인한 사용자의 home디렉토리에 숨겨진 폴더 .VirtualBox 안에 보면 VDI 디렉토리가 있다. 그 안에 보이는 vdi파일들은 가상 하드디스크 파일들이다.

그 파일들을 복사해두었다가, 문제가 생기면 덮어 써버리면 그만이다.

예를 들어서 winxp.vdi가 나의 하드디스크라면 winxp-1.vdi 처럼 복사해 둔다. winxp.vdi로 부팅하는 가상머신의 윈도우즈가 문제가 심각할 경우 winxp.vdi를 삭제하고,

winxp-1.vdi파일을 따로 하나 복사하고 그 이름을 winxp.vdi로 고친다. 그러면, 윈도우즈는 복원된 상태로 정상적으로 뜬다.

/etc/fstab 설정시 발생한 작은 문제..

윈도우와 리눅스 듀얼 부팅으로 사용하던 중…

윈도우를 리눅스에서 VirtualBox 를 이용하여 구동하기로 마음 먹었다.

윈도우를 삭제하고 리눅스내에서 설치를 하던 중…리붓을 하고나니 작은 문제가 발생하였다.

하드디스크가 마운트가 안된것..

무엇이 문제일까?

한동안 고민을 해보았다.

부팅후 mount 명령어로는 마운트가 되는데 이상하게도…/etc/fstab 에 설정을 하였을때는 도통 작동되지가 않는 것이다.

결국 해답을 찾았는데…쉬운 것이었다.

바로 grub 에 설정된 windows 의 부팅 정보를 삭제를 안하고 부팅을 하려고 하니…당연히 ext3 로 자동 마운트가 안되는 것이었다.

쉬운 해결점이었는데…의외로 오래 걸렸다.

다시금 생각하게 된다.

‘문제가 발생하면 제일먼저 로그를 확인할 것.’