2008년 11월 12일 수요일

임베디드 리눅스를 공부하고자 하는 분들이 가장 먼저 해야할일

임베디드리눅스를 공부하고자 하는분들이 가장 먼저 해야 할일

임베디드 리눅스를 해야 겠다는 생각만 가지고 있다가 이젠 시작해야지 라는 생각을 하셨다면 우선 숨을 크게 들이키시고 내벹는 행동을 반복하신후 임베디드 리눅스를 단번에 점령하겠다는 생각을 버린다. ^^; 정말 임베디드 리눅스는 한번 들어가 보면 끝이 없어서 한두달 만에 끝장을 보겠다는 생각을 가지셨다면 당장 그만 둘것! 당장 그만 두지 않더라도 조만간 그만 두게 될것이다. 왜? 한두달안에는 끝나지 않기 때문이다. 혹시 시작하는 시점의 여러분의 실력이 리눅스의 커널을 이미 분석이 끝난 실력이라면... 더구나 여러 아키텍쳐에 포팅까지 한 실력이라면 정말 한두달 사이에 끝날수 있을 것이다. 굳이 임베디드 리눅스를 따로 할 필요가 없는 실력자이므로...



·리눅스를 설치 해 본적도 없는 초 울트라 초차라면?


당장 리눅스 배포판을 구한다. PC에 리눅스를 설치한다.



·리눅스 명령에 익숙하지 않다면


우선 리눅스에 관련된 책을 한권 산다. 그리고 한번 쭈욱 읽어 본다. http://kldp.org 싸이트에 들락 날락 거리면서 http://man.kldp.org 도 참고 하면서.... 단 주의 할것은 암기력에 자신 있는 분을 제외하고는 명령을 굳이 외우려고 하지 말것 자주 사용하는 명령은 손가락이 외운다. 굳이 사용도 하지 않는 명령을 외우려고 스트레스 쌓이지 말고... 더구나 리눅스 명령어는 정말 정말 너무 많다.



·리눅스 디렉토리 구조를 모른다면

최상위 디렉토리를 외운다. 몇 개 안되므로... 그리고 서점에 간다... 리눅스 관련 책들을 보면서 디렉토리에 관련된 내용을 중점적으로 읽는다. 읽어야 하는 내용은 디렉토리 구현에 대한 것이 아니라.. 각 디렉토리를 어떻게 구분해 놓았는가를 설명한 내용들을 읽는다. 대부분의 책들이 조금씩 만 소개하므로 굳이 책들을 사려고 하지 말 고 서점에서 여러권을 설렵하는 것이 났다. 그리고 이것저것 패케지들을 손수 설치해 본다. 그러면 저절로 깨닫게 될것이다



·쉘 스크립트를 모른다면


리눅스를 하면서 쉘 스크립트를 모르면 고생문이 훤하다 사실 내가 그렇다. 그러나 쉘 스크립트를 아주 잘 할 필요는 없다. 쉘 스크립트를 읽을 정도면 된다. 쉘 스크립트를 작성할 필요가 있다면 스크립트에 대한 강좌를 인터넷에서 보고 하거나 다른 스크립트를 보면서 하면 되니까....



·유닉스 운영 체제를 모른다면

유닉스 운영체제에 대한 최대한 쉽게 설명한 책을 골라서 그냥 소설 읽는 셈 치고 읽어 본다. (참고) 쉽게 설명한 책들의 특징은
1. 그림이 많다.
2. 글씨가 크다.
3. 가격이 싸다.
4. 많은 사람들이 본다.
5. 두께가 얇다



·C 언어를 모른다면

이건 사람 얼굴에 입이 없는 셈이다. 밥 어떻게 먹으려나... 곧 굶어 죽게 될것이다. 바로 C의 기본적인 설명에 대한 책을 독파한다. 이건 정성 들여서 독파해야 한다. 임베디드 리눅스는 거의 C로 시작해서 C로 끝난다. 가끔 C++도 있지만....



·리눅스에서 도는 어플리케이션을 작성한 적이 없다.

http://users.unitel.co.kr/~sangeun5/linux/lpg.html 에 가본다. 정말 도움이 될것이다



·make 사용법을 모른다면

make [강좌- http://kldp.org/KoreanDoc/html/gcc_and_make/gcc_and_make.html] 사용법을 아주 잘 알 필요는 없다 그러나 기본적인 사용법은 알고 있어야 한다. 아주 복잡한 사용법은 이미 기술된것을 이용하는 것으로 충분하다



·리눅스가 동작하기 위한 최소한의 기본 구성에 대해 아는 것이 없다?

부팅 디스크를 만들어 본다. 여기서 주의 할것! 대부분의 분들이 켈프에 있는 부팅 디스크 만들기를 따라만 하시는데 이건 별로 효과가 없다. 부팅 디스크를 만드는 목적은 리눅스가 동작하기 위한 최소한의 기본 구성을 알고자 하는데 목적이 있다. 또한 로더의 필요성 커널과 루트 이미지의 분리와 램디스크에서 동작하는 것에 대해서 또 커널이 동작한 후에 실행되는 최소한의 진행과정을 이해하기 위한 것이다. 이를 알고자 하는데 목적을 두어야지 만드는데에만 열중하면 안된다. 또한 다른 부팅 디스크 이미지를 이용하여 그 내용을 살표보고 공부하여야 한다.



·커널 컴파일을 해 본적이 없다면?

임베디드 리눅스는 커널을 가지고 놀아야 한다. 물론 안하고 하는 방법은 있다. 그러나 대부분의 임베디드 리눅스에서 커널 컴파일과 환경 설정은 거의 필수이다. 임베디드상에서 리눅스의 커널 환경을 설정하고 컴파일하는 방식과 우리가 일반적으로 다루는 PC의 커널을 다루는 방법은 거의 대부분이 같다. PC상에서 커널을 자유자재로 가지고 논다는 것은 "임베디드상에서도 자유롭다"는 것을 의미한다



·커널의 구조를 모른다면

Uinx kernel 완전분석으로 가는길 [http://haninara.xcool.net/forStudy/download.php]이라는 책을 한번 볼것. 약간은 예전의 커널에 대한 이야기가 나오지만 커널이 어떻게 동작하는 지를 알수 있다



·어셈블러를 모른다면?

임베디드 리눅스를 함에 있어서 어셈블러를 몰라도 가능한 영역은 있다. 그러나 많은 부분에서 부딪히게 된다. 고로 어셈블러는 필요 충분 조건이다. 어셈블러라는 것이 너무도 많은 종류가 존재하므로 모두 다 익히기는 어렵지만 자신이 사용하려는 MCU의 어셈블러는 익혀야 한다. 일단 PC를 이용한 임베디드에 대해서 익히려면 PC의 어셈블러는 알아야 한다. 자유 자재로 구사할 정도로 익힐 필요는 없다. 다른 쏘스의 명령을 이해하고 자신이 필요로 하는 기능을 추가하거나 수정 할수 있을 정도면 된다



·윗글에서 제안한 리눅스의 개발과 관련한 기본을 다진후 진행하는 방법

임베디드 리눅스를 할때 많은 분들이 평가 보드를 이용한 학습을 준비한다. 그러나 이런 분들은 대부분 좌절한다. 왜? 기본기가 없는 분들이 평가 보드에 포팅하겠다고 덤비기 때문에 좌절하는 것이다. 포팅이 그리 쉬운 것은 아니다. 일단 PC에서 내공을 쌓은 후 접근하는 것이 수월하다. 임베디드 리눅스라고 PC의 리눅스와 다른 점은 거의 없다. 단지 아키텍쳐만이 다를 뿐이며 이 부분은 전체에 3%도 되지 않는다. PC에서 리눅스의 내부를 자유 자재로 드나드는 분이면 임베디드 리눅스에 접근은 너무도 쉽다. 사실 몇가지 사항을 제외하고는 임베디드 리눅스보다 PC 시스템이 더 복잡하다. 가격도 비교해보면 임베디드 장비가 더 싸다.. ^^; 자 이젠 PC에서 임베디드 리눅스를 하기 위한 접근 방법을 알아 보자. 그리고 공부하기 위하여 평가 보드를 구입하기에는 개인이 구입하는 가격이 너무 고가이다. 컴퓨터를 또하나 사는 셈인데...이게 말처럼 쉽겠는가? 고액 연봉자라면 모를까....



·디바이스 드라이버를 정복하라!!!

임베디드 시스템을 개발하는 과정에서 하드웨어쪽을 제외한 나머지 소프트웨어 측면에서 개발 비중은 로더 및 하드웨어 테스트 프로그램 10% 커널 포팅 10% 디바이스 드라이버 40% 임베디드 어플리케이션 40% 이렇다. 물론 내 개인적인 생각이므로 상황에 따라 다르겠지만 .... 그만큼 디바이스 드라이버는 중요하다. 디바이스 드라이버를 개발 한다고 평가보드를 구매 해야 하는가? 이에 대답은 "아니오" 이다. PC는 매우 복잡한 시스템이다. 임베디드에 사용되는 대부분의 기능이 PC에는 있다. 그러므로 PC에 도는 하드웨어에 관련된 디바이스 드라이버를 스스로 만들 능력이 된다면 임베디드용 디바이스 드라이버를 만들 능력은 충분해 진다. 일단 돈 안드는 PC부터 정복해라. PC가 없다면 모를까 ^^; 자 그럼 디바이스 드라이버는 어떻게 정복하는 것이 좋을까? 한번 알아보자..



·어떤 책이 좋을까?

디바이스 드라이버를 만드는 방법에 대한 책으로 대표적인것에는 오렐리의 책이 있다. 그러나 이책을 초보자가 보기에는 너무 어렵다. 그렇다고 마땅한 다른 책이 있는 것도 아니다. 고로 선택권이 없으므로 이 책을 여러번 읽어 본다. 완벽하게 이해하려고는 하지 말기를 부탁한다. 여러번 읽어 보면 어렴풋이 무슨 내용인지 이해하는 시점이 있을 것이다



·디바이스 드라이버 프로그램을 직접 해본다.

우선 오렐리의 책에 소개된 싸이트에 가서 쏘스를 가져 온다. 그리고 쏘스를 이해하려고 노력한다. 또한 KELP의 내가 쓰고 있는 디바이스 드라이버의 강좌를 계속 지켜 보거나 현재 진행되고 있는 박철님이 진행하고 있는 목요 세미나에 참가한다. 아니면 웹을 뒤지면 의외로 디바이스 드라이버 강좌를 하는 싸이트가 꽤 된다. 싸이트 이름을 내가 일일이 외우기는 힘들지만 ... ^^; ( 천재는 건망증이 심하다고들 한다. )



·프린터 포트를 이용한 캐랙터 디바이스를 만든다

대부분의 임베디드 장비에서 사용되는 디바이스는 캐랙터 디바이스로 충분하다. 고로 캐랙터 디바이스를 안다는 것은 임베디드용 디바이스 드라이버의 절반에 해당하는 내용을 안다는 의미도 된다



·자신이 사용하는 커널 버전이외의 내용은 과감하게 삭제한다.

현재 임베디드용 커널은 2.2대를 근거로 사용한다. 2.4대는 최근에 나왔으므로 아직은 적용중이다. 임베디드용 커널은 버전이 낮다. 또 2.0 대 이전 버전은 약간 적용 방식이 다른 것으로 기억한다. 이를 위해서 오렐리 책에서는 이런 저런 내용을 기술하고 있는데 실전에 사용되는 임베디드 리눅스는 사실 커널을 여러가지로 사용하겠끔 굳이 설계하지 않아도 된다. 즉 커널 버전을 덜 타는 것이다. 범용적인 PC용 디바이스 드라이버를 작성할때나 고려할 내용이다. 그러므로 여러분은 괜히 쏘스를 어지럽히는 커널의 버전 관리 에 대한 내용은 과감하게 제거하고 진행하는 것이 수명 연장에 지름길이 된다



·네트웍크용 디바이스 드라이버는 공부해라

임베디드 장비에 리눅스를 사용하는 가장 큰 목적 중에 하나가 네트워크 스택을 이용하기 위한 것이다. 리눅스 자체가 덩치가 크므로 조그마한 임베디드 장비에는 아예 탑재하지 않는다. 채산성이 전혀 맞지 않기 때문이다. 더구나 리눅스의 대부분의 어플리케이션이 네트워크에 연관되어 있다. 고로 네트워크 디바이스 드라이버는 공부해야 한다.



·기존에 디바이스 드라이버를 한번쯤 스스로 재 작성해 보라.

계속 말하는 것이지만 PC는 매우 복잡한 시스템이다. 고로 PC의 디바이스 드라이버를 구현 할수 있다는 것은 임베디드용 디바이스 드라이버를 구현 할 수 있는 능력이 된다는 것과 동일한 내용이다. 여기서 주의 할것은 PC에서 구현된 디바이스 드라이버들은 매우 안정된 상태이다. 여러분이 이렇게 완벽하게 안정된 디바이스 드라이버를 만들 수는 없다. 왜? 초짜이므로.... 똑같이 안정된 디바이스 드라이버를 작성할수 있다면 바로 리눅스의 개발에 앞장 서 주시길 부탁한다. 보통 많은 분들이 PC용 디바이스 드라이버를 재 작성할때 시리얼 포트용 디바이스 드라이버 부터 하는데 제발 시리얼 포트 부터 하지 말것... PC의 리눅스 상에서 시리얼은 정말 복잡하다. 보통 임베디드의 시리얼과는 상대가 되지 않는다. 터미날을 지원하는 기능과 가상 터미날과 연계 되어 있기 때문이다. 고로 차라리 프린터 포트나 마우스 같은 디바이스 드라이버 부터 만들어 가라... 어쩌면 랜카드용 디바이스 드라이버가 더 쉬울지도 모른다. 다시 당부 드리지만 시리얼 포트 부터 접근하지 말것....



·커널을 이해하라....

디바이스 드라이버를 공부하다보면 많은 부분들이 커널과 연계되어 있음을 알게 된다. 그러므로 디바이스 드라이버에 대해서 공부가 끝났다면 커널의 40%쯤은 이해 했다고 볼 수도 있겠다. 커널을 공부함에 있어서 구분해야 할것이 있다. 하나는 아키텍쳐 의존적인 부분과 아키텍쳐와 독립적인 부분이 있다. 리눅스는 가급적 아키텍쳐 독립적으로 구성되려고 노력한 흔적이 여기저기 보인다. 그래서 리눅스가 다른 아키텍쳐에 포팅 될수 있었던 것이다. 만약 PC의 i386계열에 의존적인 부분이 매우 많았다면 지금처럼 임베디드용으로 사용되지도 못했을 것이다. 자 커널을 이해하는 방법은 어떤게 좋을까? 어디까지 이해해야 할까? 이에 대한 나의 생각을 풀어 보겠다



·커널을 이해하기 위한 방법론 및 어디까지?

커널을 이해하기 위해서 가장 좋은 방법은 쏘스에서 흐름을 쭈욱 쫒아가 보는 것이다. 이를 위한 방법은 켈프에서 제안한 숙제중 부팅 메세지를 시리얼로 보내는 방법을 제안한다. 물론 이때 "Uinx kernel 완전분석으로 가는길이라는 책" 을 옆에 끼고 있는 것이 좋을 것이다. 물론 켈프에 조형기님이 진행하고 있는 강좌란도 무척 도움이 될것이다. 너무 완벽하게 쫒아 가려고 하지 않는 것이 좋을 것이다. 이 놈의 리눅스 커널을 쫒아 가는 것에 맛이 들리면 도통 헤어나질 못하게 된다. 필요한 만큼만 쫓아 다니면 된다. 임베디드 리눅스를 구현함에 있어서 대부분은 기존에 이미 포팅되어 있는 아키텍쳐를 이용하게 되는데 이 방법이 의미하는 것은 커널을 완벽하게 이해하기 보다는 커널 쏘스의 어떤 부분에 어떤 기능이 있는가 정도를 파악하는 선이면 된다는 것이다. 필요할때 좀더 자세하게 쏘스를 쫒아 다니면 된다. 또 내가 권유하는 방식은 당신이 필요로 하는 기능은 대부분 다른 사람이 이미 해 놓았을 가능성이 높다는 것이다. 커널에 집중하기 보다는 웹싸이트를 뒤지는 시간이 더 짧을 수 있다. 요즘은 Know Where!! 아닌가....



·정말 임베디드 리눅스를 하려면

5항까지 진행된 분이라면 6항 이후에 설명하는 과정을 수행해도 문제가 없을 것이다. 여기서 부터는 보통 일반인들이 말하는 임베디드 시스템용 리눅스를 어떻게 하는가를 설명하는 것이다



·평가 보드를 구매하라...

만약 당신이 가난한 개발자라면 이 이후에 진행은 포기해 달라.. 왜? 개인이 하기에는 너무도 벅찬 돈이 든다. 그냥 평가 보드만 사서 될일이 아니다. (이것도 정말 비싸다) 물론 평가 보드만 사도 될수 도 있지만 새로운 하드웨어적인 기능을 추가하고 시험하려면 개발 장비가 보통 고가가 아니다. 그냥 개인이 취미로 하기에는 이미 금전적인 부담이 넘어선다. 단 평가보드상에서 만족한다면 평가보드 살 능력이 되야 한다. 평가보드만으로도 꽤 많은 것을 공부 할수 있다. 단 평가보드를 구매할때 JTAG가 지원되는 평가보드를 구매하라 그나마 JTAG를 사용하는 공부는 돈이 적게 든다



·평가 보드를 구매 했다면....

평가 보드를 보통 구매하면 대부분의 문서가 따라 오게 된다. 물론 사용되는 디바이스의 설명서들이 포함되 있거나 최소한 어디서 구하는지에 대한 설명은 있을 것이다. 이런 자료를 모두 일단 확보할 것.



·MCU를 공부하라..

평가 보드에 사용되고 있는 MCU에 대해서 공부해야 한다. MCU를 모르고 임베디드를 도전하는 것은 시간낭비의 지름길이다. MCU의 구조 MCU의 하드웨어 사양 MCU의 프로그램 방법 ( 어셈블러 ) MCU의 동작 방식 뭐 이런 것이 있겠다.



·평가 보드에 사용되는 디바이스를 공부해라...

평가 보드에 사용되는 디바이스를 모두 공부할 필요는 없다. 자신이 사용하고자 하는 디바이스에 대해서 하드웨어적으로는 어떻게 연결되고 디바이스를 제어하기 위해서는 소프트웨어 적으로 어떻게 해야 하는 가를 이해 해야 한다. 이런 이해를 위해서는 해당 디바이스에 대한 리퍼런스 매뉴얼의 확보는 필수적이다. 항상 나에 가슴을 아프게 하는 것은 기술된 언어가 영어라는 점이다. 빨리 한글이 전세계 공통어로 되어야 하는데.... 나를 세계 대통령으로 밀어 주면 가장 먼저 한글을 공용어로 하고 모든 표기를 한글로 하는 세계법을 제정하겠다.



·크로스 컴파일 환경을 구축하는 것을 공부하라

임베디드 리눅스를 공부하는 것에 가장 큰 관문중에 하나가 크로스 컴파일 환경을 구축하는 것이다. 그나마 다행인것은 요즘은 아예 rpm 패케지로도 나온다는 점이다. 그래도 몇몇 cpu에 필요한 환경은 자신이 스스로 구축해야 한다. 또 평가 보드에 따라 구축하는 방법이 조금씩 다를 수 있다. 물론 평가보드에 따라오는 CD에는 일반적으로 크로스 컴파일에 필요한 화일도 따라오므로 좀 괜찮기는 하지만 아예 공부하지 않으면 조금만 문제가 생겨도 속수 무책일수 있다.



·부트 로더를 공부하라.

임베디드 리눅스를 공부하기 위해서 가장 처음 부딪히는 것이 부트 로더다. PC에서는 그 개념이 별로 중요하지 않으므로 이 문제가 별로 대두되지 않지만 임베디드에서는 바로 대두 된다. 보통은 이미 개발된 오픈된 부트 로더를 자신의 시스템에 맞게 바꾸게 된다. 그러므로 부트로더의 쏘스는 어느정도 분석하고 있어야 한다.
부트로더자료 - [http://haninara.xcool.net/forStudy/download.php]



·NFS 시스템에 대해서 공부하라

임베디드 시스템에는 커다란 보조 기억 장치가 없기 때문에 필히 네트워크를 이용한 다른 시스템의 보조 기억 장치를 마운트 사용해야 편리하다. 이를 위해 사용되는 것이 NFS이다. 고로 이에 대한 공부는 해두는 것이 좋다



·그외 나머지는 어떻게?

커널을 올리고 바꾸고 하는 것은 PC에서 공부했다면 별로 문제가 되지 않는다. 또 대부분 커널은 포팅했다. 단 일반적으로 부딪히는 문제를 늘어 놓는다면 다음과 같다



·MMU가 없다..

보통 PC에서는 MMU가 있으므로 문제가 되지 않지만 임베디드 시스템에서는 MMU가 없는 것이 일반적이다. 왜? 가격이 싸기 때문이다. 그렇다면 어떤 문제가 있을까 바로 이 문제에 대해서 공부해야 한다는 것이다. 50100용을 사용하거나 드래곤볼 을 사용한 임베디드 리눅스의 하우투 문서를 찾아 보고서 공부하는 것이 좋다



·루트 디스크 이미지와 램 디스크

임베디드 리눅스의 거의 대부분이 보조 기억 장치가 없거나 있어도 플래쉬 메모리 이다. 그래서 루트와 마운트 되는 기억 장치로 램 디스크를 많이 사용하게 된다. 문제는 램 디스크용 루트 이미지가 ROM에 있거나 플래쉬 메모리에 저장되기 때문이다. 커널의 루트 이미지 복사는 부분에 대한 공부를 필요로 하는 것이 이 때문이다.



·플래쉬 메모리에 대해서 공부 할것

플래쉬 메모리는 하드 디스크 처럼 쓰고 읽을 수 있는 저장 장치이다. 더구나 읽는 속도가 매우 빠르다. 그러나 플래쉬 메모리는 쓰는 횟수에 한계가 있다. 이에 대한 공부를 미리 하지 않으면 당신이 납품한 임베디드 장비에 대해서 고생 할 가능성이 농후하다. 이에 대하여 다른 사람은 어떤 방법론이 있는가에 대하여 미리 공부해 두는 것도 좋을 것이다. 가끔 배신감 느끼게 플래쉬에 대한 몇가지 소프트웨어가 특허에 걸려 있다.



·계속 늘어 놓으면 한도 끝도 없을 것 같으므로

정말이다.. 임베디드 리눅스라는 분야는 PC이외에 모두 다 라고 할 정도로 다양하다. 이 모든 것을 미리 공부할수는 없다. 역시 실전에 부딪히면서 배우는 수밖에



·빨리 개발하는 방법....

아마도 이 글을 읽고서 벌써 임베디드 리눅스를 공부하고 싶은 마음이 없어지는 사람들의 목소리가 들린다. 음.... 아마도 이글을 읽고 있는 분들 중에는 당장 1달안에 개발을 완료 해야 하는 분들도 있을 것이다. 이에 대한 해답은 아니지만 속성 코스에 대해서 이야기 하려고 한다. 단 이 방법은 엔지니어로써 어느정도 구력이 있는 분에 해당하는 것이지 완전 엔지니어 초짜에 해당되는 것은 아님을 미리 밝힌다.



·이미 개발된 평가 보드를 이용할 것...

자 임베디드 리눅스를 이용한 시스템을 만든다는 것은 자신이 목적으로 하는 동작이 정확하게 수행되면 된다. 그러므로 구현하고자 하는 장비와 최대한 같은 기능을 담고 있는 평가보드(개발보드) 를 구한다. 이 평가 보드에는 리눅스가 모두 설치 되어 있어야 한다. 그리고 캐랙터 디바이스의 가장 최소한에 대한 공부만 한다. 이것 마저도 안한다면 어쩔수 없다. 그리고 평가보드의 회로를 최대한 그대로 수용한 목적 시스템을 만든다. 이런 상태라면 다음과 같은 할일만 남는다.

1. 부트로더에서 초기화와 커널 부팅을 수행하는 부분만 남겨 놓고 제거한다.
2. 커널을 그대로 사용한다.
3. 대부분의 디바이스 드라이버도 그냥 사용한다.
4. 추가된 디바이스의 드라이버만 작성한다.
5. 어플리케이션을 작성한다.

유영창씨의 초보자를 위한 임베디드 리눅스 학습 가이드

[컬럼] 초보자를 위한 임베디드 리눅스 학습 가이드

1. 개요

이 문서의 내용은
정말 초보자가 임베디드 리눅스를 어떻게 접근하면 좋은가에 대한
생각을 적어 놓은 것이다.


2. 저작권

이 문서는 GNU 라이센스를 따른다.
단 최초 작성인은 유영창임을 표시하여야 한다.

3. 문서

버전 1.0

이 문서에 불만이 있거나
다른 생각이 있다면 여기로 메일을 보내 줄것
frog6502@hanmail.net

목차

1. 개요
2. 저작권
3. 문서
4. 임베디드 리눅스를 공부하기 위하여 자신의 상태에 따라서 무엇을 해
야 하는가?
4.1 임베디드리눅스를 공부하고자 하는분들이 가장 먼저 해야 할일
4.2 리눅스를 설치 해 본적도 없는 초 울트라 초차
4.3 리눅스 명령에 익숙하지 않다면
4.4 리눅스 디렉토리 구조를 모른다면
4.5 쉘 스크립트를 모른다면
4.6 유닉스 운영 체제를 모른다면
4.7 C 언어를 모른다면
4.8 리눅스에서 도는 어플리케이션을 작성한 적이 없다.
4.9 make 사용법을 모른다면
4.10 리눅스가 동작하기 위한 최소한의 기본 구성에 대해 아는 것이 없다.
4.11 커널 컴파일을 해 본적이 없다면.
4.12 커널의 구조를 모른다면
4.13 어셈블러를 모른다면
5. 윗글에서 제안한 리눅스의 개발과 관련한 기본을 다진후
진행하는 방법
5.1 디바이스 드라이버를 정복하라!!!
5.1.1 어떤 책이 좋을까?
5.1.2 디바이스 드라이버 프로그램을 직접 해본다.
5.1.3 프린터 포트를 이용한 캐랙터 디바이스를 만든다.
5.1.4 자신이 사용하는 커널 버전이외의 내용은 과감하게 삭제한다.
5.1.4 네트웍크용 디바이스 드라이버는 공부해라.
5.1.5 기존에 디바이스 드라이버를 한번쯤 스스로 재 작성해 보라.
5.2 커널을 이해하라....
5.3 커널을 이해하기 위한 방법론 및 어디까지?
6. 정말 임베디드 리눅스를 하려면
6.1 평가 보드를 구매하라...
6.2 평가 보드를 구매 했다면....
6.3 MCU를 공부하라..
6.4 평가 보드의 회로를 공부해라...
6.5 평가 보드에 사용되는 디바이스를 공부해라...
6.6 크로스 컴파일 환경을 구축하는 것을 공부하라...
6.7 부트 로더를 공부하라.
6.8 NFS 시스템에 대해서 공부하라...
6.9 그외 나머지는 어떻게?
6.9.1 MMU가 없다..
6.9.2 루트 디스크 이미지와 램 디스크
6.9.3 플래쉬 메모리에 대해서 공부 할것
6.9.4 계속 늘어 놓으면 한도 끝도 없을 것 같으므로 ...
7. 빨리 개발하는 방법....
7.1 이미 개발된 평가 보드를 이용할 것...
8.0 내가 하고 싶은 말은 ...

4. 임베디드 리눅스를 공부하기 위하여 자신의 상태에 따라서 무엇을 해
야 하는가?

4.1 임베디드리눅스를 공부하고자 하는분들이 가장 먼저 해야 할일

임베디드 리눅스를 해야 겠다는 생각만 가지고 있다가
이젠 시작해야지 라는 생각을 하셨다면

우선 숨을 크게 들이키시고 내벹는 행동을 반복하신후
임베디드 리눅스를 단번에 점령하겠다는 생각을 버린다. ^^;

정말 임베디드 리눅스는 한번 들어가 보면 끝이 없어서
한두달 만에 끝장을 보겠다는 생각을 가지셨다면 당장 그만 둘것!

당장 그만 두지 않더라도 조만간 그만 두게 될것이다.

왜?

한두달안에는 끝나지 않기 때문이다.

혹시 시작하는 시점의 여러분의 실력이 리눅스의 커널을 이미
분석이 끝난 실력이라면...

더구나 여러 아키텍쳐에 포팅까지 한 실력이라면
정말 한두달 사이에 끝날수 있을 것이다.

굳이 임베디드 리눅스를 따로 할 필요가 없는 실력자이므로...

4.2 리눅스를 설치 해 본적도 없는 초 울트라 초차

당장 리눅스 배포판을 구한다.
PC에 리눅스를 설치한다.

4.3 리눅스 명령에 익숙하지 않다면

우선 리눅스에 관련된 책을 한권 산다.
그리고 한번 쭈욱 읽어 본다.

kldp.org 싸이트에 들락 날락 거리면서
man.kldp.org 도 참고 하면서....

단 주의 할것은 암기력에 자신 있는 분을 제외하고는
명령을 굳이 외우려고 하지 말것

자주 사용하는 명령은 손가락이 외운다.
굳이 사용도 하지 않는 명령을 외우려고 스트레스 쌓이지 말고...

더구나 리눅스 명령어는 정말 정말 너무 많다.

4.4 리눅스 디렉토리 구조를 모른다면

최상위 디렉토리를 외운다.
몇 개 안되므로...

그리고 서점에 간다...

리눅스 관련 책들을 보면서 디렉토리에 관련된
내용을 중점적으로 읽는다.

읽어야 하는 내용은 디렉토리 구현에 대한 것이 아니라..

각 디렉토리를 어떻게 구분해 놓았는가를 설명한 내용들을
읽는다.

대부분의 책들이 조금씩 만 소개하므로 굳이 책들을 사려고 하지 말
고 서점에서 여러권을 설렵하는 것이 났다.

그리고 이것저것 패케지들을 손수 설치해 본다.
그러면 저절로 깨닫게 될것이다.

4.5 쉘 스크립트를 모른다면

리눅스를 하면서 쉘 스크립트를 모르면
고생문이 훤하다

사실 내가 그렇다.

그러나 쉘 스크립트를 아주 잘 할 필요는 없다.

쉘 스크립트를 읽을 정도면 된다.

쉘 스크립트를 작성할 필요가 있다면
스크립트에 대한 강좌를 인터넷에서 보고 하거나
다른 스크립트를 보면서 하면 되니까....

4.6 유닉스 운영 체제를 모른다면

유닉스 운영체제에 대한 최대한 쉽게 설명한
책을 골라서 그냥 소설 읽는 셈 치고 읽어 본다.


(참고) 쉽게 설명한 책들의 특징은

1. 그림이 많다.
2. 글씨가 크다.
3. 가격이 싸다.
4. 많은 사람들이 본다.
5. 두께가 얇다.

4.7 C 언어를 모른다면

이건 사람 얼굴에 입이 없는 셈이다.
밥 어떻게 먹으려나...

곧 굶어 죽게 될것이다.

바로
C의 기본적인 설명에 대한 책을 독파한다.

이건 정성 들여서 독파해야 한다.

임베디드 리눅스는 거의 C로 시작해서 C로 끝난다.
가끔 C++도 있지만....

4.8 리눅스에서 도는 어플리케이션을 작성한 적이 없다.


http://users.unitel.co.kr/~sangeun5/linux/lpg.html
에 가본다.

정말 도움이 될것이다

4.9 make 사용법을 모른다면

make 사용법을 아주 잘 알 필요는 없다
그러나 기본적인 사용법은 알고 있어야 한다.

아주 복잡한 사용법은 이미 기술된것을
이용하는 것으로 충분하다.

4.10 리눅스가 동작하기 위한 최소한의 기본 구성에 대해 아는 것이 없다.

부팅 디스크를 만들어 본다.
여기서 주의 할것!

대부분의 분들이 켈프에 있는 부팅 디스크 만들기를 따라만 하시는데
이건 별로 효과가 없다.

부팅 디스크를 만드는 목적은
리눅스가 동작하기 위한 최소한의 기본 구성을 알고자 하는데 목적이
있다.

또한 로더의 필요성
커널과 루트 이미지의 분리와 램디스크에서 동작하는 것에 대해서
또 커널이 동작한 후에 실행되는 최소한의 진행과정을 이해하기
위한 것이다.

이를 알고자 하는데 목적을 두어야지
만드는데에만 열중하면 안된다.

또한 다른 부팅 디스크 이미지를 이용하여
그 내용을 살표보고 공부하여야 한다.

4.11 커널 컴파일을 해 본적이 없다면.

임베디드 리눅스는 커널을 가지고 놀아야 한다.
물론 안하고 하는 방법은 있다.

그러나 대부분의 임베디드 리눅스에서
커널 컴파일과 환경 설정은 거의 필수이다.

임베디드상에서 리눅스의 커널 환경을 설정하고
컴파일하는 방식과
우리가 일반적으로 다루는 PC의 커널을 다루는
방법은 거의 대부분이 같다.

PC상에서 커널을 자유자재로 가지고 논다는 것은
임베디드상에서도 자유롭다는 것을 의미한다.

4.12 커널의 구조를 모른다면

Uinx kernel 완전분석으로 가는길이라는 책을 한번
볼것

약간은 예전의 커널에 대한 이야기가 나오지만
커널이 어떻게 동작하는 지를 알수 있다.

4.13 어셈블러를 모른다면

임베디드 리눅스를 함에 있어서
어셈블러를 몰라도 가능한 영역은 있다.

그러나 많은 부분에서 부딪히게 된다.

고로 어셈블러는 필요 충분 조건이다.

어셈블러라는 것이
너무도 많은 종류가 존재하므로 모두 다 익히기는 어렵지만

자신이 사용하려는 MCU의 어셈블러는 익혀야 한다.
일단 PC를 이용한 임베디드에 대해서 익히려면
PC의 어셈블러는 알아야 한다.

자유 자재로 구사할 정도로 익힐 필요는 없다.

다른 쏘스의 명령을 이해하고
자신이 필요로 하는 기능을 추가하거나 수정 할수
있을 정도면 된다.

5. 윗글에서 제안한 리눅스의 개발과 관련한 기본을 다진후
진행하는 방법

임베디드 리눅스를 할때
많은 분들이 평가 보드를 이용한 학습을 준비한다.

그러나 이런 분들은 대부분 좌절한다.

왜?

기본기가 없는 분들이 평가 보드에 포팅하겠다고
덤비기 때문에 좌절하는 것이다.

포팅이 그리 쉬운 것은 아니다.

일단 PC에서 내공을 쌓은 후 접근하는 것이
수월하다.

임베디드 리눅스라고 PC의 리눅스와 다른 점은
거의 없다.

단지 아키텍쳐만이 다를 뿐이며

이 부분은 전체에 3%도 되지 않는다.

PC에서 리눅스의 내부를 자유 자재로
드나드는 분이면
임베디드 리눅스에 접근은 너무도 쉽다.

사실 몇가지 사항을 제외하고는 임베디드 리눅스보다
PC 시스템이 더 복잡하다.

가격도 비교해보면 임베디드 장비가 더 싸다.. ^^;

자 이젠 PC에서 임베디드 리눅스를 하기 위한 접근
방법을 알아 보자.

그리고 공부하기 위하여 평가 보드를 구입하기에는
개인이 구입하는 가격이 너무 고가이다.

컴퓨터를 또하나 사는 셈인데...
이게 말처럼 쉽겠는가?

고액 연봉자라면 모를까....

5.1 디바이스 드라이버를 정복하라!!!

임베디드 시스템을 개발하는 과정에서

하드웨어쪽을 제외한 나머지 소프트웨어
측면에서 개발 비중은

로더 및 하드웨어 테스트 프로그램 10%
커널 포팅 10%
디바이스 드라이버 40%
임베디드 어플리케이션 40%

이렇다.

물론 내 개인적인 생각이므로

상황에 따라 다르겠지만 ....

그만큼 디바이스 드라이버는 중요하다.

디바이스 드라이버를 개발 한다고
평가보드를 구매 해야 하는가?

이에 대답은 "아니오" 이다.

PC는 매우 복잡한 시스템이다.
임베디드에 사용되는 대부분의 기능이 PC에는 있다.

그러므로 PC에 도는 하드웨어에 관련된
디바이스 드라이버를 스스로 만들 능력이 된다면

임베디드용 디바이스 드라이버를 만들 능력은 충분해 진다.

일단 돈 안드는 PC부터 정복해라.

PC가 없다면 모를까 ^^;

자 그럼 디바이스 드라이버는 어떻게 정복하는 것이
좋을까?

한번 알아보자..

5.1.1 어떤 책이 좋을까?

디바이스 드라이버를 만드는 방법에 대한 책으로
대표적인것에는 오렐리의 책이 있다.

그러나 이책을 초보자가 보기에는 너무 어렵다.
그렇다고 마땅한 다른 책이 있는 것도 아니다.

고로 선택권이 없으므로

이 책을 여러번 읽어 본다.
완벽하게 이해하려고는 하지 말기를 부탁한다.

여러번 읽어 보면 어렴풋이 무슨 내용인지
이해하는 시점이 있을 것이다.

5.1.2 디바이스 드라이버 프로그램을 직접 해본다.

우선 오렐리의 책에 소개된 싸이트에 가서
쏘스를 가져 온다.

그리고 쏘스를 이해하려고 노력한다.

또한 KELP의 내가 쓰고 있는 디바이스 드라이버의 강좌를
계속 지켜 보거나
현재 진행되고 있는 박철님이 진행하고 있는 목요 세미나에
참가한다.

아니면 웹을 뒤지면 의외로 디바이스 드라이버 강좌를 하는
싸이트가 꽤 된다.

싸이트 이름을 내가 일일이 외우기는 힘들지만 ... ^^;
( 천재는 건망증이 심하다고들 한다. )

5.1.3 프린터 포트를 이용한 캐랙터 디바이스를 만든다.

대부분의 임베디드 장비에서 사용되는 디바이스는
캐랙터 디바이스로 충분하다.

고로 캐랙터 디바이스를 안다는 것은 임베디드용
디바이스 드라이버의 절반에 해당하는 내용을 안다는 의미도 된다.

5.1.4 자신이 사용하는 커널 버전이외의 내용은 과감하게 삭제한다.

현재 임베디드용 커널은 2.2대를 근거로 사용한다.
2.4대는 최근에 나왔으므로 아직은 적용중이다.

임베디드용 커널은 버전이 낮다.

또 2.0 대 이전 버전은 약간 적용 방식이 다른 것으로 기억한다.

이를 위해서 오렐리 책에서는
이런 저런 내용을 기술하고 있는데

실전에 사용되는 임베디드 리눅스는
사실 커널을 여러가지로 사용하겠끔 굳이 설계하지 않아도 된다.

즉 커널 버전을 덜 타는 것이다.

범용적인 PC용 디바이스 드라이버를 작성할때나 고려할 내용이다.

그러므로 여러분은 괜히 쏘스를 어지럽히는 커널의 버전 관리
에 대한 내용은 과감하게 제거하고 진행하는 것이

수명 연장에 지름길이 된다.

5.1.4 네트웍크용 디바이스 드라이버는 공부해라.

임베디드 장비에 리눅스를 사용하는 가장 큰 목적 중에
하나가 네트워크 스택을 이용하기 위한 것이다.

리눅스 자체가 덩치가 크므로 조그마한 임베디드 장비에는
아예 탑재하지 않는다.

채산성이 전혀 맞지 않기 때문이다.

더구나 리눅스의 대부분의 어플리케이션이 네트워크에
연관되어 있다.

고로 네트워크 디바이스 드라이버는 공부해야 한다.

5.1.5 기존에 디바이스 드라이버를 한번쯤 스스로 재 작성해 보라.

계속 말하는 것이지만 PC는 매우 복잡한 시스템이다.
고로 PC의 디바이스 드라이버를 구현 할수 있다는 것은
임베디드용 디바이스 드라이버를 구현 할 수 있는 능력이 된다는 것과
동일한 내용이다.

여기서 주의 할것은
PC에서 구현된 디바이스 드라이버들은 매우 안정된 상태이다.
여러분이 이렇게 완벽하게 안정된 디바이스 드라이버를 만들 수는
없다.

왜? 초짜이므로....

똑같이 안정된 디바이스 드라이버를 작성할수 있다면

바로 리눅스의 개발에 앞장 서 주시길 부탁한다.

보통 많은 분들이 PC용 디바이스 드라이버를 재 작성할때
시리얼 포트용 디바이스 드라이버 부터 하는데

제발 시리얼 포트 부터 하지 말것...

PC의 리눅스 상에서 시리얼은 정말 복잡하다.

보통 임베디드의 시리얼과는 상대가 되지 않는다.

터미날을 지원하는 기능과 가상 터미날과 연계 되어 있기 때문이다.

고로 차라리 프린터 포트나 마우스 같은 디바이스 드라이버 부터
만들어 가라...

어쩌면 랜카드용 디바이스 드라이버가 더 쉬울지도 모른다.

다시 당부 드리지만 시리얼 포트 부터 접근하지 말것....

5.2 커널을 이해하라....

디바이스 드라이버를 공부하다보면
많은 부분들이 커널과 연계되어 있음을 알게 된다.

그러므로 디바이스 드라이버에 대해서 공부가 끝났다면
커널의 40%쯤은 이해 했다고 볼 수도 있겠다.

커널을 공부함에 있어서
구분해야 할것이 있다.

하나는 아키텍쳐 의존적인 부분과
아키텍쳐와 독립적인 부분이 있다.

리눅스는 가급적 아키텍쳐 독립적으로 구성되려고
노력한 흔적이 여기저기 보인다.

그래서 리눅스가 다른 아키텍쳐에 포팅 될수 있었던 것이다.

만약 PC의 i386계열에 의존적인 부분이 매우 많았다면
지금처럼 임베디드용으로 사용되지도 못했을 것이다.

자 커널을 이해하는 방법은 어떤게 좋을까?

어디까지 이해해야 할까?

이에 대한 나의 생각을 풀어 보겠다.

5.3 커널을 이해하기 위한 방법론 및 어디까지?

커널을 이해하기 위해서 가장 좋은 방법은

쏘스에서 흐름을 쭈욱 쫒아가 보는 것이다.

이를 위한 방법은 켈프에서 제안한 숙제중

부팅 메세지를 시리얼로 보내는 방법을
제안한다.

물론 이때 "Uinx kernel 완전분석으로 가는길이라는 책"
을 옆에 끼고 있는 것이 좋을 것이다.

물론 켈프에 조형기님이 진행하고 있는 강좌란도 무척
도움이 될것이다.

너무 완벽하게 쫒아 가려고 하지 않는 것이 좋을 것이다.
이 놈의 리눅스 커널을 쫒아 가는 것에 맛이 들리면

도통 헤어나질 못하게 된다.
필요한 만큼만 쫓아 다니면 된다.

임베디드 리눅스를 구현함에 있어서
대부분은 기존에 이미 포팅되어 있는 아키텍쳐를
이용하게 되는데

이 방법이 의미하는 것은 커널을 완벽하게
이해하기 보다는

커널 쏘스의 어떤 부분에 어떤 기능이 있는가 정도를
파악하는 선이면 된다는 것이다.

필요할때 좀더 자세하게 쏘스를 쫒아 다니면 된다.

또 내가 권유하는 방식은 당신이 필요로 하는 기능은
대부분 다른 사람이 이미 해 놓았을 가능성이 높다는
것이다.

커널에 집중하기 보다는 웹싸이트를 뒤지는 시간이
더 짧을 수 있다.

요즘은 Know Where!! 아닌가....

6. 정말 임베디드 리눅스를 하려면

5항까지 진행된 분이라면 6항 이후에 설명하는 과정을
수행해도 문제가 없을 것이다.

여기서 부터는 보통 일반인들이 말하는 임베디드
시스템용 리눅스를 어떻게 하는가를 설명하는 것이다.

6.1 평가 보드를 구매하라...

만약 당신이 가난한 개발자라면 이 이후에 진행은
포기해 달라..

왜? 개인이 하기에는 너무도 벅찬 돈이 든다.

그냥 평가 보드만 사서 될일이 아니다.
(이것도 정말 비싸다)

물론 평가 보드만 사도 될수 도 있지만
새로운 하드웨어적인 기능을 추가하고
시험하려면 개발 장비가 보통 고가가 아니다.

그냥 개인이 취미로 하기에는 이미 금전적인
부담이 넘어선다.

단 평가보드상에서 만족한다면
평가보드 살 능력이 되야 한다.

평가보드만으로도 꽤 많은 것을 공부 할수 있다.

단 평가보드를 구매할때
JTAG가 지원되는 평가보드를 구매하라
그나마 JTAG를 사용하는 공부는 돈이
적게 든다.

6.2 평가 보드를 구매 했다면....

평가 보드를 보통 구매하면
대부분의 문서가 따라 오게 된다.

물론 사용되는 디바이스의 설명서들이 포함되 있거나
최소한 어디서 구하는지에 대한 설명은 있을 것이다.

이런 자료를 모두 일단 확보할 것

6.3 MCU를 공부하라..

평가 보드에 사용되고 있는 MCU에 대해서
공부해야 한다.

MCU를 모르고 임베디드를 도전하는 것은
시간낭비의 지름길이다.

MCU의 구조
MCU의 하드웨어 사양
MCU의 프로그램 방법 ( 어셈블러 )
MCU의 동작 방식

뭐 이런 것이 있겠다.

6.4 평가 보드의 회로를 공부해라...

평가 보드의 회로를 읽는 법을 알아야 한다.
회로를 읽지 못하고 임베디드를 공부하려
한다면 진행하는데 한계를 느낄수 있다.

회로를 읽을수 있어야 외부 연결 커넥터에
어떻게 연결하는지를 이해 할수 있다.

6.5 평가 보드에 사용되는 디바이스를 공부해라...

평가 보드에 사용되는 디바이스를 모두 공부할 필요는 없다.
자신이 사용하고자 하는 디바이스에 대해서

하드웨어적으로는 어떻게 연결되고
디바이스를 제어하기 위해서는 소프트웨어 적으로
어떻게 해야 하는 가를 이해 해야 한다.

이런 이해를 위해서는 해당 디바이스에 대한 리퍼런스
매뉴얼의 확보는 필수적이다.

항상 나에 가슴을 아프게 하는 것은 기술된 언어가
영어라는 점이다.

빨리 한글이 전세계 공통어로 되어야 하는데....

나를 세계 대통령으로 밀어 주면
가장 먼저 한글을 공용어로 하고 모든 표기를
한글로 하는 세계법을 제정하겠다.

6.6 크로스 컴파일 환경을 구축하는 것을 공부하라...

임베디드 리눅스를 공부하는 것에 가장 큰 관문중에
하나가
크로스 컴파일 환경을 구축하는 것이다.

그나마 다행인것은
요즘은 아예 rpm 패케지로도 나온다는 점이다.

그래도 몇몇 cpu에 필요한 환경은 자신이
스스로 구축해야 한다.

또 평가 보드에 따라 구축하는 방법이 조금씩
다를 수 있다.

물론 평가보드에 따라오는 CD에는 일반적으로
크로스 컴파일에 필요한 화일도 따라오므로
좀 괜찮기는 하지만

아예 공부하지 않으면
조금만 문제가 생겨도 속수 무책일수 있다.

6.7 부트 로더를 공부하라.

임베디드 리눅스를 공부하기 위해서
가장 처음 부딪히는 것이 부트 로더다.

PC에서는 그 개념이 별로 중요하지 않으므로
이 문제가 별로 대두되지 않지만

임베디드에서는 바로 대두 된다.

보통은 이미 개발된 오픈된 부트 로더를
자신의 시스템에 맞게 바꾸게 된다.

그러므로 부트로더의 쏘스는 어느정도
분석하고 있어야 한다.

6.8 NFS 시스템에 대해서 공부하라...

임베디드 시스템에는 커다란 보조 기억 장치가
없기 때문에
필히 네트워크를 이용한
다른 시스템의 보조 기억 장치를 마운트 사용해야
편리하다.

이를 위해 사용되는 것이 NFS이다.

고로 이에 대한 공부는 해두는 것이 좋다.


6.9 그외 나머지는 어떻게?

커널을 올리고 바꾸고 하는 것은
PC에서 공부했다면
별로 문제가 되지 않는다.

또 대부분 커널은 포팅했다.

단 일반적으로 부딪히는 문제를 늘어 놓는다면
다음과 같다.

6.9.1 MMU가 없다..

보통 PC에서는 MMU가 있으므로
문제가 되지 않지만
임베디드 시스템에서는 MMU가 없는 것이 일반적이다.
왜?
가격이 싸기 때문이다.

그렇다면 어떤 문제가 있을까
바로 이 문제에 대해서 공부해야 한다는 것이다.

50100용을 사용하거나 드래곤볼 을 사용한
임베디드 리눅스의 하우투 문서를 찾아 보고서
공부하는 것이 좋다.

6.9.2 루트 디스크 이미지와 램 디스크

임베디드 리눅스의 거의 대부분이
보조 기억 장치가 없거나
있어도 플래쉬 메모리 이다.

그래서 루트와 마운트 되는 기억 장치로 램 디스크를
많이 사용하게 된다.

문제는 램 디스크용 루트 이미지가 ROM에 있거나
플래쉬 메모리에 저장되기 때문이다.

커널의 루트 이미지 복사는 부분에 대한 공부를
필요로 하는 것이 이 때문이다.

6.9.3 플래쉬 메모리에 대해서 공부 할것

플래쉬 메모리는 하드 디스크 처럼
쓰고 읽을 수 있는 저장 장치이다.

더구나 읽는 속도가 매우 빠르다.

그러나 플래쉬 메모리는 쓰는 횟수에
한계가 있다.

이에 대한 공부를 미리 하지 않으면
당신이 납품한 임베디드 장비에 대해서 고생 할
가능성이 농후하다.

이에 대하여 다른 사람은 어떤 방법론이
있는가에 대하여 미리 공부해 두는 것도 좋을 것이다.

가끔 배신감 느끼게 플래쉬에 대한 몇가지
소프트웨어가 특허에 걸려 있다.


6.9.4 계속 늘어 놓으면 한도 끝도 없을 것 같으므로 ...

정말이다..
임베디드 리눅스라는 분야는 PC이외에 모두 다 라고
할 정도로 다양하다.

이 모든 것을 미리 공부할수는 없다.
역시 실전에 부딪히면서 배우는 수밖에 ....


7. 빨리 개발하는 방법....

아마도 이 글을 읽고서
벌써 임베디드 리눅스를 공부하고 싶은 마음이
없어지는 사람들의 목소리가 들린다.

음....

아마도 이글을 읽고 있는 분들 중에는
당장 1달안에 개발을 완료 해야 하는 분들도 있을 것이다.

이에 대한 해답은 아니지만 속성 코스에 대해서
이야기 하려고 한다.

단 이 방법은 엔지니어로써 어느정도 구력이 있는 분에
해당하는 것이지 완전 엔지니어 초짜에 해당되는 것은
아님을 미리 밝힌다.

7.1 이미 개발된 평가 보드를 이용할 것...

자 임베디드 리눅스를 이용한 시스템을
만든다는 것은 자신이 목적으로 하는 동작이
정확하게 수행되면 된다.

그러므로 구현하고자 하는 장비와
최대한 같은 기능을 담고 있는 평가보드(개발보드) 를 구한다.

이 평가 보드에는 리눅스가 모두 설치 되어 있어야 한다.

그리고 캐랙터 디바이스의 가장 최소한에 대한 공부만 한다.
이것 마저도 안한다면 어쩔수 없다.

그리고 평가보드의 회로를 최대한 그대로 수용한
목적 시스템을 만든다.

이런 상태라면 다음과 같은 할일만 남는다.

1. 부트로더에서 초기화와 커널 부팅을 수행하는 부분만 남겨 놓고 제거한다.
2. 커널을 그대로 사용한다.
3. 대부분의 디바이스 드라이버도 그냥 사용한다.
4. 추가된 디바이스의 드라이버만 작성한다.
5. 어플리케이션을 작성한다.

이것이 끝이다.

8.0 내가 하고 싶은 말은 ...

내가 제안한 초짜가 임베디드 리눅스로 가는 길이
맞다고는 할수 없다.

아직도 나는 초짜이므로

하지만 기존에 개발하는 과정을 지켜본 나로써 내린
것은 위와 같은 것이다.

누군가 말했다.
임베디드 리눅스의 세계에 발을 들여 놓는 순간은
태산을 삽질해서 없에는 것과 같다는 것을

하지만 내가 해본 결과로는

임베디드 리눅스를 한다는 것은
리눅스의 본질을 파악하는 것과 거의 일맥 상통한다.

엔지니어라면 한번쯤 도전해서 이루고 싶은 영역이다.

또 생각보다 재미 있다.

당신도 해보라... 겁만 먹지 말고

천천히 가다보면

언젠가 이미 득도한 해커와
같은 반석위에 있는 자신을 발견 할 수 있을 지도 모른다.


어느날 저녁 새벽 3시쯤 근방에 이글을 마무리 하며.....

PS: 배고프다.... 그리고 졸립다....

크로스 컴파일러 툴 체인

크로스 컴파일러 툴 체인


1. 크로스 컴파일러란?

대부분의 프로그래머들은 PC 라는 동일한 환경에서 프로그램을 작성하실 겁니다.

PC에서 프로그램을 짜고 컴파일 하고, 실행 화일을 PC에서 수행 합니다.
이렇게 동일한 환경에서 동작 되는 컴파일러와 이 컴파일러에서 생성된 실행 화일을 동일한 환경에서 수행 한다면 이때의 컴파일러를 네이티브( native ) 컴파일러라고 합니다.
이와 반대로 컴파일러가 동작하는 시스템과 컴파일러에 의해서 생성된 실행 화일이 동작하는 시스템이 다를 때 이 컴파일러를 크로스(cross) 컴파일러라고 합니다.

여러분이 임베디드 시스템에 동작하는 프로그램을 작성한다면 당연히 크로스 컴파일러 환경을 구축해야 합니다. 개발 환경은 PC 일것이고 실행 화일이 동작하는 시스템은 다른 CPU 구성을 갖는 임베디드 시스템일 것이기 때문입니다. 그렇다고 모든 임베디드 시스템에 동작하는 프로그램들이 크로스 컴파일 환경을 필요로 하는 것은 아닙니다. PC와 같은 구조를 갖는 임베디드 리눅스 시스템을 만든다면 PC의 네이티브 컴파일러에서 만들어진 실행 화일이 그대로 수행될 수 있기 때문입니다.
하지만 임베디드 시스템 대부분이 저렴한 가격대를 요구하거나, 또는 특수한 기능을 수행하는 구조를 가지기 때문에 이런 경우는 조금 드믄 편입니다. 그래도 개발 프로세스를 빠르게 진행하기 위해서 익숙한 PC 구조를 사용하는 경우도 요즘은 많아 지는 추세인 것 같습니다.

어찌되었든 크로스 컴파일 환경에서의 개발은 윈도우 개발자 입장에서 보면 매우 열악한 개발 환경이 됩니다. 돈이 많은 회사야 좋은 개발 툴을 사서 이런 열악한 환경을 일부 개선하기는 하지만 그래도 열악하기는 마찬가지 입니다. 가장 큰 이유는 컴파일이 끝난 후 실행 화일을 즉시 시험하지 못하기 때문입니다. 그 외에도 개발하기 위해서 손가락이 무척 바빠지는 것도 한 요인입니다. 단순하게 마우스 클릭 한번으로 수행되는 GUI 컴파일러에 익순한 분들이 타자를 치는 것은 무척 힘든 것입니다.
그래도 리눅스에서 크로스 컴파일러를 사용하는 것에는 이유가 있읍니다.


2. 리눅스와 gcc

지금은 많은 분들이 임베디드 시스템 개발에 리눅스를 사용되고 있다는 것을 알고 있습니다.
하지만 그 이유가 리눅스 커널을 임베디드 시스템에 탑제하기 때문이라고 알고 계신다면 잘못 알고 계신 겁니다. 임베디드 시스템 개발 환경으로 리눅스를 사용하는 근본적인 이유는 gcc라는 막강한 컴파일러가 있기 때문입니다.

리눅스만 사용하시는 분이라면 리눅스 프로그램 개발을 위해서 당연히 gcc라는 컴파일러를 사용합니다. 그래서 gcc라는 것이 그냥 리눅스용 컴파일러라고 알고 있습니다. 하지만 gcc는 그렇게 단순한 컴파일러가 아닙니다. 또한 gcc는 그냥 i386 프로세서에서 동작하는 실행 화일을 만들어 내는 컴파일러도 아닙니다. 현재 존재 하는 컴파일러 중에서 가장 많은 프로세서를 지원하는 컴파일러가 바로 gcc입니다.

gcc 컴파일러의 패케지는 이미 전세계에 동작되는 대부분의 프로세서를 지원하기 위한 준비를 갖추고 있습니다. 더구나 공짜입니다. !!!
하지만 여러분은 이런 gcc가 어떻게 다른 CPU를 지원하게 할 수 있는지에 대해서는 모를 겁니다. 그냥 gcc 명령을 치면 i386 코드가 생성되기 때문입니다.


3. 크로스 컴파일러와 gcc 소스 패케지

gcc에서 i386 이외의 실행 화일을 만들기 위해서는 리눅스에 이미 설치된 gcc란 컴파일러는 소용이 없습니다. 몇 가지 옵션만 바꾸어서 gcc 수행한다고 i386 이외의 프로세서를 지원하는 코드가 생성되는 것은 아닙니다. 애초에 다른 프로세서에서 동작 될 수 있는 실행 파일을 만들 수 있겠끔 gcc를 만들어야 하는 것입니다. 그렇다고 기존에 i386에서 동작하는 gcc를 아예 다른 프로세서에서 동작하는 실행 파일을 만드는 gcc로 바꾸어 버리면 문제가 됩니다. 그 뒤로는 i386에 동작하는 어떤 프로그램도 만들 수 없기 때문입니다.
그래서 보통은 gcc의 이름을 조금 바꿉니다. 예를 들어 arm 계열의 프로세서에서 동작하는 실행 프로그램을 만들기 위해서 사용하는 gcc는 arm-linux-gcc라는 이름을 가집니다.
이름이 다른 이 두 컴파일러는 전혀 다른 컴파일러가 아닌 똑같은 gcc인 것입니다. 단지 gcc는 i386 프로세서에서 수행되는 코드를 만들어 내는 컴파일러이고 arm-linux-gcc라는 것은 arm 프로세서에서 동작되는 코드를 만들어 내는 컴파일러 일 뿐입니다.

관행적으로 네이티브용 컴파일러가 보통 gcc가 되고 크로스 컴파일러는 gcc 앞에 접두사를 붙입니다. 만약 알파 프로세서 동작하는 gcc에서 i386 계열의 실행 코드를 만드는 크로스 컴파일러는 i386-linux-gcc가 될 것입니다. (확인하지 않았습니다. ^^ )
어찌되었든 둘 다 동일하게 gcc란 패케지에서 파생한 컴파일러인 것입니다.

자.... 제가 자꾸 gcc 패케지라는 말을 쓰고 있읍니다. 이 gcc 패케지라는 것이 무엇일까요? 윈도우에서 델파이라는 개발 툴을 구매해서 설치하면 단순하게 델파이 컴파일러만 설치되는 것이 아닙니다. 개발하기 위한 이것저것들이 설치 됩니다. 이와 동일한 개념으로 gcc 패케지란 컴파일을 하기 위한 이런 저런 것을 모두 담은 것을 말 하는 것입니다.
윈도우에서와 달리 리눅스에서는 패케지들이 소스로 구성되어 있습니다. 그래서 이런 것을 gcc를 예를 들면 gcc 소스 패케지 라고 말합니다.

또 여러분이 착각하는 것중 하나가 gcc가 단순하게 c 컴파일러라고 알고 있는데 정확하게 이야기 하면 c 컴파일러가 아닙니다. c++ 소스를 컴파일 할 때 도 역시 gcc 를 사용합니다. 어셈블러를 컴파일 할 때 도 gcc를 사용할 수 있습니다. 그래서 gcc 소스 패키지에는 c 이외의 몇 가지 컴파일러들이 더 들어 있습니다.
어찌되었든 gcc 소스 패키지란 gcc 컴파일러를 만들 수 있는 소스로 구성된 것을 말 합니다. 이 gcc 소스 패케지를 이용하여 원하는 프로세스 지원 크로스(또는 네이티브) 컴파일러를 만드는 것입니다.

그런데 아주 모순 된 것 중 하나는 gcc를 만들기 위해서는 gcc가 필요하다는 점입니다. 왜냐하면 gcc 소스 패키지이기 때문입니다. 하지만 이점은 여기에서 문제 삼지 않으려 합니다. 여러분의 리눅스에는 당연히 gcc 컴파일러가 이미 설치되어 있기 때문입니다.


4. gcc의 짝꿍들

gcc 는 컴파일러입니다. 당연히 소스를 컴파일 할 수 있습니다. 그런데 gcc만 가지고 있어서는 아무런 일도 못합니다.
왜냐구요? 그 이유를 알고 싶으시다면 kelp/임베디드강좌/초보 에 holelee 님이 쓰신 gcc 이야기 시리즈를 읽어 보시기 바랍니다.

그래서 gcc 이외에 필요한 프로그램과 데이터(?)들이 있습니다. 이런 것을 모두 모은 것을 크로스 컴파일러 툴 체인이라고 합니다. 컴파일러 툴이라면 될 텐데 굳이 체인이라고 붙인 이유는 제 개인적인 생각으로는 각 패키지간에 서로 의존적이기 때문일 것으로 추측합니다.

이 툴 체인의 목록은 다음과 같습니다.
binutils - 어셈블러, 링커 그리고 라이브러리 관련 실행 화일들 모음
kernel - 리눅스 커널 ( 헤더 파일 때문에 필요함 )
gcc - 컴파일러
glibc - 라이브러리 및 헤더화일
추가적으로
gdb - 디버거 ( 이놈은 그냥 옵션으로 생각하시면 됩니다. ^^ )
가 있읍니다.

4.1 gcc의 3.0 대의 속설(?)

많은 분들은 gcc의 3.0 대에 문제가 있다고 알고 있어서 이 버전을 회피하시면서 예전 버전을 고집하시는 경향이 있습니다. 그런데 이 부분은 오해랍니다. 문제가 되는 버전은 gcc 3.0 입니다. 당연히 문제가 발생했으니 해당 버전을 고쳤겠지요 그래서 3.1 대 이후라면 별 문제는 없읍니다.
크로스 컴파일을 하시는 분이라면 최근 프로세스를 쓰기 위해서는 예전 버전으로는 한계가 있습니다. 최신 버전을 쓰셔야 지원되는 프로세스가 있습니다. 넘 겁먹지 마시고 3.0대를 쓰시기 바랍니다.

4.2 binutils

바이너리 유틸 이라고 합니다. 포함되는 내용은 다음과 같죠...

addr2line – 실행 파일의 어드레스에 대한 소스 화일명과 라인 넘버를 표현해주는 프로그램입니다.
ar - 라이브러리를 관리하는 프로그램입니다.
as - 어셈블러 입니다.
c++filt - 잘 모르겠읍니다. ^^
gasp - 어셈블러 매크로 해석기 입니다.
ld - 링커 입니다.
nm - 오브젝트안의 심볼릭을 표시해 주는 프로그램입니다.
objcopy - 오브젝트 화일을 컨버팅 해주는 프로그램입니다.
objdump - 오브젝트 화일의 정보를 표시해 줍니다.
ranlib - 라이브러리의 인덱스 화일을 생성합니다.
readelf - elf 포맷의 화일 헤더 정보를 해석해 줍니다.
size - 오브젝트 화일의 섹션 크기와 포함된 오브젝트의 총 크기를 표시해 줍니다.
strings - 프로그램 내부에 사용되는 초기화 문자열들을 골라 표시해 줍니다.
strip - 오브젝트나 실행화일의 정보를 선택적으로 제거해 줍니다.

4.3 kernel

크로스 컴파일러를 만들 때 사용되는 데이터 타입이나 시스템 콜을 참조하기 위해서 필요한 헤더 파일을 참조하기 때문에 툴 체인에 들어 갑니다. 엄밀히 말하면 kernel의 헤더 파일만 필요합니다.

4.4 gcc

패키지가 일반적으로 지원하는 것은 각 언어별로 지원합니다. 다음은 크로스 컴파일러로 쓰는 대표적인 것 들입니다.
gcc, cpp, g++, c++, gccbug, gcov
설명을 굳이 달지 않는 이유는 저는 gcc 이외에는 거의 쓰지 않기 때문에 뭐 하는 놈들인지 잘 몰라서 입니다. 이해해 주세요...

4.5 glibc

커널을 컴파일 하거나 부트 로더를 컴파일 할 때는 필요 없습니다. 하지만 응용프로그램을 사용한다면 당연히 이것이 있어야 합니다. 여러분들 중에서 glibc와 newlib 를 혼동하시는 분들이 있습니다.
glibc 는 GNU 라이브러리 입니다. 크기가 매우 커집니다.
newlib는 glibc가 매우 크기 때문에 꼭 필요한 놈들만 골라서 추려놓은 것이죠 그래서 크기가 매우 작습니다.
특별한 경우가 아니라면 저는 newlib를 별로 추천하지 않습니다. 가끔 리눅스용 프로그램을 임베디드 제품에 포팅 하다보면 없는 함수가 있어서 곤란을 겪기 때문입니다.
램이나 플래쉬 시스템이 16M 이상이고 여유가 있다면 가급적 glibc를 쓰시기를 권유합니다.

4.6 gdb

이놈은 디버거죠.. 즉 프로그램을 디버깅 할때 유용한 도구 입니다. 하지만 윈도우 디버거를 사용하시던 분이라면 매우 불편함을 느끼실 겁니다. 하지만 없는 것 보다는 있는 것이 좋습니다. printf 만 가지고 디버깅 하시면 매우 힘들기 때문입니다. 더구나 익숙해지면 의외로 막강한 기능에 놀라시게 됩니다. 이 놈을 굳이 툴 체인에 포함시키지 않는 것은 상호 연관관계가 별로 없어서 입니다.

터미널 IO Write, Read

write.c



#include
#include
#include
#include
#include

#define BAUDRATE B57600
#define MODEMDEVICE "/dev/ttyS0"
#define _POSIX_SOURCE 1 /* POSIX compliant source */
#define FALSE 0
#define TRUE 1

volatile int STOP=FALSE;

main()
{
int fd,c, res;
struct termios oldtio,newtio;
int bbb[1],aaa[1];
bbb[0]=0;

fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
if (fd <0)
{
perror(MODEMDEVICE);
exit(-1);
}

tcgetattr(fd,&oldtio);

bzero(&newtio, sizeof(newtio));
newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0;

newtio.c_lflag = 0;


tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio);


while (1) {
scanf("%d",&bbb[0]);

aaa[0]=255;
write(fd,aaa,1);
aaa[0]=0;
write(fd,aaa,1);
if(bbb[0]=='\n');
else write(fd,bbb,1);

aaa[0] = (aaa[0]^bbb[0]) & 0x7f;

write(fd,aaa,1);

}

tcsetattr(fd,TCSANOW,&oldtio);
}








------------------------------------------------------------------------

read.c





#include
#include
#include
#include
#include

#define BAUDRATE B115200
#define MODEMDEVICE "/dev/ttyS0"
#define _POSIX_SOURCE 1 /* POSIX compliant source */
#define FALSE 0
#define TRUE 1

volatile int STOP=FALSE;

main()
{
int fd,c, res;
struct termios oldtio,newtio;
//char buf[255];
//char buf[0],ab;
int buf[1];

fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
if (fd <0) {perror(MODEMDEVICE); exit(-1); }

tcgetattr(fd,&oldtio);

bzero(&newtio, sizeof(newtio));
newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0;

/* set input mode (non-canonical, no echo,...) */
newtio.c_lflag = 0;
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 1;

tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio);


while (STOP==FALSE) {
res = read(fd,buf,1);
//buf[res]=0;
printf("%c\n", buf[0]);
if (buf[0]=='z') STOP=TRUE;
}
tcsetattr(fd,TCSANOW,&oldtio);
}

NAND, NOR Flash Memory

오늘날 플래시 메모리에 관한 자료는 지나칠 정도로 많습니다. 인터넷을 검색해 보면 몇날 밤을 꼬박 새워도 그 자료를 다 읽지 못할 것입니다. 플래시 메모리는 말씀하신대로 NOR와 NAND형의 2가지가 있습니다. 하지만, 이런 이름은 내부 구조에 관련되어 기술적으로 붙여진 것이니 알려하지 마시고... 그냥 사용자 입장에서의 차이점만 알아두시기 바랍니다.

먼저 NOR형은 기존의 RAM이나 ROM처럼 어드레스 버스 및 데이터 버스를 가지는 형입니다. 따라서, 마이크로프로세서에 쉽게 인터페이스를 할 수 있지요. 하드웨어적으로나 소프트웨어적으로나 다른 메모리 소자들과 거의 유사한 방식으로 사용한다는 것입니다. 이것들은 대부분 모델명이 29Cxxx의 형태로 되어 있습니다.
초창기의 반도체 회사들은 NOR 플래시가 더 시장성이 있다고 보고 이 제품의 개발에 주력했습니다. 하지만, 초창기에는 이 전략이 맞았는지 모르지만 현재는 아닙니다. 현재 대량 수요처에는 거의 NOR형이 사용되지 않습니다...

NAND형 플래시는 사용방법이 전혀 다릅니다. 데이터 시트를 보셨다면서 이런 차이를 깨닫지 못했다면 무슨 내용을 읽으셨는지 모르겠네요...^.^ NAND 플래시에는 어드레스 버스와 데이터 버스라는 개념이 없다고 생각하시면 됩니다. 그냥 쉽게 병렬 입출력 포트가 있다고 생각하세요. 그러면 CPU가 이 포트를 통하여 먼저 어드레스값을 주고 나서 그 다음에 데이터를 라이트하거나 리드합니다. 이해가 안되시면 8255를 생각해 보세요. 8255를 사용하려면 8255의 8비트 데이터 버스를 통하여 초기화도 수행하고 입출력 데이터도 액세스하잖아요... 플래시 메모리도 그렇다는 것입니다.
그러므로 NAND 플래시 메모리를 CPU에 인터페이스하려면 좀더 신중한 하드웨어 설계가 필요합니다. 결코 어렵다는 것은 아니지만 통상적인 메모리와는 판이하게 다르다는 것입니다. 플래시를 리드, 라이트하는 프로그램도 NOR 플래시의 경우와는 전혀 다르지요. 항상 어드레스를 먼저 주고나서 읽거나 써야 하므로 불편하기 짝이 없고, 시간도 훨씬 더 많이 걸립니다.
그럼 왜 오늘날 이런 불편한 것을 많이 사용할까요? 그것은 이런 방식으로 만들면 사용은 불편하지만 내부 구조가 간단하여 훨씬 더 대용량으로 만들 수 있기 때문입니다. 값도 엄청나게 싸지고요, IC의 핀수가 적어지니 팩키지도 간단해 집니다. 1.8V나 3.3V의 저전압형 내지 저소비전력형으로 만드는 것도 더 쉽다고 합니다. 어때요? 바로 이런 특징을 종합하면 하나같이 모바일 기기에 적합한 특징들이죠... 그렇습니다. 그래서 오늘날 폭발적 인기를 누리는 USB 플래시 저장장치, 디지탈 카메라, MP3 플레이어, PDA 등에는 모두 이 NAND 플래시를 사용합니다. NOR형을 사용한다면 가격이나 소비전력, 부피 등에서 감당하기 어렵죠... 오늘날 NOR 플래시 메모리는 칩 1개에 기껏해야 수MB 정도가 들어가지만, NAND 플래시는 칩 1개에 수백 MB가 넘는 것이 흔히 있습니다. 수백 MB 용량을 NOR 플래시로 구성하려면 메모리값만 수십만원이 들어가지만 NAND 플래시 1개로 구성하면 몇만원이면 됩니다...
삼성전자를 비롯한 몇개의 똑똑한 반도체 회사들은 일찌기 이런 점에 착안하여 앞으로 NAND 플래시가 각광을 받을 것으로 예상하고 이를 개발해 왔습니다. 아니나 다를까 오늘날 이것의 인기가 폭발하면서 황금알을 낳고 있지요... NAND 플래시의 모델명은 정형화되어 있지 않고 회사별로 천차만별입니다.

이제까지의 설명에서 언급하지는 않았지만, 이와 관련하여 중요한 특징을 하나 눈치채야 합니다. 위에서 설명하였듯이 어드레스 버스 및 데이터 버스가 있는냐 없느냐는 여러가지 차이를 나타내지만, 또다른 측면에서 보면 프로그램 메모리로 사용할 수 있느냐 없느냐의 차이를 가져온다는 것입니다. 프로그램 메모리라고 하는 것은 CPU가 매 순간마다 프로그램카운터(PC)의 값을 어드레스 버스에 출력하여 명령을 읽어들이고 이를 해독하여 실행합니다. 따라서, 프로그램 메모리로 NOR 플래시는 사용할 수 있지만 NAND 플래시는 절대로 사용하지 못한다는 것입니다. 이에 비하여 NAND 플래시는 하드디스크와 같이 데이터 저장장치에 적합하지요. 그러니까 액세스가 복잡하고 느려도 상관없으며, 메모리 용량이 더 중요한 것입니다. 다시 말하면 NOR 플래시는 주기억장치에 적합하고 보조기억장치로도 쓸 수 있지만, NAND 플래시는 주기억장치로는 사용할 수 없고 보조기억장치로만 사용할 수 있다는 것입니다. 프로그램용으로 사용하는 메모리는 사용량이 적지만, 데이터 저장용으로 사용하는 메모리는 훨씬 더 대량으로 사용하죠. 그래서 모바일 시대인 오늘날은 NOR 플래시보다 NAND 플래시의 수요가 훨씬 더 많은 것입니다...
이런 차원에서 NOR 플래시를 코드저장형 플래시 메모리라고 부르고, NAND 플래시를 데이터저장형 플래시 메모리라고 부르기도 하더군요.

이제 이런 정도의 개념을 가지고 더 자세한 사항은 데이터 시트를 읽어 해결하세요...

Windows CE

1. Windows CE란( What is Windows CE? )

Windows CE는 지능적인 작동을 요구하는 가전 기기, 제어 장치 및 휴대용 장비를 운영하기 위해 개발된 작고 이식성이 뛰어난 OS이다.

2. Windows CE를 배워야 하는 이유

새 술은 새 부대에 담아야 하듯 Desktop과는 다른 환경을 지니는 모빌컴퓨터 환경에는 그에 적합한 OS가 필요하며 Windows CE는 현재 Java와 더불어 모빌 컴퓨터의 OS로 주목받고 있다. 문제는 두 OS중 대세가 무엇인지를 예측하는 것이데. 개인적으로는 2가지 이유에서 Windows CE가 승자가 될 것으로 생각된다. 첫째, 모빌 컴퓨터는 Desktop PC와 전혀 무관하게 사용될 수 없다. 모빌 컴퓨터는 Desktop과 유기적으로 Data를 교환해야 하는데 이미 Windows 환경은 Desktop환경의 표준이며 이를 계승하는 Windows CE는 사용자에게 별 거부감 없이 받아들여 질 것이다. 둘째, MS가 적극적으로 지원하기 때문이다. 과거의 전적으로 볼 때 MS는 모빌 컴퓨터 환경에서 역시 독점적인 위치를 확보하려 전력 투구 할 것이며 이런 MS를 막기란 쉽지 않을 것이다. 설령 Java가 초기에는 Windows CE에 비해 우위에 있을 수 있을지라도 결국에는 Browser싸움의 경우와 마찬가지로 Java를 수용한 Windows CE가 최후의 승자가 되지 않을까 생각된다. Windows CE는 Win32를 계승하므로 이미 많은 응용 프로그램 개발자를 확보하고 있는 셈이다. 결국 OS가 살아남기 위해서는 OS를 지원하는 응용 프로그램이 많아야하는데 Windows CE는 이런면에서 Java에 비해 우월한 위치에 있다.

3. Windows CE를 이용하는 장치( Which devices benefit from Windows CE ? )

1996년 9월 16일 페가수스로 명명되었던 Windows CE를 발표하면서 MS는 Windows CE가 다음과 같은 분야에서 사용될 수 있다고 발표했다. 소형 모빌 컴퓨터(HPC, Wallet PC, Palm PC, Auto PC), 무선 통신 기기(디지털 호출기, 셀룰러 폰), 차세대 오락/멀티미디어 기기. 특수 목적용 인터넷 접속기(인터넷 TV, 디지털 셋탑 박스)등 정보화 기기에서 사용될 수 있다고 발표했다. 현재 Windows CE를 이용한 제품이 발표되었으며 많은 업체가 Windows CE의 지원을 약속하고 있다. Windows CE가 사용되는 대표적인 분야는 Handheld PC, Palm-size PC, AutoPC이다.

4. Windows CE의 특징(Windows CE Overview)

1) 순수 32비트 운영체제로 크기가 작다.

2) Win32 API의 Subset을 사용한다.

3) 여러 종류의 CPU를 지원한다.

4) 데스크탑과 동일한 개발환경 지원.

5) 모듈성이 강하다. : Windows CE는 60개 정도의 컴포넌트로 이루어졌으며 이들을 H/W에 맞게 적절히 결함하여 OS를 구성할 수 있다.

6) 이식성이 좋다. : 다음과 같은 프로세서를 지원한다.

회사
프로세서

AMD
x86, SC400

히타치
SH3, SH4

IBM
PowerPC

Intel
x86

모토롤라
MPC821

NEC
Vr4100, Vr4102, Vr4111, Vr4300

필립스
R3910, Poseidon

도시바
TX3912





7) 통신기능 지원이 좋다 : HPC에는 Windows CE의 연결성이 잘반영되는데 적외선 포트, 시리얼 포트, 타입-II PC 카드 슬롯을 지원한다. 적외선 포트는 HPC간 무선 통신용, 시리얼 포트는 HPC와 Desktop PC간 파일의 동기화에 사용된다. Windows CE는 TAPI와 WinSock을 지원한다.

5. Windows CE를 실행하기위한 H/W조건

Windows CE를 실행하기 위해서는 최소 256KB ROM, 350KB RAM, 32-Bit CPU와 내부 스케줄링을 위한 Timer가 필요하다. 그러나. 대체로 사용자의 요구를 처리하고 그 결과를 출력하기 위한 입출력 기능을 추가하기 위해서는 1.5-2.5MB ROM이 필요하다.



Introduction to Windows CE Software Development Kit

Windows CE는 Communication, Entertainment, mobile computer에 이르는 광범위한 장치의 OS를 위해 디자인된 open and scalable Windows OS이다. WindowsCE의 융통성있는 modular구조로 다양한 형태의 소형장치에서 사용되기 위한 요구를 충족한다.( Windows CE는 Modular한 성격을 지닌다)

Window CE는 Win32를 채택하여 Windows CE-based device와 Windows NT-base Desktop간의 호환성을 보장할 수 있도록 했다. Windows CE SDK는 Win32 SDK로부터 파생되었으므로 Win32에 익숙한 개발자는 적은 노력으로 Windows CE프로그램을 개발할 수 있으며 사용자에게는 Windows와 유사한 look and feel을 제공한다.(Windows CE SDK는 Win32로부터 파생되었으며 그로인해 개발자와 사용자 모두에게 이익을 준다)

그러나, Windows CE는 Win32와는 다른 특성 또한 지니고 있다. The small-factor diskless H/W의 제약으로 인해 system resource를 사용하고 관리하는데 제약이 따른다. API의 option에 제약이 있고 때에따라서는 새로운 함수, 구조가 제공된다.(Window CE는 Win32를 기반으로 하였으나 Windows CE가 동작하게 될 H/W의 소형화 특성상 Win32 API사용에 제약이 따를 수 있으며 Win32에서는 제공되지 않는 새로움 함수가 제공되기도 한다)

Windows CE SDK는 다음과 같은 category로 구성된다. System Service, User Interface, Communication, Desktop Connectivity, Application Interface, COM-Based Object Services

Windows CE Operating System Architecture

Windows CE는 몇 개의 중요한 software module로 구성되어 있으며 이들간에는 Win32 compatible interface를 통해서 통신한다. 각 모듈은 많은 종류의 configurable component를 포함하고 있어서 feature-level service를 제공한다.

Windows CE Kernel, Windows CE Graphics Windowing and Events subsystem. Kernel은 thread, memory, resource를 관리하며 DLL을 이용함으로써 메모리 효율을 높힌다.

GWE module은 Windows NT User와 GDI가 결합되어 줄어든 형태로 볼 수 있다. GWE는 2-bits-per-pixel color display, overlapping windows, event management, controls, interprocess communication, and UNICODE를 지원한다.

Windows CE의 나머지 부분은 shell, file system, perdistent storage, database, communication, desktop connectivity, internet browsing, e-mail, and COM-based object service같은 부가적인 서비스를 제공한다.( Windows CE는 몇 개의 module로 구분될 수 있다. Kernel은 Thread와 memory를 관리하는 기능을 하며, GWE는 Graphic과 Event와 관련된 서비스를 제공한다)

Aboud System Service

Windows CE SDK는 application developer에게 메모리를 관리하고, notification을 사용하고, object store를 조작하고, power consumption을 최적화하고, GDI나 MGDI를 이용해 프로그램을 작성하는 방법을 제공하는데 이를 system service라고 한다.(당연히 system과 관련되 API을 SDK에서 지원해야 한다)

About Managing Memory

Windows CE는 두가지 형태태 ROM과 RAM을 지원한다. backup battery는 RAM을 non-volatile메모리로 만든다. ROM에는 DLL, 번들 프로그램, 리소스가 들어있다. RAM은 storage memory와 program memory로 나뉜다. storage memory는 registry와 file system이 사용하며 파일시스템 속의 모든 파일은 압축되어 저자된다. 프로그램 메모리는 시스템과 실행중인 프로그램에 의해 stack과 heap으로 사용된다. storage memory와 program memory에 대한 partition은 사용자가 정의한다. Windows CE는 번들 프로그램과 user installed program을 서로 다르게 처리한다. 번들 프로그램은 ROM에서 직접 실행하며 user-installed program은 파일 시스템에 압축된 형태로 저장되어 있다가 실행될 때 프로그램 메모리로 압축이 풀리면서 load되서 실행한다.

Windows CE는 on-demand paging의 가상메모리를 지원한다. 시스템은 사용가능한 메모리를 확인하여 limited memory condition이 발생하지 않게 한다.

Windows CE는 서로 다른 형태의 메모리(stack, heap, static and virtual memory)에 대한 할당, 해제, 모니터링을 위한 함수를 제공한다.

(Windows CE는 일반적으로 시스템의 자원이 제한된 영역에서 주로 사용되게 되므로 메모리를 효율적으로 사용하는 것은 매우 중요하다. Windows CE는 ROM과 RAM을 가지고 있는데 ROM은 시스템과 관련된 실행 파일과 데이터가 저장되고 RAM에는 사용자가 설치한 프로그램이 저장되고 실행되는 역할을 한다. RAM은 Registry와 FileSystem을 포함하는 Storage memory와 프로그램을 실행하기 위한 program memory로 나뉜다. storage memory에는 사용자가 설치한 파일이 압축된 형태로 저장되며 실행될 때는 압축이 해제되면서 program memory로 load되어 실행된다.)

About Using Windows CE Notifications

Notification은 시스템이 어떤 사건이 발생했음을 사용자나 application에 알려주는 signal이다. 이때 event는 시스템 event나 timer event가 될 수 있다.

Notification은 LED가 깜빡이거나, Dialog Box, sound가 실행되거나 기계적인 진동이 있을 수 있다. 전형적인 notification application은 schedule book이 된다. 사용자가 설정한 날짜와 시간에 대해 시스템이 이를 감지하면 taskbar에 icon을 만들 게 된다. Windows CE SDK는 event에 대한 notification에 대해 event에 대한 notification을 등록하거나, notification의 state를 결정하거나, option을 선택하거나, event를 처리하거나 하는 따위의 많은 API를 지원하게된다.

(notification에 대한 처리는 Windows 프로그램에서 새로운 사실이 아니다. 단지 시스템이 직접 notification을 처리할 수 있다는 것과 notification을 발생하는 level이 약간 다를 뿐이다. 어째든 Windows CE가 휴대용 장비에서 사용된다면 notification은 자주 사용될 것이다)

About Managing Power Consumption

Windows CE는 battery를 가능한 지속시키기 위해 능동적인 power management를 지원한다. OS는 현재 장치의 동작상화에 따라 적절한 power consumption level을 자동으로 선택한다. Windows CE는 full-speed mode, idle, suspend mode를 지원하다. 게다가 Windows CE power management system은 battery의 life time을 모니터 해서 사용자에게 battery를 교체해야할 시점을 알려준다.

(Windows CE가 Windows와 다른점은 이 Power Management에 관한 점이다 )

About Object Store

Object Store는 Windows CE에서 영구적인 데이터를 저장하기 위한 장치로 사용된다. 물리적으로는 non-volatile, battery-backed RAM이 사용된다. Object Store는 3개의 기본 요소를 지닌다.

File System : 3가지 형태의 file system이 사용된다. ROM-based file system, RAM-based filesystem, diskdrive, flash memory, SRAM을 위한 FAT file system이 그것이다. working directory에 대한 개념만이 다르고 모두는 유사하다.

The Registry :

Database : Windows CE는 built-in database manager가 있다. 이 database는 single-level hierarchy만을 지원하며 다중 database가 허용된다. Windows CE Database System API는 object searching과 sorting같은 기능을 지원한다.

Windows CE는 Object store에 대해 Transaction mode로 동작해서 accidental system interrup에 대해 data를 보전하게 된다.

About GDI

Windows CE의 GDI는 장치에 독립적으로 graphical output을 출력하기 위한 함수와 관련된 구조체의 집합이다. 이 함수들은 Win32 GDI와 매우 유사하다.

About Process and Threads

Windows CE는 multithreaded Win32 프로그래민 모델을 제공한다.Windows CE는 선점형 멀티 태스킹으로 priority-level에따라 스케줄링하게 된다. 동일한 priority를 지니는 process간에은 동일한 CPU시간을 sharing하지만 low priority process는 high-priority process에게 양보한다.

비록 Windows CE Kernel이 single address space만을 지원하지만, 다른 프로세스가 서로 간섭되는 것을 방지한다.

About User Interface Service

Windows95나 Windows NT와 마찬가지로 Windows CE에서 control은 사용자가 응용프로그램과 데이터를 교환하기 위한 친근한 인터페이스를 지원한다. Windows CE interface는 shell, windowing environment, windows control, common control, menu, dialog box와 다른 control을 지원한다.

About Windows CE Shell Service

Windows CE Shell은 OS의 입장에서는 사용자 인터페이스이며 desktop window, command bar, task bar, control panel과 recycle bin을 포함하고 있다. 이런 control들은 모든 응용프로그램에서 공통으로 사용되며 shell은 문서를 access하고, 응용프로그램을 실행하고, task간 전환, file system을 browsing 등에 대해 편리한 사용자 인터페이스를 제공한다. Windows CE 의 Shell은 Win32 Shell API의 Subset이며 몇 개의 새로운 함수가 Windows CE에 추가되기도 했다.

Shell Notification API는 응용프로그램의 이름과 event를 시스템에 등록할 수 있도록 해 특정한 event가 발생하면 그와 함께 등록된 응용프로그램을 실행하도록 한다. shell은 system resource를 coordinate하는 책임이 있다.

(Shell의 기능은 사용자에게 응용프로그램을 실행하거나 관리할 수 있는 기능을 제공하는 것으로 Windows CE에서 사용하는 Shell은 Win32 Shell API가 기반이된다. Shell은 또한 notification과 system resource를 관리하는 책임을 가지고 있다)

About Windowing Environment

Windows CE SDK는 application's user interface가 생성되고, 해제되고, 관리되어지는 window environment를 구성할 수 있는 많은 API을 제공한다. Windows CE application's user interface에는 caret, clipboard, cursor, icon, keyboard accelerator, keyboard input, message and message queue와 window control이 있다.

(Windows란 용어가 의미하듯이 window 환경을 지원하기 위한 충분한 API를 지원해야 한다. 즉 window을 생성,해제,관리할 수 있는 기능과 window와 관련된 interface( caret, cursor, icon, keyboard accelerator, keyboard input, message, message queue와 같은 것을 지원하게 된다)

About Communications

Windows CE는 다른 장치와 communication하기 위한 standard Wind32 interface를 지원한다. 이런 API 다음과 같은 기능을 하게 된다. 1. serial or dial-up LAN을 통해 desktop PC와 통신한다. 2. IrDA protocol을 사용해 적외선 통신을 지원한다. 3. serial device간의 standard communication 4. modem간 standard communication 5. internet에 대한 standard communication 6. remote file access에 대한 지원.

Windows CE communication API는 다음과 같은 6개의 categories로 구분된다. 1. WinSock의 subset, 2.Remote File Server connection and management. 3.Wind32 serial function 4. networking function 5. internet client service 6. a subset of TAPI

(Windows CE는 충분한 communication기능을 가지고 있어야 한다. Windows CE의 용도가 휴대용 장치를 동작시키기 위한 목적으로 사용되므로 장치간의 원활한 데이터 교환을 위해서는 communication기능이 반드시 필요하다. Windows CE는 desktop과의 데이터 교환을 위해 serial과 LAN을 사용하고, Windows CE를 사용하는 장치간의 IrDA통신, modem을 지원하고 Communication API는 6개의 categories에 해당하는 기능을 지원한다 )

About Desktop Connectivity

Desktop Connectivity는 다음과 같은 도구를 언급한다. 1. File Filter, 2.Tools for importing and exporting file. 3.RAPI 4.Functions for enabling a RAPI client to request services from RAPI server 5. Application setup tool 6. For installing a Windows CE application from a desktop PC 7. Connection manager 8. establishing and maintaining the connection between the desktop application and the Windows CE device

About Application Interface

Windows CE는 built-in application이 있다. Contacts, A database application for personal information management, inbox, a mail application to provide users with access to electronic mail

About COM-Based Object Services

COM-based Object Service는 Microsoft Component Object Model에 기반한 software component의 object-orient development에 관한 함수와 구조체에 대해 기술한다. 2종류의 service가 있다. 1.COM 2. Automaion

(잘 모르겠다).

Functions, Macros and Structures Used in Hello Windows CE

Hello Windows CE라고 불 리는 프로그램를 예로 standard Windows Programming과 Windows CE프로그램밍의 다른점을 기술한다.

The Windows CE WinMain Functions

다른 Windows-base program과 마찬가지로 WinMain은 Windows CE 응용프로그램의 entry point가 되며 다르것과 마찬가지로 4개의 입력파라메타를 전달받게 된다.(약간 차이가 있음)

hInstance . 이 program에 대한 handle. Windows-based program과 동일하다.

hPrevInstance. Windows CE에서는 사용되지 않으며 항상 NULL이 된다.

szCmdLine. Command Line 파라메타로 UNICODE에 적합하게 wide string에 대한 pointer가 된다. LPSTR에서 LPTSTR로 바뀌었다.

nCmdShow. 어떻게 Window가 display되야 하는지를 결정하는 flag. Windows CE는 Windows 95가 지원하는 모든 flag를 지원하지는 않는다.

(WinMain( )이 entry point로 사용되나 몇몇 제약이 있다. UNICODE를 사용하거나, display형태기 제한받게 된다)

Registering the Window Class for Windows CE

application이 window를 생성하기전에 RegisterClass를 호출해서 window class를 등록해야 한다. Windows CE는 WNDCLASS의 모든 항목을 지원하지 않으며 그 항목은 NULL로 setting한다. 지원되지 않는 항목은 style, hCursor, lpsaMenuName

(하나의 style만을 지원하는데 어떤 style이지? )

Initializing Command Controls

InitCommandControl함수는 common DLL이 command bar를 위해 load되도록한다.

Creating the Window

CreateWindow는 생성할 Window의 apperance와 function을 특징짓는다. Windows CE의 CreateWindow함수는 Windows 95와 동일한 함수파라메타를 사용하다. 기본으로 초기화하는 것이 가장좋은 방식이다.

Painting the Window and the Message Loop

The Window Procedure

WM_CREATE

Windows95-based program과 마찬가지로 message는 window procedure에서 처리된다. WM_CREATE message를 Windows CE가 받은 경우 2개의 Windows CE만의 유일한 함수가 호출된다. 1. CommandBar_Create. empty command bar를 생성한다. 2. CommandBar_AddAdornments. help와 close button을 command bar에 추가한다. help button이 눌리면 WM_HELP가 발생하고 close button이 눌리면 WM_CLOSE가 발생한다. CommandBar_AddAdornments는 OK Button을 추가할 수 있는데 이 버튼이 눌리면 WM_COMMAND에 IDOK가 발생한다. "Hello Windows CE"프로그램은 프로그램이 시작할 때 sndPlaySound( )를 호출한다. 이때 재생하는 사운드는 ROM에 번들로 저장되어있는 리소스를 사용한다. Windows CE는 16-bit wav file을 지원하나 추천되지는 않는다. 8-bit 11.025KHz나 그 이하의 파일을 사용하는 것이 바람직하다.

WM_PAINT

WM_PAINT는 언제 clinet 영역이 다시 그려져야 하는 지를 알려주게 된다. 예제 프로그램은 5개의 함수를 호출한다. BeginPaint와 EndPaint는 Windows95-based와 동일하게 동작한다.

WM_HIBERNATE

Windows CE장치는 low memory를 가지고 있으므로 시스템은 메모리를 모니터해 일정한 용량아래로 떨어지면 적당한 조치를 취해야 한다. 이 과정에서 중요한 역할을 하는 것이 WM_HIBERNATE 메시지다. 이 메시지는 low-mwmory situation이 발생하면 이를 응용프로그램에 알려준다.

The TEXT Macro

Hello Windows CE에서 사용되는 몇몇 함수는 text string을 파라메타로 받아들인다. 이 함수에서는 TEXT Macro를 사용해서 ANSI String을 UNICODE로 변환하고록 한다.

Porting Windows 95 to Programs to Windows CE

Windows CE로의 porting과 관련하여 언급할 주요 사항은 다음과 같다.

1. Win32와 Windows CE API간의 차이 2. Standard MFC와 Windows CE MFC간의 차이점 3.Memory제약과 out-of-memory recovery 4.Energy limitation 5. widely varying hardware characteristic and limitations 6.testing과 debugging간의 차이.

Difference Between the Win32 and Windows CE APIs

Windows CE API는 Standard Win32 API와 몇가지 중요한 차이를 보이고 있다.

1. It is similar, Win32의 subset만이 지원되며 지원되는 것 중에는 제한된 기능만을 제공하는 것이있다.

2. There are Windows CE-specific extensions, 다양한 장치를 지원하기 위한 API가 제공되며, Win32의 것을 대신하는 것도 있다.

3. exception handling에 제약이 있다. Win32의 structured exception handling은 지원하나, C++ exception handling은 지원하지 않는다.

(당연히 Windows CE는 Win32의 subset이므로 Win32중 제한된 기능만을 지원하게 될 것이며 Windows CE가 Desktop보다는 제약이 많은 시스템 환경에서 사용하게 되므로로 그런 하드웨어를 처리하기 위한 함수를 포함하고 있어야 한다 )

Difference Between Standard MFC and MFC for Windows CE

Windows CE용 MFC는 Standard MFC의 기능과 특성을 가능한 유지하고자 한다. 그럼에도 불구하고 사용할 수 있는 class와 각 class가 지원하는 특징 사이에는 큰 차이가 있다. Windows CE는 독자적인 class를 포함하고 있다. 가령 command bar control같은 기능.

(API나 MFC모두 차이가 있게지만 가능한 그 정도를 최소화 하려고 했을 것이며 이곳에서는 구체적인 예가 없으므로 매뉴얼을 찾아보는 수밖에 없다)

Memory Limitation

Windows CE장치는 일반적으로 desktop에 비해 사용가능한 메모리 양이 훨씬 적다. 대부분의 경우, 성공적으로 포팅을 하기 위해서는 메모리를 줄이는 것이 중점을 두어야 할 필요가 있다. 따라서, 자주 사용되는 기능만을 포함한 츠로그램을 작성하는 것이 프로그램의 사이즈를 줄이는 데 도움이 된다. 프로그램은 가능한 적은 메모리를 사용하는데 중점을 두어 작성하여야 한다. 또한 메모리를 관리하기 위해 시스템과 협력해야 한다.

(가능한 메모리를 아끼면서 프로그램을 작성하여야 한다. 불필요한 기능과 쓸데 없는 리소스를 배제하고 코드를 최적화하는 것이 필요하리라, Windows CE에서는 최소한의 메모리를 사용하는 것이 매우 중요하다. )

Energy Limitation

Hardware Characteristics

Windows CE는 desktop에 비해 smaller and less powerful한 장치에서 동작하기 위해 설계되었다. 예를 들어, screen이 작고, CPU는 느리고, 사용자 인터페이스는 less flexible하다. 반면 desktop에서는 지원되지 않는 장치를 Windows CE 장치에는 부착된 경우가 있다. 따라서 프로그램을 포팅할 때는 모든 장치에서 공통으로 사요할 수 있는 부분이 무엇이고 아닌지를 알아여 한다.

Testing and Debugging

Windows CE용 프로그램을 작성하는 것은 Win32프로그램을 작성하는 것과 매우 유사하다. 그러나, testing 과 debugginbg시에 중요한 차이가 있다. 만일 Windows CE영 프로그램을 작성한다면 대부분의 test와 debugging이 eulator에서 이루어 지게 된다.

A Systematic Approach to Porting Application to Windows CE

Porting to the Windows CE

만일 application Win16-based이면 일단 이를 Win32로 변환하는 것이 좋다. Win32는 하위 호화성을 유지하나 Windows CE는 그렇지 못하다. application에서 사용된 모든 API를 면밀히 검토해 Windows CE와 campatible하지 않는 것은 개조하거나 변경한다. 1. Win32함수가 지원되지 않을 수 있다. 2.Win32함수가 Windows CE equivalents로 대체된 것이 있다. tool and menu bar combined into a single command bar. 3.Win32가 지원되나 기능에 제약이 따른다. 4.지원되는 데이터 형의 변경이 필요하다. 5.몇몇 메시지가 지원되지 않는다.

(Win32프로그램을 Windows CE프로그램을 포팅하는 것은 그리어려운 작업은 아닐 것이다. 일단 Win32의 subset을 Windows CE가 사용한다(비록 부분적으로는 API에 제한이 있을지라도)

Managing Windows CE Memory

사용가능한 메모리는 장치에 의존적이므로 target platform의 용량을 확인해야 한다. Windows CE는 메모리를 사용하거나 mass storage를 동일한 방법으로 사용한다.

Windows CE프로그램에서는 메모리와 storage의 사용을 줄여야 한다. bitmapped-graphic같은 memory-intensive feature는 간단히 하거나 제거하는 것이 좋다. 정말필요하지 않으면 temporary file은 사용하지 않는다. 메모리 리소스가 tight해지면 Windows CE는 메모리 사용을 줄이고 사용가능한 메모리를 일정 수준으로 복귀하는 과정을 거치게 된다. 이런 프로시져는 WM_HIBERNATE 메시지로 이루어 진다. WM_HIBERNATE가 어떻게 동작하는지는 Managing Memory Section에서 언급한다.( Windows CE에서 가장 중점을 두어야 하는 부분은 메모리 관리에 관한 부분으로 가능한 불필요한 코드를 제거하고 메모리를 복귀시키는 부분을 코딩해야 한다)

Managing Available Power

Porting the Graphics Device Interface

대부분의 PC 응용프로그램들이 Windows CE에는 적합하지 않은 GDI를 가지고 있다. 따라서, 포팅전에 수정이 필요하다. OS를 작게 만들고 H/W의 제약에 의해 많은 Win32 GDI함수가 지원되지 않고 제약이 따른다. Windows CE 2.0과 함께 GDI Subsystem은 MGDI로 바뀌었다. MGDI는 전혀 새로운 display subsystem을 지원하며 이는 Windows NT에 가까운 기능을 제공한다.( 메모리 및 H/W의 제약에 따라 지원되지 않는 GDI함수가 많거나 지원한다 하더라고 사용상의 제약이 많다. Windows CE 2.0에서는 기존의 GDI를 변경한 MGDI를 사용한다)

Adapting Bitmaps and Icons

Windows CE장치는 Desktop PC에 비해 적은 스크린과 aspect ratio를 지니고 있다. 이런 제약조건에 적합하게 응용프로그램에 대한 수정이 불가피하다. 그러나, static layout를 사용하지 않는 것이 좋다.

Using Unicode

Windows CE는 UNICODE System이다. 비록 text file의 exchange를 지원하나, native format은 UNICODE이다. ASCII Code를 Unicode로 변환하기 위한 guideline은 다음과 같다.

Tchar.h를 포함한다.=> C run-time함수보다 Win32 string function을 사용한다. => TCHAR, LPTSTR를 사용해 쉽게 ASCII나 UNICODE로 compile한다.=>TEXT Macro를 string literal에 사용한다.=>문자가 더 이상 한 바이트가 아니다. 문자의 끝이 2바이트의 0으로 되어 있다. => array pointer나 char count를 증가시킬 때 sizeof(TCHAR)를 사용한다.

(UNICODE를 사용할 때의 주의할 점이 위에서 언급하고 있다)

Creating and Managing Windows

Windows CE에서 Window를 생성하고 관리하는 것은 Win32에서와 매우 동일하다. 그러나, 적은 window style과 manage option만을 가지게 된다. 아마도 가장 큰 차이점이라면 window가 이동할 수는 있지만 resize가 불가능한 점이다. window는 window가 생성될 때 설정된 size값을 지니고 있게 된다. Resize가 불가능하다는 것은 WS_OVERLAPPEDWINDOW가 지원되지 않는다는 의미이다.(WS_OVERLAPPEDWINDOW가 지원된다고 본 것같은데?)

Using Windows CE Dialog Box

Windows CE는 modal, modeless와 Windows95에서 제공하는 control을 지원한다. 그러나, 모든 control style이 지원되지는 않는다. Windows 95에 비해 적은 option을 지니지만 MessageBox를 지원한다.

Porting User Interface Controls

대부분의 standard Windows control과 common control이 지원된다. 그러나, 몇몇 제약이 있다. 가장큰 차이는 menu와 toolbar가 command bar로 통합된 점이다.

Managing Windows CE thresholds

Windows CE는 multithreaded OS이다. 그러나 Windows95/NT에 비해 몇몇 제약이 있다. 가장 큰 제약은 semaphore를 지원하지 않는다는 것이다.

Modifying the User Interface

Supporting Windows CE Communications

Windows CE는 다음과 같은 4개의 communication API를 지원한다.

.WinSock .TAPI .RAS .Serial Communication

Network Support Via Winsock

Windows CE Network Stack은 TCP/IP를 지원한다. 만일 응용프로그램에서 network traffic을 다루기 위해 winsock을 호출하였다면 거의 변경이 필요없다. IrDA specification은 WinSock annex로 부가되었다.



Managing Memory

비록 Windows CE가 개발자에게 복잡한 graphically oriented application을 개발할 수 있는 많은 tool을 제공하지 만 그런 응용프로그램은 많은 양의 RAM을 요구한다. HPC는 desktop에 비해 제한된 메모리를 지니며 이런 제한된 환경에서 성고적인 프로그램을 작성하기 위해서는 프로그램을 변경해야 한다.

Overview of Memory On the HPC

Windows CE는 가상 메모리를 가지고 있다. 이는 memory가 at granularity of a page로 할당된다. page는 OEM종속적이다. (1KB or 4KB) 사용자는 PCMCIA를 사용해 메모리를 추가할 수 있다. OS와 번들 프로그램은 ROM에서 in place로 실행된다. 이런 프로그램과 관련되서 stack, heap storage와 관련된 적은 양의 메모리만 필요하나 data와 관련된 경우에는 다른 곳이 저장된다. 2MB가 최소의 메모리 요구사항이나. 대부분의 업체는 그 이상을 공급한다. 4MB가 desktop에 비해 적은 양이나 이또한 program실행을 위해 사용되지는 않는다. HPC의 경우는 disk가 없으므로 RAM이 데이터를 저장하기 위한 공간으로 사용된다. RAM의 효과적인 사용이야말로 HPC용 프로그램을 개발하기 위한 가장 중요한 사항이다.

The Basic Layout of RAM on the HPC

RAM은 두 개의 영역으로 구분된다. Storage memory, Program Memory.

Storage Memory

Storage Memory는 desktop PC의 RAM disk와 유사하다. 이는 data와 non-system application을 저장하기 위해 사용한다. Storgae memory의 3가지 section은 서로 다른 Win32 API를 이용해 access된다.

1. The Windows CE system registry는 Windows 95나 Windows NT와 유사하다. Standard Win32 registry function을 사용한다. 2. 응용프로그램과 data는 file storage에 저장된다. 3. database관련.

Using Windows CE Registry

메모리 요구량을 줄이고, access time을 줄이고, registry key size를 제한하기 위해 다음과 같은 guidline을 따른다.

.각 key의 이름을 제한한다 .subkey level을 제한한다.

.null name을 사용하지 않는다 .많으면서 적은 크기의 registry value를 사용하지 않는다.

.Window95의 key-naming convention을 사용할 필요가 없다.(사용자가 볼 수 없으므로)

Program Memory

Program memory는 system and non-system program의 stack과 heap을 위해 사용된다.

Windows CE Address Space

Program Memory가 관리되는 것을 이해하기 위해서는 먼저 Windows CE의 메모리 구조를 살펴봐야 한다. Windows CE가 초기화될 때에는 4GB의 메모리가 할당되고 모든 progess에 의해 공유된다.이 주소는 kernel에 의해 실제의 메모리로 사상된다. version 1.0에서는 주소 공간이 33개의 32MB"slot"으로 나위었다. 이 slot외부의 데이터를 access하면 access violation을 발생한다. 각 process에는 개별 slot이 할당되며 slot zero는 현재 실행중인 process를 위해 예약되었다( 무슨 소리?)

Memory Paging

Memory는 at the granularity of a page로 할당된다. Page size는 OEM종속적이다. 현재는 1KB나 4KB가 할단된다. Version 1.0에서는 RAM-resident code와 data page는 application이 실행되는 동안 program memory로 load되어 실행된다. Version 1.01은 RAM-resident application에 대한 demand paging을 지원한다. demand paging과 함께, 만일 RAM의 shortage가 발생하면 kernel에 의해 현재 실행되지 않는 page는 제거되었다가 필요시에 다시 load된다. kernel은 어떤 page가 least need한지를 비교하지 않고 무작위로 없앤다. PCMCIA Card의 메모리에 대해서는 demand paging이 지원되지 않는다.(version 1.01) 이 경우에는 모든 프로그램이 Program memory로 load되어 실행된다.

Writing Mmory Efficient Application for Windows CE

Memory Pages

평균적으로 한 page의 절반 가량의 메모리가 낭비되므로 larger page는 더 많은 메모리를 낭비하게 된다. 작은 page size는 많은 OS overhead를 요구한다. It also decrease the amount of memory that can be addressed from the translation look aside buffer(TLB)-potentially reducing its effectiveness. 주어진 장치의 실제 메모리 size는 OEM-dependent하다. RAM usage는 major concern이므로 page size는 가능한 작게 유지된다.현재는 1KB나 4KB가 page size로 사용되며 a good rule of thumb는 memory allocation decision을 할 때에는 1kB의 page size를 사용하는 것이 좋다.

Types of Memory Allocation

응용프로그램이 메모리를 할당할 수 있는 몇 개의 독립적인 memory pool이 있다. 각 pool은 많은 갯수의 page로 구성되었으며 몇 개는 쉽게 grow나 shrink할 수 있다. 응용프로그램은 wasted RAM의 양을 최소화 하는 범위내에서 메모리를 할당하기 위해 이 pool을 사용한다.

Stack

가장 평범하게 사용되는 data storage mechanism은 stack에 data를 선언하는 것이다. stack은 1KB에서 시작해 58KB까지 메모리를 추가하게 된다. syste은 stack을 줄일 수 있으나 모든 resource가 거의 다 사용되는 경우에만 비로서 수행하게 된다. short-lived data를 위해서는 stack이 적당하나. large amount of memory를 stack에 할당하는 것은 피하는 것이 좋다.(58KB이상의 stack allocation은 access violation을 발생한다)

Static Data

static data나 global data에 대한 선언은 data를 R/W section에 저장한다. 이 section은 grow와 shrink를 하지 않는다.application's data section 은 Win32 DumoBin을 사용해 결정할 수 있다.

Virtual Memory

VirtualAlloc은 Windows CE에서 가상메모리를 지원하는 기본적인 tool이 된다. Virtualalloc을 integral number of memory page를 직절할 당하는 데도 사용할 수 있다. VirtualFree를 사용해 메모리를 free하는 경우 즉시 global virtual memory pool에 return된다. 모든 메모리 pool은 VirtaulAlloc에 근거를 두고 있다. VirtualAlloc은 단지 page만을 할당할 수 있으므로 작은 메모리 object를 할당하는 용도를 목적으로 하지 않는다. 큰 메모리 할당을 목적으로 한다면 VirtualAlloc을 사용하는 것이 가장 효율적인 방법이다. 이런 방식의 장점은 low-memory condition이 발생한 경우 메모리가 쉽게 return된다는 것이다.

Default Heap

각 process는 heap을 가지고 있으며 LocalAlloc과 LocalFree는 이에 대해 동작한다. Note that memory for the new heap is reserved but not actually committed until needed. 메모리를 할당하거나 해제하기 위해 HeapAlloc이나 HeapFree를 사용한다. 이 함수는 LocalAlloc이나 LocalFree와 근본적으로는 같으며 차이점은 HeapDestroy로 이 Heap을 해제한 후 global virtual memory pool에 복귀시킨다는 점이 다르다. 많은 수의 작은 메모리를 임시로 할당하는데 separate heap을 사용하는 것은 매우 좋은 방법이다. 메모리를 즉시 global pool에 복귀할 수 있다는 점에서. heap은 대략 500바이트의 overhead가 필요하다. 적어도 5KB의 메모리를 할당한다면 separate heap을 할당하는 것은 좋은 메모리 사용전략이 된다.

Selecting a Memory Allocation Method

다음의 criterion은 메모리 allocation method를 결정하는 데 도움이 된다.

1) 하나의 큰 메모리 allocation의 경우, VirtualAlloc을 사용한다. 2) 동일한 lifetime을 지니는 작은 데이터 item의 경우 separate heap을 사용한다. 3) 응용프로그램과 동일한 life time을 지니는 경우 static section에 저장한다. 4)함수범위내에 존재하는 경우 stack을 사용한다. 4) random overlapping lifetime을 지니는 항목의 경우, default heap을 사용한다.

Monitoring An Application's RAM Usage

현재 어느정도의 메모리를 사용하고 있는지를 알 수 있는 두 개의 도구가 있다. Map File과 Remote Memory Viewer이다.

Map File

Map File은 static section의 data를 분석하는 데 효율적이다. 각 section의 길이가 파일의 처음에 제공된다. R/W section은 두 개의 subsection으로 구성된다. .data는 초기화된 global data로 구성되며 .bss는 초기화 되지 않은 데이터로 구성된다. 또한 read-only section .rdata역시 볼 수 있다( Map File은 static data에 대한 정보를 제공한다. static data는 3가지 section으로 구분된다)

Analyzing Memory Usage with Remote Memory Viewer

일단 응용프로그램이 컴파일되고 장치로 load되면 Remote Memory Viewer는 메모리 상황을 살펴볼 수 있는 매우 유용한 도구이다. 이 프로그램은 desktop PC에서 장치의 메모리 상활을 확인할 수 있도록 해준다.

Handling Low memory Situations

Low memory situation은 다음과 같은 현상으로 응용프로그램에 알린다. 1. VirtualAlloc함수가 실패, 2. LocalAlloc or HeapAlloc함수가 heap을 grow하려고 시도하나. 실패한다. 3.stack이 grow하려고 하나 실패한다.

System Low Memory Handler

system은 항상 사용가능한 메모리를 check하고 limited memory상황이 발생하지 않도록 모니터한다. 응용프로그램이 메모리를 요구할 때 시스템은 할당하는 메모리를 제한하므로써 request를 filtering하게 된다. 이는 한 프로그램이 모든 메모리를 사용하는 것을 금지한다.

The Limited-Memory State

system은 항상 메모리 사용량을 모니터한다. 그러다, 사용가능한 메모리가 Hibernation threshold이하로 떨어지면, limited-memory체제로 들어간다. 시스템은 비동기적으로 WM_HIBERNATE message를 모든 active application에 보내기 시작하고 이 메시지는 모든 응용프로그램에게 메모리가 부족해지고 있음을 알려주게 된다. 두 개의 추가적인 threshold가 있다. low, critical . 아래의 table은 memory threshold와 maximum allowable memory allocation for the three levels of limited-memory conditions

Hibernation Threshold : system 이 limited-memory state에 들어가는 시점이 된다. WM_HIBERNATE message가 발생한다. when the system memory falls below

Low Memory Threshold : system이 low memory state에 있을 때 system이 반드시 유지해야 하는 최소한의 사용가능한 메모리.

Maximum Low Memory Allocation : system이 low memory state에 있는 경우 VirtualAlloc으로 최대한 할당될 수 있는 메모리의 양

Critical Memory Threshold : system이 critical memory state에 있을 때 시스템이 반드시 유지해야 하는 최소한의 사용가능한 메모리

Maximum Cirtical memory Allocation : system이 critical state에 있을 때 VirtualAlloc으로 할당될 수 있는 최대한의 메모리.

(무슨 소린지?)

기본적으로 시스템이 반응해야 하는 4개의 시나리오가 있다.

Request Less than the Low-memory Maximum

응용프로그램이 VirtualAlloc을 사용해 maximum allowable memory보다 적은 메모리 할당을 요구하는 경우. 비록 이런 경우의 결과 시스템의 메모리가 low-memory threshold이하로 떨어지게 될 가능성이 있는 경우 System Out of Memory Dialog Box가 Display된다. 사용자는 프로그램을 종료하거나 Program Memory의 양을 증가시킨다.

Request Greater than the Low-memory Maximum

application이 low-memory state에서 최대한 허용가능한 메모리 보다도 많은 양을 할당하고자 하는 경우. 그 결과로 시스템 메모리가 low-memory threshold이하로 떨어지면 VirtualAlloc은 실패한다. System Out of Memory Dialog Box는 Display되지 않는다. 동일한 제약이 LocalAlloc에 적용되는 것은 아니다.이는 시스템 Heap의 현재 상황에 영향을 받는다.

Requesr Less Than The Critical-Memory Maximum

application이 cirtical-memory state에서 최대 할당가능한 메모리보자 적은 메모리를 VirtualAlloc을 사용해 할당하고자 하는 경우. 그 결과 시스템 메모리가 critical memory threshold이하로 떨어질 가능성이 있으면 System Out Of Memory Dialog Box가 display된다. 사용자는 응용 프로그램을 종료하거나 Program Memory를 늘리게 된다.

Request Greater than the Critical-Memory Maximum

critical-memory maximum보다 더 많은 메모리의 할당을 요구하는 경우, 그 결과 시스템 메모리가 cirtical memory threshld이하로 떨어지면 그 요구는 실패하게 된다. 시스템의 heap의 상태에 따라, LocalAlloc의 성공여부가 결정된다.

System Out Of Memory Dialog Box

위에서 언급한 바와 같이 OS는 system out of memory dialog box를 몇몇 상황에서 display한다. 이 dialog box는 system modal로 시스템의 모든 부분을 정지시킨다.(socket connnection may hang up, other threads stop running). 이 dialog box는 사용자에게 장치가 low memory 상황임을 알리고 어떻게 처리할 것인지를 요청하게 된다. dialog box가 사라진후 어떤 선택된 응용프로그램이 마치 Close Button이 눌린 것 처럼 close된다.

Application Hibernation

system은 WM_HIBERNATE 메시지를 응용프로그램이 메모리를 해제 하기 위한 기본적인 방편으로 사용한다. 시스템에서 메모리가 필요한면 WM_HIBERNATE를 모든 혹은 일부 응용프로그램에 전달한다. 이는 오랜동안 동작하지 않는 프로그램에 우선적으로 보내며 보이지 않는 Window에는 보내지 않는다. Hibernation은 매우 중요하며 잘 동작하는 Windows CE 프로그램은 WM_HIBERNATE에 동작하게 해야 한다. application이 foreground로 실행될 때에는 시스템은 WM_ACTIVATE를 발생한다. 만일 application이 hibernating을 하고 memory를 release했어도 시스템은 이를 복구하지 않는다. 따라서 application은 WM_ACTIVATE에 대한 handler를 가지고 있어서 이 리소스를 복구해야 한다.

Handling WM_HIBERNATE

application은 WM_HIBERNATE 메시지를 받으면 다음과 같은 동작을 취하게 된다.

1. VirtualAlloc에 의해 할당된 임의의 큰 메모리 블록을 해제한다. 2. 가능한 GWES Object를 해제한다. 3.heap의 state를 저장하고 entire heap을 해제한다. 사용가능한 메모리가 줄어들수록 시스템은 WM_HIBERNATE을 increasing rate로 발생한다. 만일 시스템이 VirtualAllo이 실패하는 상황이 발생하면 stack을 줄임으로써 메모리 페이지를 해제한다. 이 stack shrink는 시스템이 맨마지막에 취한는 조치다. 이는 자칫 stack fault를 발생시킬 수 있다.stack shrink가 불가능하면 VirtualAlloc은 실패하고 그 결과가 리턴된다.

Tips for efficient Memory Utilization

Allocating Memory

16KB이상의 메모리 할당을 시도하는 것은 System Out of Memory Dialog박스나 경고없이 실패할 가능성을 항상가지고 있으므로 이에 대한 대처를 해야한다. 일단 시스템이 low-memory체계에 들어가면 8KB이상 메모리를 할당하는 것은 항상 실패할 가능성을 포함하고 있다. 또한 shutdown code에서 많은양의 메모리를 할당하지 않아야한다. 작은 메모리를 할당하는 것은 거의 실패하지 않는다. 사용자는 System out of memory dialog box을 보게 되거나 low-memory상황에 적절한 대처를 할 수 있는 기회를 지니게 된다. (8KB이상의 메모리를 할당하는 것은 피하는 것이 좋다)

Managing Data

큰 데이터를 다룰 때에도 대부분의 계산은 순서적이며 따라서 한순간에는 하나 둘 또는 세 개의 데이터만을 처리하게 된다. 예를 들어 모든 데이터를 한꺼번에 loading하는 것은 메모리의 낭비를 초래한다. 만일 대규모의 데이터를 처리해야한다면 단지 특덩한 연산과 관련된 데이터만을 load한다.버전 1.01에서는 Read-only 메모리 페이지는 시스템 자원이 부족하면 언제고 page out될 수 있다.

Using Temporary Files

가장 좋은 해결책은 Temporary File을 생성하지 않는 것이다.

Storing Data and Resource Files

Text형태나 압축되지 않은 형태로 저장된 bitmap은 메모리 사용이 매우 비효율적이다. 비록 압축을 풀고 하는 것에 시간이 걸리나 메모리를 줄일 수 있다는 점에서 가치이쓴ㄴ일이다. desktop에서 HPC로 파일이 전송될 때 어느 정도의 압축이 발생한다.

Using Graphics

graphic environment가 비록 매우 어필하는 특성이기는 하나 많은 메모리 자원을 요구한다. 따라서 가능한 graphic환경을 최소화 하기 위한 노력을 해야한다.

Providing User Feedback

비록 시스템이 low-memory condition을 처리하기 위한 기능을 가지고 있다고 해도, 모든 프로그램에 대한 이상적인 경우는 될 수 없다. 응용프로그램은 시스템이 아닌 자신의 메모리 관리 기능을 포함하는 것이 효과적일 수 있다. 가령 큰 데이터를 다운로드 받는다고 할 때 미리 시스템에 남아있는 메모리를 확인해서 다운로드의 여부를 확인할 수 있다.

Using Backup Files

Using PC-side Applications

Using Widows CE Nofitifations

Windows CE는 notification을 사용자와 응용프로그램간의 통신으로 사용한다. noification은 시스템이 어떤 사건이 발생했음을 알려주는 signal이다.

Object Store

Object store란 Windows CE가 응용프로그램에 대해 지원하는 persistent storage를 일컫는다. 예를 들어 HPC는 사용가능한 메모리에 대해 OS대한 예약된 영역이 있고 나머지 부분은 application, application run-time data, user data로 분리해서 사용된다. 이 data는 file, registry, Windows CE database에 저장될 수 있다.

Windows CE는 Object Store를 액세스할 수 있는 3개의 주요한 그룹을 가지고 있다. 1. System Registry API : Windows CE의 registry는 Windows95/NT와 매우 유사하다. Windows CE는 registry의 key와 value를 조작하기 위해 standard regristry 관련 API를 사용한다. 2.File system API : Windows CE의 Filesystem api는 Win32 Filesystem API의 subset으로 구성되었다. 이들 함수는 directory와 file을 생성하도록 하며 data를 읽거나 쓰게한다. 3.Database system API : Windows CE Database API는 Windows CE database를 생성하고 관리할 수 있도록한다. 각 database는 임의 개수의 record로 구성된다. 각 record는 one or more propertie로 구성된다.

About Object Identifiers

Object Store내의 모든 Object들은(파일, 디럭토리, 데이터베이스, 데이터베이스 레코드) 유일한 object identifier와 연관되어 있다. application은 어떤 object 에 대한 handle이라도 Object identifier를 이용해 구할 수 있다. Object store내의 object에 대한 정보를 얻기 위해서는 Winodws CE Application은 CeOidGeInfo란 함수를 호출해 원하는 object에 대한 identifier를 넘겨준다. structure에 존재하는 data는 retrive하는 object에 의존적이다. 예를 들어 object가 database record이면 CEOIDINFO 구조체의 wObjType항목은 OBJECT_RECORD를 포함하고 있으며 이는 data가 CERECORDINFO로 구성되어 있음을 의미한다. type을 알고 있으면 application은 object odentifier나 object name을 사용해 적절한 API를 호출하고 그 object에 대해 operation을 한다. Windows CE는 다음과 같은 object type과 access function을 지원한다. Windows CE는 성공적으로 object를 생성하면 object identifier를 리턴한다. 다음의 간단한 예제는 Object store내의 어떤 object라도 얻기 위해 object identifier를 사용하는 방법을 보여준다.



User Interface Service

Keyboard Input

Windows CE는 Keyboard input를 Windows 95나 Windows NT와 동일한 방식으로 처리한다. window는 keyboard input을 keystroke message형태로 받아들이며 window와 연관된 message loop는 이를 character message로 변환해야 한다. Windoes CE는 Window 95나 Windows NT가 지원하는 많은 함수를 지원한다. 그러나 desktop에서 지원하는 것과 같은 많은 key는 지원하디 않는다. INPUT구조체는 Windows NT와 동일하다. KEBDEV Structure는 지원하지 않는다. (keyboard input은 Window 95나 Windows NT에서 지원하는 것과 같은 방식으로 지원하게 된다. keyborad input이 keystroke message로 변환되어 전달된다. Windows CE에서는 Windows 95/NT가 지원하는 모든 key와 구조체를 지원하지 못한다)

Keyboard Input Functions

Windows CE는 몇 개의 Window95/NT에서와는 약간 다르게 동작하는 몇 개의 standard keyboard input함수를 지니고 있다. 또한 새로운 입력관련 함수를 지원한다. EnableHardwareKeyboard함수를 keyboard를 enable diable하기 위해 사용한다. keyboard가 disable된 경우 사용자는 keyboard가 입력됨이 않되며, 이 함수가 enabled state로 변환한 경우 menu bar, tabs, buttons and static control이 다시 그려지도록 한다. 그래서, keyboard accelerator나 관련된 정보를 display하는 방식을 변경할 수 있다.( keyboard input를 enable, diable할 수 있으며 enable되는 경우 menu bar, tab, button, static control을 다시 그리므로 enable시키면서 이와 관련된 정보를 다른 형태로 표현할 수 있다)

Windows CE에서는 GetAsynState()함수를 지원하며 이는 left right virtual key constant를 지원한다. 따라서 left right key가 눌려졌는지 검사할 수 있다. VK_LCONTROL, VK_RCONTROL, VK_LMENU, VK_RMENU, VK_LSHIFT, VK_RSHIFT가 그것이다. Windows CE에서는 VK_CONTROL, VK_LCONTROL, VK_RCONTROL, VK_MENU, VK_LMENU, VK_RMENU, VK_SHIFT, VK_LSHIFT, VK_RSHIFT의 down state를 확인하기 위해서는 GetKeyState( )함수만을 사용할 수 있다. toggle state체크 가능.

Windows CE에서는 keybd_event함수에 대해 KEYEVENT_SILENT를 추가했다. 이를 사용하면 clicking sound 없이 keystroke를 simulation할 수 있다. keybd_event를 이용하면 오랜동안 입력이 없으면 power down mode로 동작하는 기능을 금지할 수 있다. Windows CE는 KEYEVENTF_EXTENDEDKEY를 지원하지 않는다.

MapVirtualKey함수는 uMapType Parameter로 2만을 지원한다. 이는 virtual key code를 unshifted character valuefh 변환한다.

Windows CE에서는 RegisterHotkey( )함수를 위한 새로운 flag를 지원한다. MOD_FLAG, WM_HOTKEY Message가 key up과 key down event에서 window에 보내진다. WM_HOTKEY가 keyup event에 보내질 때 이는 MOD_KEYUP flag를 가지게 된다. (?) Windows95/NT와는 달리 Windows CE에서는 across thread에 대한 hotkey를 정의할 수 있다.

SendInput과 UnregisterHotKey는 Windows95/NT와 동일한 기능을 한다.

Keyboard Input Message

Windows CE는 Windos95/NT와 동일하게 대부분의 keyboard input meddage를 지원하다. 단 예외가 하나 있다. Windows CE는 scan code와 extended key flag를 지원하지 않는다. 따라서 다음의 메시지의 16-24의 값을 지원하지 않는다. 비록 이 메시지들은 동일하다. WM_CHAR, WM_DEADCHAR, WM_HOTKEY, WM_KEYDOWN, WM_KEYFIRST, WM_KEYLAST, WM_KEYUP, WM_SYSCHAR, WM_SYSDEADCHAR, WM_SYSKEYDOWN, WM_SYSKEYUP( scand code와 extended key flag를 Windows CE에서는 지원하지 않는다)

Windows CE Design Guides for Keyboard Interaction

Windows CE H/W는 가능한 desktop PC와 동일한 keyboard layout을 사용하려하마 크기의 제약으로 인해 Windows CE H/W가 모든 standard key를 지원하도록 요구되어지지는 않는다. 따라서 대부분의 Windows CE H/W는 다음과 같은 key사 없다. Delete, Insert, Num Lock, Pause, Print scrn, Scroll lock, Function Key Shift+Backspace를 delete로 사용한다.

Stylus Input(Skip)

Windows CE Shell Services

shell은 Windows CE OS의 user interface이다. Windows CE Shell은 Windows 95 shell이 기반을 두고 있으며 많은 familiar feature를 가지고 있다.(desktop window, recycle bin, taskbar and drag drop)같은 기능을 가지고 있다. Windows CE는 portable OS로 많으 H/W에서 동작하게 된다. Windows CE Shell은 Windows 95 shell과 동일하게 file을 관리하고 desktop에 shortcut을 만들 수 있다. Windows CE는 또한 유일한 기능을 지원하는데 Notification API와 Hibernation기능을 들 수 있다. clipboard는 Windows 95/NT와 동일하게 동작한다.

Windows CE Shell Functions

Windows CE Shell은 Windows95/NT가 지원하는 기능의 일부를 지원한다. Windows CE Shell은 다음과 같은 4개의 기능을 지원하는 데 이는 Windows95/NT에서는 지원하지 않는 기능이다. 1.파일에 대한 shortcut을 만든다. 2. 존재한는 shortcut의 path를 얻는다. 3.파일로부터 device independent bitmap을 load한다. 4.사용자에게 low-memory condition을 알려주는 dialog box를 실행한다.(Windows CE의 shell은 기본적으로는 Windows 95/NT와 다를 것이 없다.단지 Windows CE가 mobile환경에 이식될 수 있으므로 notification API를 지원하고 low-memory situation을 위해 hibernation기능을 포함하고 있다)

SHGetFileInfo( )의 uFlag에 SHGFI_ICON을 설정하면 icon의 handle이 SHFILEINFO에 저장된다. Windows CE는 process가 종료해도 자동으로 icon object를 제거하지 않는다.따라서 Windows CE Application작성시에는 DestroyIcon( )이란 함수를 호츨해서 icon object를 제거해야 한다. 다음에 나오는 함수는 Windows CE와 Windows 95/NT가 동일하다.(?)

??

The Windowing Environment

windowing environment는 application의 사용자 인터페이스를 생성하고 관리하는 방법을 제공한다. Windows CE에서는 windows95/NT에서와 같이 screen자체를 사용하지 않고 window를 기본적인 output device로 사용한다. Windows CE의 Windowing system은 Windows 95/NT와 매우 유사하다. 그러나 Windows CE는 다른 OS에 비해 더 다양한 platform에서 동작할 수 있다. 대부분의 Windows CE platform이 portable로 제작되었으므로 display screen이 작고 desktop OS의 많은 windowing featire가 적용되지 않는다.그러나, 비록 target device가 display screen을 포함하고 있지 않더라고 window를 생성해야 한다(보이지 않더라도) 왜냐하면 message를 받기 위해서는 window가 필요하다.

(Windows CE의 Windowing기능은 Windows95/NT와 유사하다)

Window Management

Window은 screen상의 직사각형 영역으로 application display가 출력되고 사용자입력을 받아들이는 부분이다. 비록 많은 window의 생성이 가능하나 사용자의 입력을 받아들이는 부분은 항상 하나밖에 없다. Windows CE내의 모든 window는 Window Class에 속한다. window class is a set of attributes that Windows CE used as a template to create a iwindow. Windows CE에서의 window management가 desktop OS의 방식과는 다르다는 것을 발견할 수 있다. Windows CE는 MDI와 DDE를 지원하지 않는다. Windows CE는 window properties를 지원하지 않는다. window와 instance-specific information을 연결하기 위해서는 cbWndExtra field를 사용해서 그 window에 대한 추가의 byte를 등록한다. Windows CE는 window class내의 unaligned access를 허용하지 않는다. 또한 GWL_USERDATA값을 지원하지 않는다. 필요한 바이트를 할당하고 SetWindowLing( )과 GetWindowLong()을 사용한다.

Windows CE 장치의 screen은 일반적으로 작으며 장치마다 다르다. 따라서 절대 죄표로 지정하지 않는 것이 좋다. windows CE에서는 window의 size를 window생성시에 기술해 주며 Windows CE는 maximize & minimize를 지원하지 않는다. 그러나, 사용자는 window를 back of Z order로 보낼 수도 복귀시킬 수도 있다.

Windows CE는 SW_MINIMIZW, SW_RESTORE, SW_SHOWMAXIMIZED, SW_SHOWMINIMIZED, SW_SHOWNOACTIVATE를 WinMain의 nCmdShow파라메타 값으로 지원하지 않는다. Windows CE에서는 만일 visible top-level window가 WS_OVERLAPPED style을 가지고 있으면 taskbar에 button이 생긴다. taskbar에 button이 있는 window에 대해서만 WM_HIBERNATE 메시지를 받을 수 있다.

Window Style

Windows CE는 Windows 95/NT와 매우 유사한 기능을 제공한다. windows CE에서는 모든 window가 WS_CLIPCHILDREN과 WS_CLIPSIBLINGS sytle을 가지고 있다. Windows CE는 두 개의 확장된 style을 가지고 있다. WS_EX_NOACTIVE : 이 style을 가지고 생성된 window는 active될 수 없다. child window이 이 style을 가지고 있는 경우 이 child window로 이동한 경우에도 top-level window는 active되지 않는다. 이 style의 window는 stylus input을 받아들일 수 있으나 focus는 반아들이지 못한다. WS_EX_NOANIMATION : 이 style을 가지고 생성된 window는 animated exploding and imploding rectangle을 보여줄 수 없으며 taskbar에 button을 만들지 못한다.( ? )

다음에 기술하는 style은 windows 95/NT와 동일하게 windows CE에서도 동작한다.

WS_CHILD : child window를 생성하며 WS_POPUP style과 동시에 사용될 수 없다. WS_DISABLED : 사용자의 입력을 받아 들이수 없는 window를 생성한다. WS_GROUP : control group의 첫 번째 control을 기술한다. group은 첫 번째 control과 이후에 정의된 control로 구성된다. WS_GROUP이 기술되기 전까지의 모든 control. group매의 첫 번째 control은 WS_TABSTOP 속성을 지닐 수 있어 사용자는 group to group move가 가능하다. 사용자는 group내의 control간의 focus변경을 direction key를 이용해 할 수 있다. WS_POPUP : popup style의 window를 생성한다. WS_TABSTOP : TAB key를 사용자가 눌렀을 때 input focus를 받을 수 있도록 한다. WS_VISIBLE : 생성시 보이는 window. WS_EX_NOACTIVATE : activated 될 수 없는 window를 생성한다. WS_EX_TOPMOST : 모든 non-topmost window위에 존재하는 window를 생성하고 그들위에 존재한다. 비록 window가 deactivated되었어도, SetWindowPos( )를 이용해 이 style를 설정하게 된다.

Window functions

Windows CE는 outside of the command bar에 menu bar를 지원하지 않는다. 따라서, AdjustWindowRectEx( )의 bMenu를 FALSE로 셩정해야 한다. CreateWindow( ), CreateWindowEx( )의 hMenu를 항상 NULL로 설정한다. 만일 hMenu를 child-window의 identifier로 사용하지 않을 거라면, Windows CE 1.0에서는 owned window를 지원하지 않는다. MDI를 지원하지 않는다. Window style에 제약이 있다. DestrioyWindow( )는 WM_DESTROY를 발생하며 WM_NCDESTRIY는 지원하지 않는다. Windows CE는 EnumThreadWindows( )를 지원하지 않는다. 그러나, EnumWindows( )와 GetWindowsThreadProcessId( )를 이용해 구현할 수 있다. Windows CE는 window class내에서의 unaligned access를 지원하지 않는다. 따라서, GetClassLong( )과 SetClassLong( )의 nIndex파라메타값이 4BYTE의 배수가 되어야 한다. GetClassLong( )은 GCE_ATOM, GCL_CBCLDEXTRA, GCL_CBWNDEXTRA, GCL_HBRBACKGROUND, GCL_HCURSOR, GCL_HICONSM, GCL_HMODULE, GCL_MENUNAME, GCL_WNDPROC는 지원하지 않는다. 만일 Windows CE가 Iconcurs를 사용한다면( 적절한 target application에서의 mouse cursor지원)GCL_HCURSOR값을 사용할 수 있다.

command bar는 client area의 일부가된다. 따라서 이는 GetClientRect( )에 포함된다.

desktop에서 mouse에 적용되는 것과 같이 Windows CE의 stylus에도 동일하게 GetDoubleClickTime( )이 적용된다. Windows CE는 GetScrollPos( )와 GetScrollRange( )를 지원하지 않는다. GetScrolInfo( )를 scroll bar의 현재 위치를 얻기 위해 사용한다.

Windows CE 2.0과 그이후에 버전에서는 GetSysColor( )의 nIndex 파라메타로 새로운 2개의 값과 lpaElements를 SetSysColor( )를 위해 지원한다.

Windows CE는 GetSystemMetrix의 모든 nIndex값을 지원하지 않는다. GetUpdataRgn( )의 bErase를 무시하고 window의 background를 지우지 않으며 아무런 drawing도 하지 않는다.

GetWindowLong( )과 SetWindowLong( )함수는 GWL_HINSTANCE나 GWL_HWNDPARENT를 지원하지 않는다. Windows CE에서는 바이트 align이 되어야 하므로 4의 배수가 되어야 한다. Windows CE에서는 유효한 window handle을 InvalidateRect( )와 ValidateRect( )에 전달해야 한다. Windows95/NT에서는 NULL이 설정되면 모든 window를 다시 그리나 Windows CE에서는 이를 지원하지 않는다. Windows CE에서는 MoveWindow( )의 bRepaint값을 무시하고 이를 TRUE로 간주한다. RegisterClass( )함수의 경우, WNDCLASS의 lpszMenuName을 지원하지 않으며 이를 NULL로 설정한다. 만일 Windows CE장치가 mouse를 지원하지 않는 다면 HCursor을 NULL로 설정한다. 새 window class를 증록할 때에는 Unicode로 해야한다. ScrollWindowEx( )함수에 SW_SCROLLCHILDREN을 설정할 수 없다. 왜냐하면 한번에 한방향으로만 window을 scroll할 수 있기 때문이다. SetWindowPos( )함수에 SWP_FRAMECHANGED flag를 설정하는 경우 Windows CE는 모든 non-client를 다시그린다. 이는 client의 size를 바꿀 수도 있다.

레지스터

산술적·논리적 연산이나 정보 해석, 전송 등을 할 수 있는 일정 길이의 2진 정보를 저장하는 중앙 처리 장치(CPU) 내의 기억 장치. 주기억 장치에 비해 접근 시간이 빠르다.

누산기, 프로그램 계수 장치(PC), 지시 레지스터, 명령어 레지스터 등이 있는데 이를 좀 더 상세히 분류하면 다음과 같다.

(1)누산기:산술 및 논리 연산의 결과를 임시로 기억하는 레지스터.

(2)주소 레지스터:기억 주소나 장치의 주소를 기억하는 레지스터. 명령 주소를 나타내는 레지스터를 명령 계수기라고 하는데, 이 명령 계수기의 기능은 실행 중인 명령이나 다음에 실행할 명령의 위치를 보관한다.

(3)산술 레지스터:덧셈의 덧수, 곱셉의 곱수, 비교 또는 자리가 이동될 단어 등을 보유한 레지스터.

(4)블록 레지스터:회선 제어 컴퓨터에서 사용되기 위해, 또는 받아들인 정보를 저장하기 위해 서로 연결된 저장 블록을 지시하는 레지스터.

(5)경계(境界) 레지스터:다중 프로그래밍 시스템(MPS)에서, 각 사용자가 차지한 기억 장치의 프로그램 블록의 상한 주소 또는 하한 주소를 나타내는 레지스터.

(6)버퍼 입력 레지스터:자기 테이프나 디스크와 같은 입력 장치 또는 매체로부터 데이터를 받아 내부 기억 장치에 전달하는 레지스터.

(7)버퍼 출력 레지스터:내부의 기억 장소에서 데이터를 받아서 자기 테이프와 같은 출력 매체에 전송하는 버퍼 역할을 하는 레지스터.

(8)검사 레지스터:일시적으로 저장된 정보와 연속적인 정보의 전달 결과를 비교, 점검하는 레지스터.

(9)순환 레지스터:저장된 정보가 오른쪽 또는 왼쪽으로 이동되고, 한쪽 끝 부분의 정보가 다른 쪽 끝으로 다시 삽입되는 이동 레지스터.

(10)제어 레지스터:현재의 동작에 이어 다음 단계에 수행할 명령어의 주소를 가지고 있는 레지스터.

(11)지연선 레지스터:지연선과 신호 재생 기능 및 피드백 기능을 통합한 레지스터. 시간 지연 레지스터라고도 한다.

(12)지정 레지스터:데이터를 보관하는 레지스터.

(13)E 레지스터:누산기와 같은 기능을 연장하기 위한 레지스터.

(14)확장 레지스터:소규모 시스템에서 산술 연산이나 논리 연산 또는 데이터 전송 동작을 수행할 때 누산기를 보조하는 8비트 레지스터.

(15)외부 레지스터:제어 기억 장치 속에서 특수한 주소에 자리하고 있어 프로그램에 의해 참조될 수 있는 레지스터.

(16)플립플롭 레지스터:병렬로 되어 있는 2진수를 저장하거나 직렬형 데이터를 한 비트씩 한쪽 끝에서 받아 저장할 때 사용되는 레지스터.

(17)부동 소수점 레지스터:부동 소수점의 연산에 사용되는 레지스터.

(18)범용 레지스터:여러 목적으로 사용될 수 있는 레지스터. 즉 필요에 따라 누산기, 기억 레지스터, 주소 레지스터, 지시 레지스터 등의 기능을 수행하는 레지스터.

(19)곱수/곱하임수 레지스터:곱셈에서 곱수/곱하임수를 기억하는 레지스터.

(20)지시 레지스터:주소를 계산할 때 사용되는 레지스터. 명령 주소나 색인을 수정할 때 사용된다.

(21)입력 레지스터:입력 장치로부터 데이터를 받아 프로그램의 지시에 의해 내부 기억 장소에 전달을 완료할 때까지 그 데이터를 보유하는 레지스터.

(22)명령어 레지스터:현재 수행 중인 명령어 부호를 저장하고 있는 레지스터.

(23)자기(磁氣) 이동 레지스터:자기 코어를 2진 기억 요소로 사용하고, 그 안에서 2진 정보가 오른쪽 또는 왼쪽으로 이동하는 레지스터.

(24)연산 레지스터: 연산 또는 조작의 종류가 기억된 레지스터로서, 실행 단계 상황을 기록 분석하기 위해서 사용되며, 명령이나 진행 중인 프로그램의 동작 부호를 저장한다. OP(operation) 레지스터라고도 한다.

(25)프로그램 레지스터:프로그램의 현재 명령을 저장하고 그 프로그램이 실행되는 동안 컴퓨터의 동작을 제어하는 제어 장치 속의 레지스터.

(26)R 레지스터:하위 숫자 10개를 가지는 레지스터.

(27)복귀 부호 레지스터:곧 이어질 후속 프로그램의 실행을 제어하는 데이터를 저장하는 레지스터.

(28)순서열 레지스터:명령의 진행 순서를 저장하는 레지스터.

(29)순서 제어 레지스터:다음에 처리할 명령을 기억하는 하드웨어 레지스터.

(30)자리 옮김 레지스터:한 문자에 대해 왼쪽이나 오른쪽으로 자리 옮김이 가능한 레지스터. 스테핑(stepping) 레지스터라고도 한다.

(31)대기 레지스터:프로그램상의 오류나 컴퓨터의 오동작으로 처리가 잘못되었을 때, 재동작을 할 수 있도록 올바른 정보를 저장하는 레지스터.

(32)기억 레지스터:컴퓨터의 기억 장치 내에 있는 레지스터로서, 기억 장치에서 보내 왔거나 보내 올 데이터를 일시적으로 보관하는 레지스터.

*** 프로그래머 십계명 ***

*** 프로그래머 십계명 ***



1. 정보모음에 소홀히 하지 말고 설명서를 읽음에 게을리 하지 말지어다.

오늘 필요 없는 정보는 내일 필요하리라.

가장 가치 있고도 저렴한 지식은 책 속에 있느니라.

서점과 동료의 책꽂이에 무엇이 꽂혀 있는지 때때로 살피어라.

무심코 흘렸던 종이 한 장이 너의 근심을 풀어 주었으리라.

설명서는 충분히, 꼼꼼히 읽을지어다.

모든 의문은 설명서를 안 보는 데서 생기니라.

그렇더라도 모두 다 읽을 필요는 없느니라.

많은 정보가 능사는 아니니라.

정보의 가치를 찾는 법부터 배우라.

세상엔 너무나 많은 자료와 정보가 넘쳐난다.

알알이 모두 끌어 모을 생각을 하기 보단 정보를 하나로 꿰는 법부터
먼저 배우는것이 너의 근심에서 쉽게 벋어나게 하는 방법이 되리라.

일을 시작하기전에 필요한 정보를 꼼꼼히 먼저 챙기는 법부터 배워라.

너희는 먼저 개발 의뢰서를 꼼꼼히 읽을지어다.

만약 개발 의뢰서가 없다면 발주자에게 요구할 지어다.

개발 의뢰서 없는 프로그램은 존재하지 않으니라.



2. 너의 PC가 안전하다고 믿지 말지어다.

5분 후에 정전이 되고 내일 너의하드가 맛이 가리라.

그러니 너의 소중한 소스코드는 정기적으로 여러 군데에 단계별로 백업해 두어라.

PC는 평상시엔 안전하다.

그런 실수를 저지르는것은 네자신이거나 아니면 외부적인 요인에 기인한다.

항상 백업을 철저히 해두며 백업에 백업까지도 챙겨두라.

그리고 백업을 했다면 리스트를 작성하라.

쓸데없는 백업은 백해 무익하나니 리스트를 항상 유지할 지어다.

너희는 노트를 옆에 끼고 살 지어다.

노트는 너의 생명이며, 너희가 기억하지 못하는 모든것을 상기시켜 줄지어다.



3. 변하는 수를 다룰 때에는 늘 조심할지어다.

정수가 절대로 그 한계를 넘지 않으리라 가정하는 것은 어리석음이라.

127 ,-128 ,255 ,32767 ,-32768 ,65535, 이 숫자들을 너의 골수에 새기어라.

0.0은 0이 아니니 실수는 원래부터 결코 정밀하지 않느니라.

부호 없는 것과 있는 것을 어울리거나 정수끼리 나눌 때에는 늘 조심하여라.

변수는 프로그램의 근원, 프로그램을 작성할때 가장 유의 할것이 바로
변수의 이름 짓기니라. 이름보고도 성격을 알수있게 해두라.

그러나 변수는 성질이 드러우니 변수에 성격을 부여할때는 조심스럽게 할지어다.

너희는 코딩하기 이전에 계획을 할 지어다.

이는 프로그래머가 코더가 아닌 것이니라.



4. 무슨 일을 반복시킬 때에는 처음과 끝에 유의할지어다.

너의 컴퓨터는 1보다는 0을 좋아 하니라.

배열의 첨자가 그 범위를 넘지 않을지 손 댈 때마다 따져 보아라.

수식에 1을 더하거나 뺄 때에는 늘 긴장하라.

너의 프로그램은 단지 한 번 덜해서 틀리고 한 번 더해서 다운되느니라.

프로그램을 작성할땐 계산, 판단, 비교를 그 모든걸 컴에게 되도록 맡기지말라.

네손으로 미리 계산하고 그 결과를 사용하는 방법이 최선이니라.

컴퓨터는 의지가 없나니 네가 잘못하든 잘하든 아무런 상관이 없느라.

너희는 머리가 악세사리가 아님을 기억하고 항상 생각하고 항상 노트에 적을 지어다.



5. 항상 모든 경우의 수를 고려하고 섣불리 생략하지 말지어다.

절대로 없어 나지 않을 일은 반드시 일어나고, 가장 드물게 일어날 일이 가장 너를 괴롭히리라.

그러하니 언제나 논리에 구멍이 없는지 꼼꼼히 따져 보고, if를 쓸때에는 else 부터 생각하라.

논리적인 오류는 성급함에서 생기나니 처음엔 항상 원리와 원칙을 지키라.

생각은 네가 하라 그리고 그 결과를 컴에게 시켜라.

IF를 쓰기전에 규칙을 세우라.

먼저 IF의 결과에대한 규칙부터 세우고 따져라.

그리고 논리적인 계산을 IF문장안에서 하지 말라.

하나의 IF문장속에 수많은 논리연산은 버그의 원인이니라.

어느 정도의 프로그램에 대한 윤곽이 잡히면 프로토 타입을 만들지어다.

프로토타입은 프로그램에 대한 시뮬레이션이며 발주자의 요구를 빨리 수용 하는 방법이니라.



6. 함수 안에서 매개 변수값은 결코 믿지 말지어다.

지금 그 매개 변수가 결코 가질 수 없다는 값을 내일부터는 가지리라.

그러하니 매개 변수 값이 올바름을 항상 검사할지어다.

그렇더라도 처리 속도가 문제가 되는 경우는 예외이니라.

함수도 하나의 독립적인 프로그램이란것을 잊지말며, 네가 프로그램을
작성할땐 모든 함수가 돼도록이면 독립적으로 돌아가도록 할지어다.

함수의 매계변수는 항상 그옆에 작은 컴맨트와 초기화를 잊지말라.

처음부터 속도문제를 생각하지 말라.

모든 루틴을 최적화 할순 없다.

전체 프로그램중에 단 20%가 전체 실행시간에 80%를 점유한다.

프로토 타입에대한 발주자의 의견을 꼼꼼히 들을 지어다.

이는 발주자에 대한 신뢰도의 척도니라.



7. 오류를 알려 주는 기능은 있는 대로 모두 활용할지어다.

컴파일러의 경고는 모두 켜 두어라.

경고는 곧 오류이니라.

오류를 알리는 함수의 결과를 확인하지 않는 우를 범하지 말지어다.

모든 파일 입출력과 모든 메모리 할당은 조만간 실패할 것이라.

컴파일러가 모든 경고기능을 동원해도 알려주지 않는 것은 많다.

중요한 건 오류가 생기기전에 규칙을 지켰는지 생각하라.

파일의 입출력과 메모리의 항당은 항상 쌍으로 생각해서
열었다면 닫아주고 활당받았다면 돌 려주라.

프로그램의 매인턴앤스를 게을리하지 말지어다.

이는 프로그램 만드는 일 보다 중요한 일이니라.



8. 한 번의 수정과 재컴파일만으로 연관된 모든 것이 저절로, 강제로 바뀌도록 할지어다.

어떠한 것을 수정했을 때에 연관된 것이 따라서 변하지 않는다면 그것이 곧 벌레이니라.

컴파일러로 하여금 매개 변수 리스트를 완전하게 검사하도록 하고 언젠가 손대야 하거나
따라서 변해야 하는 수치는 전부 매크로로 치환하며, 형 정의를 적극 활용하여라.

이미 완벽한 루틴을 손대지 말라.

프로그램이 무너지는 가장 첫번째이유는 도미노 현상 때문이나니 한번의 수정과
재컴파일로 쓸데없는것을 손대게 하지 말라.

컴파일러가 매개변수 리스트를 챙기지 말게 하라.

프로그램에 들어가기 전엔 미리 함수명과 매개변수 리스트를 만들어라.

너희는 프로그램의 도큐멘트를 만드는일에 게으르지말지어다.

이는 사용자가 너의 프로그램에 대해서는 바보이기 때문이니라.



9. 사용자가 알아서 잘 써 주리라고 희망하지 말지어다.

너의 프로그램은 항상 바보와 미*놈만이 쓰느니라.

사용 설명서를 쓸 때에는 결코 빠뜨리지 말아라.

빠뜨린 만큼 사용자는 너를 괴롭힐 것이니라.

사용자는 나쁜놈이다.

쓸데없는짓을 잘한다.

무식하다.

인간성도 더럽다.

대부분이 바보며 가끔 똑똑한 사람도 있는데 그 놈은 더 하다.

모든것을 설명하지 말며 온갇기능을 가진 하나의 프로그램을 작성하려 들지 말라.

많은 기능이 필요한 프로그램은 나누어서 작게 따로 만들어주라.

너희는 공부하는데 게으르지 말지어다.

자고나면 새로운 하드웨어와 새로운 소프트 웨어가 나오기 때문이니라.



10. 매사에 겸손하고 항상 남을 생각할지어다.

가장 완벽한 프로그램일수록 가장 완벽하게 숨은 벌레가 있느니라.

네가 이 세상 최고의 프로그래머라고 떠들며 자만할 때, 옆집 곳간에서는
훨씬 더 뛰어난 것을 묵묵히 만들고 있느니라.

아무렴 프로그래밍은 혼자 잘나서 할 게 아니니, 너로 인해
다른 사람들도 더불어 잘 되면 그 얼마나 좋은 것이냐.

프로그래머는 논리적으로 생각하여야 하지만 프로그램은 비논리적으로 작성하라.

프로그래머가 경지에 들면 누가 누가 잘하는지 알수가 없는 법,
또한 프로그래머로서의 '무지'에 대해서 잊지라마
프로그래머의 '무지'는 생략하고, 선택하고, 단순화시키고, 명백하게하는 것이니라.

항상 새로운 아이디어와 새로운 생각으로 무장하라.

그리고 나누라 나누는곳에 기쁨있나니....

너희는 모든 프로그램에 대해서 위의 프로시줘를 따를 지니라.

printf 디버거

1. 디버깅 단계어서만 printf 출력

//#define NDEBUG

#ifndef NDEBUG
#define dp(fmt,args...) printf( fmt, ## args )
#define dlp(fmt,args...) printf( "[%s %d]" fmt, __FILE__,__LINE__, ## args )
#else
#define dp(fmt,args...)
#define dlp(fmt,args...)
#endif


#define NDEBUG 라는 문장이 없으면
위 문장들은 출력을 발생하게 됩니다.


만약 프로그램 전체에서 dp를 사용한 문자열의 출력을 제거하고 싶다면
그냥 컴파일 옵션에서 -DNDEBUG 라는 것만 추가 하면됩니다



Makefile 에 있는
CFLAGS += -Wall -O2 -g

CFLAGS += -Wall -O2 -g -DNDEBUG
로 바꿔도 됩니다.



printf( "%s %s %d\n", __FILE__, __FUNCTION__, __LINE__ );
이것은 이 문장이 적혀진 라인을 포함하는 파일명과 함수명 그리고
파일의 라인번호를 출력하게 합니다.



2. 한 라인의 시작 문자열 맨 앞에서는 '\r' 문자를 사용하는 것이 좋습니다.

예를 들어

printf( "message line 1\n" );
printf( "message line 2\n" );
printf( "message line 3\n" );

이라고 한다면 이것을 다음과 같이 고쳐 주어야 합니다.

printf( "\rmessage line 1\n" );
printf( "\rmessage line 2\n" );
printf( "\rmessage line 3\n" );



3. \n을 사용하기 전까지는 화면에 출력되지 않는다.


리눅스에서 printf 문은 '\n' 을 만나기 전까지는 출력 처리가 되지 않는
다는 점을 기억합시다.!!!!

ARM 용 크로스 컴파일러 제작

========================================================
"ARM 용 크로스 컴파일러 제작"
2004/ 10/ 01
========================================================

0. 무한한 도전.

현재 나와있는 가장 최신 소스를 사용하여 크로스 컴파일러를 만들어 보겠습니다.
저는 상당히 삽질을 많이 했지만..
이문서를 보시는 분은.. 그냥 따라해보면 만들어 질겁니다.

사용한 소스는 다음소스를 사용했으며..

1. binutils-2.15.91.0.1.tar.bz2
2. gcc-3.4.2.tar.bz2
3. glibc-2.3.3.tar.bz2

복잡한 설명보다.. 간단한 명령으로 구성되어 있으므로..
리눅스와 조금만 친하면 누구나 가능하리라 생각합니다.


보실때 참고사항

1. 라인 첫글자 #은 Bash Script의 주석입니다.
자동으로 크로스 컴파일러를 만드는 스크립트를 만들려고 하다가...
2. 라인의 두번째 또는 세번째에 있는 $ 는 User Prompt 입니다.
3. 라인 끝에있는 ;\ 는 여러줄 입력할때 사용하는것 아시죠
크로스 툴 만들때 일일이 한줄씩 입력할려니 귀찮아서..
4. 같은 명령이 중북되어 있을수도 있는데.. 테스트하면서 이것저것 해본 흔적입니다.
5. 다른 여러 문서에는 Tools을 만들때 root 계정으로 작업을 하시는데
여기서는 사용자 계정으로 작업을 하도록 되어 있습니다.
root 계정으로 작업을 하면 자칫 라이브러리를 날려먹는다든지..
상당히 위험하기 때문에 권하지 않습니다.


1. 준비사항

각 파일이 들어갈 곳을 만들고.. 패스를 설정 해준다.

#!/bin/sh
export HOME_DIR=/home/Xels <-- Xels 라는 계정을 만들어서 작업을 할때.
#export HOME_DIR=$HOME ;\ <-- 일반 계정으로 작업을 할때
export KNL_DIR=$HOME_DIR/knl ;\
export PXA_DIR=$HOME_DIR/usr ;\
export SRC_DIR=$HOME_DIR/src ;\
export WRK_DIR=$HOME_DIR/wrk ;\
export TST_DIR=$HOME_DIR/tst
export PATH=$PXA_DIR/bin:$HOME_DIR/bin:$PATH

cd $HOME_DIR
mkdir -p $KNL_DIR <-- 커널소스가 있는곳
mkdir -p $PXA_DIR <-- 컴파일된 바이너리 파일, 라이브러리 파일이 들어가는곳
mkdir -p $SRC_DIR <-- 작업할 소스가 있는곳
mkdir -p $WRK_DIR <-- 개발하는 파일이 있는곳
mkdir -p $TST_DIR <-- 간단히 테스트하는 파일이 있는곳


2. 사용할 커널작업

cd $KNL_DIR
wget ftp://ftp.kernel.org/pub/linux/kernel/v2.4/linux-2.4.21.tar.gz
wget ftp://ftp.arm.uk.linux.org/pub/linux/arm/kernel/v2.4/patch-2.4.21-rmk1.gz
wget ftp://ftp.arm.uk.linux.org/pub/linux/arm/people/nico/diff-2.4.21-rmk1-pxa1.gz

tar -xzf linux-2.4.21.tar.gz
mv linux-2.4.21 linux-2.4.21-rmk1-pxa1 ;\
ln -s linux-2.4.21-rmk1-pxa1 linux
cd linux
gzip -cd ../patch-2.4.21-rmk1.gz | patch -p1
gzip -cd ../diff-2.4.21-rmk1-pxa1.gz | patch -p1

cd include
rm asm; ln -s asm-arm asm
cd asm
rm arch proc; ln -s arch-pxa arch; ln -s proc-armv proc

cd ../../
make menuconfig
cd ../
cp -dpR linux-2.4.21-rmk1-pxa1 linux-2.4.21-rmk1-pxa1-org


# ln -s $HOME_DIR $PXA_DIR/arm-linux

$ cd $PXA_DIR/arm-linux/
# $ mv lib lib.bak
$ ln -s ../lib/ lib


3. Binutils 컴파일

binutils-2.15.91.0.2.tar.bz2 버전도 컴파일에는 문제가 없으나..
glibc 컴파일 할때 내부 오류가 발생하는 문제가 있다.

# Build Binutils
cd $SRC_DIR
wget ftp://ftp.kernel.org/pub/linux/devel/binutils/binutils-2.15.91.0.1.tar.bz2

tar -xjf binutils-2.15.91.0.1.tar.bz2
cd binutils-2.15.91.0.1
mkdir -p pxa;cd pxa
../configure --target=arm-linux --prefix=$PXA_DIR
# ../configure --target=arm-elf --prefix=$PXA_DIR --with-cpu=xscale
make && make install
cd ../..
rm -rf binutils-2.15.91.0.1


4. Gcc 컴파일

# Gcc 초벌 설치 <-- Newlib를 사용해도 된다.
cd $SRC_DIR
wget ftp://ftp.gnu.org/gnu/gcc/gcc-3.4.2/gcc-3.4.2.tar.bz2

tar -xjf gcc-3.4.2.tar.bz2
cd gcc-3.4.2
perl -pi -e 's/^(TARGET_LIBGCC2_CFLAGS.*)/$1 -Dinhibit_libc -D__gthr_posix_h/' gcc/config/arm/t-linux
echo 'T_CFLAGS = -Dinhibit_libc -D__gthr_posix_h' >> gcc/config/arm/t-linux
mkdir -p pxa;cd pxa
../configure --target=arm-linux --prefix=$PXA_DIR --with-headers=$KNL_DIR/linux/include \
--disable-shared --disable-threads --enable-languages=c
make && make install
# ls -la $PXA_DIR/bin ; arm-linux-gcc -v
cd ../..
rm -rf gcc-3.4.2
# 패치를 하지 않으면.. ~.h 파일을 찾지못하는 error 가 발생한다.


5. Glibc 설치

cd $SRC_DIR
wget ftp://ftp.gnu.org/gnu/glibc/glibc-2.3.3.tar.bz2
wget ftp://ftp.gnu.org/gnu/glibc/glibc-linuxthreads-2.3.3.tar.bz2

tar -xjf glibc-2.3.3.tar.bz2; tar -C glibc-2.3.3 -xjf glibc-linuxthreads-2.3.3.tar.bz2
cd glibc-2.3.3

patch -p0 < ../glibc-2.3.3-arm.giih.patch <-- 패치내용은 아래에서 참고.

$ vi Makeconfig

gnulib := -lgcc -lgcc_eh --> gnulib := -lgcc 이렇게 수정.
mkdir -p pxa ; cd pxa

# $ CC=arm-linux-gcc ../configure --host=arm-linux --build=i686-pc-cygwin --prefix=$PXA_DIR --with-cpu=xscale \
# --with-headers=$KNL_DIR/linux/include --enable-add-ons=linuxthreads --enable-shared

# $ CC=arm-linux-gcc ../configure --host=arm-linux --build=i686-pc-cygwin --prefix=$PXA_DIR \
# --with-headers=$KNL_DIR/linux/include --enable-shared --enable-add-ons=linuxthreads

# $ CC=arm-linux-gcc ../configure --host=arm-linux --build=i686-pc-linux-gnu --prefix=$PXA_DIR --with-cpu=xscale \
# --with-headers=$KNL_DIR/linux/include --enable-add-ons=linuxthreads --enable-shared

$ CC=arm-linux-gcc ../configure --host=arm-linux --build=i686-pc-linux-gnu --prefix=$PXA_DIR \
--with-headers=$KNL_DIR/linux/include --enable-add-ons=linuxthreads --enable-shared

make && make install
cd ../..
rm -rf glibc-2.3.3


# $ cd $PXA_DIR/arm-linux/ <-- 이부분은 앞에서 처리했슴.
# $ mv lib lib.bak
# $ ln -s ../lib/ lib

$ cd $PXA_DIR/lib --> 라이브러리 패치 (이부분이 생략되면 gcc 컴파일때 Error 발생)
$ strings libc.so
$ cp libc.so libc.so.org
# $ sed -e '/*** BUG/d' libc.so > libc.so.new
$ sed '/BUG/d' libc.so > libc.so.new
# $ vi libc.so
$ mv -f libc.so.new libc.so

$ strings libpthread.so
$ cp libpthread.so libpthread.so.org
# $ vi libpthread.so
$ sed '/BUG/d' libpthread.so > libpthread.so.new
$ mv -f libpthread.so.new libpthread.so

# $ cp $PXA_DIR/lib/libc.so $PXA_DIR/arm-linux/lib/libc.so
# $ cp $PXA_DIR/lib/libpthread.so $PXA_DIR/arm-linux/lib/libpthread.so


6. Gcc 재설치

cd $SRC_DIR
$ tar -xjf gcc-3.4.2.tar.bz2
$ cd gcc-3.4.2
$ mkdir pxa;cd pxa
# $ ../configure --target=arm-linux --prefix=$PXA_DIR
# $ make --> Error 발생... 그냥 넘어갈때가 없구먼...
#../../gcc/gthr-posix.h:46: error: parse error before "__gthread_key_t" <-- 이런 Error

$ ../configure --target=arm-linux --prefix=$PXA_DIR --exec-prefix=$PXA_DIR --with-headers=$PXA_DIR/include --libdir=$PXA_DIR/lib
$ make && make install --> Gcc 설치 성공
$ arm-linux-gcc -v <-- 확인

# $ cp -f ~/usr/arm-linux/lib/* ~/usr/lib/


7. 패치항목

o. patch file 만들기 참고

$ cp csu/Makefile csu/Makefile.org <-- 편집기로 수정하기전 파일을 Original file로 보관한다.
$ vi csu/Makefile

-CFLAGS-initfini.s = -g0 -fPIC -fno-inline-functions
+CFLAGS-initfini.s = -O1 -g0 -fPIC -fno-inline-functions

$ cp linuxthreads/Makefile linuxthreads/Makefile.org
$ vi linuxthreads/Makefile

-CFLAGS-pt-initfini.s = -g0 -fPIC -fno-inline-functions
+CFLAGS-pt-initfini.s = -O1 -g0 -fPIC -fno-inline-functions

$ cp sysdeps/generic/framestate.c sysdeps/generic/framestate.c.org
$ vi sysdeps/generic/framestate.c

#ifndef __USING_SJLJ_EXCEPTIONS__
frame_state_for = fallback_frame_state_for;
#else
frame_state_for = abort;
#endif

$ cp sysdeps/arm/machine-gmon.h sysdeps/arm/machine-gmon.h.org
$ vi sysdeps/arm/machine-gmon.h

-static void mcount_internal (u_long frompc, u_long selfpc);

#define _MCOUNT_DECL(frompc, selfpc) \
-static void mcount_internal (u_long frompc, u_long selfpc)
+void mcount_internal (u_long frompc, u_long selfpc)

여기까지 수정을 했으면 패치파일을 만든다.

$ diff -uNr csu/Makefile.org csu/Makefile > ../glibc-2.3.3-arm.giih.patch
$ diff -uNr linuxthreads/Makefile.org linuxthreads/Makefile >> ../glibc-2.3.3-arm.giih.patch
$ diff -uNr sysdeps/generic/framestate.c.org sysdeps/generic/framestate.c >> ../glibc-2.3.3-arm.giih.patch
$ diff -uNr sysdeps/arm/machine-gmon.h.org sysdeps/arm/machine-gmon.h >> ../glibc-2.3.3-arm.giih.patch

이렇게 만들어진 glibc-2.3.3-arm.giih.patch 패치파일을 위에서 사용한다.


8. 마치며..

도움이 될지 모르겠네요..
잘못된 부분이나.. 보다 나은 방법도 있으면 과감히 태클주세요.
곧바로 검토하겠습니다.

함수 일람표

C 타입 매크로 함수(prototype in ctype.h)

문자 조작 함수(prototype in string.h)

수학용 연산 함수(prototype in math.h)

표준 입출력 함수(prototype in stdio.h)를 분류해서 올렸습니다.



C 타입 매크로 함수(prototype in ctype.h)


함수명 : isalnum

구 분 : int isalnum (int c);

기 능 : 문자 c가 문자이거나 숫자이면, 즉 c가 A-Z, a-z, 0-9 사이이면 0이 아닌 수를,

아니면 0을 반환한다.


함수명 : isalpha

구 분 : int isalpha (int c);

기 능 : 문자 c가 문자이면, 즉 A-Z, a-z, 사이이면 0이 아닌 수를, 아니면 0을 반환한다.


함수명 : isascii

구 분 : int isascii (int c);

기 능 : 문자 c가 0-127 사이면 0이 아닌 수를, 아니면 0을 반환한다.


함수명 : isascii

구 분 : int iscntrl (int c);

기 능 : 문자 c가 delete 문자이거나 일번적인 컨트롤 문자이면 0이 아닌 수를, 아니면 0을

반환한다.


함수명 : isdigit

구 문 : int isdigit (int c);

기 능 : 문자 c가 숫자이면, 즉 0-9 사이이면 0이 아닌 수를, 아니면 0을 반환한다.


함수명 : isgraph

구 문 : int isgraph (int c);

기 능 : c가 공백 문자를 제외한 출력 가능한 문자이면 0이 아닌 수를, 아니면 0을 반환

한다.


함수명 : islower

구 문 : int islower (int c);

기 능 : 문자 c가 소문자이면 0이 아닌 수를, 아니면 0을 반환한다.


함수명 : isprint

구 문 : int isprint (int c);

기 능 : 문자 c가 출력 가능한 문자이면 0이 아닌 수를, 아니면 0을 반환한다.


함수명 : isspace

구 문 : int isspace (int c);

기 능 : 문자 c가 space 문자이면, 즉 space, tab, carriage return, newline, vertical tab,

formfeed이면 0이 아닌 수를, 아니면 0을 반환한다.


함수명 : ispunct

구 문 : int ispunct (int c);

기 능 : 문자 c가 punctuation 문자이면 0이 아닌 수를, 아니면 0을 반환한다.


함수명 : isupper

구 문 : int isupper (int c);

기 능 : 문자 c가 대문자이면, 즉 A-Z 사이이면 0이 아닌 수를, 아니면 0을 반환한다.


함수명 : isxdigit

구 문 : int isxdigit(int c);

기 능 : 문자 c가 숫자이면, 즉 0-9 사이이면 0이 아닌 수를, 아니면 0을 반환한다.


함수명 : toascii

구 문 : int toascii (int c);

기 능 : 정수형 수 c를 아스키 문자 c로 변환시켜 준다.


함수명 : tolower

구 문 : int tolower (int c);

기 능 : 문자 c를 소문자로 변환아여 준다.


함수명 : toupper

구 문 : int toupper (int c);

기 능 : 문자 c를 대문자로 변환하여 준다.



문자 조작 함수(prototype in string.h)


함수명 : strcat

구 문 : char * strcat (char *dest, const char *src);

기 능 : dest 문자열의 끝에 src의 문자열을 확장한다. 확장된 문자열의 길이는 dest문자

열의 길이와 src 문자열의 길이의 합과 같다. dest 문자열의 포인터를 반환한다.


함수명 : strchr

구 문 : char * strchr (const char *s, int c);

기 능 : 문자열 s에서 문자 c가 나타나는지 검사한다. strchr은 문자열에서 처음으로 해당

하는 문자가 나타나는 곳의 포인터를 반환한다.


함수명 : strcmp

구 문 : int strcmp (const char *s1, const char *s2);

기 능 : 두 문자열 s1과 s2가 같은지를 검사한다. 만약 문자열이 같으면 0을 반환하고,

s1이 s2보다 작으면 음수를, 크면 양수를 반환한다.


함수명 : strcpy

구 문 : char * strcpy (char *dest, const char *src);

기 능 : 문자열 str를 문자열 dest로 복사한다. dest의 포인터를 반환한다.


함수명 : strerror

구 문 : char * strerror (int errnum);

기 능 : 정수형으로 쓰여진 에러 번호에 해당하는 에러 메시지 문자열에 대한 포인터를

반환한다.


함수명 : strlen

구 문 : size_t strlen (const char *s);

기 능 : 문자열의 길이, 즉 문자열에 포함된 문자의 개수를 반환한다. strlen은 NULL로

끝나는 문자를 고려하지 않는다.


함수명 : strstr

구 문 : char * strstr (const char *s1, const char *s2);

기 능 : 문자열 s1에서 문자열 s2가 포함되는지를 검사한다. strstr은 문자열 s2가 시작

하는 s1 문자열에서의 포인터를 반환한다.


함수명 : strtok

구 문 : char * strtok(char *s1, const char *s2);

기 능 : strtok는 문자열 s1이 s2에서 정의된 구별자(delimiters)에 의해 0개나 그 이상의

토큰으로 구성되어 있는지를 검사한다.


함수명 : strtol

구 문 : long strtol (char *s, char * * endptr, int radix);

기 능 : strtol은 문자열 s를 long 정수형으로 바꾸어 준다.


함수명 : strupr

구 문 : char * strupr (char *s);

기 능 : strupr는 문자열 s에 포함된 모든 소문자를 대문자로 바꾸어 준다.



수학용 연산 함수(prototype in math.h)


함수명 : abs

구 문 : int abs(int x);

기 능 : 정수 x의 절대갑을 반환한다.


함수명 : acos

구 문 : double acos (double x);

기 능 : 수 x의 arc cosine 값을 계산하여 반환한다.


함수명 : asin

구 문 : double asin (double x);

기 능 : 수 x의 arc sine 값을 계산하여 반환한다.


함수명 : atan

구 문 : double atan (double x);

기 능 : 수 x의 arc tangent 값을 계산하여 반환한다.


함수명 : atan2

구 문 : double atan2 (double y, double x);

기 능 : 수 y/x의 arc tangent 값을 계산하여 반환한다.


함수명 : atof

구 문 : double atof (const char *s);

기 능 : 문자열 s를 부동 소수점 수로 변환하여 반환한다.


함수명 : atoi

구 문 : int atoi (const char *s);

기 능 : 문자열 s를 정수로 변환하여 반환한다.


함수명 : atol

구 문 : long atoll (const char *s);

기 능 : 문자열 s를 정수로 변환하여 반환한다.


함수명 : ceil

구 문 : double ceil (double x);

기 능 : 실수 x보다 큰 정수 중 최소의 정수를 반환한다.


함수명 : cos

구 문 : double cos (double x);

기 능 : 실수 x의 cosine 값을 계산하여 반환한다.


함수명 : cosh

구 문 : double cosh (double x);

기 능 : 실수 x의 hyperbolic cosine 값을 계산하여 반환한다.


함수명 : exp

구 문 : double exp(double x);

기 능 : ex를 계산하여 반환한다.


함수명 : fabs

구 문 : double fabs (double x);

기 능 : 부동 소수점 수 x의 절대값을 계산하여 반환한다.


함수명 : floor

구 문 : double floor (double x);

기 능 : 부동 소수점 수 x보다 작은 정수중 최대값을 반환한다.


함수명 : fmod

구 문 : double fmod (double x, double y);

기 능 : x/y의 나머지를 계산하여 반환한다.


함수명 : labs

구 문 : long labs (long x);

기 능 : long 정수 x의 절대값을 계산하여 반환한다.


함수명 : ldexp

구 문 : double ldexp (double x, int exponent);

기 능 : x ´ 2exp를 계산하여 반환한다.


함수명 : log

구 문 : double log (double x);

기 능 : x의 자연 대수갑 ln(x)를 계산하여 반환한다.


함수명 : log10

구 문 : double log10 (double x);

기 능 : x의 십진 대수값 log10(x)를 계산하여 반환한다.


함수명 : modf

구 문 : double modf (double x, double *ipart);

기 능 : 실수 x를 정수 부분과 소수점 아래 부분으로 나눈다. 정수 부분은 ipart에 저장

하고, 소수점 아래 부분은 반환한다.


함수명 : pow

구 문 : double pow (double x, double y);

기 능 : xy를 계산하여 반환한다.


함수명 : pow10

구 문 : double pow10 (int p);

기 능 : 10p를 계산하여 반환한다.


함수명 : sin

구 문 : double sin (double x);

기 능 : 수 x의 sine 값을 계산하여 반환한다.


함수명 : sinh

구 문 : double sinh (double x);

기 능 : 수 x의 hyperbolic sine 값을 계산하여 반환한다.


함수명 : sqrt

구 문 : double sqrt (double x);

기 능 : 수 x의 양의 제곱근을 계산하여 반환한다.


함수명 : tan

구 문 : double tan (double x);

기 능 : 수 x의 tangent 값을 계산하여 반환한다.


함수명 : tanh

구 문 : double tanh (double x);

기 능 : 수 x의 hyperbolic tangent 값을 계산하여 반환한다.


함수명 : hypot

구 문 : double hypot (double x, double y);

기 능 : hypot은 z2=x2+y2을 만족하는 z값 중에서 양수인 z의 값을 계산하여 반환한다.



표준 입출력 함수(prototype in stdio.h)


함수명 : fclose

구 분 : int fclose (FILE *stream);

기 능 : stream에 지정된 파일 스트림을 닫는다. 성공하면 0을 반환하고, 실패하면 EOF를

반환한다.


함수명 : fcloseall

구 분 : int fcloseall (void);

기 능 : 열려진 모든 스트림을 닫는다. 이때, 표준 입출력 스트림인 stdin, stdout, stdprn,

stderr, staux는 제외된다. fcloseall 함수의 실행이 성공하면 닫혀진 스트림들의 총

개수를 반환하고, 만약 오류가 발생하면 EOF를 반환한다.


함수명 : fdopen

구 분 : FILE *fdopen (int handle, char *type);

기 능 : 함수 creat, dup, dup2, open의 수행 결과 얻어진 파일 핸들과 스트림을 연결 시

켜 준다.


함수명 : fgetc

구 분 : int fgetc (FILE *stream);

기 능 : 명명된 파일 스트림으로부터 하나의 문자를 읽어 들인다. 성공한 경우 읽어 들인

문자를 정수로 변환하여 반환하고, 파일 스트림의 끝에 도달했거나 오류가 발생했

을 때는 EOF를 반환한다.


함수명 : fgetchar

구 분 : int fgetchar (void);

기 능 : 표준 입력 스트림으로부터 하나의 문자를 읽어 들인다. 성공한 경우는 읽어 들인

문자를 정수형으로 바꾸어 반환하고, 파일의 끝에 도달했거나 오류가 발생했을 때

는 EOF을 반환한다.


함수명 : fgetpos

구 분 : int fgetpos (FILE *stream, fops_t *pos);

기 능 : 주어진 파일 스트림과 관련된 파일 포인터의 현재 위치를 pos라는 포인터가 가리

키는 곳에 저장한다. fops_t라는 형은 stdio.h에 다음과 같이 정의 되어 있다.

typedef long fops_t;

성공한 경우에는 0을 반환하고, 실패한 경우에는 0 이외의 정수값을 반환하고

errno를 EBADF 또는 EINVAL로 설정시킨다.


함수명 : fgets

구 분 : char *fgets (char *s, int n, FILE *stream);

기 능 : stream으로 명명된 파일 스트림으로부터 문자열을 읽어 들여 스트링 변수 s에

저장한다. 읽어 들이는 문자열의 길이는 n-1이며, 중간에 개행 문자인 ‘\n’이 있

으면 읽기를 멈춘다. 함수 fgets는 성공하면 포인터 s의 값을 반환하고, 파일의

끝에 도달하거나 오류가 생기는 경우는 NULL을 반환한다.


함수명 : fopen

구 분 : FILE *fopen (const char *path, const char *mode);

기 능 : path에 지정된 경로에 의해 명명된 파일을 열어 파일 스트림에 연결 시킨다.

fopen 생성된 파일 스트림에 대한 포인터를 반환한다.


함수명 : fprintf

구 분 : int fprintf (FILE *stream, const char *format [,arg1, arg2,...]);

기 능 : format에 지정된 출력 형식을 stream으로 명명된 파일에 출력한다. format에 지정

된 서식 지정자에 따라 arg1, arg2 등의 자료를 출력할 수도 있다. 함수 fprintf는

성공한 경우에는 출력된 바이트의 개수를 반환하고, 오류가 발생한 경우에는 EOF

를 반환한다.


함수명 : fputc

구 분 : int fputc (int c, FILE *stream);

기 능 : 문자 c를 stream 으로 명명된 파일 스트림에 출력한다. 성공한 경우에는 문자 c

를 반환하고 , 실패한 경우에는 EOF를 반환한다.


함수명 : fputchar

구 분 : int fputchar (int c);

기 능 : 문자 c를 표준 출력 장치인 stdout으로 출력한다. fputchar(c)는 fputc(c, stdout)

으로 정의되어 있다. 성공한 경우에는 문자 c를 반환하고, 실패한 경우에느 EOF을

반환한다.


함수명 : fputs

구 분 : int fputs (const char *s, FILE *stream);

기 능 : 문자열 s를 stream으로 명명된 파일 스트림에 출력한다. 개행 문자를 출력하지는

않으므로 커서가 다음 라인으로 이동하지는 않는다 fputs는 성공하면 출력한 최후

의 문자를 반환하고, 실패한 경우에는 EOF을 반환한다.



함수명 : fread

구 분 : size_t fread (void *ptr, size_t,size, size_t n, FILE *stream);

기 능 : 주어진 입력 스트림으로부터 n개의 자료를 읽어 포인터 ptr이 가리키는 블록에

저장한다. 이때 각각의 자료의 크기는 size 바이트이다. 함수 fread의 수행이 성공

하면 읽어 들인 자료의 개수를 반환하고, 파일의 끝이거나 오류가 발생하면 0을

반환한다.



함수명 : freopen

구 분 : FILE *freopen (const char *path, const char *mode, FILE *stream);

기 능 : 파일 포인터 stream이 가리키는 파일을 닫고, 대신 path에 명명된 파일을 열어

파일 포인터 stream에 연결시킨다. 이때 mode는 fopen이나 freopen 함수에서

사용한 것과 동일한 방법으로 사용하면 된다. freopen은 성공한 경우 파일 포인터

인 stream을 반환하고, 실패하면 NULL을 반환한다.



함수명 : fscanf

구 분 : int fscanf (FILE *stream, const char *format [,address, ...]);

기 능 : 서식 지정 문자열인 format에 명시된 형태로 입력을 읽어 들인다. 서식 지정 문자

열 format에 대한 설명은 scanf 함수를 참조하면 된다. fscanf는 성공하면 읽어 들

인 자료의 입력 필드 수를 반환한다. 만약 파일의 끝에 도달하면 EOF을 반환하고,

입력이 없으면 0을 반환한다.


함수명 : fseek

구 분 : int fseek (FILE *stream, long offset, int whence);

기 능 : 파일 스트림에서 파일 포인터의 위치를 변경 시킨다, 현재 파일 포인터 stream이

가리키는 파일에서 whence의 위치로부터 offset 바이트 만큼 떨어진 위치로 파일

포인터를 옮긴다. 텍스트 모드 파일 스트림에서 offset은 0또는 ftell 함수에 의해

반환된 값이어야 한다.


함수명 : fsetpos

구 분 : int fsetpos (FILE *stream, const fops_t *pos);

기 능 : 파일 포인터 stream을 새로운 위치로 설정시킨다. 새로운 위치 pos는 이전에 실

행된 fgetpos 함수에 의해 반환된 값을 사용한다. fsetpos는 성공한 경우에 0을 반

환한다. 실패한 경우에는 0 이외의 정수를 반환하고, errno를 0 이외의 값으로 설

정한다.


함수명 : ftell

구 분 : long ftell (FILE *stream);

기 능 : 파일 포인터의 현재 값을 반환한다. 오프셋은 파일의 시작점으로부터 바이트 단위

로 측정된다. ftell이 반환한 값은 fseek 함수에 의해 사용된다. ftell은 성공한 경우

파일 포인터의 현재 값을 반환한다.


함수명 : fwrite

구 분 : size_t fwrite (const void *ptr, size_t size, size_t n, FILE *stream);

기 능 : n개의 자료를 주어진 출력 파일에 덧붙여 쓴다. 이 때, 각각의 자료의 크기는

size 바이트며, ptr은 쓰여질 자료의 시작 위치를 가리키는 포인터이다.


함수명 : getc

구 분 : int getc (FILE *stream)

기 능 : 파일 포인터 stream 이 가리키는 파일로부터 하나의 문자를 읽어 반한하고, 파일

포인터를 다음 문자로 이동시킨다. getc는 성공한 경우에는 읽어 들인 문자를 정수

형으로 변환시켜 반환하며, 오류가 발생하거나 파일의 끝에 도달하면 EOF을 반환

한다.


함수명 : getchar

구 분 : int getchar (void)

기 능 : getc(stdin)으로 정으되어 있으며, 표준 입력으로부터 하나의 문자를 읽어들여 정

수로 변환하여 반환한다.


함수명 : gets

구 분 : char *gets (char *s);

기 능 : 표준 입력 stdin으로부터 문자열을 읽어 들인다. 개행문자(’\n’)는 문자열의 끝을

나타내는 ‘\0’으로 입력된다. 성공한 경우에는 s를 반환하고, 오류가 발생한 경

우에는 EOF인 경우에는 NULL을 반환한다.


함수명 : getw

구 분 : int getw (FILE *stream);

기 능 : 파일 포인터 stream이 가리키는 파일로부터 정수를 읽어 들인다. getw는 텍스트

모드로 열려진 파일에는 사용할 수 없다. 성공한 경우에는 읽혀진 정수를 반환하고,

오류가 발생한 경우에는 EOF을 반환한다.


함수명 : perror

구 분 : void perror (const char *s);

기 능 : stderr스트림으로 시스템 오류 메시지를 출력한다.


함수명 : printf

구 분 : int printf (const char *format [,argument, ...]);

기 능 : 서식 지정 문자열인 format의 형태에 따라 표준 출력 스트림 stout에 문자열을 출

력한다. 이 때, 서식 지정자에 따라 자료를 출력할 수 있다. format 문자열 내에 존

제하는 서식 지정자의 수와 출력할 자료의 수는 같아야 한다. 서식 지정 문자열

format은 아래와 같은 두 종류의 문자들로 이루어 진다.


- 일반 문자 : 출력 스트림에 그대로 출력되는 문자

- 서식 지정자 : 인자 리스트에 존재하는 인자들 중 해당하는 인자의 서식을 지정

한다.


함수명 : putc

구 분 : int putc (int c, FILE *stream);

기 능 : 파일 포인터 stream이 가리키는 파일에 하나의 문자 c를 출력한다. putc는 성공하

는 경우는 출력된 문자를 반환하고, 실패한 경우는 EOF을 반환한다.


함수명 : putchar

구 분 : int utchar (int c);

기 능 : putchar(c)는 putc(c, stdout)으로 정의되어 있으며, 표준 입력 스트림 stdout으로

부터 하나의 문자 c를 출력한다. 성공한 경우는 출력된 문자를 반환하고, 실패한

실패한 경우는 EOF을 반환한다.


함수명 : puts

구 분 : int puts (const char *s);

기 능 : puts함수는 출력할 문자열 s에 개행 문자 ‘\n’를 붙여 출력한다. 그러므러 문자

열 s를 출력후 커서가 한 라인 아래의 왼쪽으로 이동한다. 성공하면 0 또는 양의

정수를 반환하고, 실패하면 EOF을 반환한다.


함수명 : putw

구 분 : int putw (int w, FILE *stream);

기 능 : 파일 포인터 steram이 가리키는 파일에 정수 w를 출력한다. putw는 성공하는 경우에는

정수 w를 반환하고, 실패하는 경우에는 EOF을 반환한다.


함수명 : rename

구 분 : int rename (const char *oldname, const char *newname);

기 능 : oldname 이라고 명명된 파일의 이름을 newname으로 변경시킨다. old name에 지정된 디렉

토리와 newname에 지정된 디렉토리는 달라도 된다. 두 개의 디렉토리가

다른 경우에는 파일을 다른 디렉토리로 옮기는 역할을 한다. 성공적으로 파일 이름

을 변경시킨 경우에는 0을 반환한다. 오류가 생긴 경우에는 -1을 반환하고, errno

를 아래의 상수들 중의 하나로 설정한다.

ENOENT 파일이나 디렉토리가 존재하지 않는 경우

EACCES 이름 변경이 허용되지 않는 경우

ENOTSAM 동일한 디바이스가 아닐 경우


함수명 : rewind

구 분 : void rewind (FILE *stream);

기 능 : 파일 포인터를 스트림의 시작점으로 이동시킨다. rewind(stream)는

feek(stream,0L)와 같은 의미이다.


함수명 : scanf

구 분 : int scanf (const char *format [, address...]);

기 능 : 표준 입력 스트림 stdin으로부터 자료를 읽어 들인다. 이때 서식 지정문자열

format에 지정된 형식에 따라 자료를 읽어 들인다.


함수명 : setbuf

구 분 : void setbuf (FILE *stream, char *buf);

기 능 : 입출력 버퍼 사용시 자동적으로 할당되는 버퍼를 할당하는 대신에 buf라는 특정한

버퍼를 지정하여 사용한다. 반드시 파일 포인터 stream에 파일이 할당된 후 buf

를 사용하여야 한다.


함수명 : setvbuf

구 분 : int setvbuf (FILE *stream, char *buf, int type, size_t size);

기 능 : 입출력 버퍼 사용시 자동적으로 할당하는 버퍼를 할당하는 대신에 buf라는 특정한

버퍼를 지정하여 사용한다. 반드시 파일 포인터 stream에 파일이 할당된 후 buf를

사용하여야 한다. size는 버퍼의 크기로서 0보다는 크거나 같고, 32767보다는 작아

야 한다.


함수명 : sprintf

구 분 : int sprintf (char *buffer, const char *format [, argument, ...]);

기 능 : argument들을 서식 지정 문자열 format에 지정된 형식에 따라 buffer라는 문자열

로 출력한다. 성공하면 출력된 바이트 수를 반환하고, 실패하면 EOF을 반환한다.


함수명 : sscanf

구 분 : int sscanf (const char *buffer, const char *format [, address, ...]);

기 능 : buffer라는 문자열로부터 자료를 입력 받아 서식 지정 문자열 format에 지정된 형

식에 따라 변환하여 그 값을 인자로 쓰인 address에 저장한다. scanf의 수행이 성

공하면 입력된 필드의 수를 반환하며, 만약 파일의 끝에 도달하면 EOF을 반환한다.


함수명 : strerror

구 분 : char *strerror (int errnum);

기 능 : errnum과 관련된 오류 메시지 문자열을 가리키는 포인터를 반환한다.


함수명 : tmpfile

구 분 : FILE *tmpfile (void);

기 능 : 임시 파일을 이진 모드로 열고, 수정을 위해 (w+b) 모드로 한다. tmpfile에 의해

생성된 파일은 프로그램이 종결되거나, 파일을 닫기 위한 함수 fclode를 사용하면

자동으로 제거된다.


함수명 : tmpnam

구 분 : char *tmpnam (char *s);

기 능 : 파일 이름을 생성하여 임시 파일의 이름으로 사용한다.


함수명 : ungetc

구 분 : int ungetc (int c, FILE *stream);

기 능 : 문자 c를 stream으로 명명된 입력 스트림에 되돌려 놓는다. 이 때, stream은 반드

시 열려진 상태여야 한다. getc나 fread함수가 호출되어 stream에서 하나의 문자를

읽으면 ungetc에 의해 되돌려진 문자가 읽혀지게 된다. ungetc가 성공하면 스트림

으로 되돌여진 문자를 반환하고, 실패하면 EOF을 반환한다.


함수명 : unlink

구 분 : int unlink (const char *path);

기 능 : path에 지정된 파일을 삭제한다. 어떠한 DOS 드라이브나 경로, 파일명도 path에 사용될

수 있다. 단 와일드 카드의 사용은 허용되지 않는다. 읽기 전용 파일은

unlink 함수를 사용하여 삭제할 수 없으며, unlink로 삭제하려면 chmod나 _chmod

함수를 사용하여 읽기 전용(read only) 속성을 다른 것으로 바꾸어야 한다. unlink함

함수의 수행이 성공하면 0을 반환한다. 만약 오류가 발생한 경우에는 -1을 반환하

고 errno를 다음의 값들 중 하나로 설정한다.


함수명 : vfprintf

구 분 : int vfprintf (FILE *stream, const char *format, va_list arglist);

기 능 : v...printf 형태의 함수들은 ...printf 형태의 함수와 같은 기능을 한다.

vfprintf함수가 printf함수와 다른 점은, fprintf 함수는 인자 리스트를 받아서 출력하고,

vprintf함수는 인자 리스트에 대한 포인터를 받아서 출력한다는 점이 다르다.


함수명 : vfscanf

구 분 : int vfscanf (FILE *stream, const char *format, va_list arglist);

기 능 : v...scanf형태의 함수들은 ...scanf형태의 함수와 같은 기능을 한다. vfscanf함수가

fscanf 함수와 다른 점은, fscanf함수는 인자 리스트를 입력 받고, vfscanf 함수는

인자 리스트에 대한 포인터를 입력 받는다는 점이 다르다.


함수명 : vprintf

구 분 : int vprintf (const char *format, va_list arglist);

기 능 : vprintf함수는 printf함수와 같은 기능을 한다. vprintf 함수가 printf함수와 다른 점은,

scanf 함수는 인자 인자 리스트를 입력 받고, vscanf 함수는 인자 리스트에 대한

포인터를 입력 받는다는 점이 다르다.


함수명 : vscanf

구 분 : int vscanf (const *format, va_list arglist);

기 능 : vscanf 함수는 scanf 함수와 같은 기능을 한다. vscanf 함수가 scanf 함수와 다은

점은, scanf 함수는 인자 리스트를 입력 받고, vscanf 함수는 인자 리스트에 대한

포인터를 입력 받는다는 점이 다르다.


함수명 : vsprintf

구 분 : int vsprintf (char *buffer, const char *format, va_list arglist);

기 능 : vsprintf 함수는 인자 리스트에 대한 포인터를 받아서 서식 지정 문자열 format에

지정된 형식에 맞추어 buffer라는 문자열로 출력된다.


함수명 : vsscanf

구 분 : int vsscanf (const char *buffer, const char *format, va_list arglist);

기 능 : vsscanf함수는 자료를 입력 받아서 서식 지정 문자열 format에 지정된 형식에 따

라 변환하여 인자 리스트에 존재하는 address에 저장한다.