소개 

리눅스 시스템 프로그래밍(:12)관련 온라인 북을 만들기 위해서 생성한 위키(:12)페이지로, 문서는 다음과 같은 성격을 가진다.
  • 난이도 시스템 프로그래밍 초/중급
  • 대상 C(:12) 프로그래밍 입문과정을 거친자. 리눅스 환경에서의 C 프로그래밍과 연결된다. Linux 운영체제(:12)를 다룰 수 있는자. 리눅스 시스템 프로그래밍 입문자
  • 목표 리눅스 운영체제(:12)의 이해 리눅스 시스템 프로그래밍의 이해 C언어를 통한 리눅스 시스템 제어
  • 흥미위주가 아닌 낮은 수준에서 리눅스(:12) 시스템을 이해시키는데 주력한다.
문서구조는 다음과 같다.
  • 장,절,소절 의 3단계 깊이를 가진다.
  • 설명을 위한 도입부와 본문 정리를 위한 결론의 3부분으로 이루어진다.
    • 도입부는 A4지 반장 내외로 3문단 이내로 한다.
    • 본문은 문단단위로 이루어지며, 설명,잠깐,코드,그림의 4가지 구성요소를 가진다. 잠깐은 간략하게 짚고넘어갈 수 있는 팁수준의 내용을 담는다.
    • 결론은 요점정리와 문제출제로 한다. 


문서 프로젝트

경로제목
Ch01_IntroJoinc와 함께하는 리눅스 시스템 프로그래밍 : 1장 소개
Ch02_BeginningJoinC와 함께하는 리눅스 시스템 프로그래밍 2장 시작하기
Index리눅스 시템 프로그래밍 : 목차정리
ch03_EnvJoinc와 함께하는 리눅스 시스템 프로그래밍 3장 입력과 출력
ch04_UserJoinc와 함께하는 리눅스 시스템 프로그래밍 4장 - 유저 환경
ch05_ProcessJoinc와 함께하는 리눅스 시스템 프로그래밍 5장 프로세스
ch06_Signal리눅스 시스템 프로그래밍 6장 - Signal
ch07_Thread리눅스 시스템 프로그램밍 7장 쓰레드
ch08_IPC리눅스 시스템 프로그래밍 8장 IPC
ch09_Time리눅스 시스템 프로그래밍 9장 - 시간


1 소개 

1.1 리눅스를 접한게 언제 였더라 

리눅스를 본격적으로 접한게 1998년이였던 것으로 기억된다. 알짜 RedHat 5.3 인가 하는 RedHat(:12)의 한글판 버젼이 왠일로꽤 세인의 이목을 집중시켰던 적이 있었는데, 서점에 꽂혀있는걸 보고 냉큼 구입해서 집에 있는 486 컴퓨터에 설치했다. 그게 인연이 되어서 2007년 10월 지금에 이르렀다.

그때를 생각해보면, 리눅스에 유독 열광했던거 같다. 지금 생각해보면 단순함의 극치를 달리던 window:::maker(:12)가 그때는 왜 그리 멋져보였는지 모르겠다. 아이콘바꾸고 배경화면 바꾸고, 메뉴바꾸는 것만으로 몇날 몇일을 보냈던거 같다. 그러다가 IRC(:12)를 알게 되고, 다시 linux 채널에 들어가서 시간이 가는줄 모르고 리눅스 관련 이야기에 열중을 했다.

대학생활을 하긴 했지만 전공에 관심도 없었고, 그렇다고 잘 놀지도 못했었다. 뭔가 새로운 것이 필요했었는데, 그 때 리눅스가 나타난 것이라고 해야 할려나 싶다. 지금 생각해 보면 불행이기도 하고 다행이기도 한거 같다. 리눅스 대신에 여자에게 좀 관심을 가졌더라면, 지금은 좀더 밝은 세상에서 살고 있지 않을까라는 아쉬운 생각이 들기도 하는 반면, 그나마 리눅스에라도 관심을 가져서 굶지않고 살지라는 생각도 들고.

1.2 C 언어 

리눅스에 어느정도 익숙해졌을 무렵, 접한 언어가 php(:12) 였다. 결과가 눈에 바로 보이는게 재미있기도 하고 거기에 때마침 인터넷 벤쳐열풍이 불어 닥치던 때라서, 역시 밤낮을 가리지 않고 php를 가지고 놀았다. 지금 생각해보면 php를 이용해서 무언가를 학습하기 보다는 단지 아주 재미있는 장난감 정도로 생각을 했었던거 같다. 웹프로그래밍을 통해서 프로그래밍 세계에 발을 들여놓은 셈이다.

Linux를 접하고 php를 가지고 놀던 처음 1년 정도의 시기가 아마도 내가 무엇엔가 하나에 집중을 한 거의 유일한 시기가 아니였나 싶다. 그 뒤로 지금까지 어떤종류의 일이 되었던지 그때 처럼 집중을 했던 적은 없었던거 같다.

그러다가 C(:12)언어를 접하게 되었다. 교양과목으로 전산을 했던지라 hello world 정도는 출력할 줄 알았지만 hello world를 출력하는게 전부였던 때였다. 사실 C언어는 php에 비하자면 절대 재미있는 언어가 아니다. 그렇다고 전공이 이쪽 계통이라서 언어에 대한 개념이 있었던 것도 아니니, C언어의 필요성을 느꼇을 리도 없고 - 내 전공은 원자력 공학이다 -.

그냥 회사에서 php 가지고 이것저것 만들고 있는데, 어느날 php만으로는 모든걸 할 수 없다는 것을 깨닫게 되었다. 당시 php가지고 하던일이 웹메일 시스템 만들기였다. smtp(:12) 서버로 부터 메일을 받으면 이것을 디코딩하고 분류해서 Mysql(:12) 디비에 집어 넣는 일을 하는 시스템이였다. 뭐 기능을 구현하는 자체는 큰 무리는 없었는데, 디코딩에 너무 많은 시간이 걸린다는게 문제였다. 그때 php 버전이 3.0이였는데, php만을 가지고는 도저히 어떻게 시간을 줄일 수 있는 방법이 없는 거였다.

그래서 찾아낸게 C 언어였다. C 언어로 디코딩하는 부분만 구현해서, 테스트를 해봤더니 - 잘 기억은 나지 않지만 - 대략 5-10배 정도의 성능의 차이가 생기는 거였다. 그뒤로 코어의 진행은 C로 하게 되고, 지금까지 쭉 이어오고 있다. 현재는 C,C++ 언어를 주력으로 사용하고 php, perl 을 보조언어로 사용하고 있다.

1.3 시스템 프로그래밍을 다루게 되다. 

이렇게 해서 C 언어를 사용하게 되었다. 꽤나 어려울줄 알았는데, 왠걸 ? php와 문법도 비슷하고 별거 아니네, 라고 만만하게 보고 프로젝트에 C를 사용했는데....

지금도 그때 일이 생각 날 정도로 엄청난 고생을 했었다. 개고생을 하고나서 터득한 것은
  1. 언어에 있어서 문법은 중요한게 아니다.
  2. 중요한것은 언어가 다루는 환경이다.
라는 두가지 명제다. 이 두가지 명제를 몸으로 구르면서 터득한 거다.

문법 그건 아무것도 아니었다. 문법만 익히는 것은 초등학생 데려다 놓고 대충해도 한달이면 충분하다. 문제는 환경이다. 리눅스 시스템을 모르고 C 를 이용한 시스템 프로그래밍에 멋도 모르고 뛰어들었으니, 프로그램이 제대로 돌아갈리가 없다.

1.4 시스템 프로그래밍의 중요성을 깨닫다 

sadsense나름 개고생 하고나서, 약간 정신을 차리게 된 나는 정식으로 유닉스 시스템 프로그래밍에 대해서 공부를 시작했다. 그래봤자 독학이긴 하지만 꾸준히 한 덕택에 지금은 그럭저럭 필요한 프로그램 만들고, 분석할 수 있는 수준에 이르렀다. 이 과정에서 터득한 것이라면 시스템 프로그래밍의 중요성이다.

시스템 프로그래밍의 중요성에 대해서 얘기하고자 하지만, 현실에서는 시스템 프로그래밍 기술이 정말 중요한가 ? 라는 얘기를 듣곤한다. 프로그램을 만드는 프로그램을 이용해서 프로그램을 만드는 세상인데, 굳이 별로 재미도 없어보이는시스템 프로그래밍쪽을 공부해야 하느냐란 것이다. 훌륭한 Visual 개발툴과 잘 만들어진 라이브러리(:12)와 컴포넌트 기타 저작툴들이 널려있다.

이론상으로는 그럴듯 하다. 실제로 그런세계가 올지도 모른다. 컴퓨터에게 은행업무를 효율적으로 하기 위한 고객관리 프로그램이 필요하거든 한번 만들어봐라고 하고 몇가지 조건만 주면 그럴듯한 프로그램을 만들어내는 시대가 올지도 모른다.

그러나 (프로그래머의 입장에서는)다행스럽게도 지금의 컴퓨터는 산업전반에서 요구하는 모든 종류의 요청에 대해서 뚝딱하고 프로그램을 만들어낼 만큼 똑똑하지 못하다. 조금씩 인간이 개입하는 여지가 줄어들기는 하겠지만 당분간은 말로만으로 프로그램이 생성되어서, 프로그래머가 필요없는 세상은 오지 않을 것 같다.

결국 컴퓨터가 자동으로 할 수 없는 것은 인간이 책임질 수 밖에 없다. 이러한 영역이 주로 시스템 프로그래밍영역이 된다. 메뉴, 창, 버튼, 입력상자의 배치와 같은 프로그램의 외형은 컴퓨터가 자동으로 해낼 수 있지만 그 밑단의 시스템영역에서 이루어지는 데이터의 저장, 다중작업, 데이터 통신과 같은 일들은 경험있는 프로그래머가 반드시 필요하다. 여기에 덧하여 최적화라는 컴퓨터가 자동으로 수행할 수 없는 영역도 있다. 최적화라는 것은 프로그램의 성능을 좀더 높이기 위해서 시스템의 자원 사용을 최적화 하는 일련의 작업들이다. 메모리를 어떻게 사용할 것인지, 프로그램간에 데이터 통신은 어떻게 할건지, 대량의 데이터를 병렬처리 하기 위해서 어떤 시스템 통신 모델을 사용할 건지에 따라서 수십% 혹은 수백 %의 성능의 차이가 날 수 있는데, 이런 일은 자동화가 불가능한 영역이다. 역시 시스템에 대한 지식을 가진 경험있는 시스템 프로그래머가 필요하다.

결론은 이렇다. 아주 간단한 프로그램이 아닌한은 제대로 돌아가는 프로그램을 만들고자 한다면, 혹은 취미로 프로그램을 작성하고자 하는 생각 이 아니라면 시스템 프로그래밍은 선택사항이 아닌 필수 사항이다.

1.5 일반적인 프로그래밍 학습 과정 

공부에는 정도라는게 없다고 한다. 그럴듯도 하지만 선배들의 경험에 따른 더 좋은 방법이라는 것은 존재한다. 다행히도 프로그래밍을 하려는 여러분은 아무도 발을 내딛은 적이 없는 오지를 횡당하는게 아니다. 여러분이 가고자 하는 길을 많은 선배들이 앞서서 갔으니, 그들의 경험을 따를 필요가 있다.

그 경험에 의하자면 대략적인 프로그래밍 학습과정은 다음과 같다.
  1. 언어를 익힌다.
    perl, python, java, C++, C 등의 다양한 언어가 있다. 이중 하나의 언어를 선택한다. 여기에서는 C를 선택하도록 할 것이다. 일반적인 언어의 문법과 특징을 익히는데에는 한달이면 충분할 것이다. 그 이상 시간을 끄는 것은 낭비라고 생각된다.
  2. 시스템 프로그래밍을 한다. 우리가 하고자 하는 거다.
  3. 네트워크:::프로그래밍(:12)을 한다. 모든 컴퓨터가 인터넷(:12)에 연결된 세상에 살고 있으니, 네트워크 프로그래밍은 필수라고 할 수 있다.
  4. 시스템 프로그래밍을 한다. 네트워크 프로그래밍을 하다보면, 좀더 깊은 수준에서의 시스템 프로그래밍 기술이 필요하다는 걸 느끼게 될 것이다. 기존에 배웠던 시스템 프로그래밍을 좀더 깊은 수준에서 공부하게 된다.
  5. 자료구조(:12)와 알고리즘(:12)
    컴퓨터는 데이터를 처리하는 일을 한다. 그러므로 고수준의 프로그램을 작성하기 위해서는 데이터(자료)를 어떻게 구조화 하고, 어떤 알고리즘(:12)을 이용해서 효과적으로 처리해야 할지를 알고 있어야 한다.
  6. 응용 이제 게임을 하던지, 보안관련 프로그램을 작성하던지 혹은 데이터 베이스 관련일을 하던지 응용하는 일만 남아 있다. 시스템 프로그래밍과 네트워크 프로그래밍은 앞으로 나아가기 위한 초석이라고 보면 될것이다. 

이 방식의 단점이라면 고리타분하다는 점일 거다. 많은 사람들은 눈에 보이는 것을 좋아한다. 하지만 나중에 고생하고 싶지않다면, 제대로된 기반하에서 더 멀리보고 더 많은 것을 해보고 싶다면 위의 과정을 차근히 밟아나가길 바란다.

2 리눅스 시스템 프로그래밍 

2.1 운영체제와 시스템 프로그래밍 

시스템 프로그래밍이란 컴퓨터 시스템을 다루는 프로그래밍을 의미한다. 여기에서 컴퓨터 시스템이란 컴퓨터를 이루는 구성요소들인 모니터,키보드,메모리, 하드디스크,랜카드를 의미한다. 그렇다고 해서 프로그래머가 모니터, 키보드, 메모리와 같은 기계장치에 직접 명령을 내려야 하는 건 아니다. 인간과 컴퓨터 사이에 운영체제(:12)가 존재하기 때문이다.
  
 Computer System 
   Monitor         | 운 |
   Memory          |    |
   Hard Disk     <-| 영 |--> 프로그래머
   LAN Card      <-|    |-->
   Sound Card      | 체 |
   Printer         |    |
   ....            | 제 |
운영체제가 있는 덕분에 프로그래머는 컴퓨터 기계장치에 직접명령을 내리지 않고, 운영체제를 통해서 간접적으로 명령을 내리는 정도로 컴퓨터 시스템을 제어할 수 있게 된다.

은행창구가 있는 덕분에 복잡한 금융거래를 간단하게 할 수 있는 것과 같은이치다. 돈을 송금하는 과정은 여러단계의 매우 복잡한 과정을 거쳐야 할것이다. 그러나 고객은 그 과정을 알 필요 없다. 그냥 "이돈을 어디어디 계좌로 보내주세요"라는 내용을 적은 명세표만 직원에게 주면 된다. 나머지 일은 창구직원이 알아서 해준다.

시스템 프로그래머에게 있어서 운영체제는 프로그래머와 컴퓨터 시스템간의 창구역할을 하는 프로그램으로 이해하면 될 것이다.

프로그래머가 운영체제에게 어떤 요청을 할때는 이러이러한 일을 해주세요라고 명세표를 작성해야 할 것이다. 이러한 요청을 쉽게 하도록 하기 위해서 운영체제는 시스템 함수라는 것을 제공한다. 예를 들어, 리눅스 운영체제는 메모리할당과 관련되어서 malloc()이라는 시스템 함수를 제공한다. 그러면 프로그래머는 다음과 같은 방법으로 메모리 할당을 요청하게 된다.
malloc(2*1024*1024) /* 2메가의 메모리 공간을 요청 */
요청을 받은 운영체제는 복잡한 과정을 거쳐서 메모리를 할당하고, 메모리가 할당된 공간을 프로그래머에게 알려준다. 이제 프로그래머는 할당된 공간을 이용하기만 하면 된다.

이러한 요청 명세는 안타깝게도 운영체제마다 약간의 차이가 있다. 윈도우와 리눅스가 다르고, 리눅스와 솔라리스가 또 다르다. 때문에 윈도우 시스템 프로그래밍 기술을 리눅스 시스템 프로그래밍을 하는데 이용하는 데에는 많은 어려움이 따른다.


Unix 운영체제 계보
물론 운영체제가 다르다고 해도, 작동방식은 비슷하기 때문에 한쪽 운영체제의 시스템 프로그래밍 지식을 다른 운영체제에서 전혀 써먹을 수 없는 건 아니다. 많은 운영체제들이 운영체제의 할아버지뻘즘 되는 Unix(:12) 운영체제를 그 기반으로 하고 있기 때문에 함수명이라든지 사용방법 기능이 비슷비슷한 경우가 많기 때문이다. 하지만 여전히 어려운건 사실이다.

그러므로 시스템 프로그래밍에 발을 들여놓으려고 한다면, 운영체제를 선택하는게 중요한 요소가 된다. 물론 여기에서는 여러분이 리눅스 운영체제를 선택했다고 가장할 것이다. 왜 리눅스 운영체제를 선택했는지는 아래에서 설명하도록 하겠다.

2.2 리눅스를 선택한 이유 

이론이 있을 수 있지만 모든 운영체제의 아버지는 Unix(:12)이다. 대부분의 운영체제가 Unix(:12)계보를 타고 있다. 맥 OS는 물론이고, Unix 운영체제의 자칭 타칭 경쟁자인 윈도우즈 조차도 Unix의 영향을 받고 있다.

Unix를 아는 것은 운영체제를 아는 것이고 운영체제를 아다는 것은 컴퓨터 시스템을 안다는게 된다.

여기에서 짚고 넘어갈게 있다. 명확히 하자면 Unix는 운영체제가 아니라는 점이다. Unix는 계보라고 보는게 적당하다. 이 Unix 계보안에 Minix, Solaris, Next, Linux, BSD와 같은 운영체제들이 존재한다. 이들 운영체제는 Unix 계보에 포함되기 위한 여러가지 요소들을 충실히 구현하고 있다. 이들을 통들어서 Unix운영체제 혹은 *nix 운영체제라고 한다. Unix 계보에 포함된 다양한 운영체제들은 서로 다른 이름을 가지고 있지만 동일한 계보에 있는 형제들인고로, 사용방법 프로그래밍 방법등이 거의 동일하다. Linux에서 작성된 프로그램은 거의 수정없이 다른 Unix 운영체제에서 동일하게 사용할 수 있다.

왼쪽 유닉스 계보를 보기 바란다. 대략 수십종의 운영체제들이 존재하는걸 알 수 있다. 그런데 왜 하필 리눅스를 선택했을까 ?
  1. 개인적으로 리눅스를 좋아하기 때문이다.
  2. 운영체제 계보의 왕형님격인 Unix를 따르면서도 저렴한데다가 x86 시스템에서 돌아간다. 게다가 Open:::Source(:12)다. Linux에서 배운 프로그래밍 기술은 다른 유닉스 운영체제인 Solaris, BSD 등에도 거의 그대로 적용할 수 있다. 이러한 특징 때문에 한때는 저렴하게 Unix 운영체제를 경험할 수 있는 최고의 학습용 운영체제로 사용되었다. 지금은 최고의 학습용 운영체제일 뿐만 아니라 성공적으로 산업에 진입한 운영체제로 대접을 받고 있다. 산학협력형 운영체제라 할만하다. 

이상 간단하게 리눅스를 선택한 이유를 들어보았다. 학습하기 좋고 산업현장에서도 써먹을 수 있으니 이 아니 좋은가.

ShowComment(323)

2.3 리눅스의 전망 

20세기말까지의 산업구조는 대량생산 대량소비를 달성하기 위한 목적에 부합하게 만들어져 있었다. 이를 위해서 생산시설과 소비시설, 이들을 지원하기 위한 자원과 에너지를 한정된 공간에 집적시키게 된다. 이러한 결과 소비와 생산을 위한 거대도시, 에너지집약적인 산업들 즉 원자력발전소와 대규모 공업단지, 물류단지등이 나타나게 된다.

정보처리산업 역시 마찬가지였다. HP, Oracle, MS, IBM과 메인프레임, Unix에서 볼 수 있는 것처럼 거대하고 강력한 정보처리기계를 만들고, 여기에 자원과 에너지를 집중시켰음을 알 수 있다.

이런 고에너지기반의 산업은 한계에 부닥치게 된다. 에너지가 집적됨에 따라서, 필연적으로 발생하는 환경오염, 거대하고 기계화된 조직을 관리하기 위한 방만하고 비효율적인 관리조직, 자원의 급격한 고갈이라는 문제때문에 발생하는 비용이 에너지를 집적함으로써 얻을 수 있는 이익을 초과하는 시점에 다다랐기 때문이다.

이렇게 되어서, 거대한 도시를 유지하는 대신에 소규모의 여러개의 도시를 유지하고 이들을 네트워크로 묶고 권한을 분산하는 정책을 사용하게 된다. 이렇게 되자, 산업구조역시 바뀌게 되는데, 대규모화된 도시의 획일화된 소비패턴을 지원하기 위한 획일화된 대규모 공업단지를 유지하는 대신에, 각 지역에 분산된 공간에서 각 소비자의 특징에 맞는 물건을 생산하는 방식의 구조적인 변화가 진행이 된다.

이렇게 산업과 도시생활패턴이 변경되자. 정보처리 산업역시 그러한 방식으로 변화가 된다. Web2.0, 개인화, SN, 블로그, SA등 분산과 네트워크 효과를 중요시 하게 되고, 이에 따라서, 거대하고 강력한 정보처리기계, 소프트웨어를 사용하는 대신에, 유연하고 자유롭게 제어가능한 하드웨어와 소프트웨어의 사용을 지향하게 된다. 덜 강력하고 덜 비싼 자원을 사용하는 대신에, 각각의 자원에 권한을 분산시키고, 이를 네트워크화 해서 원하는 정보를 얻어내는 그런 환경이다.

리눅스와 Mysql, Apache 기타 수많은 공개소프트웨어들이 - 충분히 성숙하지 못했음에도 불구하고 - 각광을 받는 것은 우연이 아니라 필연이다.

리눅스는 이러한 산업과 생활패턴의 변화에 따라서, 그 영역을 지속적으로 확대해 나갈 것이다.



출처 - http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/system_programing/Book_LSP/Ch01_Intro



'Development > Linux Programming' 카테고리의 다른 글

linux prog - linux startup  (0) 2013.10.03
linux programming - library  (0) 2013.10.03
Posted by linuxism
,


리눅스를 처음 사용하는 분들을 위한 북마크

1 목적 

리눅스를 처음 시작하려면 무엇부터 봐야 할까요? 안타깝게도 초보자들이 시작할 때 봐야 하는 자료는 여기저기에 흩어져 있습니다. 이러한 자료들을 한 페이지에 모으려고 시작하였습니다. 리눅스는 우리가 가장 흔히 접하는 운영체제 윈도우와는 달리, 사용자가 많은 부분을 선택할 수 있습니다. 또한 선택할 수 있는 폭이 상당히 넓기 때문에 어렵게 느껴질 수도 있습니다. 이 게시물을 통하여 좀 더 쉽게 선택할 수 있기 바랍니다.

2 리눅스(Linux)란? 

리눅스는 운영체제입니다. 마이크로소프트사의 윈도우와 같은 역할을 하는 프로그램입니다. 또한 리눅스는 커널이라고 불리우는 운영체제 핵심 부분의 이름이기도 하며 보통 운영체제의 이름이기도 합니다. 따라서 윈도우에서 하는 모든 일을 리눅스에서도 할 수 있습니다. 다만 하는 방법이 다를 뿐입니다. 그래서 어렵게 느껴질 뿐입니다.

리눅스는 특정한 회사에서 제작되는 프로그램이 아닙니다. 전세계 개인 또는 회사의 프로그래머들과 사용자들의 오픈소스 프로젝트입니다. 여기에 참여하는 대표적인 회사들로는 IBM, HP, DELL, ORACLE 등이 있습니다. 유명한 개인으로는 리누스 토발즈, 에릭 레이몬드 등이 있습니다. 더 궁금하시면 [http]http://www.linuxfoundation.org/publications/linuxkerneldevelopment.php 또는 [http]http://www.linuxfoundation.org/publications/Who_Writes_Linux.pdf 를 참조하세요.

배포판은 리눅스라는 운영 체제를 사용자가 쉽게 설치하여 사용할 수 있도록 구성하여 배포하는 것을 말합니다. 무료로 배포하는 것도 있고, MS사의 윈도우처럼 판매되는 것도 있습니다. 판매되는 제품들은 CD/DVD로 배포되며, 상용 프로그램이 들어 있기도 하고, 기술 지원을 받을 수 있습니다.

참고할 만한 사이트입니다.

3 배포판 선택 

아래에 있는 배포판들은 서버 또는 데스크톱용으로 주로 사용되는 배포판입니다. 이 목록에 있는 것이 배포판의 전부는 아니지만, 가급적이면 이 중 하나를 선택하여 최신 버전으로 사용하십시오. 대개 한국어 환경을 무리 없이 지원하며, 사용자가 많아서 돌발 상황이나 모르는 것이 생기면 질문하기도 쉽습니다. 설치하여 사용할 수 있는 프로그램 패키지도 많이 지원합니다. 하드웨어가 오래 되었거나 사양이 낮다면 대안으로 http://www.damnsmalllinux.org 이나 http://www.xubuntu.org 를 고려해볼 만합니다.

참고로 레드햇 9.0은 제작사에서 지원이 중단된 아주 오래된 배포판입니다. 윈도우 XP를 사용하지 않고 윈도우 95를 사용하면서 안 좋다고 투덜대는 격입니다.

더 많은 배포판 정보는 http://en.wikipedia.org/wiki/List_of_Linux_distributions 와 http://distrowatch.com 를 참고하세요. 2009년 7월 시점에서 최신 배포판은 페도라 11, 우분투 9.04, 맨드리바 2009.1, 데비안 5.0, 오픈수세 11.1 등입니다. 각각 배포판별 설치 및 설정 방법을 알고 싶으면 http://howtoforge.com/howtos/desktop 을 참고하십시오. 갓 리눅스를 사용하신 분들에게 강력히 추천해 드립니다.

4 설치하기 전에 알아둘 것 

PC에 윈도우가 설치되어 있는 경우 리눅스를 사용할 수 있는 방법은 아래와 같습니다.
  • 윈도우를 삭제하고 리눅스를 설치한다.
  • 윈도우 파티션 크기를 조절(resize)하여 리눅스를 설치할 공간을 만들어 설치한다.
  • 윈도우에서 VMWare와 같은 가상 머신 프로그램을 이용하여 설치한다.
  • 윈도우에서 coLinux나 andLinux 같은 리눅스 배포판을 설치하여 사용한다. 또는 우분투의 Wubi 를 이용한다.
  • 라이브 CD나 라이브 USB로 배포되는 리눅스 배포판을 사용한다. 

4.1 파티션과 드라이브 

IDE 장치만 있는 컴퓨터에서 파티션과 드라이브는 다음과 같이 인식됩니다.

리눅스하드웨어윈도우
/dev/hdaIDE 프라이머리 마스터보통 윈도우 하드 디스크 'C'
/dev/hdbIDE 프라이머리 슬레이브보통 윈도우 하드 디스크 'D' 또는 ODD
/dev/hdcIDE 세컨더리 마스터보통 윈도우 하드 디스크 'E'
/dev/hddIDE 세컨더리 슬레이브보통 윈도우 하드 디스크 'F'

SCSI나 USB 이동식 디스크, 최근 많이 사용되는 SATA 하드 디스크 등은 sda, sdb, sdc 등의 이름이 붙습니다. 배포판에 따라서 IDE 장치라도 SATA 장치처럼 하드디스크에 sda, sdb, sdc 등의 이름이 붙을 수도 있습니다.

윈도우에서는 하드 디스크 파티션을 나누면 C, D, E와 같이 알파벳 한 글자 드라이브 이름이 붙지만 리눅스에서는 /dev/sda1, /dev/sda2, /dev/sda3과 같이 /dev 아래에 (장치 이름)(파티션 순서)처럼 이름이 붙습니다. 윈도우에서는 보통 자동으로 되던 부분이라 리눅스를 처음사용하시는 분들이 많이 어려워 하시지만 사실 간단합니다.

4.2 하드웨어 설치 

최근 리눅스 배포판은 설치할 때 대부분 하드웨어를 자동으로 인식하여 설정을 하므로 별 문제가 없습니다. 다만 일부 하드웨어의 경우 수동으로 설정해야 할 때도 있습니다. 대개 그래픽 카드나 무선랜 카드입니다. 자신의 하드웨어를 별도로 설정해야 하는가 알아보려면, 아래의 홈페이지 등을 참고하여 하드웨어 호환 여부를 확인합니다.

다음 목록은 리눅스 배포판에서 제공하는 하드웨어 호환성 목록입니다.다음 목록은 특정 하드웨어의 리눅스 호환성을 다루고 있습니다.대개 이 정도 사이트만 탐색하면 리눅스 지원 여부를 찾을 수 있지만, 그래도 모르겠으면 다음과 같이 해 보십시오.

  • 검색 엔진에서 "하드웨어 모델명(또는 칩셋명) linux"로 검색해 보십시오. 사용기가 나올 수도 있습니다.
  • 일부 하드웨어 제조사는 홈페이지에서 리눅스 드라이버를 제공합니다. HP 프린터, 엔비디아 및 ATI 그래픽 카드 등이 있습니다. 

5 한글 설정 

윈도우에서 사용하는 한글 글꼴은 굴림, 궁서, 돋움, 바탕, 맑은 고딕이 있습니다. 이들 글꼴은 윈도우와 함께 배포되는 상용 글꼴로, 대부분 리눅스 배포판에 포함될 수 없습니다. 따라서 이들 대신 은 글꼴이나 은진체 등의 공개 한글 글꼴이 사용됩니다. 윈도우에서 사용하던 글꼴과 모양이 달라서 처음에 적응이 힘들 수도 있습니다.

최근에는 다양한 공개 한글 글꼴이 나와서, 이들을 설치하여 사용할 수도 있습니다.좀 더 참고할만한 자료입니다.리눅스에서 사용하는 글꼴은 fontconfig 라는 프로그램이 관리합니다. 따라서 글꼴 미세 조정에 관심이 많다면 이 프로그램의 설정 방법을 연구하시면 됩니다. 대부분의 경우 배포판의 글꼴 설정을 사용해도 무방합니다.

6 리눅스 프로그램 

리눅스에서 프로그램은 어떻게 설치할까요? 윈도우에서 새 프로그램을 설치하려면 프로그램 홈페이지에서 exe나 msi 파일을 다운로드 받아서 설치하였습니다. 리눅스에서는 rpm, deb과 같은 패키지 파일을 프로그램 홈페이지가 아닌 배포판 중앙 저장소에서 다운로드 받아서 설치합니다. 배포판 중앙 저장소에 모든 프로그램 정보가 다 들어 있을 때의 장점은 필요한 프로그램이 있을 때 일일이 홈페이지에서 다운로드받지 않아도 리눅스 배포판에 포함된 프로그램 추가/제거 도구를 통하여 모든 프로그램을 손쉽게 설치할 수 있습니다.

초보자들은 이 방식을 잘 이해하지 못할 수 있습니다. 그러나 한 번에 많은 프로그램을 설치하려고 한다면 일일이 설치하는 것보다 배포판 중앙 저장소에서 한번에 설치하는 것이 편하게 느껴질 겁니다.

많은 대형 배포판은 중앙 저장소가 잘 갖추어져 있어서 필요한 프로그램은 그냥 가져다 설치하면 됩니다. 하지만 중앙 저장소에 원하는 프로그램이 없다면 어떻게 해야 할까요? 일부 프로그램 제작자들은 홈페이지에서 패키지 파일을 배포하기도 합니다. 그런 경우에는 패키지 파일을 받아다 설치하면 됩니다. 패키지 파일도 없다면, 그 때 프로그램 원본 코드에서 실행 파일을 만들어서 설치하면 됩니다. 간혹 가다가 리눅스 초보자들이 '모든 프로그램을 소스에서 컴파일해서 설치해야 한다'고 생각하실 수도 있는데, 보통 소스 컴파일은 최후의 방법으로 여겨집니다.

다음 웹 사이트는 리눅스에서 사용하는 프로그램을 다루고 있습니다.

7 리눅스 데스크톱 구조 

오픈소스 프로그램
|
그놈, KDE 및 Xfce, Fluxbox 등
|
X.org + Qt/GTK
|
리눅스 커널 + GNU 프로그램
리눅스 데스크톱을 구성하는 프로그램을 알고 싶으면 http://en.wikipedia.org/wiki/Freedesktop.org 를 참고하십시오.

또한 윈도우의 테마처럼 리눅스 데스크톱도 테마, 배경화면, 아이콘 등을 자신의 취향대로 변경할 수 있습니다.

8 초보자 필독 

그리고 http://wiki.kldp.org/wiki.php/초보자코너 의 내용을 읽어보세요. 책이 필요없을 정도입니다.

9 보안 문제 

윈도우가 자동 업데이트를 통해서 매주 업데이트를 하듯이 리눅스도 자동 업데이트를 제공합니다. 리눅스 배포판마다 업데이트 방법이 다르기 때문에 배포판별 업데이트에 관한 문서를 참고하여 늘 최신 버전의 리눅스를 사용하십시오. 자동 업데이트를 사용하면 프로그램을 새 버전으로 업그레이드하거나, 보안 문제를 해결하거나, 성능이 더 좋아집니다.

그런데 왜 리눅스에는 별도의 백신이 없을까요? 리눅스에서는 윈도우에서 실행되던 바이러스, 악성코드가 실행되지 못합니다. 그리고 리눅스 프로그램의 보안 문제가 발생하면 프로그램 제작자들이 재빠르게 문제를 해결하여 새 버전을 배포합니다. 예로 과거 모질라 파이어폭스에서 보안 결함이 발견되었을 때 사흘만에 패치된 새 버전이 나왔습니다. 따라서 리눅스 환경에서는 별도의 백신 없이도 시스템을 안전하게 유지할 수 있습니다. 리눅스용 백신들은 리눅스 시스템 자체를 검사하기보다는 리눅스 시스템을 통해서 전달되는 파일에 붙어 있는 바이러스를 진단하는 데 사용됩니다.

10 누가 리눅스를 만드는지 알고 싶다면? 

Linux Kernel Development: How Fast it is Going, Who is Doing It, What They are Doing, and Who is Sponsoring Ithttp://www.linuxfoundation.org/docs/lf_linux_kernel_development_2010.pdf

11 추천 사이트 

만약 리더를 두고선 리눅스 설치를 위한 세미나를 진행하고자 한다면 
http://tldp.org/HOWTO/Installfest-HOWTO/ 와 http://kldp.org/node/81966 를 참고하세요.

12 정보 

이 게시물은 수시로 갱신됩니다.

별도로 리눅스 서버 입문자를 위한 북마크 리눅스 서버 운영 초보자를 위한 북마크 위키를 게시하였습니다.



출처 - http://wiki.kldp.org/wiki.php/LinuxUserBookmarkForNovice







'Development > Linux Programming' 카테고리의 다른 글

linux prog - intro  (0) 2013.10.03
linux programming - library  (0) 2013.10.03
Posted by linuxism
,


리눅스 C/C++ : 12장 라이브러리


Hello World 다시 보기


 hello world 프로그램을 다시 한번 보기로 하자.

          #include <stdio.h>

          

          int main(int argc, char **argv)

          {

              printf("Hello World!!!\n");

              return 1;

          }          

 위 프로그램을 자세히 뜯어보면, #include문이 보일 것이다. 이것이 어디에 쓰는 물건인지 자세히 알아보도록 할 것이다. 우리는 7장 함수편에서 함수에 대해서 다루었다. 이를 통해서 우리는 함수를 사용하기 위해서는함수선언과 함수원형이 필요하다는 것을 알게 되었다. 함수를 사용하는 이유는 중복되는 코드를 따로 묶어 둠으로써, 코드관리를 쉽게 하기 위함이라는 것도 역시 알고 있다. 하지만 편하겠지라고만 알고 있을 뿐, 실제 어떻게 편하게 사용되는지는 경험을 해보진 못했다.

 자.. 우리는 함수라는 것을 알고 있다. 그렇다면 어떻게 해야 함수를 더 편하게 사용할 수 있을까. 답은 함수를 위한 코드를 따로 분리시킨다 이다. 위의 Hello World 프로그램은 이러한 전형적인 모습을 보여주고 있다. printf 함수는 거의 모든 프로그램에서 필수적으로 사용되는 함수다. 이런 코드를 사용자가 필요할때 마다 일일이 사용하는건 여간 귀찮은일이 아닐 것이다. 그렇다면 printf 함수를 별도의 코드로 만들어서, 모듈형태로 만들어 두면 될것이다. 그래서 printf 함수가 필요할 때, 가져다 쓰기만 하면 된다.

 그런데, 컴파일러는 printf 함수가 어떤 모습을 가지는지 알 수가 없다. 그러니까 리턴값이 무엇이고, 인자로 무엇이 사용되는 지를 알 수가 없다는 얘기가 된다. 그러므로 컴파일러에게 printf 함수의 정보를 알려줄 수 있어야 한다. 그게 #include 문이 하는 일이다. stdio.h는 표준입출력과 관련된 함수의 정보가 들어있는 파일로 헤더파일이라고 부른다. 이 헤더파일에는 printf 함수가 선언되어 있다. stdio.h 헤더파일은 /usr/include 디렉토리 밑에 존재한다.

 이제 우리는 stdio.h 만을 include 시킴으로써, 어느 코드에서든지 간단하게 printf 함수를 사용할 수 있게 된다.

컴파일 과정


 이제 위의 hello world 프로그램이 어떻게 컴파일이 되는지 알아보도록 하자. 프로그램의 이름은 hello.c 이다.

  1. 컴파일러는 hello.c 프로그램을 읽어 들인다.
  2. hello.c 코드를 해석해서, 기계어 형태의 object 파일로 만든다. object 파일은 컴퓨터가 해석할 수 있는 단위 모듈이다.
  3. 여기에 printf 함수가 정의되어 있는 이미 만들어져 있는 object 파일과 hello object 파일을 서로 링크(연결)한다.
  4. 완전한 실행 파일이 만들어 진다.

덧셈 함수를 가진 프로그램


 그럼 덧셈 함수를 가진 계산기 프로그램을 만들어서, 모듈별로 작성하고 이것들을 object 파일로 만들어서 link 시켜서 실행파일을 만드는 방법에 대해서 알아보도록 하겠다.

 모듈별로 작성하지 않고, 하나의 파일로 이루어진 프로그램은 아래와 같이 작성할 수 있을 것이다.

          #include <stdio.h>

          int sum(int a, int b);

          int main(int argc, char **argv)

          {

              int value;

              value = sum(120, 199);

              printf("%d\n", value);

          }

          int sum(int a, int b)

          {

              return a+b;

          }
          

 아주 간단하며 문제없이 작성될 것이다. 또한 덧셈을 위한 sum 이라는 함수를 만들었으니, 이후 덧셈계산이 필요할 때 마다, 그냥 sum 함수를 그대로 쓰기만 하면 될것이다. 그런데 이 프로그램은 통짜로 작성되어 있기 때문에, 다른 프로그램에서 sum 함수를 사용할려고 하면 copy & paste 할 수 밖에 없다. 이것은 비효율 적이다. 이제 sum 함수를 모듈형식으로 완전히 분리 시켜 보도록 하자. 이를 위해서는 다음과 같이 3개의 파일이 만들어져야 한다.

  • sum 함수의 선언이 들어 있는 include 파일
  • sum 함수를 사용할 main 함수가 있는 C 파일
  • sum 함수가 정의되어 있는 C 파일

 include 파일은 아주 간단하게 만들 수 있다. include 파일의 이름은 sum.h 로 하겠다.
          int sum(int a, int b);
          

 이제 sum 함수가 정의되어 있는 C 코드를 만들어보자. 역시 간단하다. 파일이름은 sum.c로 하겠다.
          int sum(int a, int b)

          {

              return a + b;

          }
          

 마지막으로 main 함수를 만들어 보자. 파일이름은 calc.c 로 하겠다.
          #include "sum.h"

          #include <stdio.h>

          

          int main()

          {

              int value;

              value = sum(130, 199);

              printf("%d\n");

          }
          

헤더파일의 경로


 우리는 #include 키워드를 이용해서, 포함시킬 헤더파일을 지정할 수 있다. 이때 헤더파일의 완전한 경로를 포함시켜 줘야 한다. 만약 따움표를 사용했다면, 이는 현재 디렉토리에서 헤더파일을 찾겠다는 것을 의미한다. 그렇지 않고 <> 를 사용했다면, 표준 Include 디렉토리와 컴파일러 옵션을 통해서 지정된 디렉토리에서 찾게된다. 유닉스 시스템의 경우 /usr/include 가 표준 Include 파일이 된다.

 헤더파일을 찾을 경로의 지정은 -I옵션을 이용하면 된다. 예를 들어 /home/yundream/include 에서 찾도록 하길 원한다면
          # gcc -I/home/yundream/include -o sum sum.c
          

 와 같이 하면 된다.

 만약 /home/yundream/include 를 헤더파일 찾기 경로로 지정하고 싶다면, 다음과 같이 하면 된다.

          #include "/home/yundream/include"
          

모듈별 분할 컴파일


 자 이제 sum.h, sum,c, calc,c 3개의 파일이 만들어졌다. 이 3개의 파일을 컴파일해서 실행가능한 프로그램을 만들어보자.

 위에서 언급되었듯이 가장 먼저 해야할일은 sum.c 와 calc.c 를 기계어가 해석가능한 object 코드로 만드는 일이다. 오브젝트 코드는 gcc에 -c 옵션을 이용해서 만들어낼 수 있다.
          # gcc -c sum.c calc.c          

 이제 sum.o 와 calc.o 라는 파일이 만들어진걸 확인할 수 있을 것이다. 확장자 .o는 이 파일이 오브젝트 파일이라는 것을 알려준다. 이제 두개의 object 파일을 링크시켜서 실행파일을 만들면 된다. -o 옵션을 이용하면, 만들어진 오브젝트 파일들을 합쳐줄 수 있다.

          # gcc -o calc sum.o calc.o          

 이제 실행파일인 calc가 만들어졌다.

 이렇게 만들어진 object 파일은 기계어로 만들어져 있기 때문에, 이후에 사용할때는 sum.c를 다시 object 파일로 컴파일할 필요가 없다. 그냥 sum.o 프로그램에 링크시켜주기만 하면 된다. 다음과 같은 프로그램을 만들어보자. 프로그램의 이름은 mycal.c로 하자.

          #include "sum.h"

          #include <stdio.h>

          

          int main(int argc, char **argv)

          {

            int value;

            int a;

            int b;

            if (argc != 3)

            {

              printf("Usage : %s num1 num2\n", argv[0]);

              return 1;

            }

          

            a = atoi(argv[1]);

            b = atoi(argv[2]);

            value = sum(a, b);

            printf("%d + %d = %d\n", a, b, value);

            return 0;

          }          

 이 프로그램은 첫번째 프로그램보다 더 진보된 프로그램으로, 프로그램의 명령행 인자로 받아들인 숫자를 더할 수 있도록 되어 있다. atoi(3)는 문자열을 int형 숫자로 변환해주는 함수다. sum 함수는 이미 컴파일 되어서 object 파일로 만들어져 있으므로, 별도로 컴파일할 필요가 없다. 다음과 같은방법으로 실행파일을 만들 수 있다.

          # gcc -c mycal.c

          # gcc -o mycal sum.o mycal.o
          
          - sum.o라는 오브젝트 파일을 실행파일에 링크 시켜 놓은 것이다. 
          

4칙연산 프로그램


 위의 프로그램은 덧셈만을 지원하고 있다. 여기에 덧붙여 뺄셈, 나눗셈, 곱샘까지 지원하는 프로그램을 만들어 보도록 하자. 각각의 연산은 모두 함수로 작성되며, 각각의 함수가 헤더파일과 함수가 정의된 C 코드 파일을 가지게 될 것이다. 그렇다면, 이 프로그램은 4칙연산을 위한 4개의 함수와 4개의 헤더파일 1개의 main 함수를 포함하는 C 파일로 구성될 것이다.

  • 헤더파일 : sum.h, sub.h, mul.h, div.h
  • 함수정의된 C 파일 : sum.c, sub.c, mul.c, div.c
  • main 함수파일 : simplecal.c

 먼제 헤더파일을 작성해보자.

sum.h
          int sum(int a, int b);
          

sub.h
          int sub(int a, int b);
          

mul.h
          int mul(int a, int b);
          

div.h
          int div(int a, int b);
          

 이제 함수의 정의를 담고 있는 4개의 C 소스코드 파일을 만들어야 한다.

sum.c
          int sum(int a, int b)

          {

              return a + b;

          }
          

sub.c
          int sub(int a, int b)

          {

              return a - b;

          }
          

mul.c
          int mul(int a, int b)

          {

              return a * b;

          }
          

div.c
          int div(int a, int b)

          {

              return a / b;

          }
          

 이제 main 함수를 가진 코드를 만들면 된다.

          #include "sum.h"

          #include "sub.h"

          #include "mul.h"

          #include "div.h"

          

          int main(int argc, char **argv)

          {

             int a = 1200, b=25;

          

            printf("sum : %d\n", sum(a, b));

            printf("sub : %d\n", sub(a, b));

            printf("mul : %d\n", mul(a, b));

            printf("div : %d\n", div(a, b));

          }
          

 코드를 만들었다면, gcc를 이용해서 object를 만들고 이것들을 링크시켜서 실행파일로 만들면 된다.

          # gcc -c sum.c sub.c mul.c div.c simplecalc.c

          # gcc -o simplecalc sum.o sub.o mul.o div.o simplecalc.o
          

라이브러리


 이렇게 단위 함수를 별개의 소스코드와 헤더파일로 나누어서 관리하게 되면, object 혹은 단위 소스코드 파일을 재활용할 수 있다는 장점을 가진다. 그러나 여전히 불편한 점이 있다. 함수가 많아지면, 자칫 수십개의 오브젝트 파일이 생성될 수 있을건데, 이들을 관리하는건 매우 귀찮은 일이기 때문이다.

 그렇다면 4개의 object 파일을 하나로 묶을 수만 있다면, 함수들을 더 편리하게 관리할 수 있을 것이다. 이렇게 오브젝트들을 하나의 파일로 다시 묶은 것을 라이브러리(library)라고 한다.

 라이브러리는 다시 정적 라이브러리와 공유 라이브러리로 나뉜다.

- 정적 라이브러리는 실행파일에 완전히 포함되어버리는 형식의 라이브러리를 말한다.
- 공유 라이브러리는 실행파일에 포함되지 않고, 실행될때 해당 라이브러리를 불러오는 형식의 라이브러리를 말한다.


정적라이브러리

 static library라고 부르기도 한다. 이 라이브러리는 단순한 오브젝트의 모음일 뿐이다. 정적라이브러리는ar이라는 프로그램을 통해서 만들 수 있다. 그럼 ar을 이용해서 위의 사칙연산을 위한 4개의 오브젝트를 모아서 libmycalc.a라는 이름의 정적라이브러리를 생성해보도록 하자. rc 옵션을 이용하면, 정적라이브러리를 만들 수 있다.

 r은 정적라이브러리를 만들겠다는 옵션이고, c는 새로 생성을 하겠다는 옵션이다.
          # ar rc libmycalc.a sum.o sub.o mul.o div.o

 libmycalc.a 라는 파일이 생성된걸 확인할 수 있을 것이다. t 옵션을 이용하면, 해당 라이브러리가 어떤 오브젝트를 포함하고 있는지도 확인할 수 있다. t 옵션을 사용하면 된다. 참고로 정적 라이브러리의 이름은libNAME.a의 형식을 따라야 한다.

          # ar t libmycalc.a

          div.o

          mul.o

          sum.o

          sub.o

 그럼 정적라이브러리를 이용해서 실행파일을 만들어 보도록 하자. 이전에는 4개의 오브젝트 파일을 모두 링크시켜줘야 했지만, 이제는 libmycalc.a 만 링크시켜주면 된다.

 라이브러리의 링크방식은 오브젝트를 링크하는 것과는 약간 차이가 있다. library의 위치를 명확히 명시해 주어야 한다. 를 명시해-L 옵션을 이용해서 라이브러리가 있는 디렉토리의 위치주고, -l옵션을 이용해서, 라이브러리 파일의 이름을 정해줘야 한다. 다음은 simplecalc.c 를 정적라이브러리를 이용해서 컴파일하는 방법을 보여준다.

          # gcc -o simplecalc simplecalc.c -L ./ -l mycalc
          
- -L./은 현재 디렉토리를 라이브러리 찾기 디렉토리로 하겠다는 의미
- -l 옵션뒤에 붙이는 라이브러리 파일의 이름에 주목할 필요가 있다. 라이브러리 이름은 lib와 .a를 제외한 이름을 사용한다.


공유 라이브러리

 공유 라이브러리는 함께 사용하는 라이브러리라는 의미다. 즉 정적 라이브러리 처럼 실행파일에 붙는 것이 아니고, 시스템의 특정디렉토리에 위치하면서, 다른 모든 프로그램들이 공유해서 사용할 수 있게끔 제작된 라이브러리다. 그러므로 공유 라이브러리를 사용하도록 제작된 프로그램은 실행시에 사용할 라이브러리를 호출하는 과정을 거치게 된다.

 공유 라이브러리역시 오브젝트를 이용해서 만든다는 점에서는 정적라이브러리와 비슷하지만, 호출시에 링크하기 위한 부가적인 정보를 필요로 하므로, 정적라이브러리와는 전혀 다른 형태로 만들어 진다. 정적라이브러리와 이름이 헛갈릴 수 있으니, 라이브러리 이름은 mycalcso 로 하겠다.

          # gcc -fPIC -c sum.c sub.c mul.c div.c

          # gcc -shared -W1,-soname,libmycalcso.so.1 -o libmycalcso.so.1.0.1 sum.o sub.o mul.o div.o
          
  • 오브젝트 파일을 만들때 부터 차이가 있는데, -fPIC 옵션을 줘서 컴파일 한다.
  • 그다음 -shared 옵션을 이용해서 공유라이브러리 파일을 생성한다.

 위의 과정을 끝내고 나면, libmycalcso.so.1.0.1 이라는 파일이 생성이 된다. 이 라이브러리는 프로그램을 컴파일할때와 실행시킬때 호출이 되는데, 호출될때는 libmycalcso.so 를 찾는다. 그러므로 ln 명령을 이용해서 libmycalcso.so 링크파일을 생성하도록 하자.

          # ln -s libmycalcso.so.1.0.1 libmycalcso.so          

 이렇게 링크를 만들게 되면, 여러가지 버전의 라이브러리 파일을 이용할 수 있으므로 관리상 잇점을 가질 수 있다. 새로운 버전의 라이브러리가 나올 경우, 오래된 버전의 라이브러리를 쓰는 프로그램은 실행시 문제가 발생할 수 있는데, 이런 문제를 해결할 수 있기 때문이다.

 이제 링크하는 과정이 남았다. 링크과정은 정적 라이브러리를 사용할때와 동일하다.

          # gcc -o simplecalcso simplecalc.c -L ./ -l mycalcso        

 이제 프로그램을 실행시켜 보도록 하자. 아마 다음과 같은 에러메시지를 만나게 될 것이다.

          # ./simplecalcso

          ./simplecalcso: error while loading shared libraries: libmycalc.so: 

          cannot open shared object file: No such file or directory          

 이러한 에러가 발생하는 원인에 대해서 알아보도록 하자. 정적라이브러리는 실행파일에 라이브러리가 붙여지므로, 일단 실행파일이 만들어지면, 독자적으로 실행이 가능하다. 그러나 공유라이브러리는 라이브러리가 붙여지는 방식이 아니고, 라이브러리를 호출해서 해당 함수코드를 실행하는 방식이다. 그러므로 공유라이브러리 형식으로 작성된 프로그램의 경우 호출할 라이브러리의 위치를 알고 있어야만 한다.

 위의 simplecalcso 프로그램을 실행시키면, 이 프로그램은 libmycal.so 파일을 찾을 것이다. 이때 파일을 찾는 디렉토리는 /etc/ld.so.conf에 정의 되어 있다.

          # cat /etc/ld.so.conf

          /usr/lib

          /usr/local/lib          

 만약 위에서 처럼되어 있다면, 프로그램은 /usr/lib 와 /usr/local/lib 밑에서 libmycal.so 를 찾게 될 것이다. 그런데 libmycal.so 가 없으니, 위에서와 같은 에러가 발생하는 것이다.

 가장 간단한 방법은 라이브러리 파일을 ld.so.conf에 등록된 디렉토리중 하나로 복사하는 방법이 될 것이다. 혹은 환경변수를 이용해서, 새로운 라이브러리 찾기 경로를 추가할 수도 있다. 이때 사용되는 환경변수는LD_LIBRARY_PATH 다.

          # export LD_LIBRARY_PATH=./:/home/myhome/lib          

 이제 프로그램을 실행시키면 LD_LIBRARY_PATH 에 등록된 디렉토리에서 먼저 검색하게 되고, 프로그램은 무사히 실행 될 것이다.

공유라이브러리와 정적라이브러리의 장단점

 이들 2가지 라이브러리의 장단점에 대해서 알아보도록 하자. 장단점을 알게되면 어떤 상황에서 이들 라이브러리를 선택할 수 있을지 알 수 있을 것이다.

 정적라이브러리의 장점은 간단한 배포방식에 있다. 라이브러리의 코드가 실행코드에 직접 붙어버리는 형식이기 때문에, 일단 실행파일이 만들어지면 간단하게 복사하는 정도로 다른 컴퓨터 시스템에서 실행시킬 수 있기 때문이다. 반면 동적라이브러리는 프로그램이 실행될때 호출하는 방식이므로, 라이브러리까지 함께 배포해야 한다. 라이브러리의 호출 경로등의 환경변수까지 덤으로 신경써줘야 하는 귀찮음이 따른다.

 일반적으로 정적라이브러리는 동적라이브러리에 비해서 실행속도가 빠르다. 동적라이브러리 방식의 프로그램은 라이브러리를 호출하는 부가적인 과정이 필요하기 때문이다.

 정적라이브러리는 실행파일 크기가 커진다는 단점이 있다. 해봐야 얼마나 되겠느냐 싶겠지만, 해당 라이브러리를 사용하는 프로그램이 많으면 많을 수록 X 프로그램수만큼 디스크 용량을 차지하게 된다. 반면 공유라이브러리를 사용할 경우, 라이브러리를 사용하는 프로그램이 10개건 100개건 간에, 하나의 라이브러리 복사본만 있으면 되기 때문에, 그만큼 시스템자원을 아끼게 된다.

 마지막으로 버전 관리와 관련된 장단점이 있다. 소프트웨어 개발 세계의 불문율이라면 버그 없는 프로그램은 없다이다. 어떠한 프로그램이라도 크고작은 버그가 있을 수 있으며, 라이브러리도 예외가 아니다.

 여기 산술계산을 위한 라이브러리가 있다. 그리고 정적 라이브러리 형태로 프로그램에 링크되었어서 사용되고 있다고 가정해보자. 그런데 산술계산 라이브러리에 심각한 버그가 발견되었다. 이 경우 산술계산 라이브러리를 포함한 A 프로그램을 완전히 새로 컴파일 해서 배포해야만한다. 문제는 이 라이브러리가 A 뿐만 아니라 B, C, D 등의 프로그램에 사용될 수 있다는 점이다. 결국 B, C, D 프로그램 모두를 새로 컴파일 해서 배포해야 하게 된다. 더 큰 문제는 어떤 프로그램이 버그가 있는 산술계산 라이브러리를 포함하고 있는지 알아내기가 힘들다는 점이다.

 공유라이브러리 형태로 작성하게 될경우에는 라이브러리만 새로 컴파일 한다음 바꿔주면된다. 그러면 해당 라이브러리를 사용하는 프로그램이 몇개이던간에 깔끔하게 문제가 해결된다.

 실제 이런 문제가 발생한 적이 있었다. zlib 라이브러리는 압축을 위한 라이브러리로 브라우저웹서버, 압축관리 프로그램등에 널리 사용된다. 많은 프로그램들이 이 zlib를 정적라이브러리 형태로 포함해서 배포가 되었는데, 심각한 보안문제가 발견되었다. 결국 zlib를 포함한 모든 프로그램을 새로 컴파일해서 재 설치해야 하는 번거로운 과정을 거치게 되었다. 공유라이브러리였다면 문제가 없을 것이다.

 이상 정적라이브러리와 공유라이브러리를 비교 설명했다. 그렇다면 선택의 문제가 발생할 것인데, 자신의 컴퓨터나 한정된 영역에서 사용할 프로그램을 제작하지 않는한은 공유라이브러리 형태로 프로그램을 작성하길 바란다. 특히 인터넷을 통해서 배포할 목적으로 작성할 프로그램이라면, 공유라이브러리 형태로 작성하는게 정신건강학적으로나 프로그래밍 유지차원에서나 좋을 것이다.



출처 - http://kwonhanseung.blogspot.kr/2012/11/cc-12.html





'Development > Linux Programming' 카테고리의 다른 글

linux prog - intro  (0) 2013.10.03
linux prog - linux startup  (0) 2013.10.03
Posted by linuxism
,