본문 바로가기
카테고리 없음

System Programming (Linux)

by winter_sunshine 2023. 9. 11.

여러분 ~ 벌써 9월이네요. 무더운 여름은 가고, 선선한 가을이 찾아오고 있습니다~

그 말은 2023년이 얼마 남지 않았다는 이야기겠죠..?

다들 개강을 하셨을텐데 의미있는 2학기가 되길 바라겠습니다!

 

여러분들을 오랜만에 찾아뵈었는데요. 이번 시간부터는 Operating System 시간에 다룬 개념들을 바탕으로

Linux 운영체제의 여러 가지 요소들에 대한 서비스를 프로그래밍으로

직접 제어하는 기술을 다루는 것을 목표로 나아갈 예정입니다.

왜 키워드가 "시스템 프로그래밍" 인 지, 다들 눈치채셨나요?

네 맞습니다. OS에서 다뤘던 '시스템 호출'과 같이 시스템에 연관된 프로그래밍을 중점적으로 다룰 예정이라,

"시스템 프로그래밍"이라는 키워드로 설명하였습니다. 

그럼 시작하겠습니다~


※ 실습환경

1.  VMware (가상 머신)

2.  Ubuntu Linux (우툰부 리눅스 운영체제)

 

 

※ 블로그 참고자료

도서명:   시스템프로그래밍 리눅스&유닉스

저자:       이종원

출판사:    한빛아카데미


 

1.   리눅스/유닉스  란?

  • 리눅스 & 유닉스
    • '서버용 운영체제'로 주로 사용
    • 최근엔 원조격이라고 할 수 있는 유닉스를 리눅스가 서버 운영체제 시장에서 밀어냄
    • 금융권에서는 유닉스 시스템을 리눅스 시스템으로 대체하는 U2L이 확산
  • 유닉스의 주요 표준
    • ANSIC 표준
      • 미국 표준 협회로, 국제적으로 영향력 있는 표준을 정함
      • ANSI에서 표준화한 C 언어 명세가 ANSI C 표준으로, C 언어 문법과 라이브러리, 헤더 파일 등을 정의
    • POSIX
      • 유닉스에 기반을 두고 있는 표준 운영체제 인터페이스
      • 서로 다른 유닉스 시스템 사이에서 상호 이식이 가능한 응용 프로그램을 개발하기 위해 정해진 표준
      • IEEE에서 정의한 규격으로, 유닉스 시스템의 공통 응용 프로그래밍 인터페이스를 정리
    • 단일 유닉스 명세 (SUS)
      • 운영체제가 유닉스라는 이름을 사용하기 위해 지켜야 하는 표준의 총칭
      • IEEE, ISO(JTC 1 SC22), 오픈 그룹의 표준화 작업결과물에 바탕을 두고 있으며 오스틴 그룹이 개발 및 유지·관리를 담당
      • 1980년대 중반부터 시작된 유닉스의 시스템 인터페이스를 표준화하기 위한 프로젝트에서 출발
    • 시스템 V 인터페이스 정의 (SVID)
      • AT&T 유닉스 시스템 V의 인터페이스를 정의
      • 프로그램과 장치에서 이용할 수 있는 시스템 호출과 C 라이브러리에 관한 표준을 포함
      • POSIX나 X/Open 작업은 부분적으로 SVID에 기반
      • 1995년에 발표된 SVID 버전 4는 XPG4 및 POSIX 1003.1-1990과 호환성을 유지
      • SVID는 POSIX와 단일 유닉스 명세에 포함되면서 중요도가 떨어짐

 

2.   '시스템(System)' 이란?

  • 리눅스, 유닉스와 같은 "운영체제(Operating System)"를 의미
  • "운영체제"는 하드웨어 리소스를 관리하고 응용 프로그램을 실행하기 위한 환경을 제공

 

3.   '시스템 호출' (System Call)  이란?

  • 시스템이 제공하는 서비스를 프로그램에서 이용할 수 있도록 지원하는 '프로그래밍 인터페이스'를 의미
  • 사용자 모드( user mode ) 에서 커널 모드( Kernel mode)로  '모드 변경 (mode change)' 를 의미.

    ※ 리눅스/유닉스에서 동작하는 프로그램을 작성하려면 간단한 프로그램을 제외하고 대부분 '시스템 호출'을 이용

 

4.  '시스템 호출 함수'  란?

  • '시스템 호출(system call)'지원해주는 함수
    • 시스템 호출 함수 내부 에는 '시스템 호출 코드'가 존재
  • 쉘에서 man 명령어를 입력했을 때, 섹션 번호'2' 인 함수
    • ex) fork(), open(), access(), pipe() ... 등
      • man 명령으로 검색하면 섹션 번호가 가장 낮은 것이 기본으로 출력됨
      • man 명령의 결과를 출력하는 형식리눅스와 유닉스에서 차이가 있음
  • 사용 예시
    • 리턴값 = 시스템 호출 함수명(인자,  ... );

 

5.   '라이브러리'  & '라이브러리 함수'   란?

  • '라이브러리'
    • 미리 컴파일된 함수를 묶어서 제공하는 특수한 형태의 파일
    • 리눅스 시스템에서 라이브러리는 보통 /user/lib에 위치
    • '정적 라이브러리'
      • 프로그램을 컴파일할 때 같이 적재되어 실행 파일을 구성
    • '공유 라이브러리'
      • 실행 파일에 포함되지 않아 메모리를 효율적으로 사용하기 위해 사용
  • '라이브러리 함수'
    • '라이브러리'에 포함된 함수
    • 쉘에서 man 명령어를 입력했을 때,섹션 번호가  '3' 인 함수

 

6.  시스템 프로그래밍  vs   C 응용 프로그래밍   

  • 시스템 프로그래밍
    • 시스템 호출 함수(섹션 2번)를 사용하여 코딩하는 것
  • C 응용 프로그래밍
    • 라이브러리 함수(섹션 3번)를 사용하여 코딩하는 것

 

[예제 1-1]  시스템 호출의 오류 처리하기

 

시스템 호출 함수: access()
실행 결과

  • 위 예제의 관전 Point
    • "extern" 키워드를 사용하여 errno라는 시스템 변수 (전역 변수)를 선언하였기 때문에
      • errno 시스템 변수를 메모리에 할당 X
      • #include <errno.h> 헤더 파일을 적용
    • 시스템 호출 함수access()를 통해 시스템 호출을 진행
      •  시스템 호출 함수를 사용하기 위해서 #include <unistd.h> 헤더 파일을 적용
      • access()가 정상 작동하면  0을 반환,  오류 발생 시  -1 을 반환
      • 오류가 발생되면, 해당 오류에 맞는 오류코드를 errno 변수에 설정
        • ex) 파일을 찾을 수 없는 경우 (존재 X) =>  오류코드(errno 값)는  '2  (mode 종류는 상관없음)
        • 오류코드(errno 값)의 의미를 해석하려면
          • 리눅스asm-generic/errno-base.h 파일에 정의되어 있고
          • 유닉스sys/errno.h 파일에 정의
    • int access(const char *pathname,  int mode)
      • pathname : 파일 또는 디렉토리의 경로
      • mode : 접근 확인 모드
        • F_OK : 파일이 존재하는지 확인
        • R_OK : 읽기 권한이 있는지 확인
        • W_OK : 쓰기 권한이 있는지 확인
        • X_OK : 실행 권한이 있는지 확인

 

[예제 1-2]   라이브러리 함수의 오류 처리하기

라이브러리 함수: fopen()
실행 결과

  • 위 예제의 관전 Point
    • 라이브러리 함수fopen()을 통해 오류를 처리
    • FILE,  fopen()을 사용하기 위해  #include <stdio.h> 헤더파일 적용
    • 오류 메세지를 출력하는 방식 2가지 존재
      1. strerror()를 통해 오류코드(errno)를 오류메세지로 변환
        • strerror()는 ANSI C에서 추가로 정의한 함수
        • 함수의 인자로 errno에 저장된 값을 받아 오류 메시지를 리턴
        • 리턴된 오류 메시지를 사용자가 적절하게 가공할 수 있다는 장점
        • strerror()은 라이브러리 함수,  #include <string.h>
      2. perror()를 통해 다이렉트로 오류메세지를 출력
        • perror() 함수는 errno에 저장된 값을 읽어 이에 해당하는 메시지를 표준 오류(파일 기술자 2번)로 출력
        • perror() 함수의 인자로는 일반적으로 프로그램 이름을 지정하는 것이 좋음
        • perror()은 라이브러리 함수,   #include <stdio.h>

 

7.  메모리(Heap) 할당 :  malloc()

  • malloc() 함수의 특징
    • 인자로 지정한 크기의 메모리를 할당하는 데 성공하면 메모리의 시작 주소를 리턴
    • 만약 메모리 할당에 실패하면 NULL 포인터를 리턴
    • 인자로 지정하는 메모리 크기는 바이트 단위
    • 할당된 메모리에는 어떤 형태의 데이터도 저장할 수 있음
    • malloc() 함수는 할당된 메모리를 초기화하지 않는다는 데 주의

 

8.  메모리(Heap) 할당 : calloc()

  • calloc() 함수의 특징
    • nmemb × size 바이트 크기의 배열을 저장할 메모리를 할당
    • 할당된 메모리를 0으로 초기화
  • 요소가 10개이고 각 요소의 크기가 20바이트인 배열을 저장할 수 있는 메모리를 할당 하는 예

 

 

9.  메모리(Heap) 추가 할당  :  realloc()

  • realloc() 함수의 특징
    • 이미 할당받은 메모리에 추가로 메모리를 할당할 때 사용
    • 이전에 할당받은 메모리와 추가할 메모리를 합한 크기의 메모리를 새롭게 할당하고 주소를 리턴
    • 이때 이전 메모리의 내용을 새로 할당된 메모리로 복사
  • malloc() 함수로 할당받은 메모리에 추가로 100바이트를 할당하는 예

 

 

10.  메모리 해제 : free()

  • free() 함수의 특징
    • 사용을 마친 메모리를 해제하고 반납
    • free() 함수가 성공하면 ptr이 가리키던 메모리는 더 이상 의미가 없음

 

 


지금까지 1장 "시스템 호출과 라이브러리" 에 대해 알아봤습니다.

다음 시간에는 6장 "프로세스 정보" 에 대해 알아 볼 예정입니다.

감사합니다~! 좋은 하루 되세여 ㅎㅎ