Skip to content

태그: linux

Domain-based Split Tunnels
network
VPN을 구성할 때, 특정 도메인에 대해서만 VPN을 활성화하고 싶은 경우가 있을 수 있다. 해당 기능에 대해 TailScale과 Netbird는 아래와 같은 방식으로 제공한다. TailScale에서 제공하는 방식 (문서) DNS 쿼리를 로컬 TailScale 서버로 날리도록 한다. 로컬 데몬에서는 8.8.8.8과 같은 도메인 서버에 다시 요청을 날려서, 도메인 쿼리 결과를 기록해놓은 후 결과를 그대로 돌려준다. 기록한 IP에 대해 커넥터로 지정된 호스트에 라우팅하도록 한다. private 네트워크에 성공적으로 통신할 수 있다. Netbird에서 제공하는 방식 VPN 클라이언트에서 도메인 쿼리 결과를 주기적(기본 60s)으로 불러와 기록해놓는다. 저장된 IP 목록에 해당하는 요청이 발생하면 Netbir
CPU Load Average
kernel
리눅스 커널에서는 CPU Load을 평균으로 산출하여 스케쥴링 알고리즘과 CPU 로드 밸런싱등에 사용한다. 여기서 산출하는 CPU Load 평균은 해당 CPU 실행큐에 대해서 전역적(global)으로 걸리는 부하 평균이다. 이동평균(Moving Average) 리눅스 커널에서는 CPU 부하 평균(Load Average)을 “이동평균” 방식으로 산출한다. 이동평균(Moving Average)은 선택한 범위(날짜 혹은 시간)안에서 발생한 수치들의 평균이다. 예를들어 정리하면 다음과 같다. 1일 이동평균은 1일동안 발생한 수치들의 평균. 5일 이동평균은 5일동안 발생한 수치들의 평균. 15일 이동평균은 15일동안 발생한 수치들의 평균. 1분 이동평균은 1분동안 발생한 수치들의 평균. 5분 이동평균은 5분동안
cgroup
process
cgroup은 Control group의 약자로, 커널에서 프로세스를 계층적 그룹으로 합쳐 관리하기 위한 기능이다. cgroup을 통해 해당 그룹이 사용할 수 있는 CPU, memory를 제한하는 등의 제어를 할 수 있다. cgroup 설정 방법 cgroup는 /sys/fs/cgroup 하위의 파일로 정의된다. cgroup은 오직 프로세스(태스크)들을 그룹화 하는 역할만 하며 내부적으로 자원을 제한하거나 할당하는 역할은 서브시스템에서 수행한다. cgroup 설정을 수정하기 위해선 cgroup 가상파일시스템을 마운트하여 파일 및 디렉토리를 직접 조작하거나, 사용자 도구(Debian, ubuntu는 cgroup-bin/RHEL, CentOS는 libcgroup)를 사용할 수 있다. 서브시스템 서브시스템은 cgr
eBPF로 서버 성능 Profiling하는 법: Pyroscope의 구현 살펴보기
공부
eBPF를 사용한 모니터링을 공부하며 Pyroscopee의 eBPF 기능에 관심이 생겼다. 구현 코드를 살펴보면서 eBPF를 활용하는 방법과 그에 연관된 Linux 기능을 익힐 수 있었는데, 내용을 되새기기 위해 공부했던 부분을 전체적으로 풀어 설명해보려 한다. 우선 관련된 기술 배경부터 알아보자. Pyroscope Grafana Pyroscope는 애플리케이션을 지속적으로 프로파일링하는 오픈소스 플랫폼이다. 프로파일링(profiling)이란? 프로그램을 실행하면서 성능을 측정하고, 분석하는 행위를 프로파일링이라고 한다. 함수 혹은 메소드가 CPU를 얼마나 오랫동안 사용하는가, 얼마나 많이 호출되는가 메모리를 얼마나 자주 할당 및 해제하는가, 얼마나 많이 할당하느냐 와 같은 정보를 측정한다. 애플
kprobe와 kretprobe
linux
kprobe와 kretprobe는 커널 코드에 동적으로 중단점을 삽입하여 사용자가 정의하는 핸들러 함수가 실행되도록 하는 도구이다. kprobe는 함수 또는 함수에서 특정 오프셋만큼 떨어진 곳에서 핸들러 함수를 실행해주고, kretprobe는 함수가 끝난 후에 핸들러 함수를 실행하게 한다. kprobe의 동작 방식 kprobe는 커널의 중단점을 삽입할 주소 (함수 + 오프셋)에 존재하는 명령어를 복사해둔 뒤 중단점을 삽입하는 명령어로 덮어씌운다 (i386에서는 int3 명령어로 1바이트이다.) 그럼 i386에서는 int3 명령어를 실행하는 순간 breakpoint exception이 발생해서 kprobe 핸들러로 넘어가게 된다. 그렇게 kprobe에 등록된, 중단점 이전에 실행되어야 하는 pre_h
메모리 로딩
bpf
BPF는 일반적인 프로그램과 유사한 방식으로 개발하기 때문에 유사한 실행파일 및 메모리 구조를 가지고 있지만, 커널 안에서 제한된 환경으로 실행되기 때문에 로딩(loading) 또한 다른 방식으로 실행된다 데이터 유형 일반적인 실행파일에서 가장 중요한 두 가지는 코드와 데이터이다. 코드는 말그대로 상위언어를 컴파일한 머신코드를 의미하고, 데이터는 실행시 코드가 참조하는 메모리를 의미한다. 데이터는 스택과 힙같이 실행시 메모리가 할당/해제되는 동적 데이터와 전역변수처럼 코드에서 선언되는 정적 데이터로 나뉘는데, 정적 데이터는 실행파일을 로딩할 때 메모리가 할당되고 해당 메모리를 참조하는 코드도 재배치(relocation)된다. 그리고 정적 데이터는 크게 읽기전용 변수, 초기화된 전역변수 그리고
서브프로그램
bpf
BPF는 일반적으로 하나의 함수(main 함수)가 하나의 섹션이 되고, 하나의 섹션이 하나의 프로그램이 된다. 그리고 커널에서 해당 프로그램을 실행할 때는 프로그램의 시작 위치가 메인함수의 시작 위치이기 때문에 간단히 처음부터 실행하면 된다. 하지만 아래와 같이 메인함수에서 공통함수를 호출하는 경우처럼 두 개 이상의 함수가 필요한 경우에는 프로그램의 시작 위치를 어떻게 보장할까? BPF는 이러한 상황에서 시작 위치 보장을 위해 서브프로그램이라는 기능을 제공한다. 아래 코드는 bcc의 filetop 예제코드이다. 해당 예제는 vfs_read와 vfs_write 커널함수에서 각각 사용할 두 개의 BPF 메인함수와 두 개의 함수에서 사용하는 공통함수(probe_entry)로 구성되어 있다. static
epoll
systemcall
Epoll은 리눅스에서 select의 단점을 보완하여 사용할 수 있도록 만든 I/O 통지 모델이다. 파일 디스크립터를 커널이 관리하기 때문에 CPU는 계속해서 파일 디스크립터의 상태 변화를 감시할 필요가 없고, 관찰대상의 정보를 매번 전달하지 않아도 된다. select는 어느 파일 디스크립터에 이벤트가 발생하였는지 찾기 위해 전체 파일 디스크립터에 대해서 순차검색을 위한 FD_ISSET 루프를 돌려야 하지만, Epoll는 이벤트가 발생한 파일 디스크립터들만 구조체 배열을 통해 넘겨주므로 메모리 카피에 대한 비용이 줄어든다. level vs edge trigger epoll의 이벤트 탐지 방법은 level-trigger와 edge-trigger 두 가지가 있다. level-trigger: 특정한 조건이 유
BPF ring buffer
bpf
BPF 프로그램은 수집한 데이터를 후처리하고 로깅하기 위해 정보를 User space로 전송하는데, 대부분의 경우 이를 위해 BPF Perf buffer(Perfbuf)를 사용한다. Perfbuf는 CPU마다 하나씩 생성되는 순환 버퍼로, Kernel space와 Use space간 데이터를 효율적으로 교환할 수 있도록 한다. 하지만 Perfbuf에는 두가지의 문제점이 있었다. 각 CPU에 대해 별도의 버퍼를 사용하기 때문에 데이터 스파이크에 대응하기 위해서 각각의 버퍼크기를 크게 할당해주어야 한다. 이 때문에 필요한 것 보다 더 많은 메모리 공간이 낭비될 수 있다. 연관된 이벤트가 서로 다른 CPU에서 빠르게 발생하는 경우 이벤트가 순서대로 전달되지 않을 수 있다. 이 때문에 이벤트를 옳은 순서로
X window
etc
X Window는 컴퓨터 그래픽 사용자 인터페이스(GUI)를 제공하기 위한 Unix, Linux 계열 운영 체제에서 사용되는 시스템이다. X Window 시스템은 네트워크 환경에서 그래픽 화면을 표시하고 입력 장치와 상호 작용할 수 있는 기능을 제공한다. X window의 구조라고 한다. 특징 클라이언트-서버 모델: X 클라이언트는 X 서버에서 동작하면서 서버에게 명령을 전달하고, X서버는 클라이언트에게 명령 요청의 결과를 디스플레이 장치에 출력해주거나 사용자 입력을 클라이언트에게 제공해주는 역할을 한다. 따라서 디스플레이 장치에 독립적이다. 모듈화: X Window 시스템은 모듈화되어 있으며, 다양한 그래픽 라이브러리와 툴킷을 사용하여 응용 프로그램을 개발할 수 있다. 이로 인해 다양한 스타일과
쉘 단축키
linux
커서 이동하기 Ctrl + A: 현재 입력중인 라인의 시작 위치로 이동한다. Ctrl + E: 현재 입력중인 라인의 마지막 위치로 이동한다. Ctrl + XX: 현재 입력중인 위치와 라인의 시작 위치를 번갈아 이동한다. Alt + F: 현재 입력중인 라인에서 한 단어를 건너뛰어 이동한다. Alt + B: 현재 입력중인 라인에서 앞쪽으로 한 단어를 건너뛰어 이동한다. Ctrl + F: 현재 입력중인 라인에서 한 글자 앞으로 이동한다. Ctrl + B: 현재 입력중인 라인에서 한 글자 뒤로 이동한다. 텍스트 조작 Ctrl + U: 현재 입력중인 라인의 현재 위치부터 라인의 처음까지를 잘라내어 클립보드에 저장한다. 만약 현재 위치가 라인의 마지막이라면, 전체 라인을 잘라내기한다. Ctrl + K: 현재 입력
사용자 관리
authority
root 계정의 UID 값은 0이다. root 이외에 UID가 0인 사용자가 없도록 해야 한다. TMOUT 환경 변수를 사용해 일정시간 미사용시 자동으로 로그아웃 되도록 설정하여 보안을 강화할 수 있다. 사용자 인증 모듈인 PAM을 이용해 root 계정으로의 직접 로그인을 차단할 수 있다. 일반 사용자에게 특정 명령어에 대한 root 권한이 필요할 때는 su 명령어보다는 sudo 명령어를 이용하도록 한다. 계정 관리 계정 정보가 저장되어있는 디렉토리에 대해 알아보자. /etc/passwd 비밀번호를 파일 내 계정 정보와 함께 저장하는 일반 정책에서 사용된다. passwd 파일의 로그인 쉘을 점검하여 로그인이 불필요한 계정에 대한 접근권한을 설정해야 한다. [user_account]:
LVM
disk&dir
LVM이란 Logical Volume을 효율적이고 유연하게 관리하기 위한 커널의 한 부분이자 프로그램이다. 기존방식이 파일시스템을 블록 장치에 직접 접근해서 R/W를 했다면, LVM은 파일시스템이 LVM이 만든 가상의 블록 장치에 R/W를 하게 된다. 이처럼 LVM은 물리적 스토리지 이상의 추상적 레이어를 생성해서 논리적 스토리지(가상의 블록 장치)를 생성할 수 있게 한다. 직접 물리 스토리지를 사용하는 것보다 다양한 측면에서 뮤연성을 제공하기 위해, 유연한 용량 조절, 크기 조정이 가능한 스토리지 풀(Pool), 편의에 따른 장치 이름 지정, 디스크 스트라이핑, 미러 볼륨 등 기능을 가지고 있다. LVM의 주요 용어를 알아보자. PV(Physical Volume) LVM에서 블록 장치(블록 단위로 접근하는
Linux 디렉토리 구조
disk&dir
/bin: 기본 명령어 저장 /sbin: 시스템 관리를 위한 명령어들이 저장 /etc: 환경설정에 연관된 파일들과 디렉터리들이 저장 2016(1) /etc/rc.d: 시스템의 부팅과 런 레벨 관련 스크립트들이 저장 /etc/inittab: init을 설정하는 파일 /etc/issue: 로그인을 위한 프롬프트가 뜨기 전에 출력되는 메시지를 설정하는 파일 /etc/issue.net: issue 파일과 기능은 같으나, 원격지 상에서 접속(telnet 등)할 경우에 출력되는 메시지 설정 /etc/motd: 로그인 성공 후 쉘이 뜨기 전에 출력되는 메시지를 설정하는 파일 /etc/nologin.txt: 사용자의 쉘이 /sbin/nologin으로 지정되어 있을 때, 로그인 거부 메시지를 설정하는 파일 •
RAID
disk&dir
RAID(Redundant Array of Independent Disks) 직역하면 복수 배열 저가/독립 디스크이다. 저장장치 여러 개를 묶어 고용량, 고성능인 저장 장치 한 개와 같은 효과를 얻기 위해 개발된 기법이다. RAID의 주 사용 목적은 크게 가용성과 고성능 구현으로 구분된다. 동작 방식에 따라 Level 0~6으로 분류한다. 주로 사용되는 것은 0, 1, 5, 6이며 무정지 구현을 극도로 추구하면 RAID 1, 고성능 구현을 극도로 추구하면 RAID 0, RAID 5, 6은 둘 사이에서 적당히 타협한 형태이다.. RAID 10이나 RAID 01과 같이 두 가지 방식을 혼용하는 경우도 있다. RAID 0: 스트라이핑 기능(분배 기록) 사용 여러 개의 멤버 하드디스크를 병렬로 배치하여 거대한
백업
disk&dir
Day-zero Backup: 시스템을 설치한 후 사용자들이 시스템을 사용하기 전에 시스템을 백업하는 것 Full Backup: 주기적으로 시스템을 백업하는 것 Incremental Backup: 특정한 이벤트 후 또는 주기적으로 이전의 백업 후 변경된 파일들만 백업 하는 것 단순 백업: 첫 백업 때 풀 백업을 진행한 후, 그 다음부터 변경분 백업을 수행하는 것 다단계 백업(Multilevel Backup): 큰 규모나 중요한 시스템의 백업을 수행하는 것 디렉터리 단위 백업 명령어 tar 마운트된 파일시스템 내에서 백업 [-g]: 증분 백업을 위한 옵션 cpio 많은 양의 데이터를 테이프 드라이브에 백업하기 위한 명령어 네트워크를 통한 백업 / 증분 백업을 지원하지 않는다. 주요 옵션 [-c]
파일 시스템
disk&dir
ext 리눅스 초기에 사용되던 파일 시스템 ext2 ext3가 개발되기 이전까지 가장 많이 사용하는 파일 시스템으로 리눅스 파일 시스템 대부분의 기능을 제공하는 파일 시스템이다. ext2는 뛰어난 안정성과 속도로 가장 유명한 파일 시스템으로 자리잡았고 ext3 또한 ext2에 기반해서 개발되었다. 또한 쉽게 호환되며 업그레이드도 어렵지 않게 설계되어 있다. ext3 ext2에서 fsck의 단점을 보완하기 위해 저널링 기술을 도입한 파일시스템 저널링(Journaling) 기술: 데이터를 디스크에 쓰기 전에 로그에 데이터를 남겨 fsck보다 빠르고 안정적인 복구 기능을 제공 최대 볼륨크기 2TB~16TB 최대 파일크기 16GB~2TB 지원 하위 디렉터리 수 :32000개 ext4 ex
파일 종류
disk&dir
파일 형태로 표현된 커널 내 객체, 즉 OS의 자원이다. 유닉스 시스템은 OS 자원을 파일 형태로 표현한다. OS 자원이라고 함은 디스크, CPU, 네트워크, RAM 등을 말한다. 리눅스에서 이런 자원에 데이터 전송, 장치 접근 시 사용하는 파일을 특수 파일이라고 한다 device files, pipes, socket, ... 특수 파일은 장치와 데이터를 주고 받는 통로이다 데이터 블록이 없으며(디스크에 저장 X) 장치 번호를 inode에 저장한다. 모니터나 프린터 역시 특수 파일을 통해 데이터를 주고 받는다. 디바이스는 반드시 HW를 말하는것이 아니고 SW적인 디바이스도 있다. 파일 종류 문자 : 일반 파일d : 디렉토리b : 블록 장치 특수 파일c : 문자 장치 특수 파일l : 심볼릭 링크 device
디버깅
kernel
커널 디버깅에는 세 가지 요소가 필요하다. 버그가 처음 등장한 커널 버전을 파악할 수 있는가? 버그를 재현할 수 있는가? 커널 코드에 관한 지식을 갖추고 있는가? 버그를 명확하게 정의하고 안정적으로 재현할 수 있다면 성공적인 디버깅에 절반 이상 달성한 것이다. ​ 출력을 이용한 디버깅 printk()와 웁스(oops) 커널 출력 함수인 printk()는 C 라이브러리의 printf() 함수와 거의 동일하다. 주요 차이점은 로그수준(Loglevel)을 지정할 수 있다는 점이다. 가장 낮은 수준인 KERN_DEBUG 부터 가장 높은 수준인 KERN_EMERG 까지 7단계로 설정할 수 있다. printk()의 장점은 커널의 어느 곳에서도 언제든지 호출할 수 있다는 점이다. 인터럽트 컨텍스트, 프
메모리 관리와 캐시
kernel
1. 페이지 (Page) &x26; 구역 (Zone) 프로세서가 메모리에 접근할 때 가장 작은 단위는 byte 또는 word지만, MMU와 커널은 메모리 관리를 페이지 단위로 처리한다. 페이지 크기는 아키텍처 별로 다르며 보통 32-bit 시스템에선 4KB, 64-bit 시스템에선 8KB다. 커널은 하나의 페이지를 여러 구역(zone)으로 나눠 관리한다. (&x3C;linux/mmzone.h>에 정의) ZONE_DMA: DMA를 수행할 수 있는 메모리 구역 ZONE_DMA32: 32-bit 장치들만 DMA를 수행할 수 있는 메모리 구역 ZONE_NORMAL: 통상적인 페이지가 할당되는 메모리 구역 ZONE_HIGHMEM: 커널 주소 공간에 포함되지 않는 ‘상위 메모리’ 구역 메모리 구역의 실제 사용
모듈과 장치 관리
kernel
1. 정의 모듈: 커널 관련 하위 함수, 데이터, 바이너리 이미지를 포함해 동적으로 불러 올 수 있는 커널 객체를 의미한다. 장치: 리눅스 커널은 장치를 블록 장치, 캐릭터 장치, 네트워크 장치 3가지로 분류한다. 모든 장치 드라이버가 물리장치를 표현하는 것은 아니며 커널 난수 생성기, 메모리 장치처럼 가상 장치도 표현한다. 2. 모듈 사용하기 모듈 만들기 모듈 개발은 새로운 프로그램을 짜는 것과 비슷하다. 각 모듈은 소스파일 내에 자신의 시작위치(module_init())와 종료위치(module_exit())가 있다. 아래는 ‘hello, world’를 출력하는 간단한 모듈의 코드이다. include &x3C;linux/init.h>include &x3C;linux/module.h>inclu
시스템 콜과 인터럽트
kernel
커널은 시스템콜의 일관성, 유연성, 이식성​ 3가지를 확보하는 것을 최우선 사항으로 생각하고 있다. 따라서 커널은 POSIX 표준에 따라 표준 C 라이브러리 형태로 시스템콜을 제공한다. 리눅스 커널에서 시스템콜은 네 가지 역할을 수행한다. 사용자 공간에 HW 인터페이스를 추상화된 형태로 제공한다. 시스템에 보안성 및 안정성을 제공한다. 인터럽트(및 트랩)와 함께 커널에 접근할 수 있는 유일한 수단이다. 사용자 공간과 기타 공간을 분리해 프로세스별 가상환경(가상메모리, 멀티태스킹 등)을 제공한다. 리눅스의 시스템콜은 다른 OS보다 상대적으로 갯수가 적고 수행속도가 빠르다. 리눅스는 시스템콜 핸들러 호출 흐름이 간단하기 때문이다. 리눅스는 context switching 속도가 빠르기 때문이
유저모드와 커널모드
kernel
커널은 중요한 자원을 관리하기 때문에, 사용자가 그 자원에 쉽게 접근하지 못하도록 모드를 2가지로 나눈다. 커널모드 운영체제 내부에서 실제로 하드웨어를 제어할 수 있다. 모든 자원(드라이버, 메모리, CPU 등)에 접근, 명령을 할 수 있다. 커널 모드에서 실행되는 모든 코드는 단일 가상 주소 공간을 공유한다. 따라서 커널 모드 드라이버는 다른 드라이버 및 운영 체제 자체와 격리되지 않는다. 유저모드 접근할 수 있는 영역이 제한적이어서 프로그램의 자원에 함부로 침범하지 못하는 모드이다. 여기서 코드를 작성하고, 프로세스를 실행하는 등의 행동을 할 수 있다. 사용자 모드에서 모든 프로세스는 별도의 가상 주소 공간을 할당받는다. Mode bit CPU 내부에 Mode bit 을 두어 kern
이식성
kernel
이식성이란, 특정 시스템 아키텍처의 코드가 (가능하다면) 얼마나 쉽게 다른 아키텍처로 이동할 수 있는지를 의미한다. 이 장에서는 핵심 커널 코드나 디바이스 드라이버를 개발할 때 이식성 있는 코드를 작성하는 방법에 대해서 알아본다. 리눅스는 인터페이스와 핵심 코드는 아키텍처 독립적인 C로 작성됐고, 성능이 중요한 커널 기능은 각 아키텍처에 특화된 어셈블리로 작성해 최적화시켰다. 좋은 예로 스케줄러가 있다. 스케줄러 기능의 대부분은 &x3C;kernel/sched.c> 파일에 아키텍처 독립적으로 구현돼있다. 하지만, 스케줄링의 세부 과정인 context switching과 memory management를 책임지는 switch_to(), switch_mm() 함수는 아키텍처별로 따로따로 구현돼있다.​
커널 모듈
kernel
모듈은 요청 시 커널에 로드 및 언로드할 수 있는 코드 조각이다. 시스템을 재부팅할 필요 없이 커널의 기능을 확장한다. 예를 들어, 한 가지 유형의 모듈은 커널이 시스템에 연결된 하드웨어에 액세스할 수 있도록 하는 디바이스 드라이버이다. 모듈이 없으면 모놀리식 커널을 빌드하고 커널 이미지에 직접 새로운 기능을 추가해야 하고, 새로운 기능을 원할 때마다 커널을 다시 빌드 및 재부팅해야 한다는 단점이 있다. 따라서 모듈을 이용하면 커널 컴파일 시간을 단축할 수 있다. 로드 가능한 커널 모듈(LKM, Loadable Kernel Module)은 런타임에 Linux 커널에 코드를 추가하거나 제거하는 메커니즘이다. 모듈 없이 Linux 커널에 코드를 추가하려는 경우 가장 기본적인 방법은 커널 소스 트
타이머
kernel
커널은 &x3C;asm/param.h> 헤더파일에 시스템 타이머의 진동수를 HZ라는 값에 저장한다. 일반적으로 HZ 값은 100 또는 1000으로 설정돼있고, 커널 2.5 버전부터 ​기본값이 1000으로 상향됐다. 장점: 타이머 인터럽트의 해상도와 정확도가 향상돼 더 정확한 프로세스 선점이 가능해졌다. 단점: 타이머 인터럽트 처리에 더 많은 시간을 소모하고, 전력 소모가 늘어난다. 실험결과 시스템 타이머를 1,000Hz로 변경해도 성능을 크게 해치지 않는다는 결론이 났다. &x3C;linux/jiffies.h>에 jiffies 라는 전역변수에는 시스템 시작 이후 발생한 틱 횟수가 저장된다. 타이머 인터럽트가 초당 HZ회 발생하므로 jiffies는 1초에 HZ만큼 증가한다. 따라서 시스템
파일시스템
kernel
VFS(Virtual FileSystem)는 시스템콜이 파일시스템이나 물리적 매체 종류에 상관없이 공통적으로 동작할 수 있도록 해주는 인터페이스다. 파일시스템 추상화 계층은 모든 파일시스템이 지원하는 기본 인터페이스와 자료구조를 선언한 것이다. VFS는 슈퍼블록(superblock), 아이노드(inode), 덴트리(dentry), 파일(file) 4가지 객체로 구성돼있다. 슈퍼블록: 파일시스템을 기술하는 정보(+ file_system_type, vfsmount 구조체)를 저장한다. 아이노드: 파일이나 디렉토리를 관리하는 데 필요한 모든 정보를 저장한다. 덴트리: 디렉토리 경로명 속 각 항목의 유효성 정보 등을 저장한다. 파일: 메모리 상에 로드 된 열려있는 파일에 대한 정보를 저장한다. 한 파일
프로세스 관리
kernel
1. 프로세스와 구조체 프로세스는 프로그램 코드를 실행하면서 생기는 모든 결과물이다. 일반적인 의미: 실행 중인 프로그램 포괄적인 의미: 사용 중인 파일, 대기 중인 시그널, 커널 내부 데이터, 프로세서 상태, 메모리 주소 공간, 실행 중인 하나 이상의 스레드 정보 등 프로세스는 fork() 호출 시 생성되고, 기능을 수행한 뒤, exit()를 호출해 종료된다. 부모 프로세스는 wait() 호출로 자식 프로세스 종료 상태를 확인할 수 있다. 스레드는 프로세스 내부에서 동작하는 객체이고, 개별적인 PC, Stack, Register(context)를 가지고 있다. 리눅스 커널은 프로세스와 스레드를 구분하지 않는다. 리눅스 커널에 대한 접근은 오직 시스템 콜과 ISR로만 가능하다. 커널
프로세스 스케줄러
kernel
1. 정의 및 역사 스케줄러는 어떤 프로세스를 어떤 순서로 얼마나 오랫동안 실행할 것인지 정책에 따라 결정한다. 스케줄러는 시스템의 최대 사용률을 끌어내 사용자에게 여러 프로세스가 동시에 실행되고 있는 듯한 느낌을 제공해야 한다. 스케줄러는 비선점형 스케줄러와 선점형 스케줄러로 나뉜다. 선점형 스케줄러는 일정한 timeslice 동안 전적으로 프로세서 자원을 사용할 수 있고, 시간이 지나면 다음으로 우선순위가 높은 프로세스에 선점된다. 1991년 리눅스 첫 버전부터 2.4 버전까지는 단순한 스케줄러를 제공했다. 2.5 버전부터 대대적인 스케줄러 개선작업을 통해 O(1) 스케줄러라는 이름의 새로운 스케줄러를 구현했다. Timeslice 동적 계산이 O(1)에 수행되며 프로세서마다 별도의 wait qu
Linux Package
linux
리눅스 패키지(Linux Package)란 리눅스 시스템에서 소프트웨어를 실행하는데 필요한 파일들(실행 파일, 설정 파일, 라이브러리 등)이 담겨 있는 설치 파일 묶음이다. 패키지는 종류는 소스 패키지(Source Package)와 바이너리 패키지(Binary Package)가 있다. 소스 패키지(Source Package)는 말 그대로 소스 코드(C언어..등)가 들어 있는 패키지로 컴파일 과정(configure,make,make install 명령어)을 통해 바이너리 파일로 만들어야 실행할 수 있다. 즉, 소스 패키지는 설치할 때 컴파일 작업도 진행되므로 설치 시간이 길고 컴파일 작업 과정에서 오류가 발생할 수 있다. 바이너리 패키지(Binary Package)는 성공적으로 컴파일된 바이너리
Linux 배포판
linux
• RedHat RPM 기반으로 제작된 리눅스 배포판 현재는 기업용 배포판으로 상업적으로 배포하고 있으며, 무료 버전으로는 페도라가 있다. • Fedora RPM 기반. 레드햇 계열 레드햇의 지원을 받아 개발 및 유지보수가 이루어진다. 페도라의 업데이트 후에 문제점을 파악하여 레드햇 리눅스(RHEL)에 업데이트를 반영하는 방식으로 운영되고 있다. • Debian GNU의 후원을 받는 리눅스 배포판 패키지 설치 및 업그레이드가 단순하다. (패키지 관리 – dpkg, apt) • Ubuntu 데비안 계열 영국 회사인 캐노니컬의 지원을 받음 유니티(Unity)라는 고유한 데스크톱 환경을 사용 • Slackware 초창기에 나온 배포판으로 현재까지 살아있는 가장 오래된 배포판이다. 패트릭 볼커딩에
Linux 특징 및 관련용어
linux
리눅스 토발즈가 커널 개발 / 커널: 소스 공개, 누구나 수정 및 패키징하여 자유롭게 배포 가능 GNU(GNU’s Not UNIX) 리처드 스톨만 유닉스와의 호환 + 더 놓은 기능의 운영체제를 만들고자 했던 프로젝트 자유로운 유닉스를 만들고자 함 / 자유로운 소프트웨어 사용 / 상업화 반대 GCC, BASH, EMACS FSF(Free Software Foundation) 자유 소프트웨어: 상업적 목적으로 사용 가능 / 소스 코드 임의로 개작 가능 / 소스 코드 수정 시 반드시 소스 코드 공개 리처드 스톨만 자유 소프트웨어의 생산, 보급, 발전을 목표로 만든 비영리 조직 자유 소프트웨어 재단 / 무료나 공짜의 뜻X, ‘구속되지 않는다’는 관점에서의 자유 라이선스 GPL(General
Swap메모리
memory
Swap 메모리란, 실제 메모리 Ram이 가득 찼지만 더 많은 메모리가 필요할때 디스크 공간을 이용하여 부족한 메모리를 대체할 수 있는 공간을 의미한다. 실제로 메모리는 아니지만, 디스크 공간을 마치 가상의 메모리처럼 사용하기 때문에 가상 메모리라고 부른다. 실제 메모리가 아닌 하드디스크를 이용하는 것이기 때문에 속도면에서는 부족할 수 있으나 성능의 제약으로 메모리가 부족한 경우엔 유용하게 사용할 수 있다. Swap 메모리 확인 swapon -s 또는 free -h 명령어를 통해 Swap 메모리를 확인할 수 있다. 아직 Swap 메모리를 설정하지 않은 상태이기 때문에, Swap의 total 메모리가 0으로 뜬다. Swap 메모리 설정 Swap 메모리를 설정하기 위해선, 우선 Swap 메모리를 저장할 파일에
VSS, RSS, PSS, USS
memory
VSS (Virtual set size) VSS는 프로세스의 액세스 가능한 전체 주소 공간이다. 이 크기에는 (malloc과 같은 방법으로) 할당되었지만 기록되지 않은 RAM에 상주하지 않을 수 있는 메모리도 포함된다. 따라서 VSS는 프로세스의 실제 메모리 사용량을 결정하는 데 큰 관련이 없다. RSS (Resident set size) RSS는 프로세스를 위해 실제로 RAM에 보관된 총 메모리이다. RSS는 공유 라이브러리를 사용하는 경우에 중복해서 카운팅하기 때문에 정확하지 않다. 즉, 단일 프로세스의 메모리 사용량을 정확하게 나타내지 않는다. PSS (Proportional set size) PSS는 RSS와 달리 공유 라이브러리를 고려하여 비례한 크기를 나타낸다. 세 프로세스가 모두 30
Virtual Networking Interface
network
리눅스는 컨테이너 기술의 기반이 되는 virtual networking 관련 기능들을 제공한다. virtual networking에 자주 사용되는 대표적인 네트워크 인터페이스를 알아보자. Bridge Linux Bridge는 일반적인 네트워크 스위치와 유사하게 동작한다. Bridge는 주로 라우터, 게이트웨이, VM 등에서 패킷을 목적지로 전달(forwarding)하는 역할을 수행한다. Bridge는 STP, VLAN filter, multicast snooping등의 기능도 추가적으로 지원한다. 아래의 소스코드는 리눅스에서 Bridge를 생성하고, 서로 다른 네트워크 인터페이스와 연결하는 과정을 코드로 작성한 예시이다. 이 과정을 거치면, 브릿지를 통해 VM 1, VM 2과 network naemspac
iptables
network
Iptables 방화벽은 규칙을 관리하기 위해 테이블을 사용한다. 이 테이블은 사용자가 익숙한 형태에 따라 규칙을 구분한다. 예를 들어 만약 하나의 규칙이 network 주소 변환을 다룬다면 그것은 nat 테이블로 놓여질 것이다. 만약 그 규칙이 패킷을 목적지로 허용하는데 사용된다면 그것은 filter 테이블에 추가 될 것이다. 이러한 각각의 iptables 테이블 내에서 규칙들은 분리된 체인안에서 더 조직화(organize)된다. 테이블들이 일반적인 규칙의 목적에 의해 정의되는 동안 빌트인 체인들은 그것들을 트리거 하는 netfilter hook들을 표현한다. 체인들은 기본적으로 언제 규칙이 평가될지를 결정한다. 아래는 빌트인 체인들의 이름인데 이것들은 netfilter 이름을 그대로 사용한다. PRE
network namespaces
network
컨테이너는 namespace를 사용하여 같은 host 안에서 자원을 격리한다. network namespace는 도커와 같은 컨테이너에서 네트워크 격리를 구현하기 위해 쓰인다. 기본적으로 호스트는 외부 네트워크와 연결하기 위한 인터페이스와 Routing Table, ARP Table을 가지고 있는데, 컨테이너를 만들면 그 컨테이너에 대한 network namespace가 생성되어서 호스트의 네트워크 인터페이스와 완전히 분리된다. 대신에, 추가적으로 컨테이너 각각에 가상의 인터페이스와 Routing Table, ARP Table을 설정하면 설정대로 통신을 할 수 있게 된다. 호스트에서는 각 네트워크 인터페이스의 네트워크 요소를 확인할 수 없으며, 각 네임스페이스도 호스트가 외부와 통신하기 위해 쓰는 네트워크
ifconfig
주요명령어
ifconfig는 시스템에 설치된 네트워크 인터페이스 정보를 확인하거나 수정하는 명령어이다. ifconfig [인터페이스][옵션] 형식으로 입력하며, 아무 옵션 없이 ifconfig를 입력하면 현재 설정된 네트워크 인터페이스 상태를 보여준다. lo는 루프백 인터페이스로 자기 자신과 통신하는 데 사용하는 가상 장치이며, 흔히 랜카드라고 불리는 유선 네트워크 인터페이스는 eth0, 무선 네트워크 인터페이스는 wlan0라고 명명한다. IP 주소는 호스트에 하나씩 부여되는 것이 아니라 네트워크 인터페이스에 할당되기 때문에 각 네트워크 인터페이스마다 다른 IP 주소를 할당할 수 있다. 내가 테스트해본 서버에서는 embedded NIC인 eno1와 가상 이더넷 인터페이스인 veth, 그리고 lo 등의 여러 네트워크 인
프로세스 관리
process
시스템이 구동 될 때, 커널은 /etc 에 위치한 init 이라는 스크립트를 실행함으로써 시스템 서비스들을 차례대로 시작시킨다. 이 서비스들은 데몬 프로그램(background)으로 구현되어 있기 때문에 로그인하지 않은 상태에서도 필요 작업들을 수행한다. 프로그램은 프로그램을 실행시킬 수 있는데, 이를 부모와 자식 프로세스라고 표현한다. ps 리눅스는 다중 사용자, 사용 작업 시스템이기 때문에 여러 개의 프로세스를 동시에 수행하기 때문에 항상 어떤 프로세스들이 실행되고 있는지 모니터링할 필요가 있다. ps는 이를 위해 현재 시스템에서 실행 중인 프로세스에 관한 정보를 출력하는 명령어이다. Terminal window /proc 디렉터리 이하에 프로세스와 연관된 가상 파일시스템의 내용을 토대로
환경변수와 프로세스
process
환경변수는 시스템의 속성을 기록하고 있는 변수이다. ​일반적으로 프로세스의 환경변수는 프로세스 자신의 정보를 저장하거나 변경하는 용도로 사용된다. 즉, 프로세스 간 통신이 주 목적인 개체는 아니며, 이를 통한 IPC는 부가적인 기능이 된다. 환경변수는 아래 그림처럼 구성된다. 이 환경변수는 보통 Shell에서 정의하고 저장하는,데 Shell에서 프로그램을 실행시키면 프로그램이 시작하는 순간 셸의 환경변수를 모두 복사해서 프로세스이 들고 있게 된다. 따라서 그 이후에 셸의 환경변수를 바꾼다고 해도 이미 시작한 프로그램의 환경변수는 바뀌지 않는다. 이후 새로 시작하는 프로그램의 환경변수가 바뀔 뿐이다. 해당 정보는 pseudo-filesystem인 /proc 안에서 확인할 수 있다. /proc/&x3C;pid
shell
shell
쉘은 사용자가 운영체제의 서비스를 사용할 수 있도록 사용자의 입력을 기반으로 프로그램을 실행해 주는 역할을 한다. 즉, 커널과 사용자 사이의 인터페이스 역할을 담당한다. 커널은 쉘로부터 전달 받은 명령을 기계가 이해할 수 있는 언어로 변환하여 CPU, I/O, 메모리 등 다양한 리소스에 접근해 주는 역할을 한다. 다시 말해, 쉘은 사용자(프로그램)에게 받은 명령을 전달받아 커널이 이해할 수 있도록 해석하여 전달하고, 커널은 하드웨어와 직접적으로 통신한다. 사용자는 시스템 손상 방지를 위해 접근할 수 있는 영역이 제한되어 있어 하드웨어에 엑세스하기 위해선 시스템 콜이라는 특정 작업을 수행해야 한다. 시스템 콜 (System Call) 시스템 콜은 Mode bit를 기반으로 0이면 커널모드, 1이면 사용자 모
fork와 exec
systemcall
fork pid_t fork(void); 새로운 자식 프로세스를 생성할 때 사용하는 시스템 호출 함수이다. 자식 프로세스는 부모 프로세스의 PCB를 그대로 상속받는다. 함수의 반환값은 자식 프로세스에게 0, 부모에게는 자식 프로세스의 id이다. pid_t vfork(void); vfork()도 fork()와 마찬가지로 자식 프로세스를 생성하는 함수이다. fork()와 달리 자식 프로세스가 먼저 실행됨을 보장한다. 따라서 생성된 프로세스가 exec계열 함수를 이용하여 새 프로그램으로 실행하는 경우에 주로 사용한다. vfork()로 프로세스를 생성한 경우 부모의 주소 영역을 참조하지 않을 것이라고 생각하여 부모 프로세스의 공간을 자식에게 복사하지 않는다. 복사하는 시간이 소요되지 않으므로 fork 보다
thread 관련 systemcall
systemcall
우선 스레드란, 프로세스 내에 실행되는 흐름의 단위이다. 프로세스는 반드시 1개 이상의 쓰레드를 가지고 있다. 프로세스와 다르게 한 프로세스 안의 스레드들은 메모리 자원을 공유한다. pthread_create pthread_create는 말 그대로 thread를 생성하는 시스템 콜이다. 이 시스템 콜을 사용하는 경우 -pthread 옵션과 함께 컴파일해야 한다. 각 옵션의 의미는 다음과 같다. thread: 성공적으로 함수가 호출되면 이 포인터에 thread ID가 저장된다. 이 인자로 넘어온 값을 통해서 pthread_join과 같은 함수를 사용할 수 있다. attr: 스레드의 특성을 정의한다. 만약 스레드의 속성을 지정하려고 한다면 pthread_attr_init등의 함수로 초기화해야한다.
리눅스 시스템 프로그래밍 프로젝트
systemcall
선택과목으로 리눅스 시스템 프로그래밍을 수강하며 진행한 프로젝트 코드 및 배운점에 대해 정리한다. 이 프로젝트에서 개발하는 Application은 아래의 기능을 포함한다. Text File(swblocks.txt)에 기록된 S/W 블록 정보로부터 여러 S/W 블록들을 초기화시킨다. 기록된 파일에는 파일 이름과 파라미터가 아래와 같이 세미콜론으로 구분되어 있다. SwBlock1; Param1; Param2; Param3SwBlock2; Param1; Param2SwBlock3; Param1 S/W 블록의 이상동작(블럭 다운) 발생 시 재초기화를 수행한다. 즉, 해당 블록에 해당하는 프로세스를 재시작한다. 각 S/W 블록의 최종 초기화 시간 및 재초기화 횟수를 출력한다. 프로젝트를 동작시켰