2주차
시스템 콜
- 커널이 노출하는 서비스 인터페이스와 해당 사용자 영역의 엔티티 호출은 시스템 호출의 모음, 시스템 콜이라 부른다.
- 리눅스에는 수백 개의 시스템 콜이 존재
- 우리 프로그램은 일반적으로 시스템 콜을 직접 호출하지 않고, C 표준 라이브러리라고 부르는 것을 통해 호출한다.
- 표준 라이브러리는 래퍼 기능을 제공, glibc 같은 다양한 구현체에서 사용할 수 있다.
래퍼 라이브러리
- 래퍼 라이브러리는 중요한 작업을 수행
- 시스템 콜 실행의 반복적인 저수준 처리를 다룸
- 시스템 콜은 소프트웨어 인터럽트로 구현 -- 예외 처리기로 제어권을 넘기는 예외를 발생시킨다.
- syscall.h와 아키텍처 종속 파일 (커널은 시스템 콜 테이블이라 부르는 파일을 사용)에 정의된 메모리에 있는 함수 포인터 배열을 통해 시스템 콜과 해당 핸들러를 추적한다.
- 시스템 콜 멀티플렉서처럼 동작하는 system_call() 함수를 사용하면 먼저 하드웨어 컨텍스트를 스택에 저장한 다음, 검사를 수행(ex: 추적이 수행되는지 여부), 그 이후 sys_call_table의 각 시스템 콜 번호의 인덱스가 가리키는 함수로 점프한다.
- 시스템 콜 멀티플렉스(Multiplexing): 하나의 공통된 인터페이스를 통해 여러 가지 시스템 콜을 구분해서 처리하는 방식
- sysexit로 시스템 콜이 완료되면, 래퍼 라이브러리는 하드웨어 컨텍스트를 복원하고, 프로그램 실행은 사용자 영역에서 다시 실행한다.
시스템 콜 멀티플렉스 (Multiplexing)
- 운영체제 안에는 시스템 콜이 수백가지가 있음
- 그러나 cpu는 시스템 콜용 진입점(entry point)을 아주 제한된 몇 개만 가진다.
- 하나의 진입점으로 들어온 요청을 "번호"로 구분해서 처리함.
예시 흐름(x86 Linux 기준)
- 유저 프로그램에서 write()호출
- 내부적으로 syscall 명령 -> 커널 진입
- cpu는 레지스터(RAX)값으로 write에 해당하는 시스템 콜 번호 1번을 확인
- 커널은 1번 = sys_write()라고 판단하고 해당 함수 실행
- 커널 확장
- $ uname -srm: 커널 버전 확장
- 커널을 확장? : 원래 없던 기능을 동적으로 추가하거나, 수정해서 운영체제가 새로운 기능을 지원하도록 만드는 것
모듈
- 모듈: 요청 시 커널에 로드할 수 있는 프로그램이다.
- 커널을 다시 컴파일하거나, 시스템을 재부팅할 필요가 없다.
- $ lsmod : /proc/modules 를 통해 볼 수 있음, 커널에 로딩되어 실행 중인 드라이버나 기능 모듈 목록을 확인할 수 있다.
- $modprobe --show-depends async_memcpy
커널을 확장하는 현대적인 방법 (eBPF)
- 리눅스 커널의 기능, 리눅스 커널 버전 3.15
$ uname -srm
Linux 4.18.0-477.27.1.el8_8.x86_64 x86_64
- Linux: 운영체제 커널 이름(리눅스)
- 4.18.0-477.27.1.el8_8.x86_64: zjsjf qjwjs wjdqh
- x86_64: 아키텍처 (64비트 cpu용 커널)
BPF 성능 분석 도구 (Brendan Gregg)
eBPF 공부하려면
- 마이클 커리스크의 "리눅스 API의 모든 것" 에이콘 출판, 2012년
- 리눅스 커널 교육 Linux Kernel Teaching
- 리눅스 커널 분석 Anatomy Kernel Teaching
- 운영체제 커널 Operating System Kernels
- 커널 초보자 KernerNewbies
- 커널 통계 kernelstats : 시계열로 확인하는 흥미로운 배포판 통계
- 리눅스 커널 맵(The Linux Kernel Map): 커널 구성 요소와 종속성을 시각적으로 표현
메모리 관리
- Understanding the Linux Virtual Memory Manager
- 리눅스 커널의 슬랩 할당자 The Slab Allocator in the Linux Kernel
- 커널 문서 Kernel docs
시스템 콜
- 리눅스 인터럽트 기본 개념(Linux Interrupts; The Basic Concepts)
- 리눅스 커널: 시스템 콜(The Linux Kernel: System Calls)
- 리눅스 시스템 콜 테이블: Linux System Call Table
- syscalls.h 소스코드: syscall.h source code (https://oreril.ly/mezjr)
- x86및 x86_64 시스템 콜 조회
eBPF
- Matt Oswalt - Introduction to eBPF
- eBPF 맵 문서
추상화 사다리를 약간 올라가 이 책에서 주 인터페이스라고 간주하는 쉘(수동으로 사용하는 방식과 스크립트를 통한 자동화 모두)로 이동할 준비가 됨
3주차
3장 셸과 스크립팅
터미널, 즉 cli를 사용할 수 있는 셸을 이용해 리눅스와 상호작용 하는 데 중점
- 수동
- 디렉터리 목록 출력, 파일 찾기, 파일 내부 내용 찾기
- 디렉터리 간 혹은 원격 시스템 간 파일 복사
- 이메일이나 뉴스를 읽거나 터미널에서 트윗 보내기
- 셸 스크립팅(스크립팅)
- 우리 대신 셸이 해석하고 차례로 실행할 수 있는 특수한 종류의 파일에 있는 일련의 명령을 자동으로 처리
터미널
- 텍스트로 된 사용자 인터페이스(UI)를 제공하는 프로그램이다.
- 환경변수 TERM은 사용중인 터미널 애뮬레이터 값을 가지고 있으며, infocmp 를 통해 구성할 수 있다.
셸
-
터미널 내부에서 실행되며, 명령 인터프리터 역할을 하는 프로그램이다.
-
셸은 스트림을 통해 입력, 출력을 처리, 변수를 지원, built-in 명령
-
일반적으로 대화식 사용과 스크립트 사용을 모두 지원한다.
-
공식적으로 셸은 sh
로 정의, 최근에는 대부분 bash 셸이 기본으로 널리 쓰이고 있음
-
어떤 셸이 사용되고 있는지 궁금하다면?
file -h /bin/sh
echo $0
echo $SHELL
스트림
- 셸은 입력과 출력을 위한 3가지 파일 디스크립터(File Descriptor: FD)를 모든 프로세스에 제공한다.
- stdin (FD 0)
- stdout (FD 1)
- stderr (FD 2)
- 셸에 입력하는 명령은 키보드에서 입력(stdin)을 가져오고, 출력(stdout)을 화면에 전달한다.
- $ curl https://example.com 2> /dev/null | \ wc -l
변수
- 리눅스가 노출하는 구성 항목을 처리하려는 경우(ex: 셸이 $PATH 변수에 저장된 실행 파일을 찾는 위치)
- 긴 값을 한 번 정의해 입력을 줄이는 경우
- 환경 변수: 셸 전체의 설정, env 명령어
- 셸 변수: bash에서 set명령어로 목록을 나열할 수 있다. 하위 프로세스는 셸 변수를 상속하지 않는다.
- export 명령어를 사용해 환경 변수를 만들 수 있다. 접근하고 싶을 때는 $를 붙이고, unset으로 변수를 제거한다.
종료 상태
- 리눅스 명령은 종료될 때 상태를 반환한다. 상태값은 0은 명령이 오류 없이 성공적으로 실행됐음
- 1~255 사이의 값: 실패
- 종료 상태 확인 시: echo $?를 사용한다.
내장 명령어
작업 제어
- 기본적으로 명령을 입력하면, 그 명령은 일반적으로 화면과 키보드를 제어하며, 이를 포어그라운드에서 실행된다고 한다.
- 하지만 대화식으로 무언가를 실행하고 싶지 않거나, stdin 입력이 전혀 없는 서버의 경우
- 프로세스를 백그라운드에서 실행하려면 명령 마지막에 &를 넣고, 포어그라운드 프로세스를 백그라운드로 보내려면 ctrl + z를 누르면 된다.
- 이미 실행 중이지만 앞에 nohup이 붙지 않은 프로세스의 경우에는 이미 실행 이후라도 disown을 사용하면 동일한 효과를 얻을 수 있다.
- watch -n 5 "ls" &
- jobs
- fg: 프로세스를 포어그라운드로 가져올 수 있다.
모던 리눅스 명령어
- exa로 디렉터리 내용 나열하기
- h: human readable
- t: 수정 시간 기준으로 정렬
- r: 정렬 결과를 역순으로 보여줌
- G: 색상 없이 출력을
- A: 숨김파일도 표시, 단 .과 ..은 제외
rg로 파일에서 콘텐츠 찾기
- 전통적으로는 grep
- 최근에는 rg를 사용
- find . -type f -name "*.yaml" -exec grep "sample" '{}' \; -print
- rg -t "yaml" sample
jq로 처리하는 json 데이터
- 특정 값만 뽑아내려면 awk나 sed 대신 jq를 사용해보자
- jq는 실제 대체 명령어라기보단 널리 사용되는 텍스트 데이터 형식인 json용 특수 도구에 가까움
modern-unix 저장소 (https://oreil.ly/cBAXt) 목록이 있음
Fish SHELL
- 현대적인 리눅스/유닉스용 셸(shell)중 하나로, 사용자가 더 쉽게 쓰고 보기 좋게 만든 셸
- Friendly Interactive Shell의 약자
- 자동 완성, 문법 하이라이팅, 간결한 문법 등
- bash보다 더 편리하고 보기 좋게 터미널을 쓰고 싶을 때
- shell script 작업보다 터미널 작업 중심인 경우
그 밖의 최신 셸
- z셸: zsh는 본셸과 유사하며 강력한 자동 완성 시스템과 풍부한 테마를 지원한다.
- Oil shell: 파이썬과 자바스크립트 사용자 대상
- murex
- 누셸(Nushell): 강력한 쿼리 언어
- 파워셸(powershell)