race condition
·
[ Laboratory ]/Advanced Operating System
multi threading 환경에서 두 개 이상의 스레드가 shared data 를 동시에 write 하면서 동기화되지 않은 상태일 때 프로그램 실행 결과가 interleaving (명령어 섞임)에 따라 달라지는 오류스레드는 addr space를 공유해서 여러 스레드가 code, heap, global variable 공유하기 때문에 동시에 접근 가능하다. 그러나 연산은 대부분 cpu에서 atomic하지 않고 변수에서 레지스터로 읽어오는 mov, 연산을 수행하는 add 등의 연산, 다시 결과를 변수에 쓰는 mov 총 3단계로 이루어진다. 그래서 특정 스레드의 작업 결과가 동기화되기 전에 접근해서 읽은 값으로 작업을 수행하면 업데이트가 정확하게 반영되지 않을 수 있다. lost update!!t1이 50..
lock free vs wait free
·
[ Laboratory ]/Advanced Operating System
동시성 lock free는 전체 시스템이 멈추지 않고 progress하는 것을 보장한다. 어떤 스레드가 일부 중단되더라도 전체적인 연산은 계속 progress한다. = 최소한 하나의 스레드는 매번 forward progress그러나 개별 스레드가 반드시 완료된다는 보장은 없다. = 다른 스레드가 무한히 뒤로 밀릴 수 있는 starvation 가능성 대신 CAS 같은 원자적 연산, HW primitive로 쉽게 구현할 수 있다. wait free는 모든 스레드가 유한한 step 내에서 반드시 함수와 연산을 끝낸다는 것을 보장한다. 가장 강력한 동시성 보장이지만 구현 복잡도가 매우 높다. 어떤 스레드도 무한 루프나 무한 retry에 빠지지 않는다. = 경쟁이 심하더라도 모든 스레드가 bounded tim..
io_uring
·
[ Laboratory ]/Advanced Operating System
io_uring은 syscall을 최대한 줄이고, 모든 I/O를 async하게 수행하고, 유저와 커널이 공유하는 ring buffer를 통해서 I/O를 교환한다. 두 개의 queue를 ring buffer로 사용하는데 SQ = submission queue에는 유저 프로그램이 이런 io를 해달라고 요청을 적는 공간이고 CQ = completion queue에는 커널이 I/O 끝났다고 완료 결과를 적는 공간이다. mmap으로 유저와 커널이 syscall 없이도 공유할 수 있다. 유저 스페이스에서 SQ entry들을 SQ에 push하면한 번의 syscall로 커널에 요청 처리 시작을 알리고 커널이 I/O를 수행하게 된다.완료되면 CQE가 CQ에 기록되고 유저는 CQ에서 바로 읽어서 결과를 확인할 수 있기 ..
interrupt vs polling
·
[ Laboratory ]/Advanced Operating System
polling 폴링은 CPU가 디바이스가 일을 끝냈는지 알아내기 위해 주기적으로 status register를 계속 읽어보는 방식이다. CPU가 디스크 등 I/O 디바이스에 작업을 요청하면 CPU는 그 장치가 끝났는지 계속 status register를 반복적으로 체크하고 디바이스가 완료 상태로 바뀌면 CPU가 다음 동작을 진행하게 된다. 구조는 단순하지만 CPU가 계속 일하고 있는 디스크를 계속 확인하고 기다리는 polling 중이므로 이 시간동안 다른 테스크가 CPU를 사용할 수 없기 때문에 CPU 시간이 낭비된다. interrupt 인터럽트는 I/O 디바이스가 일을 스스로 완료한 후에 CPU에게 끝났음을 알리는 방식이다. CPU가 디스크 등 I/O 디바이스에 작업을 요청하면 CPU는 요청 프..
ABI stability
·
[ Laboratory ]/Advanced Operating System
Application Binary Interface = ABI는 바이너리 프로그램이 운영체제나 라이브러리와 상호작용하기 위한 ‘바이너리 레벨 인터페이스, 소스코드가 아닌 컴파일된 실행 파일이 정상 작동하기 위해서 꼭 지켜야할 규칙을 의미한다. 하나라도 바뀌면 기존 컴파일되어있는 바이너리는 정상 동작하지 못하기 때문에 ABI stability는 시스템 버전 업데이트 후에도 일관되게 안정성을 유지하는 것을 말한다. 운영체제나 라이브러리 내부 구현이 바뀌더라도 업데이트 이후 전과 동일하게 동작해야하고 바이너리를 재컴파일하지 않아도 성능과 기능이 유지되어야 하는 것을 의미한다.
리눅스 eBPF, kfunc
·
[ Laboratory ]/Advanced Operating System
리눅스 커널에서 기능을 확장하는 가장 대표적이고 고전적인 방법은 커널 모듈이다.하지만 최근에는 리눅스의 eBPF 기반의 안전한 확장과 커널 내부 함수까지 호출 가능한 kfunc의 사용이 많아지고 있다. 커널 공간 내부에서 유저가 정의한 코드를 안전하게 실행하기 위해서 필요한 환경 전체를 extended Berkeley Packet Filter = eBPF라고 한다. 단순한 가상 머신만 포함하는 것이 아니라 eBPF 프로그램인 bytecode와 verifier, runtime, helper function, map 등이 포함된다. 유저가 작성한 eBPF 프로그램은 정적 분석 기반으로 안전성을 검증하는 verifier의 검증을 통과해야 실행이 가능하다. 이를 통해 커널 모듈처럼 위험하지 않으면서 런타임 중에..