Python Library/오픈 소스 프로그래밍

[오픈소스 프로그래밍] Unix, Linux에 대한 소개

바보1 2022. 4. 18. 18:40

Linux에 대해 알기 전에 Unix OS에 대해 먼저 알아야 합니다.

Unix의 특징으로는

  • 다양한 종류의 시스템 사이에서 서로 이식할 수 있음
  • 다중 사용자 및 다중 작업을 지원

Unix 시스템의 개념으로는 

  • 일반 텍스트 파일
  • 명령줄 인터프리터
  • 계층적인 파일 시스템 (트리 구조)
  • 장치 및 특정한 형식의 프로세스 간 통신을 파일로 취급 -> 통일을 시킴으로써 개발하기 좋음

초기의 Unix는 서버에 쓰는 OS였습니다.

 

이러한 유닉스는 아래와 같은 형태로 발전되어 왔습니다.

 

유닉스의 역사

 

이처럼 유닉스는 처음에는 서버 같은 중형 컴퓨터에 사용하도록 고안이 되었으며, 여러 가지 유틸리티가 공개되면서 일반 사용자들에게 확산되었습니다.

다중 사용자, 다중 작업이 가능하고 프로그램 개발이 쉬운 운영체제인 덕분에 대부분의 통신 서비스 프로그램은 unix를 기반으로 하고 있습니다.


1. Unix의 종류와 특성

 

 

1.1 Linux

 

엄밀하게 말하면 리눅스라는 용어는 리눅스 커널만을 뜻하지만, 리눅스 커널과 GNU 프로젝트의 라이브러리와 도구들이 포함된, 전체 운영체제를 나타내는 말로 흔히 쓰입니다.

유닉스와 리눅스는 둘 다 OS입니다.

리눅스는 유닉스에서 파생된 운영체제이고, 리눅스는 유닉스와 다르게 리눅스 OS 소스코드를 무료로 배포했다는 점입니다.

 

대표적인 리눅스 배포판으로는 Ubuntu, Radhat, debian 등이 있습니다.

 

Linux의 특징으로는

  • 소스코드가 공개돼 있어 개발자가 원하는 대로 특정 기능을 추가할 수 있음
  • 어느 플랫폼에도 포팅(porting)이 가능
  • 무료

 

1.2 Mac OS

 

Apple 컴퓨터의 운영체제로 개인용 컴퓨터에 GUI를 처음으로 도입함

특징으로는

  • 문서 편집이나 그래픽 분야에서 많은 사랑을 받고 있음
  • Apple의 스마트폰인 iPhone, iPad등에도 내장되어서 사용

 

1.3 Solaris

 

Unix 계열 운영체제 중 하나이고, Linux보다 훨씬 먼저 출시된 상용 운영체제입니다.

특징으로는

  • 처음에는 SUN에서 제작한 CPU를 사용한 기종에서만 사용되는 전용 운영체제로 전문가들이 주로 사용
  • 인텔 아키텍처의 대량 보급으로 인하여 인텔용 Solaris도 출시됨

 

1.4 모바일 운영체제

 

리모, 삼성 바다가 있지만, 가장 친숙한 안드로이드 (Android)가 있습니다.

앱은 누구나 만들 수 있지만, 정말로 전문가가 되고 싶다면 Linux 커널도 할 줄 알아야 합니다.

 

 


2. GNU

 

GNU Project는 대표적인 오픈 소스 프로젝트입니다.

컴퓨터 사용자가 많아지면서 상업용 목적 소프트웨어들의 라이선스 비용에 반대합니다.

free software : 누구나 소프트웨어의 복사, 사용, 연구, 수정, 배포 등에 제한이 없음

 

GNU는 GNU is Not Unix의 약자로

unix의 기능을 포함하고 있지만, unix code를 포함하지 않습니다. 즉 직접 다 만들었다는 얘기입니다.

커널 부분을 제외한 모든 주요 구성 요소를 개발하였고, 이후 리누스 토발즈가 리눅스 커널을 개발하여 발표했습니다.

 

GNU의 라이선스 정책으로는 

  • GPL (GNU General Public License) -> 무조건 싹 다 공개해야 함
  • LGPL (GNU Lesser GHeneral Public License) -> GPL보다는 조금 약화

가 있습니다.

 


3. UNIX의 시스템 구조

 

 

유닉스의 시스템 구조는 아래와 같습니다.

  • Hardware : CPU, Memory, Disk, Peripherals (각종 주변 장비들 통신, 시리얼....)
  • Kernel
    • Process management
    • File management
    • Memory management
    • Devide management
  • System call
    • 개발자와 유닉스 커널의 인터페이스입니다.
  • Commands, Utilites, Application programs
    • kernel services using library routines or system clal

커널은 하드웨어와 딱 붙어서 실행합니다. 따라서 섬세하고 아주 조심스러운 작업을 해야 하고, 누구나 쉽게 접근하면 안 됩니다. 

누군가가 내 메모리나 CPU에 침범해서 정보를 빼간다면 그건 아주 큰 문제가 됩니다.

따라서 커널은 system call, shell, library routines 등 몇 개의 큰 겹으로 쌓여 있습니다.

 

시스템 콜은 사용자가 하드웨어를 사용해야 할 때 시스템 함수를 직접 호출할 수 없으므로, 사용자가 커널에게 요청하는 인터페이스입니다.

 

어떤 응용 프로그램에서 시스템 호출을 해야할 때, library routines에 따라서 라이브러리에 있는 시스템 호출을 불러야 합니다. -> User Mode

이때 라이브러리에 있는 시스템 호출은 system call을 통하여 커널에 부탁합니다. -> Kernel Mode

 

간단하게 넘어가지만 자세한 내용은 운영체제 카테고리에서 다루겠습니다.

 

 

유닉스의 커널은 Monolithic Kernel Module입니다.

User의 아래에 Libraries, Commands, Shell 등등이 있고, 그 아래에 System Call, 그 아래에 Trap Table이 있는데 아무튼 중요한 건

하나의 커널을 쓴다는 뜻입니다.

 

다른 커널 모듈로는 Micro Kernel이 있습니다. 차이점은 다음과 같습니다.

Micro가 최신 기술이기는 하나, 많이 안 씁니다. 용량이 적어서 서버나 임베디드 같은 곳에서 많이 사용합니다.

 

이것도 자세한 내용은 운영체제에서 다루겠습니다.

 


4. Unix의 명령어

 

 

명령어에 대해 알기 전에 Unix 파일의 디렉터리 구조를 알아야 합니다.

디렉터리 구조는 아래와 같습니다.

home 디렉터리는 사용자의 디렉터리이고 나머지는 시스템의 디렉터리입니다.

 

파일 이름은 250 개수 이하여야 하며, '/'를 제외한 어떤 특수문자도 안 됩니다.

 

 

이러한 디렉터리, 파일에 작업하는 명령어에 대해 알아보겠습니다.

 

 

4.1 디렉토리 명령어

 

  • ls - 현재 디렉터리의 구성 요소를 알려줍니다.
  • pwd - 현재 디렉토리의 경로를 알려줍니다.
  • mkdir, rmdir - 디렉터리를 만들거나, 디렉토리를 삭제함
    • rmdir file1 file2를 통해 여러 폴더를 삭제, rmdir -p filename을 통해 하위 폴더까지 삭제
  • cd - 현재 위치를 다른 디렉터리로 바꿈
    • cd/test -> test 디렉터리로 이동, cd .. -> 상위 디렉토리로 이동, cd -> home 디렉토리로 이동

 

4.2 파일 명령어

 

  • vi filename - 파일을 만들거나 수정함
    • i - input mode
    • esc - command mode
    • :wq - write and quit
  • cat - 파일의 콘텐츠를 설명 (출력)
  • cp - 파일을 복제함
    • cp file.txt newfile.txt
  • mv - 파일의 이름을 변경하거나 경로를 바꿈
    • mv filename filename -> rename
    • mv filename directory -> move
  • ls -al - 숨겨진 파일들까지 포함하여 자세한 설정까지 보여줌
  • rm finame - 파일을 삭제함
  • rm -r directory - 디렉터리까지 포함하여 파일 혹은 디렉터리를 삭제함
    • 보통 강제로 디렉터리와 하위 폴더, 파일까지 다 삭제하면 rm -rf directory를 사용함

 

4.3 Tree 명령어

 

  • du - disk usage에 대한 현황을 보여줌, 특정 디렉터리를 기준으로 디스크 사용량 확인
  • find - 파일을 찾아주는 명령어
    • find -> 현재 디렉터리에서만, find . -name "filename" -> 현제 디렉토리 아래 모든 파일 및 디렉토리 검색
    • find / -name "filename" -> 전체 시스템 중 특정 파일을 검색
  • sudo fdisk -l - 디스크 파티션 테이블을 만들거나 조작
  • df - 이때 디스크의 용량을 체크함, 리눅스 시스템 전체의 디스크 사용량 확인

 

 

4.4 Linux Manual

 

  • man man - 리눅스의 매뉴얼을 보여줌
    • man df -> df의 매뉴얼을 보여줌
    • man -k file -> man에서 keyword file을 가지는 애를 찾음
  • grep - 패턴과 매칭 되는 줄을 출력함
    • man -k file | grep read -> man 페이지에서 file의 키워드를 가지는 애를 찾고, 거기서 read와 매칭되는 줄을 출력함

 

4.5 Process 명령어

 

  • ps - 현재 사용하고 있는 프로세스를 출력함
    • ps -la, ps -a
  • kill -9 pid# - pid# 을 강제 종료함
  • top - 프로세스가 실행하고 있는 실제 시간을 알려줌, 시스템의 상태를 전반적으로 알려준다.

kill이 좀 중요하긴 한데 자세한 내용은 다음의 쉘 프로그래밍에서 알려드리겠습니다.

 


5. GNU에서의 C 프로그래밍

 

 

Unix에서는 vi / vim으로 코드를 작성하고, CC (C Compiler), GCC (GNU Compiler Collection)를 통해서 컴파일합니다.

 

fred.c, bill.c라는 파일이 있다고 가정합시다.

gcc -c bill.c fred.c를 쓰면 bill.o, fred.o가 생성됩니다.

 

오브젝트 파일은 기계가 읽을 수 있는 언어로 변환이 된 파일입니다.

 

이때 gcc -o mypgm bill.o fred.o를 통하여 오브젝트 파일을 실행 가능한 파일로 변환할 수 있습니다.

 

이후 실행하기 위해서는 ./mypgm을 쓰면 됩니다.

 

자세한 예시는 나중에 보여드리겠습니다.

 

5.1 Make

 

Make는 파일 관리 유틸리티입니다.

파일 간의 종속 관계를 파악하여 기술 파일 (Makefile)에 적힌 대로 컴파일러에 명령합니다.

 

장점 : 각 파일에 대한 반복적 명령 자동화로 시간 절약, 프로그램 종속 구조를 빠르게 파악 가능 -> 관리가 용이하고 단순 반복 작업 및 재작성, 재빌드를 최소화함

 

Makefile에 대한 예시는 나중에 보여드리겠습니다.

 

Make는 우선 해당 파일이 최신인지 체크합니다.

만약에 수정 사항 없이 make를 통해 빌드하면 명령어를 수행하지 않습니다.

하지만 만약에 수정 사항이 생기면 수정된 파일만 다시 빌드합니다.

 

또한 재빌드를 최소화하기 위해 몇몇 다른 버전의 실행 파일도 만들 수 있습니다.

 

기본적인 문법은 라인의 첫 시작에 tab을 쓰면 안 된다는 것이고, 라인의 끝에서 계속 문장을 이어나가고 싶다면 \를 입력, 만약 comment line을 쓰고 싶다면 앞에 #을 붙이면 됩니다.

 

 

5.2 Macros

 

매크로는 쓰면 더 편해집니다.

예를 들어 매크로를 정의할 때 name = hello world를 하면 되고, ${name}을 쓰면 참조해서 hello world를 출력합니다.

 

이때 내부 매크로로는 $@, $?이 있는데, 자세한 내용은 쉘 프로그래밍에서 알려드리겠습니다.

 


6. Debugging with GDB (GNU Debugger)

 

 

소스코드 디버거는 semantic(run-time)한 에러를 찾아냅니다.

이것은 syntax(compile-time) 에러에는 사용되면 안 됩니다.

 

디버깅 순서는 다음과 같습니다.

  1. Setting break-points : 프로그램을 잠시 중지할 체크 포인트를 세팅합니다. 이후 그 포인트에서의 값과 결과가 출력됩니다.
  2. Displaying program vaues and attributes : 프로그램 실행에 따른 현재의 값을 보여줍니다.
  3. Step line-by-line : 프로그램을 라인별로 실행합니다.

 

이때 디버깅 옵션을 쓰기 위해서는 우선적으로 컴파일할 때 에러가 없어야 합니다.

이후 컴파일 에러가 없는 것이 확인되면 다시 한번 '-g' 컴파일러 명령과 함께 다시 컴파일합니다.

ex) gcc -g source_code_file.cpp

-g 옵션은 컴파일러가 gdb가 디버깅을 하는 동안 필요한 데이터의 특별한 파일 / 테이블을 만듭니다.

 

컴파일이 정상적으로 됐으면 gdb를 통해 디버깅할 수 있습니다.

ex) gdb executable_file

그리고 gdb 프롬프트는 현재 사용자가 gdb 환경에 있다는 것을 보여주고, 오로지 gdb의 명령어만 사용할 수 있습니다.

UNIX의 명령어는 사용할 수 없습니다.

 

만약에 중간에 프로그램을 중지하고 싶다면 ctrl-c를 누르면 됩니다.

그러면 어떤 라인이 실행이 되었는지, 변수의 값들은 어떤지를 확인할 수 있습니다.

 

다시 프로그램을 실행하고 싶다면 cont를 입력하여 다시 실행할 수 있습니다.

 

gdb 디버거를 나가고 싶다면 quit를 입력하면 됩니다.

 

gdb 환경 안에서 help를 입력하면 다양한 정보를 얻을 수 있습니다.

 

 

6.1 구체적인 디버거 순서

 

  1. 실행 파일에 gdb를 넣기 위해서는 -g 옵션을 쓰면 됩니다.
  2. gdb에 "break main" 명령어를 작성합니다. main에서 멈추기 위해서, 보통은 [함수명]을 적어도 됨
  3. "run" 명령어를 작성하면 main을 만나면 프로그램이 잠시 중지됩니다.
  4. "step", "next" 명령어를 사용하면 프로그램이 다시 실행됩니다. 이때 중요한 점은 "step"은 함수의 호출 안으로 들어가고, "next"는 함수의 호출을 뛰어넘습니다.
  5. "print var_name" 명령어를 사용함으로써 해당 변수의 값을 볼 수 있습니다.

 

 

감사합니다.

 

 

 

지적 환영합니다.