Chapter 0 시작하며_0.1 컴퓨터 시스템이란 무엇인가?_0.2 현대의 컴퓨터 시스템은 어떤 모습일까?_0.3 이 책에서 배울 내용_0.4 이 책을 시작하기에 앞서__0.4.1 리눅스, C 및 GNU 컴파일러__0.4.2 기타 표기법과 설명선PART I C 프로그래밍 언어Chapter 1 C 프로그래밍 기초_1.1 C 프로그래밍 시작하기__1.1.1 C 프로그램의 컴파일과 실행__1.1.2 변수와 C의 숫자 타입__1.1.3 C의 데이터 타입_1.2 입력과 출력__1.2.1 printf__1.2.2 scanf_1.3 조건문과 반복문__1.3.1 C의 부울값__1.3.2 C의 반복문_1.4 함수__1.4.1 스택_1.5 배열과 문자열__1.5.1 배열 소개__1.5.2 배열 접근 방법__1.5.3 배열과 함수__1.5.4 문자열과 C 문자열 라이브러리 소개_1.6 구조체__1.6.1 구조체 타입의 정의__1.6.2 구조체 타입의 변수 선언__1.6.3 필드 값 접근__1.6.4 함수에 구조체 전달_1.7 정리Chapter 2 C 프로그래밍 심화_2.1 프로그램 메모리와 범위_2.2 C의 포인터 변수__2.2.1 포인터 변수_2.3 포인터와 함수_2.4 동적 메모리 할당__2.4.1 힙 메모리__2.4.2 malloc과 free__2.4.3 동적 할당된 배열과 문자열__2.4.4 힙 메모리와 함수를 위한 포인터_2.5 C의 배열__2.5.1 1차원 배열__2.5.2 2차원 배열_2.6 문자열과 문자열 라이브러리__2.6.1 정적으로 할당된 문자열(문자 배열)__2.6.2 동적으로 문자열 할당__2.6.3 C 문자열과 문자를 조작하기 위한 라이브러리_2.7 C 구조체__2.7.1 C struct 타입 리뷰__2.7.2 포인터와 구조체__2.7.3 구조체의 포인터 필드__2.7.4 구조체 배열__2.7.5 자기 참조 구조체_2.8 C의 입출력(표준 및 파일)__2.8.1 표준 입출력__2.8.2 파일 입출력__2.8.3 C에서 텍스트 파일 사용__2.8.4 stdio.h의 표준 및 파일 I/O 함수_2.9 일부 고급 C 기능__2.9.1 switch 구문__2.9.2 커맨드 라인 인수__2.9.3 void * 타입과 타입 리캐스팅__2.9.4 포인터 산술__2.9.5 C 라이브러리: 사용, 컴파일, 연결__2.9.6 나만의 C 라이브러리 작성 및 사용__2.9.7 C를 어셈블리로 컴파일_2.10 정리Chapter 3 C 디버깅 도구_3.1 GDB로 디버깅__3.1.1 GDB 시작하기__3.1.2 GDB 예시_3.2 GDB 명령어의 세부 사항__3.2.1 GDB의 키보드 단축키__3.2.2 자주 쓰는 GDB 명령어_3.3 발그린드로 메모리 디버깅__3.3.1 힙 메모리 접근 오류가 있는 예시 프로그램__3.3.2 Memcheck를 사용하는 방법_3.4 고급 GDB 기능__3.4.1 GDB와 make__3.4.2 실행 중인 프로세스에 GDB 연결__3.4.3 포크에서 프로세스 따라가기__3.4.4 시그널 제어__3.4.5 DDD 설정 및 버그 수정_3.5 어셈블리 코드 디버깅__3.5.1 GDB를 사용한 바이너리 코드 검사__3.5.2 DDD를 사용한 어셈블리 디버깅__3.5.3 GDB 어셈블리 디버깅 명령어 및 예시__3.5.4 어셈블리 디버깅에서 자주 사용하는 명령어 요약_3.6 GDB로 멀티스레드 프로그램 디버깅__3.6.1 GDB와 Pthreads__3.6.2 GDB 스레드 관련 명령어__3.6.3 예시_3.7 정리PART II 컴퓨터 시스템 기초Chapter 4 바이너리와 데이터 표현_4.1 숫자의 밑과 부호가 없는 정수__4.1.1 10진수__4.1.2 부호가 없는 2진수__4.1.3 16진수__4.1.4 저장 공간 제한_4.2 진수 변환__4.2.1 2진수와 16진수 변환__4.2.2 10진수로 변환__4.2.3 10진수를 변환_4.3 부호가 있는 2진수 정수__4.3.1 부호가 있는 수__4.3.2 2의 보수_4.4 2진 정수 산술 연산__4.4.1 덧셈__4.4.2 뺄셈__4.4.3 곱셈과 나눗셈_4.5 정수 오버플로__4.5.1 총 주행 거리계 비유__4.5.2 2진수 정수 오버플로__4.5.3 오버플로 요약__4.5.4 오버플로에 따른 결과_4.6 비트와이즈 연산자__4.6.1 비트와이즈 AND__4.6.2 비트와이즈 OR__4.6.3 비트와이즈 XOR__4.6.4 비트와이즈 NOT__4.6.5 비트 시프트_4.7 정수 바이트 오더_4.8 2진수에서의 실수__4.8.1 고정 소수점 표현__4.8.2 부동 소수점 표현__4.8.3 올림의 영향_4.9 정리Chapter 5 컴퓨터 아키텍처_5.1 현대 컴퓨팅 아키텍처의 기원__5.1.1 튜링 머신__5.1.2 초기의 전기 컴퓨터__5.1.3 그래서 폰 노이만은 무엇을 알았나?_5.2 폰 노이만 아키텍처__5.2.1 CPU__5.2.2 처리 장치__5.2.3 제어 장치__5.2.4 기억 장치__5.2.5 입력 및 출력(I/O) 장치__5.2.6 폰 노이만 머신_5.3 논리 게이트__5.3.1 기본 논리 게이트__5.3.2 그 외 논리 게이트_5.4 회로__5.4.1 산술 및 논리 회로__5.4.2 제어 회로__5.4.3 저장 회로_5.5 프로세서 만들기: 종합하기__5.5.1 ALU__5.5.2 레지스터 파일__5.5.3 CPU_5.6 프로세서의 프로그램 명령 실행__5.6.1 클럭 주도 실행__5.6.2 정리: 완전한 컴퓨터에서의 CPU_5.7 파이프라이닝: CPU를 더 빠르게_5.8 고급 파이프라인 명령 고려 사항__5.8.1 데이터 해저드__5.8.2 제어 해저드_5.9 미래를 내다보기: 오늘날의 CPU__5.9.1 명령 수준 병렬화__5.9.2 멀티코어 및 하드웨어 멀티스레딩__5.9.3 예시 프로세서_5.10 정리PART III 어셈블리 프로그래밍Chapter 6 C 아래로: 어셈블리에 뛰어들기_6.1 어셈블리 학습의 이점__6.1.1 가치 있는 프로그램의 세부 사항을 감추는 고수준의 추상화__6.1.2 리소스가 제한돼 컴파일러를 사용할 수 없는 컴퓨팅 시스템__6.1.3 취약점 분석__6.1.4 시스템 수준 소프트웨어에서 중요한 코드 순서_6.2 후속 장들에서 학습할 내용Chapter 7 64비트 X86 어셈블리(X86-64)_7.1 어셈블리 살펴보기: 기본__7.1.1 레지스터__7.1.2 고급 레지스터 표기__7.1.3 명령 구조__7.1.4 피연산자가 포함된 예시__7.1.5 명령 접미사_7.2 흔히 사용하는 명령__7.2.1 한층 구체적인 예시_7.3 산술 명령__7.3.1 비트 시프트 명령__7.3.2 비트와이즈 명령__7.3.3 부하 효과 주소 명령_7.4 조건부 제어와 반복문__7.4.1 사전 준비__7.4.2 어셈블리에서의 if 구문__7.4.3 어셈블리에서의 for 반복문_7.5 어셈블리에서의 함수__7.5.1 함수 매개변수__7.5.2 예시 추적__7.5.3 main 추적_7.6 재귀__7.6.1 애니메이션: 콜 스택 변화_7.7 배열_7.8 행렬__7.8.1 연속적인 2차원 배열__7.8.2 비연속적 행렬_7.9 어셈블리에서의 구조체__7.9.1 데이터 정렬과 구조체_7.10 실제 사례: 버퍼 오버플로__7.10.1 유명한 버퍼 오버플로 악용 사례__7.10.2 살펴보기: 추측 게임__7.10.3 자세히 살펴보기__7.10.4 버퍼 오버플로: 첫 번째 시도__7.10.5 현명한 버퍼 오버플로: 두 번째 시도__7.10.6 버퍼 오버플로에서 보호하기Chapter 8 32비트 X86 어셈블리(Ia32)Chapter 9 ARM 어셈블리Chapter 10 어셈블리 핵심 교훈_10.1 공통 특징_10.2 더 읽어보기PART IV 성능 최적화 및 관리Chapter 11 저장소와 메모리 계층_11.1 메모리 계층_11.2 저장소__11.2.1 1차 저장소__11.2.2 2차 저장소_11.3 지역성__11.3.1 코드에서의 지역성 예__11.3.2 지역성부터 캐시까지__11.3.3 시간적 지역성__11.3.4 공간적 지역성_11.4 CPU 캐시__11.4.1 다이렉트 맵트 캐시__11.4.2 캐시 실패 및 어소시에이티브 설계__11.4.3 셋 어소시에이티브 캐시_11.5 캐시 분석과 발그린드__11.5.1 이론적 분석과 벤치마킹__11.5.2 실세계에서의 캐시 분석: 캐시그린드_11.6 예측하기: 멀티코어 프로세서에서의 캐싱__11.6.1 캐시 일관성__11.6.2 MSI 프로토콜__11.6.3 캐시 일관성 프로토콜 구현__11.6.4 멀티코어 캐싱과 관련된 더 많은 정보_11.7 정리Chapter 12 코드 최적화_12.1 코드 최적화 첫 단계: 코드 프로파일링__12.1.1 콜그린드를 사용한 프로파일링__12.1.2 루프 불변 코드 이동_12.2 그 외 컴파일러 최적화__12.2.1 함수 인라이닝__12.2.2 루프 언롤링_12.3 메모리 고려 사항__12.3.1 루프 상호 교환__12.3.2 지역성을 개선하는 컴파일러 최적화: 분열과 융합__12.3.3 massif를 사용한 메모리 프로파일링_12.4 핵심 교훈__12.4.1 좋은 데이터 구조와 알고리즘 선택하기__12.4.2 가능한 표준 라이브러리 함수 사용하기__12.4.3 느낌이 아닌 데이터에 기반한 최적화__12.4.4 복잡한 코드는 여러 함수로 분할하기__12.4.5 코드 가독성을 우선시하기__12.4.6 메모리 사용에 주의하기__12.4.7 컴파일러는 계속해서 개선되고 있다Chapter 13 운영 체제_13.1 OS의 동작과 실행__13.1.1 OS 부팅__13.1.2 인터럽트와 트랩_13.2 프로세스__13.2.1 멀티프로그래밍과 컨텍스트 스위칭__13.2.2 프로세스 상태__13.2.3 프로세스 생성 및 파기__13.2.4 fork__13.2.5 exec__13.2.6 exit와 wait_13.3 가상 메모리__13.3.1 메모리 주소__13.3.2 가상 주소를 물리 주소로 변환__13.3.3 페이징__13.3.4 메모리 효율성_13.4 프로세스 간 통신__13.4.1 시그널__13.4.2 메시지 전달__13.4.3 공유 메모리_13.5 정리 및 기타 OS 기능PART V 병렬 프로그래밍Chapter 14 멀티코어 시대의 공유 메모리 활용_14.1 멀티코어 시스템 프로그래밍__14.1.1 멀티코어 시스템이 프로세스 실행에 미치는 영향__14.1.2 스레드를 사용한 프로세스 실행 가속화_14.2 첫 번째 멀티스레드 프로그램 작성__14.2.1 스레드 생성과 조인__14.2.2 스레드 함수__14.2.3 코드 실행__14.2.4 스칼라 곱셈 다시 살펴보기__14.2.5 스칼라 곱셈 계산: 다중 인수_14.3 스레드 동기화__14.3.1 상호 배제__14.3.2 세마포어__14.3.3 기타 동기화 구조체_14.4 병렬 프로그램의 성능 측정__14.4.1 병렬 프로그램의 성능__14.4.2 더 살펴볼 주제_14.5 캐시 일관성과 거짓 공유__14.5.1 멀티코어 시스템에서의 캐시__14.5.2 거짓 공유__14.5.3 거짓 공유 수정_14.6 스레드 안전성__14.6.1 스레드 안전성 문제 해결_14.7 OpenMP를 사용한 암시적 스레딩__14.7.1 프라그마__12.7.2 헬로 스레딩: OpenMP 버전__14.7.3 더 복잡한 예시: OpenMP에서의 CountSort__14.7.4 OpenMP에 대해 자세히 알아보기_14.8 정리__14.8.1 주요 요점__14.8.2 더 읽어보기Chapter 15 기타 병렬 시스템 및 병렬 프로그래밍 모델_15.1 이종 컴퓨팅: 하드웨어 가속기, 범용 GPU 컴퓨팅, CUDA__15.1.1 하드웨어 가속기__15.1.2 GPU 아키텍처 개요__15.1.3 GPGPU 컴퓨팅__15.1.4 CUDA__15.1.5 기타 GPGPU 프로그래밍 언어_15.2 분산 메모리 시스템, 메시지 전달 및 MPI__15.2.1 병렬 및 분산 처리 모델__15.2.2 통신 프로토콜__15.2.3 메시지 전달 인터페이스__15.2.4 MPI 헬로 월드__15.2.5 MPI 스칼라 곱셈__15.2.6 분산 시스템의 과제_15.3 엑사스케일 그 이상: 클라우드 컴퓨팅, 빅 데이터, 그리고 컴퓨팅의 미래__15.3.1 클라우드 컴퓨팅__15.3.2 맵리듀스__15.3.3 미래를 바라보며: 기회와 도전