Archieve/CS(20)
-
L7 프로토콜 - HTTP
Application Layer, L7 먼저 Application Layer라고도 불리는 L7은 유저와 네트워크 간의 인터페이스 역할을 수행하는 계층이다. 해당 계층에서는 애플리케이션 및 사용자 간의 통신과 데이터 전송 방식을 다양한 방식으로 정의하게 되는데, 이를 프로토콜이라고 부르게 된다. L7 내에는 매우 다양한 프로토콜이 존재한다. 가장 대표적으로는 웹 애플리케이션의 통신을 가능하게 하는 HTTP와 HTTPS부터, 파일 전송에 활용되는 FTP, 이메일 메세지를 전송하는 SMTP, 이메일 수신에 사용되는 IMAP/POP3, google.com을 해석하게 해주는 DNS, 초기 주소 할당시에 사용되는 DHCP, 터미널 접속 시 사용되는 SSH 등 굵직한 프로토콜들이 L7 프로토콜로 분류된다. 모든 프로..
2023.08.08 -
IPv4에서 IPv6로의 전환 매커니즘
몇 일전 면접에서 받았던 질문이다. "그럼 IPv4에서 IPv6로의 전환은 어떻게 가능할까요? IoT 솔루션의 경우에는 많은 경우에서 IPv6를 사용하는 걸로 알고 있는데 혹시 이 부분에 대해서 답변 주실 수 있나요?" 워딩은 정확하진 않지만, 대략적으로 이런 워딩의 질문을 받았던 것으로 기억한다. 생각지도 못한 질문이였고, 솔직히 말해서 그게 가능하겠구나라는 생각도 면접장에서 처음 했었다. 사실 너무나 당연하게도 IPv4 주소체계를 사용하는 머신이 있고 IPv6 주소체계를 사용하는 머신이 있다면, 어떤 프로토콜을 사용하고 DHCP에서 어떻게 주소를 받아왔는지만 다르지 두 머신의 연결이 불가능할 이유는 당연히 없다. 질문 자체도 생각할 여지가 많았지만 그리 잘 답변하지는 못했던 것 같다. 그럼에도 이 질..
2023.08.06 -
정적 라이브러리
앞선 글에서 링커가 다수의 재배치가능 목적파일들을 읽어들이고 이들을 연결해서 한 개의 출력 실행파일을 만든다고 가정해왔다. 실제로, 모든 컴파일 시스템은 관련된 객체 모듈들을 정적 라이브러리라고 부르는 한 개의 파일로 패키징하는 매커니즘을 제공하며 이 라이브러리는 다음에 링커의 입력으로 제공될 수 있다. 출력 실행파일을 만들 때, 링커는 응용 프로그램이 참조하는 라이브러리 내의 객체 모듈만을 복사한다. Approach 1 (컴파일러에 의존) 정적 라이브러리가 없다고 하더라도 컴파일러를 통해서 C의 모든 표준함수에 대한 호출을 인식하고 이에 기반한 코드를 작성할 수도 있다. 다만 이러한 방식은 컴파일러에 상당한 복잡성을 제공하고, 함수가 추가되고 삭제될 시에 새로운 컴파일러 버전이 필요하게 될 수도 있다...
2022.12.05 -
실행가능한 목적파일
앞선 글에서 어떻게 링커가 다수의 목적 모듈을 하나의 실행 간으 목적파일로 합치는지 살펴보았다. 우리의 C 프로그램은 아스키 텍스트 파일로 일생을 시작해서 프로그램을 메모리에 로드하고 실행하는데 필요한 모든 정보를 포함하는 하나의 바이너리 파일로 변환되었다. 위 그림은 전형적인 ELF 파일에 있는 정보들의 종류를 요약한 것이다. 실행 가능 목적파일의 포맷은 재배치가능한 목적파일의 포맷과 유사하다. ELF 헤더는 우선 이 파일의 전체적인 포맷을 설명한다. 또한 프로그램이 실행될 경우 첫 번째 인스트럭션의 주소인 프로그램 엔트리 포인트를 포함한다. .text, .rodata, .data 섹션들은 이들 섹션들이 각자의 최종 런타임 주소로 재배치되었다는 점을 제외하고는 재배치 가능 목적파일에 있는 섹션들과 유사..
2022.12.03 -
Linking(링킹) 소개
링킹 링킹은 여러 개의 코드와 데이터를 모아 연결하여 메모리에 로드될 수 있고 실행될 수 있는 하나의 파일로 만드는 작업이다. 링킹은 컴파일 시에 수행될 수 있으며, 이때 소스 코드는 기계어로 변환된다. 프로그램이 메모리에 로드되고, 로더에 의해 실행될 수 있을때에는 로드 타임에, 응용 프로그램에 의해서 심지어 실행 시에도 수행될 수 있다. 초기 컴퓨터 시스템에서는 주로 수동으로 링킹이 이뤄졌지만, 현대의 시스템에서는 링커라고 부르는 프로그램에 의해 자동으로 수행된다. 다음의 예시를 통해 링커를 이해해보자. /* main.c */ void swap(); int buf[2] = {1, 2}; int main() { swap(); return 0; } /* swap.c */ extern int buf[]; ..
2022.12.02 -
시간 지역성을 위한 캐시 재배치
c = (double *) calloc(sizeof(double), n*n); /* Multiply n x n matrices a and b */ void mmm(double *a, double *b, double *c, int n) { int i, j, k; for (i = 0; i < n; i++) for (j = 0; j < n; j++) for (k = 0; k < n; k++) c[i*n + j] += a[i*n + k] * b[k*n + j]; } 다음의 코드가 있다고 가정하자. 그리고 이해의 편의를 위해 추가적으로 다음도 가정한다. 각 배열은 double의 n x n 배열이며, sizeof(double) == 8 이다. 32바이트 블록 크기를 갖는 (B = 32) 단일 캐시를 가지고 있다. ..
2022.12.01