CS

    [OS] 저수준에서 교착 상태에 대비하는 방법

    [OS] 저수준에서 교착 상태에 대비하는 방법

    1. 교착 상태란? 면접관: 교착 상태에 대해 설명해주시면 채용하겠습니다. 면접자: 저를 채용해주시면 교착 상태에 대해 설명하겠습니다. 간단하게 예를 들면 이런 상황이라고 할 수 있다. 면접관은 내가 교착 상태를 설명하기를 기다리고 있지만 면접자는 자신을 채용해주기를 기다리고 있다. 누군가가 양보하지 않는 한 둘은 영원히 기다리게 될 것이다. 이번엔 코드로 예시를 들어보겠다. 스레드 1은 아래의 함수를 실행한다. void *do_work_one() { pthread_mutex_lock(&first_mutex); pthread_mutex_lock(&second_mutex); /* Do some work */ pthread_mutex_lock(&second_mutex); pthread_mutex_lock(&..

    배열 인덱스와 캐시 미스

    배열 인덱스와 캐시 미스

    결론적으로 메모리에 적게 접근하는 것보다 캐시 미스 비율을 낮추는 게 성능에 더 큰 영향을 미친다. 즉, 메모리에 자주 접근을 하더라도 배열 인덱스에 효율적으로 접근하게 코드를 작성하면 좋다는 것이다. 우선 캐시와 캐시 미스가 무엇인지, 이것과 배열 인덱스는 또 무슨 상관인지 알아볼 것이다. 1. 배열 인덱스만 바꿔도 성능이 바뀐다 for(i = 0; i (0, 1) -> (0, 2) -> (0, 3) ... for(i = 0; i < N; i++) for(j = 0; j < N; j++) sum += arr[j][i] 반면에 이..

    저수준에서 최적화하는 여러가지 방법

    저수준에서 최적화하는 여러가지 방법

    CSAPP 5장이 컴파일러의 최적화 기법에 대한 내용인데 통념과 다른 점이나 재미있는 기법들이 많았다. 그 중 몇 가지를 소개한다. 1. 연산을 줄인다고 해서 성능이 좋아지는 것은 아니다 두 코드를 비교해보자. // 곱셈 2번 하는 버전 double poly(double a[], double x, long degree){ long i; double result = a[0]; double xpwr = x; for(i = 1; i = 0; i--){ result = a[i] + x*result; } return result; } 이 코드에서 계산하는 다항식은 \(a[0] + x(a[1] + x(a[2] + ... + x(a[degree - 1] + xa[degree])))\)이다. 위의 다항식과 똑같다. 단..

    [CSAPP] 반복문, 조건문, 배열 어셈블리 코드

    [CSAPP] 반복문, 조건문, 배열 어셈블리 코드

    3.60 음 아래의 어셈블리 코드와 동일한 프로그램이 되도록 C 코드의 빠진 부분을 채워라. 함수 결과가 레지스터 %rax에 저장되는 것을 기억하라. # long loop(long x, int n) # x in %rdi, n in %esi loop: movl%esi, %ecx movl$1, %edx movl $0, %eax jmp.L2 .L3: movq%rdi, %r8 andq%rdx, %r8 orq%r8, %rax salq%cl, %rdx .L2: testq%rdx, %rdx jne.L3 rep; ret long loop(long x, long n) { long result = _____; long mask; for(mask = _____; mask _____; mask = _____) { result..

    C로 다형성 간단히 구현하기

    C로 다형성 간단히 구현하기

    클린 아키텍처 5장 객체 지향 프로그래밍 파트에서 함수 포인터를 개발자가 직접 다루는 것의 위험성을 언급했었다. 하지만 책에서 그런 위험이 있다고 알려주는 것만으로는 얼마나, 어떻게 위험한지 알 수 없다. 그래서 C로 직접 함수 포인터를 사용하는 코드를 포스팅한 블로그를 우연히 발견했는데 코드가 어려워서 더 간략화한 버전으로 바꿨다. 더 자세히 이해하고 싶다면 해당 포스팅을 참고하는 것이 좋다. 저분의 블로그에서처럼, Person과 Dog, 그리고 이들의 상위 타입인 Animal. Person과 Dog 구조체는 각각 walk_person(), walk_dog() 함수를 갖는 것처럼 구현할 것이다. (자바처럼 클래스 내에 메소드를 포함할 수는 없다. 사실 개발자가 이름을 보고 아, 이것은 Person 구조..

    정적 언어와 동적 언어의 모듈 불러오는 방식 차이 실험

    정적 언어와 동적 언어의 모듈 불러오는 방식 차이 실험

    정적 언어와 동적 언어의 대표적인 차이점은 변수 타이핑 시점이다. 정적 언어는 컴파일 타임에, 동적 언어는 런타임에 변수의 타입을 확정한다. 이는 잘 알려져있는 사실이다. 그러나 외부 모듈을 불러오는 방식에도 차이가 있다는 것은 이번에 처음 알게 되었다. 이에 대해 알아본 이유는, 클린 아키텍처 10장 ISP(인터페이스 분리 원칙) 파트에 다음과 같이 설명하기 때문이다. 정적 언어: include 선언문 때문에 소스코드 의존성 발생 > 재배포, 재컴파일 필요 동적 언어: 선언문 없고 런타임에 추론하기 때문에 소스코드 의존성 없음 > 재배포, 재컴파일 필요 없음 하지만 파이썬도 import문으로 외부 모듈을 불러와서 쓰는데 선언문이 없다는 게 무슨 뜻인지 이해할 수 없었다. 그래서 수동 컴파일을 하며 간단..

    [클린 아키텍처] 6장. 함수형 프로그래밍

    함수형 프로그래밍이 무엇일까: 정수 제곱하기 객체 지향 언어인 자바와 함수형 언어인 클로저로 정수를 제곱한 결과를 출력하는 코드를 작성하며 차이점을 비교해볼 것이다. for(int i=0; i

    [클린 아키텍처] 5장 객체 지향 프로그래밍

    객체 지향 프로그래밍의 시초 아이디어는 함수 호출 스택 프레임을 힙으로 옮기는 것이었다. 그게 객체 지향과 무슨 상관일까? 스택 프레임은 함수를 호출할 때 할당되고, 함수 호출이 종료될 때 같이 사라진다. 이를 통해 스택 프레임에는 지역 변수가 저장된다는 것을 유추할 수 있다. 힙에는 동적으로 할당된 변수가 저장된다고 널리 알려져 있다. 예를 들어 C에서는 malloc()으로 생성한 변수가 힙에 저장될 것이다. 이 malloc() 함수를 쓰는 법을 배울 때, 사용 후 free()로 해제해야 메모리 누수를 예방할 수 있다는 말을 들어본 적 있을 것이다. 그 말은 free()로 해제하지 않으면 계속해서 malloc()으로 생성한 변수가 메모리에 남아있다는 뜻이다. 이를 이용한 것이 객체 지향 프로그래밍이다...

    [CSAPP 2장] 숙제문제4 - 부동소수점

    [CSAPP 2장] 숙제문제4 - 부동소수점

    2.83 0.y y y y ...와 같은 무한 스트링으로 이뤄진 이진 표시를 갖는 숫자들에 대해 생각해보자. y는 k비트 길이의 순열이다. 예를 들어 \( \frac{1}{3} \)을 이진수로 표시하면 0.0101010101...(y = 01, k = 2)이며, \( \frac{1}{5} \)은 0.001100110011...(y = 0011, k = 4)료 표시한다. A. \(Y = B2U_k(y)\)라고 하자. 즉 Y는 이진수 표시 y를 갖는 십진수이다. 무한 스트링으로 나타낸 값을 Y와 k를 사용한 식으로 나타내시오. 힌트: 이진 소수점을 k만큼 우측으로 이동한 효과에 대해 생각해보라. B. 다음과 같은 y 스트링의 숫자 값은 얼마인가? (a) 101 (b) 0110 (c) 010011 A. n =..

    [CSAPP 2장] 숙제문제3 - 오버플로우, 곱셈 & 나눗셈 비트 연산

    [CSAPP 2장] 숙제문제3 - 오버플로우, 곱셈 & 나눗셈 비트 연산

    2.76번 빌드업XDR 라이브러리의 보안 취약성XDR 라이브러리는 널리 사용되는 프로그램 간 자료구조를 공유하는 모듈이다. 이 라이브러리를 구현한 코드에서 곱셈 결과를 프로그램에 알려주지 않은 채로 오버플로우를 발생시키는 보안 취약성이 있다는 것이 발견되었다.void *copy_elements(void *ele_src[], int ele_cnt, size_t ele_size) { /* * 각각 ele_size 바이트 크기를 갖는 ele_cnt개의 객체를 * 빈 버퍼로 복사한 후 버퍼를 리턴한다 */ void *result = malloc(ele_cnt * ele_size); if(result == NULL) return NULL; void *next = result; int i;..