시스템 프로그래밍
커널 및 핵심 시스템 라이브러리로 개발을 합니다. 라이브러리를 통해 하위 레벨에서 동작하는 시스템을 개발합니다. 이 때 시스템 소프트웨어를 작성하는 기술을 시스템 프로그래밍이라 합니다.
시스템 콜
운영체제에 리소스나 서비스를 요청합니다. 이 때 사용자 영역에서 커널 내부로 들어가는 함소 호출을 시스템 콜이라 합니다. read(), write()와 같은 익숙한 함수뿐만아니라 get_narea(), set_tid_address() 같은 생소한 함수도 있으며 매우 다양한 편입니다.
C 라이브러리
유닉스 애플리케이션의 핵심은 바로 C 라이브러리입니다. 기본 C 라이브러리 뿐 만 아니라 시스템 콜에 대한 래퍼와 스레드 지원, 기본 애플리케이션 기능에 대한 내용도 포함하고 있습니다.
C 컴파일러
리눅스는 표준 c 컴파일러로 gnu 컴파일러 컬렉션을 제공하는데, 원래 gcc는 c 컴파일러인 cc의 gnu 버전이었습니다.
api와 abi
시스템 레벨에서 보면 호환성에 영향을 주는 2가지 내용이 있는데, 바로 api와 abi이다. 둘다 서로 다른 컴퓨터 소프트웨어 간의 인터페이스를 정의하고 기술합니다.
API
소프트웨어의 소스코드 레벨에서 서로 인터페이스 하는 방식을 정의합니다. Api의 표준 인터페이스는 함수이면 상위 레벨의 소프트웨어에서 더 하위 레벨의 소프트웨어를 호출할 수 있습니다.
ABI
Abi는 특정 아키텍처 간에서 동작하는 소프트웨어 간의 바이너리 인터페이스를 정의합니다. Abi는 애플리케이션 내에서의 상호 동작, 커널과 애플리케이션, 혹은 애플리케이션과 라이브러리 간의 상호 동작에 대해서 정의합니다.
표준
리눅스는 가장 중요하고 유력한 표준인 posix와 sus 호환을 지키려고 노력합니다. Posix와 sus는 특히 유닉스 호환 운영체제 인터페이스를 위한 c api를 명세하고 있는데 실질적으로 이 표준은 시스템 프로그래밍 혹은 최소한 유닉스 호환 시스템상에서의 시스템 프로그래밍에 대한 공통 부분을 기술하고 있습니다.
파일과 파일 시스템
파일은 리눅스에서 가장 기본적이고 핵심이 되는 추상화 개념입니다. 파일 디스크립터는 사용자 영역에서 공유되며 응용 프로그램이 파일에 접근할 때 직접 사용합니다. 리눅스 시스템 프로그래밍 대부분은 바로 이 파일 디스크립터를 열고 조작하고 닫는 작업입니다.
일반 파일
우리가 흔히 파일이라고 부르는 것은 일반 파일을 의미합니다. 파일 오프셋은 커널이 열린 파일마다 유지하는 메타데이터의 핵심입니다. Inode는 유닉스 파일 시스템에서 디스크에 저장된 물리적인 객체임과 동시에 리눅스 커널에서 자료구조로 표현되는 논리적인 개념입니다.
디렉터리와 링크
디렉터리는 파일에 접근하기 위한 이름을 제공하는 데 디렉터리는 inode 대신에 사람이 읽을 수 있는 이름으로 나타낸다.
하드 링크
지금까지 살펴본 바로는 다른 이름으로 동일한 inode를 가리키지 못하게 하는 방법은 없었습니다. 하드 링크는 복잡한 파일시스템 구조에서 동일한 데이터를 여러 경로 이름이 가리킬 수 있게 허용합니다.
심벌릭 링크
하드 링크가 다른 파일 시스템으로 확장되지 못하는 이유는 inode가 속한 파일시스템 외부에서는 inode 번호가 무의미하기 때문입니다. 유닉스 시스템은 여러 파일시스템에 걸쳐 사용할 수 있도록 좀 더 단순하지만 덜 투명한 링크인 실벌릭 링크를 제공합니다.
특수 파일
특수 파일은 파일로 표현되는 커널 객체입니다. 블록 디바이스 파일, 캐릭터 디바이스 파일, 네임드 파이프, 유닉스 도메인 소켓이 그 4가지입니다.
파일 시스템과 네임 스페이스
다른 유닉스 시스템과 마찬가지로 리눅스 파일과 디렉터리를 나타내기 위한 통합된 전역 네임스페이스를 제공합니다.
네임스페이스에서 정해진 장소를 마운트 포인트라고 하며 개별 파일 시스템은 여기에 마운트 됩니다. 마운트된 파일 시스템은 여기에 마운트 됩니다.
프로세스
프로세스는 실행 중인 오브젝트 코드를 말하는 데 언제나 활성화 상태로 실행 중인 프로그램입니다. 프로세스를 오브젝트 코드라 말했지만 정확히는 단순한 오브젝트 코드를 넘어 데이터, 리소스, 상태, 가상화된 컴퓨터를 포함합니다. 커널은 동작 중인 모든 프로세스가 시스템 프로세서를 공유하도록 빈틈없고 투명하게 프로세스를 선점하고 스케줄링합니다.
스레드
각 프로세스는 실행 스레드를 하나 이상 포함합니다. 스레드는 프로세스 내부에서 실행하는 활동 단위이며, 코드를 실행하고 프로세스 동작 상태를 유지하는 추상 개념입니다. 스레드는 스택, 프로세서 상태, 오브젝트 코드의 현재 위치를 포함합니다. 기타 프로세스에 남아 있는 대부분의 리소스는 모든 스레드가 공유합니다.
프로세스의 계층 구조
리눅스에서 프로세스는 프로세스 트리라는 엄격한 계층 구조를 형성합니다. 프로세스 트리는 init 프로그램으로 알려진 첫 번째 프로세스가 루트가 됩니다. 새로운 프로세스는 fork() 시스템 콜로 만들어 집니다. 뷰모 프로세스가 먼저 종료되면 커널은 고아가 된 자식 프로세스를 init 프로세스에 입양시킵니다. 프로세스가 종료되면 시스템에서 바로 제거되지 않고 프로세스 일부를 메모리에 계속 유지해서 자식 프로세스가 종료될 떄 부모 프로세스가 상태를 검사할 수 있도록 합니다. 프로세스가 종료되었는데 기다리는 부모 프로세스가 없다면 이떄 좀비가 탄생합니다.일상적으로 init프로세스는 자기에게 딸린 자식 모두를 기다려서 새로 입양된 프로세스가 영원히 좀비로 남지 않도록 보살핍니다.
사용자와 그룹
리눅스에 권한은 사용자와 그룹 형태로 제공합니다. Uid는 고유한 양수 값이며 사용자를 구분합니다. 프로세스마다 자신을 실행하는 사용자가 누구인지 파악하는 용도라 uid가 하나 붙으며 이를 프로세스의 실제 uid라고 합니다.
권한
리눅스의 표준 파일 접근 권한과 보안 메커니즘은 전통적인 유닉스와 동일합니다. 파일마다 소유자, 소유자 그룹, 그리고 세 가지 접근 권한 비트가 입니다. 이 비트는 소유자, 소유자 그룹, 그외 모든 사용자가 파일을 읽고 쓰고 실행하는 능력을 기술합니다. 리눅스는 전통적인 유닉스 접근 권한 이외에 acl도 지원합니다. Acl은 복잡하고 저장 공간을 많이 차지하지만, 좀더 상세하고 정확한 접근 권한과 보안 제어 기능을 제공합니다.
시그널
시그널은 비동기식 단방향 알림 메커니즘입니다. 커널에서 프로세스로, 프로세스에서 다른 프로세스로, 아니면 프로세스 자기 자신에게 시그널을 보낼 수 있습니다. 일반적으로 시그널은 세그멘테이션 폴트나 사용자가 Ct기+c를 누르는 경우와 같이 프로세스에 특정 사건이 발생했음을 알려줍니다.
프로세스간 통신
프로세스 사이에서 일어나는 정보 교환과 알림은 운영체제가 담당하는 가장 중요한 작업입니다. 리눅스 커널은 표준화한 메커니즘은 물론이고 한두 가지 독자적인 메커니즘을 포함해서 과거부터 내려오는 유닉스 IPC 메커니즘 대부분을 구현합니다. 리눅스에서 지원하는 IPC 메커니즘은 파이프, 네임드 파이프, 세마포어, 메시지 큐, 공유 메모리, 뮤텍스가 있습니다.
헤더 파일
리눅스 시스템 프로그래밍은 여러 헤더 파일을 중심으로 돌아갑니다. 커널 자체와 glibc는 시스템 프로그래밍에 사용되는 헤더 파일을 제공합니다. 이런 헤더는 표쥰 C 계열과 일반적인 유닉스 계열을 포함합니다.
에러 처리
에러 검사 및 처리의 중요성은 두말할 필요도 없습니다. 시스템 프로그래밍에서 에러는 함수 리턴 값으로 확인이 가능하며 특수한 변수인 errno로 에러가 발생한 구체적인 이유를 알 수 있습니다. Glibc는 라이브러리와 시스템 콜 양쪽을 지원하도록 errno 값을 공정하게 제공합니다.
'SW > 리눅스' 카테고리의 다른 글
리눅스 비디오 플레이어 종류 및 추천 (0) | 2019.01.14 |
---|---|
Linux 명령줄 텍스트 편집기 종류 및 추천 (0) | 2019.01.13 |
Linux용 무료 클라우드 스토리지 소프트웨어 종류 및 추천 (0) | 2019.01.13 |
Linux 웹 브라우저 종류 및 추천 (0) | 2019.01.12 |
리눅스 시스템 "파일 입출력"에 대해 알아볼까요? (0) | 2018.12.23 |