The Secret Life of Programs - 05. Computer Architecture

프로시저, 서브루틴, 함수

  • 함수를 호출, 실행하고 다시 원래 자리로 돌아오기 위해서는 어디서 함수를 호출하였는지를 기억해야 하는데, 이는 바로 프로그램 카운터의 값이다.
  • 반환 주소를 저장하고, 이를 간접 호출하여 분기해서 돌아오는 과정은 많은 작업이 필요하므로 대부분의 기계는 이를 구현한 명령어를 제공한다.

스택

  • 반환 위치 저장할 메모리 주소가 하나뿐이라면 반환 위치가 덮어씌워지기 때문에 재귀 함수를 사용할 수 없다.
  • 따라서, 함수를 호출할 때에는 반환 위치를 LIFO로 가져오기 위해 스택을 사용하며, 스택의 크기를 초과하는 것을 스택 오버플로, 빈 스택에서 데이터를 가져오려고 하는 경우를 스택 언더플로라 한다.
  • 함수가 호출될 때마다 반환 주소 이외에도 각각의 독립된 로컬 변수를 사용하기 때문에, 로컬 변수 역시 스택에 저장하면 각각의 함수 호출을 독립적으로 구성할 수 있다. 이렇게 매 함수 호출 시 스택에 저장되는 데이터의 모음을 스택 프레임이라 한다.

인터럽트

  • 폴링(Polling)은 자원을 많이 소비할 수 있으므로, 인터럽트 시스템이 필요하다.
  • 인터럽트 요청이 발생하면, 처리중인 명령어까지는 마무리한 후 프로그램을 중단하고 인터럽트 핸들러라는 프로그램(함수)을 실행하고, 다시 원래 프로그램이 중단된 위치부터 실행을 계속한다.
  • 이를 위해 인터럽트에 대응하고 실행 중이던 프로그램으로 돌아가기까지 걸리는 시간을 제한해야 하며, 스택에 인터럽트 발생 이전의 상태를 저장하였다가 복구해줘야 한다.
  • 인터럽트 벡터: 컴퓨터는 각 인터럽트에 대응하는 인터럽트 핸들러 주소를 지정하는 포인터를 가지고 있는데, 이를 인터럽트 벡터라 한다.

상대 주소 지정

  • 여러 프로그램을 동시에 사용할 때, 타이머를 통해 각 프로그램이 실행되는 시간을 제한하여 스위칭하는 스케줄링 방식을 시분할이라 한다.
  • 이를 위해 각 프로그램에 다른 공간을 허용하는데, 이 때 한 프로그램이 다른 프로그램이 사용하는 메모리에 접근하면 여러 가지 문제가 발생할 수 있다.
  • 이를 방지하기 위해 메모리 주소를 절대적으로 지정하는 것은 바람직하지 않으며, 상대 주소 지정을 통해 프로그램이 접근할 수 있는 메모리 주소를 재배치한다.

메모리 관리 장치

  • 한 프로그램이 의도치 않게, 또는 의도적으로 허용되지 않은 메모리에 접근하는 것은 바람직하지 않으므로 이를 위해 메모리 관리 장치(Memory Management Unit)이 사용된다.
  • 프로그램은 가상 주소를 사용하여 작성되고, MMU는 이를 물리적 주소로 변환하는 역할을 한다.
  • MMU는 페이징 기법을 활용하여 실제 가능한 물리주소 범위보다 넓은 범위의 가상 주소를 사용할 수 있게 해준다.

가상 메모리

  • MMU의 페이징 기법으로 확장된 메모리 가용 영역보다 더 큰 영역이 필요할 경우, OS는 현재 필요하지 않은 페이지를 느리지만 용량이 큰 디스크로 옮겨버리고(swap out), 추후 다시 접근이 필요할 때 다시 메모리에 불러들인다(swap in).
  • 이는 성능을 크게 저하시키지만, 메모리가 부족해서 실행할 수 없는 프로그램을 실행할 수 있게 해준다.

메모리 계층과 성능

  • CPU에 비해 메모리가 느리기 때문에, 메모리 계층이라는 개념을 적용, CPU에 캐시라는 하드웨어를 추가하여 CPU가 필요로 할 가능성이 높은 데이터를 미리 읽어옴으로써 성능 향상을 기대할 수 있다.

메모리상의 데이터 배치

  • 실행 전에는 크기를 알 수 없는 데이터, 즉 동적 데이터를 다루기 위해 힙(heap)이라는 영역을 사용한다.

프로그램 실행

  • 링커는 재사용 등을 위해 조각난 프로그램을 하나로 연결하여 실행 가능한 프로그램을 만들어주는 프로그램이다.
  • 라이브러리를 프로그램에 직접 가져다 붙이는 방식을 정적 링크라 하고, 공유 라이브러리를 사용하여 여러 프로그램이 같은 라이브러리를 사용할 수 있도록 하는 방식을 동적 링크라 한다.
  • 공유 라이브러리의 명령어는 해당 라이브러리를 사용하는 모든 프로그램에서 공통이므로, 라이브러리 함수를 작성할 때는 호출하는 프로그램의 스택과 힙을 사용하도록 함수를 설계한다.
  • 프로그램이 합쳐져 실행파일이 되면, 런타임 라이브러리가 추가되어 프로그램 실행시 가장 먼저 실행되고 이후 진입점의 명령어가 수행되면서 프로그램이 실행된다.
  • 런타임 라이브러리는 프로그램이 사용할 메모리 설정을 수행하면서 스택과 힙 영역을 설정하고 데이터의 초깃값도 설정하는 역할을 한다.

The Secret Life of Programs - 04. Computer Anatomy

CPU

  • Arithmatic Logic Unit: 연산자와 피연산자를 입력받아 결과값과 결과 코드를 리턴
  • Shifter: 조합 논리(Combinational Logic)만으로는 구현할 수 없는 Shift 연산을 수행
  • Excecution Unit
    • 메모리에서 명령과 피연산자를 가져와서 ALU에 전달하고 리턴값을 메모리에 저장
    • 메모리에서 실행해야하는 명령의 위치를 기억하기 위해 메모리 위치를 참조하는 PC(Program Counter)를 사용

명령어 집합

  • 명령어(instruction)를 네 필드(opcode, 두 개의 operand, result)로 나누어 표시한다면 아래 2가지 문제점으로 인하여 명령어를 처리하기 어렵다.
    1. operand와 result 필드에 들어가는 주소 값으로 쓸 수 있는 비트가 부족
    2. 한 번에 여러 메모리 주소에 접근해야 함
  • 따라서 opcode와 주소로만 구성된 single-address 명령어를 사용하며, 이를 위해 누산기(accumulator)라는 레지스터를 사용한다.
  • 그럼에도 모든 메모리 주소 영역을 명령어에 담을 수 없으므로 3종류의 주소 지정 모드(즉시, 직접, 간접)를 통해 참조할 수 있는 주소의 영역을 확장한다.
  • 따라서 명령어의 구성은 아래 이미지와 같이 나타낼 수 있다.

메모리 + 입/출력 + CPU + 명령어

  • 컴퓨터는 메모리에서 명령어를 가져오는 상태(fetch)와 명령을 실행하는 상태(execute)를 반복
  • 즉, 컴퓨터의 처리 방식은 프로그램 카운터 값을 메모리의 주소 버스에 먹이고, 메모리의 값(수행해야 하는 명령어)을 다시 명령어 레지스터에 먹여 명령어를 저장하는 절차의 반복

이메일 개봉/링크 클릭 추적하기

Open Tracking

Open tracking은 이메일 수신자가 해당 이메일을 개봉하였는지를 알려준다. 이를 위해 메일침프는 이메일 HTML 하단에 Open tracker(또는 Web beacon)이라는, 캠페인별로 유니크한 작은 투명 그래픽을 임베드한다. 이후 수신자가 해당 메일을 열게 되면, 그 투명 그래픽을 메일침프 서버에서 다운받게 되면서 메일 개봉 처리가 된다. Out-of-office같은 자동화 답장은 그래픽을 다운받지 않기 때문에 미개봉으로 처리된다.
Web beacon을 사용한 추적은 Open tracking을 위한 표준이며, 구독자의 참여 정도를 알 수 있게 해주지만 몇 가지 제약 사항이 따른다. 숨겨진 그래픽 이미지를 기반으로 작동하기 때문에 수신자가 이메일을 열람하는 환경에 따라서 작동하지 않을 수 있는데, 예를 들어 이메일 클라이언트가 해당 이미지를 표기하지 않는 경우에는 작동하지 않는다.

Click Tracking

수신자가 메일에 포함된 URL을 클릭하게 되면, 해당 URL은 Mailchimp의 서버를 경유하여 로그에 기록된 후 목표 주소에 리다이렉트된다.

이메일 링크 브랜딩은 open tracking에 쓰이는 비콘 click tracking이 달린 링크가 SendGrid가 아니라 서비스 사용자의 도메인을 향하게 해준다. 스팸 필터와 수신 서버는 이메일에 포함된 링크를 검사하여 이메일의 신뢰도를 평가하는데, 이 때 해당 링크가 연결된 루트 도메인의 평판(reputation)을 사용하게 된다. 링크 라벨링을 통해 클릭 트래킹 링크가 사용자가 컨트롤할 수 없는 도메인을 경유하지 않도록 함으로써 이메일 전달성의 향상을 기대할 수 있다.

출처

SendGrid Documentation

Mailchimp Documentation