1-1 C언어 개론


1. C는 프로그래밍 언어이다.

-프로그래밍 언어란 사람과 컴파일러가 이해할 수 있는 약속된 언어.

-컴파일러의 역할은 프로그래밍언어로 작성된 프로그램을 컴퓨터가 이해할 수 있도록 기계어로 번역해주는 역할

// 기계어는 0과 1로 이루어진 비트열이다.


2. C언어의 특징

- Low-Level 언어 : 컴퓨터가 이해하기 쉬운 언어. ex) 어셈블리어
- High-Level 언어 : 사람이 이해하기 쉬운 언어. ex) C언어

- Low-Level 언어는 하드웨어 의존도가 높으며, 프로그래밍하기가 어려운 편이지만 그만큼 하드웨어에 최적화를 시킬 수 있어서 효율적이다.


3. C언어의 장점

1) 절차지향적이라 이해하기 쉽다.
2) 이식성이 좋다.
3) 효율성이 높다.

- C언어는 Low-Level 언어의 특성을 가지고 있다.


1-2 프로그램의 완성 과정

- 프로그램 작성 -> 컴파일 -> 링크 -> 실행파일 생성

1) 프로그램 작성 과정에서 프로그래머는 C언어로 소스코드를 작성한다.( = 코딩 )
2) 컴파일 과정에서 컴파일러는 소스코드를 기계어로 변환한다. 그 결과가 object file 이다.
3) 링크 과정에서는 컴파일된 코드를 라이브러리 파일과 연결시켜준다. 그 결과가 실행 파일(exe file)이 된다.

'학부 전공 > C' 카테고리의 다른 글

6. printf함수와 scanf함수  (0) 2010.07.08
5. 상수와 기본 자료형  (0) 2010.07.08
4. 데이터의 표현방식  (0) 2010.07.07
3. 변수와 연산자  (0) 2010.07.06
2. 프로그램의 기본 구성  (0) 2010.07.06

 * Hash Table
- 최악의 경우를 따지지 않고, 평균적인 경우 즉 대부분의 경우에만 가능한 자료구조
- 조건에 맞으면 동작이 상수 시간 안에 끝나고, 간단하다.
- delete가 복잡하다. delete가 많은 상황에서는 쓰지 않는다.

- idea : 지정석. ex) 100만개의 가능한 키가 모두 등장.

- 정의 : 키 값 k,  k->h(k)
 h(k) : Hash Function. 범위는 0부터 배열의 크기-1 까지.
- k는 h(k)에 저장한다.

- Hash function. (입력값과 무관해 보이는 결과값을 원함)
 k % n
 (p*k) % n
 string folding

-Overflow handling (거의 발생하지 않는다. 따라서 성능에 특별한 영향을 안 줌)
 Open Addressing : linear probing(+1, +2 ...), quadratic probing(^2, ^3 ....) , rehashing(다른 hash함수 사용)
, random probing( pseude random number generator 사용)
 Chaining : 해당 인덱스를 링크드 리스트로 만들어서 저장
 Overflow bucket : 특정 공간을 만들어서 overflow된 값들을 저장. 디스크에서 주로 사용.
 Dynamic Hashing : 넘치면 두배로 늘림. 늘린후 hash값을 모두 재계산 하거나 lazy separation을 사용
 Bloom Filter : hash table보다 훨씬 큰 bitmap filter를 사용. table에 없는 값을 search할 경우 filter에서 걸러짐. 실제로 많이 사용됨.


 * RADIX
-내부 구조에 관심을 가져보자
-많은 경우에 O(nlog n). 범위가 좁고 개수가 적당할수록 성능이 보장됨
- Compression : Run-Length Encoding, Differential Encoding, Huffman Encoding

  Huffman Encoding
- idea : 자주 등장하는 character를 짧은 bit sequence로 표현.
- 각 character의 등장 확률이 미리 주어졌을 때, 최적의 prefix-tree code 생성
- radix의 한 예. tree의 좌, 우가 의미하는 바가 key의 내용에 관계가 있음.

- counting sort : 배열의 데이터가 곧 해당하는 인텍스 넘버의 개수.
- bucket sort : 배열에 버켓을 범위별로 나눠서 넣은 후 각각을 sort.
- radix sort : 배열에 버켓을 2개만 놓고 1개는 첫비트가 0인것, 나머지 1개는 1인것으로 넣음. 그리고 반복.

 * Binary Trie
- retrieve, 꺼내기 쉬운 자료구조
- 키 : integer ( 2진수로 표현 )
- 왼쪽 child는 해당 비트가 0 인 것, 오른쪽 child는 해당 비트가 1인 것.

- Compressed Binary Trie : 특정 노드 이하로 하나의 leaf만 존재할 경우, 그 leaf까지의 모든 비트를 한 레이블에 모아서 적어놓음. delete가 복잡해짐

- Radix trie, Patricia : compressed binary trie의 변형. interner node를 없앰.

- string trie : child로 가는 edge가 해당 칸의 문자열을 의미.

- Aho-corasick Trie : multiple keyword matching.

- Suffix tree : index structure. compressed trie 기반. 사전에 사용.



'학부 전공 > 자료구조' 카테고리의 다른 글

10. 탐색구조  (0) 2010.06.15
5. Tree  (0) 2010.06.08
4. Linked List  (0) 2010.06.07
3. Stack / Queue  (0) 2010.06.07
2. 배열  (0) 2010.06.07

- 최악의 경우에도 insert, search, delete가 O(log n)을 유지

10.2 AVL tree
- 정의 : Binary tree + label
- 각각의 node에 left, right label 표기
-left label : 왼쪽 subtree의 depth
-right label : 오른쪽 subtree의 depth
- left label과 right label이 2 이상 차이가 안 나게 유지.
(항상 같거나 1 차이.)

-Search : binary search tree와 동일. O(log n)
-Insert : binary search tree Insert + Tree 보정 ( label 조건을 만족시키기 위함)
-일단 insert를 시키고 난 후, search한 PATH를 따라 올라가다가 최초로 조건을 만족시키지 않는 node에서 Rotation.

 *Rotation
-LL, LR, RL, RR
-LL의 경우: 최초로 조건을 만족시키지 않는 node를 right child로 만들고, 그 자리에 left child를 올림.
 left child의 right child는 원래 root node의 left child로 바꿈.
 RR의 경우 좌우 대칭
-LR의 경우 : 최초로 조건을 만족시키지 않는 node를 right child로 만들고, 그 자리에 left child의 right child를 올림.
 root로 올린 node의 left child는 원래 자리의 parent에 붙이고, right child는 원래의 root node에 붙임.

 - Rotiation을 진행 하더라도 기본적인 크기 관계가 변하면 안 됨.


10.3   2-3 tree

- 정의 : 각 node에 키가 1개 혹은 2개, 따라서 각 node의 child가 2개 혹은 3개. 모든 leaf는 같은 level.
- search : O(log n)
- insert : search를 한 후에, leaf에 빈자리가 있으면 그냥 insert, 빈자리가 없으면 leaf를 split해서 중간값을 parent로 올려보내고 반복.


10.4   2-3-4 tree

- 각 node에 키가 1개 혹은 2개 혹은 3개.
- 나머지는 2-3 tree와 같으나 insert를 할 때, split을 하면서 내려오게 할 수 있다.-> tree를 한번 내려오면 insert가 끝남.


10.5 Red-Black tree
- 2-3-4 tree의 변형
- 2-3-4 tree를 binary tree형태로 표현.
- child node로 가는 link를 black으로, 같은 node에 있는 키로 가는 link를 red로 표시.

-특징 : root에서 leaf까지 black link의 수는 항상 동일, 어떤 path에서도 red link가 연속으로 등장하지 않는다.

-insert 과정은 AVL tree의 Rotation과 같다.


- AVL, 2-3, 2-3-4, Red-Black tree를 통틀어 Balanced tree라 부른다.


 * Skip list
- head와 tail이 더미 노드인 링크드 리스트가 층으로 쌓여있는 자료구조
- 모든 동작이 O(log n)에 된다.


'학부 전공 > 자료구조' 카테고리의 다른 글

Hash Table, Radix, Binary Trie  (0) 2010.06.15
5. Tree  (0) 2010.06.08
4. Linked List  (0) 2010.06.07
3. Stack / Queue  (0) 2010.06.07
2. 배열  (0) 2010.06.07

-그래프의 특수한 경우

- Connected Graph with no cycle

 *정의
1. 하나 이상의 노드로 이루어진 자료구조
2. 노드들 중 하나는 root이다.
3. root를 제외한 나머지 노드들은 subtree들로 분할된다.
4. root와 subtree의 root 사이에는 edge가 있다.

 *용어
- node의 subtree root를 node의 child라고 부른다.
- degree(차수) : node의 child 수
- degree가 0인 node : leaf, terminal
- A가 B의 child => B는 A의 parent
- parent가 같은 node들 => 형제(sibling)
- root level : 1, node level : parent level + 1, 제일 큰 level : heght or depth
- parent, parent의 parent, ,,,,,, => 조상(ancestor)
- child, child의 child, ...... => 자손(descendant)
 

5.1.1 Tree의 표현(child를 표현하는 방법)
1) 배열 방법 
2) Left child - Right sibling
3) Binary Search Tree

5.2 Binary Tree
 - child가 최대 2개인 tree

5.2.3 Binary tree의 표현
 - 배열에 embeded.
 - 배열의 i에 있는 node의 children은 2i, 2i+1에 존재

5.3 Tree Traversal
-정의 : root에서 시작해서 node들을 "지정된 순서"에 따라서 "방문"하는 것
-종류 : preorder, inorder, postorder
-트리에 다항식을 넣으면 전위/중위/후위 연산자 표현이 가능하고, 변수를 넣으면 기계어를 만들 수 있다.

5.6 Heap
 - 우선 순위 큐를 만들 때 사용
 - Complete Binary Tree.
 - 어떤 노드의 키 값은 children의 키 값보다 작다.
 - Heap Insert : up-heap. leaf중에서 제일 오른쪽에 추가한 후, parent와 비교해서 조건에 안 맞으면 교환. 그리고 반복
 - Heap Delete : down-heap. root를 보내주고, leaf중에서 제일 오른쪽에 있는 것을 root로 올린 후, children과 비교해서 조건에 안 맞으면 교환. 그리고 반복.

 - tree는 재귀적으로 코딩하면 더 쉬워진다.

5.7 Binary Search Tree 
- Binary tree
- left, right의 children
- node a의 left subtree : a의 키보다 작은 키 값
- node a의 right subtree : a의 키보다 큰 키 값

- Insert : Search를 한 후, 실패했다면 그곳에 새 child로 insert
- Delete : leaf일 때는 그냥 삭제, one child 일때는 child를 parent에 붙여주고 삭제, two children 일때는 오른쪽으로 한번, 왼쪽으로 계속 내려가서 만나는 leaf랑 해당 노드를 바꾼 후, 바뀐 leaf를 삭제.


5.10 Union-Find
-집합의 연산 중 합집합과 대표 원소 찾기(집합 이름 찾기, 두 원소가 같은 집합에 있는지 확인)

-Minimum Spanning Tree 문제
-연결을 유지하면서 최소 비용 쓰기
방법1 : 한 노드르 찍고, 최소 비용 edge를 추가 해나감.
방법2 : 전체 edge를 sorting한 다음, 최소 비용 edge부터 추가 해나감

-항상 사이클을 만들지 않는다.
-사이클 검사 : 방법1 일때는 Tree에 이미 포함된 노드 둘을 연결할 때 사이클이 생기고, 방법2 일때는 같은 덩어리에 있는 노드 둘을 연결할 때 사이클이 생김.

-구현 : 배열상에서 구현. 포인터는 index, 무제한 tree, 포인터 방향은 child->parent. 즉 해당 node는 자신의 parent의 index의 값을 가지고 있음.

- 성능 : Find와 Union 둘 다 tree depth에 비례.
- Path Compression 사용




'학부 전공 > 자료구조' 카테고리의 다른 글

Hash Table, Radix, Binary Trie  (0) 2010.06.15
10. 탐색구조  (0) 2010.06.15
4. Linked List  (0) 2010.06.07
3. Stack / Queue  (0) 2010.06.07
2. 배열  (0) 2010.06.07

-Linked List의 특징 : 순서를 유지한다. 삽입과 삭제를 주로 한다. Binary Search가 불가능 하다.

-Node와 Link로 구성되어 있다.
-Node는 데이터를 저장하는 Linked List의 구성단위이고, Link는 Node와 Node를 연결하는 포인터이다.

-Multi thread에서는 포인터 하나로 delete를 수행할 수 없다. 

-메모리 사용이 유연한 장점이 있다.


*다항식
-다항식 표현에 다양하게 사용된다.

*동치관계(등호의 예)
1) Reflexive : 모든 a에 대해서 a = a이다.
2) Symmetric : 모든 a,b에 대해서 a = b이면 b = a이다.
3) Transitive : 모든 a,b,c에 대해서 a = b, b = c이면 a = c이다.

-동치관계의 일부가 주어졌을 때, 주어진 것으로 유추할 수 있는 자연스러운 partition을 계산하는데 쓰인다.

-DFS(depth first search : 깊이 우선 탐색)




'학부 전공 > 자료구조' 카테고리의 다른 글

Hash Table, Radix, Binary Trie  (0) 2010.06.15
10. 탐색구조  (0) 2010.06.15
5. Tree  (0) 2010.06.08
3. Stack / Queue  (0) 2010.06.07
2. 배열  (0) 2010.06.07

- Search를 고려하지 않음
- Insert와 Delete 대신에 Push와 Pop을 씀.
- 값에 의존하지 않고 순서에만 의존.

*Stack : Last-in First-out 방식(LIFO)
*Queue : First-in First-out 방식(FIFO)

-Queue에서는 full 과 Empty 일 때 top,bottom포인터의 상대위치가 같기 때문에 구별해주어야 한다.


*미로찾기
-길을 찾다가 막혀있으면 왔던 길을 되돌아 간다. 왔던 길의 좌표를 Stack에 저장해 놓을 수 있다.

*수식의 계산
-infix(중위표기법) : 연산자를 연산하려는 두 숫자 사이에 두는 방법. 예) 3 + 5
-postfix(후위표기법) : 연산자를 연산하려는 두 숫자 뒤에 두는 방법. 예) 35+
-prefix(전위표기법) : 연산자를 연산하려는 두 숫자 앞에 두는 방법. 예) +35

이 중에서 인간이 이해하기 쉬운 표현은 infix, 프로그램 입장에서 이해하기 쉬운 표현은 postfix.

 *infix를 postfix로 변환하는 알고리즘
1. 피연산자인 경우 출력
2. 연산자인 경우 Stack top의 연산자와 우선순위를 비교하여 입력된 연산자의 우선순위가 더 높을 경우 Push하고, Stack top의 연산자의 우선순위가 더 높을 경우 Pop한 후 반복 비교.

 *postfix로 된 수식을 계산하는 알고리즘
1. 피연산자이면 Stack에 Push
2. 연산자이면 Stack에서 피연산자 2개를 Pop해서 계산 한 후, 결과는 Push


-최하위 우선순위를 가지는 연산자를 하나 지정해서 Stack에 미리 넣어두면, 코드가 단순해진다.


'학부 전공 > 자료구조' 카테고리의 다른 글

Hash Table, Radix, Binary Trie  (0) 2010.06.15
10. 탐색구조  (0) 2010.06.15
5. Tree  (0) 2010.06.08
4. Linked List  (0) 2010.06.07
2. 배열  (0) 2010.06.07

 * 자료구조의 operation
- insert
- search
- delete

-배열의 정의 : 연속된 주소에 "같은 type"의 data item에 저장되는 자료구조.

-배열의 (유일한) 장점 : K번째 item을 상수 시간에 접근 가능.
-배열의 단점 : 크기변경이 어렵다.

-배열의 4가지 사용방법
1. Packed Sorted
2. Unpacked Sorted
3. Packed Unsorted
4. Unpacked Unsorted
-용도에 따라 4가지를 구별해서 쓴다. 각각 operation 성능이 조금씩 다르다.

- Binary search의 성능 : O(log n)


'학부 전공 > 자료구조' 카테고리의 다른 글

Hash Table, Radix, Binary Trie  (0) 2010.06.15
10. 탐색구조  (0) 2010.06.15
5. Tree  (0) 2010.06.08
4. Linked List  (0) 2010.06.07
3. Stack / Queue  (0) 2010.06.07


5.1 기억장치 시스템의 특성들

-액세스 : CPU가 어떤 정보를 기억장치에 쓰거나 기억장치로부터 읽는 동작.

 *기억장치의 엑세스 유형들
 -순차적 액세스 : 기억장치에 저장된 정보들을 처음부터 순서대로 액세스한다.
 -직접 액세스 : 읽기/쓰기 메카니즘이 각 레코드나 블록의 근처로 직접 이동한 후에 순차적 검색을 통하여 최종 위치에 도달한다.
 -임의 액세스 : 기억장치 내의 모든 저장 위치들이 고유의 주소를 가지고 있어서 별도의 읽기/쓰기 메카니즘을 가지고 있다.
 -연관 액세스 : 각 기억장소에 키값에 해당하는 비트들과 데이터가 함께 저장되어 있어서 액세스 요구에 포함되어 있는 비트 패턴과 기억장소의 키 비트를 비교하여 일치하는 기억장소의 데이터가 읽혀진다.(특수한 용도로만 사용)


 *기억장치 시스템을 설계하는 데 있어서 고려해야 할 주요 특성 : 용량, 액세스 속도

 1. 용량
-기억장치에서 용량을 나타내는 단위 : 바이트 또는 단어(=CPU가 내부 연산에서 한 번에 처리할 수 있는 데이터 비트의 수)
-전송 단위 : CPU가 한 번의 기억장치 액세스에 의하여 읽거나 쓸 수 있는 비트 수.
-내부 기억장치에서는 전송 단위가 기억장치 모듈로 들어가고 나오는 데이터 선들의 수(버스의 폭)와 같다.
-주소 지정 단위는 보통 워드이지만 더 작은 바이트 단위를 사용하는 경우도 있음.

 2. 액세스 속도
-액세스 시간 : 주소와 읽기/쓰기 신호가 기억장치에 도착하는 순간부터 데이터가 저장되거나 읽혀지는 동작이 완료되는 순간까지의 시간.
-사이클 시간 : 액세스 시간과 데이터 복원 시간을 합친 시간. 데이터를 읽은 후에 내용이 지워지는 기억장치에만 해당한다.
-데이터 전송률 : 기억장치로부터 읽혀지거나 쓰여질수 있는 초당 비트 수를 말한다. 액세스 시간의 역수에 한번에 읽혀지는 데이터 비트 수를 곱해서 구한다.


 *기억장치의 유형
1. 물리적인 재료에 의한 분류 : 반도체 기억장치, 자기-표면 기억장치
2. 데이터를 저장하는 성질에 이ㅡ한 분류 : 휘발성 기억장치, 비 휘발성 기억장치.


5.2 기억장치 계층

-컴퓨터 기억장치 설계에 있어서 가장 중요한 요소들 : 용량, 속도, 가격
 
 *특성들 간의 상관관계
-액세스 속도가 높아질수록, 비트 당 가격도 높아진다.
-용량이 커질수록, 비트당 가격은 낮아진다.
-용량이 커질수록, 액세스 속도는 낮아진다.

-위와 같은 어려움을 해결하기 위하여 여러 종류의 기억장치들을 이용하여 계층적 기억장치 시스템을 구성한다.

-계층적 구조에서는 하위 레벨로 갈수록 비트당 가격이 감소, 용량 증가, 접근 시간이 증가, 접근빈도가 감소한다.

 *성능 향상
-적중률 : 접근하고자 하는 데이터가 그 레벨에 있을 확률.
- 1레벨의 접근 시간 T1, 2레벨의 접근시간 T2, 첫 레벨의 적중률이 H이면, 평균접근시간 T는 다음과 같다.
 T = H * T1 + (1-H)*(T1+T2) = T1 + (1-H)*T2
- 적중률이 100%에 가까워질수록 평균접근시간은 1레벨의 접근시간에 가까워진다.

-캐쉬 기억장치 : 주기억장치와 CPU의 속도차이로 인한 성능저하를 줄이기 위해 설치하는 고속의 반도체 기억장치

-참조의 지역성 : 기억장치의 액세스가 몇몇 특정 영역에 집중되는 현상
-프로그램이 실행되는 동안에 일반적으로 지역성의 원리에 의하여 첫 번째 계층의 기억장치에 대한 액세스 횟수가 두번째 계층의 기억장치에 대한 액세스보다 훨씬 더 많음
-지역성의 원리가 적용되면 높은 성능 향상을 얻을 수 있음.



5.3 반도체 기억장치

- 반도체 기억장치의 기본 요소는 기억장치 셀(memory cell)
 * 셀의 특징
-두 개의 안정된 상태(Write,Read)를 가진다.
-상태를 설정할 수 있다.
-현재 상태를 감지할 수 있다.
-선택,제어,입출력 단자를 가지고 있다.


5.3.1 RAM

-RAM(Random  Access Memory) : 임의 액세스 방식을 이용하는 반도체 집적회로 기억장치.
-칩 내의 어느 위치에 있든, 액세스에 걸리는 시간이 같다.
-데이터를 읽는 것과 쓰는 것이 모두 가능하다.
-휘발성(volatile)이다. 즉, 전원 공급이 중단되면 데이터가 소실된다. 따라서 일시적 저장장치로 사용된다.
-칩 선택(CS), 읽기(RD), 쓰기(WR) 신호들과 주소 버스(AD0~9)와 데이터버스가 있다.

-RAM은 제조기술에 따라 DRAM과 SRAM으로 분류된다.
-DRAM(Dynamic RAM) : capacitor에 전하를 충전하는 방식으로 데이터를 저장하는 기억 소자들로 이루어져 있다. capacitor가 방전하는 성질이 있기 때문에 주기적으로 재충전이 필요하다. 
-SRAM(Static RAM) : 기억소자로서 플립-플럽을 이용한다. 재충전이 필요없다. 

-DRAM의 소자가 SRAM의 소자보다 더 작다. 따라서 단위 면적당 더 많은 소자들을 집적시킬 수 있으므로 밀도가 더 높고, 같은 용량의 SRAM보다 가격이 싸다. 다만 재충전시간이 필요하기 때문에 약간 느리다.
-DRAM은 용량이 큰 주기억장치로 많이 사용되고, SRAM은 높은 속도가 필요한 캐쉬 기억장치로 사용된다.

 * 기억장치 설계
-예) 16Mbit DRAM 칩의 조직
1M X 16 비트로 구성 : 1M개의 16비트 워드로 구성. 하나의 칩으로 16비트 처리 가능. 1M개의 칩으로 구성.
4M X 4 비트로 구성 : 4M개의 4비트 워드로 구성. 하나의 칩으로 4비트 처리 가능. 4M개의 칩으로 구성.
16M X 1 비트로 구성 : 16M개의 1비트 워드로 구성. 하나의 칩으로 1비트 처리 가능. 16M개의 칩으로 구성.

-1K개의 칩은 10비트의 주소버스 필요.(1M개의 칩은 20비트)


5.3.2 ROM

-ROM(Read Only Memory) : 영구 저장이 가능한 반도체 기억장치. 읽는 것만 가능하고 쓰는 것은 불가능하다. 
-시스템 초기화 프로그램, 진단 프로그램, 자주 사용되는 함수들을 위한 서브루틴들, 제어 유니트의 마이크로 프로그램등에 사용된다.

-PROM(Programmable ROM) : 제조과정에서 기록하지 않고 나중에 전자적으로 기록한다. ROM보다 저렴하다.
-EPROM(Erasable Programmable ROM) : 쓰기 연산을 수행하기 전에 자외선을 이용하여 데이터를 전부 지우는 과정이 필요하다. PROM보다 비싸다.
-EEPROM(Electrically Erasable ROM) : 쓰기 전에 데이터를 지울 필요가 없다. 바이트 단위의 쓰기가 가능하다. 쓰기 연상에 많은 비용이 소요된다. 가격이 더 비싸다.
-플래쉬 기억장치 : 가격과 기능면에서 EPROM과 EEPROM의 중간 정도. 쓰기 전에 기존 데이터를 지워야 하지만 EPROM보다 훨씬 빠르게 지울 수 있다. 블럭 단위로 지우고 쓸 수 있다. 집적 밀도가 높다.


'학부 전공 > 컴퓨터구조' 카테고리의 다른 글

4. 제어 유니트  (3) 2010.04.29
rcv : receiver
app : application

3.1 트랜스포트 계층 서비스와 원리

- 트랜스포트 계층 프로토콜은 서로 다른 호스트들 상에서 동작하는 응용 프로세스들 사이에 논리적 통신(logical communication)을 제공한다.

-송신 측(send side)에서는 응용 계층으로부터 온 메세지를 세그먼트(segment)로 쪼갠(break) 다음, 헤더를 추가하여 네트워크 계층으로 보낸다.
-수신 측(rcv side)에서는 네트워크 계층으로부터 온 세그먼트(segment)를 재조립(reassemble)한 뒤 헤더를 제거하여 응용 계층으로 보낸다.

-인터넷에서 app은 TCP와 UDP, 두 가지 프로토콜을 사용할 수 있다.

3.1.1 트랜스포트 계층과 네트워크 계충 사이의 관계

-트랜스포트 계층 프로토콜이 서로 다른 호스트들 상에서 동작하고 있는 프로세스들 사이의 논리적 통신을 제공하는 반면, 네트워크 계층 프로토콜은 호스트들 사이의 논리적 통신을 제공한다.

-비유를 하자면, 멀리 떨어진 두 집에 아이들이 반대편 집의 아이들과 편지를 주고 받을 때를 가정하자. 각각의 집에서는 편지를 모아서 우체통에 넣는 일을 하는 아이가 한 명씩 있다. 아이들을 편지를 그 일을 맡은 아이에게 주고, 편지를 모은 아이는 그 편지를 우체통에 넣어 보내고, 우체국에서 오는 반대편 집에서 보낸 편지를 가져와 아이들에게 나누어주는 일을 한다.
집을 호스트, 아이들을 프로세스라고 하고 편지를 메세지라고 한다면, 우편 당번은 트랜스포트 계층이고, 우체국은 네트워크 계층이라고 할 수 있다.

3.1.2 인터넷에서의 트랜스포트 계층

-트랜스포트 계층은 비신뢰적(unliable)이고, 비연결형(unorder) 서비스를 제공하는 UDP와 신뢰적(liable)이고, 연결형(inorder)서비스를 제공하는 TCP를 제공한다.

-네트워크 계층 프로토콜은 IP(internet protocol)인데, IP는 호스트들간에 논리적 통신을 제공하는 최선형(Best-effort) 전달 서비스이다. IP는 세그먼트를 전달하기 위해 최선의 노력을 하지만 어떠한 보장(데이터의 무결성이나 세그먼트의 순서 보장)도 하지 않는다.

-TCP와 UDP의 가장 기본적인 기능은 IP전달 서비스를 두 프로세스들 간의 전달 서비스로 확장하는 것이다. 이 것을 다중화(Multiplexing)와 역다중화(demultiplexing)라고 한다. 

-UDP는 헤더에 오류 검출을 포함함으로써 무결성 검사를 제공한다.

-TCP는 무결성 검사 뿐만이 아니라 흐름제어(flow control)와 혼잡제어(congestion control), 순서번호/확인응답/타이머 등을 사용함으로써 데이터의 신뢰적인 전송을 제공한다.

-TCP 혼잡 제어(congestion control)은 app에 제공되는 서비스이다. 각각의 TCP연결이 링크의 대역폭을 공평하게 공유하도록 한다. 이것은 과도한 양의 트래픽으로 링크가 폭주하는 것을 방지한다.


3.2 다중화와 역다중화

-여러 app 프로세스로부터 데이터를 받아 세그먼트를 생성하고 헤더를 추가하여 네트워크 계층에게 넘겨주는 작업을 다중화(Multiplexing)라 하고, 네트워크 계정에서 받은 데이터를 올바른 app 프로세스에게 전달하는 작업을 역다중화(demultiplexing)라 한다.

-TCP와 UDP는 세그먼트 헤더에 소스의 포트번호와 목적지의 포트번호를 포함하여 다중화와 역다중화를 가능하게 한다.

-잘 알려진 포트번호(well-known port number) : 0~1023까지의 포트번호. HTTP나 FTP등에 미리 예약되어 있다.

-세그먼트에 포트번호가 두개 필요한 이유 : 만약 목적지에서 같은 포트번호를 가진 프로세스가 두개 이상 동작하고 있다면, 목적지의 트랜스포트 계층 프로토콜은 어느 프로세스에 세그먼트를 줘야 할지 모르게 된다. 따라서 세그먼트에 출발지의 세그먼트를 보낸 프로세스의 포트번호까지 포함함으로써, 해당 세그먼트가 어느 프로세스에 가야 하는지 알게 된다.

-두 개의 클라이언트가 같은 소스 포트번호를 설정하고 서버에 세그먼트를 보내면, 세그먼트의 헤더에 있는 두 포트넘버가 동일하기 때문에 생길수도 있지만, IP 데이터그램(네트워크 계층의 데이터 단위)의 헤더에 소스와 목적지의 IP가 포함되어 있기 때문에 결과적으로 혼란이 발생하지 않는다.


3.3 비연결형 트랜스포트 : UDP

-UDP는 트랜스포트 계층 프로토콜이 할 수 있는 최소한의 기능으로 동작한다. 
  다중화/역다중화 기능과 간단한 오류 검사를 제외하곤 아무것도 하지 않는다.

-UDP는 세그먼트를 송신하기 전에 hand-shake(통신 설정)을 하지 않는다. 
  그래서 UDP를 비연결형이라고 한다.

 *UDP를 쓰는 이유
1.hand-shake, 즉 연결 설정이 없다. 따라서 연결을 시작하기 위한 delay가 없다.
2.연결 상태(connection state)가 없다. 따라서 TCP보다 훨씬 간단하다.
3.패킷 헤더 오버헤드가 적다. TCP는 20바이트의 헤더 오버헤드를 가지지만 UDP는 8바이트의 헤더 오버헤드를 가진다.
4.전송률이 조절되지 않는다. 혼잡 제어 메커니즘이 없기 때문에 링크가 혼잡한 것과 상관없이 보낼 수 있다.

-UDP를 사용할 때, 어플리케이션이 특정한 기능(확인 응답 메커니즘, 재전송 메커니즘)만 갖추고 있다면, 신뢰성을 보장할 수 있다. 

3.3.1 UDP 세그먼트 구조
소스 포트 넘버
목적지 포트 넘버
길이
검사합(checksum)
응용데이터(메시지)


3.3.2 UDP 검사합(checksum)

-검사합은 세그먼트 안에 있는 모든 16비트 워드를 합한 다음, 1의 보수를 수행해서 얻는다.

-수신측에서 검사합이 포함된 모든 워드를 더하고 나면 1로 채워진 합을 얻을 수 있다. 만약 0이 들어 있다면 그 패킷에는 오류가 있음을 알 수 있다. 하지만 UDP는 오류를 발견해도 단지 app에게 경고를 할 뿐이다.


3.4 신뢰성 있는 데이터 전송의 원리

-신뢰적인 데이터 전송 프로토콜에서는 데이터가 변형되거나 손실되지 않는다. 그리고 전송된 순서대로 전달된다.

-rdt_send()는 reliable data protocol의 송신과 관련된 호출이다.
-udt_send()는 unreliable data protocol의 송신과 관련된 호출이다.
-프로토콜이 상위 계층(app계층)에 데이터를 전달하려고 할 때, deliver_data()를 호출한다.

3.4.1 신뢰적인 데이터 전송 프로토콜의 구축

 *완전하게 신뢰적인 채널 상에서의 신뢰적인 데이터 전송 : rdt 1.0
-하위의 채녈이 완전히 신뢰적인 가장 간단한 경우.
-FSM : finite-state machine. 변화를 일으키는 이벤트는 평행선 위에, 이벤트가 발생했을 때 취해지는 행동은 평행선 아래에 나타낸다.
-송신 측은 app계층의 호출을 기다리다가 호출되어 데이터를 받( rdt_send(data) )으면, 패킷에 첨부( make_pkt(packet,data) )하고 보낸( udt_send(packet) ) 다.
-수신 측은 network계층의 호출을 기다리다가 호출되어 패킷을 받( rdt_rcv(packet) )으면, 패킷으로부터 데이터를 추출( extract(packet, data) )한 후, 데이터를 app계층으로 전달( deliver_data(data) )한다.

 *비트 오류를 가진 채널 상에서의 신뢰적인 데이터 전송 : rdt 2.0
-패킷들이 송신된 순서대로 수신되지만, 패킷에 비트 오류가 생길 수 있다고 가정.
-positive ack(이하 ack)과 negative ack(이하 nak)이 사용된다. ack은 정확히 수신되었다는 것이고, nak은 재전송을 요청하는 것이다.
 *ARG(Automatic Repeat reQuest)프로토콜 : 네트워크에서 재전송을 기반으로 하는 신뢰적인 데이터 전송 프로토콜
1.오류 검출 : 검사합(checksum)필드를 사용하여 오류를 검출 할 수 있다.
2.수신자 피드백 : ACK와 NAK을 사용하는 것으로 송신자가 수신자의 상태를 알 수 있어야 한다.
3.재전송 : 송신자가 재전송을 할 수 있어야 한다.

-송신 측은 두가지 상태를 가진다. 상위 계층으로부터의 호출을 기다리는 상태에서, 패킷을 보내고 난 후에는 수신측에서 보내오는 ACK이나 NAK을 기다리는 상태가 된다. 이 상태에서는 상위 계층에서의 호출에 응하지 않는다. 이 상태에서 ACK을 받았을 경우, 상위 계층의 호출을 기다리는 상태로 돌아가고, NAK을 받았을 경우, 해당하는 패킷을 재전송하고 다시 신호를 기다린다. 그래서 rdt 2.0과 같은 프로토콜을 stop-and-wait 프로토콜이라 한다.

-수신 측은 송신측에서 온 패킷에서 오류가 검출되었을 경우, NAK신호를 보내고, 오류가 검출되지 않았으면 상위계층에 데이터를 보낸 후에 ACK신호를 보낸다.

- rdt 2.0에서는 치명적인 결점이 있다. ACK나 NAK 패킷의 변형의 가능성에 대해서는 고려하지 않고 있는 것이다. 

 *ACK 또는 NAK가 변형되었을 경우 처리 방법
1.ACK 또는 NAK 패킷의 재전송을 요청한다. 하지만 그 재전송마저 변형될 가능성이 있다.
2.패킷에 오류 검출뿐만 아니라 오류로부터의 회복도 할 수 있도록 충분한 검사합(checksum)비트를 추가하는 것이다.
3.왜곡된 ACK 또는 NAK을 받았을 경우 단순히 패킷을 재전송한다. 하지만 수신 측에서 재전송인지 새로운 패킷인지 알 수 없다.
->이 문제를 해결하기 위해 패킷에 순서 번호를 삽입한다. 

-rdt 2.1에서는 송신자가 4개의 상태, 수신자가 2개의 상태를 가진다. 이것은 순서번호가 0일 때와 1일때를 구별하기 위해서이다. 순서 번호를 제외한 나머지 이벤트와 동작은 상태가 0일 때와 1일 때가 같다.

-rdt 2.2에서는 NAK 신호 대신에 이전 패킷의 ACK 신호를 보낸다. 즉 송신 측에서 상태가 1인 패킷을 보냈는데 상태가 0인 ACK 신호가 왔다면 재전송을 해야 한다.

 *비트 오류를 갖는 손실 채녈 상에서의 신뢰적인 데이터 전송 : rdt 3.0
-실제 네트워크 상에서는 패킷의 손실이 일어난다. ACK 또는 NAK 신호가 왜곡되는 것이 아니라 아예 손실되어 버린다면, 송신측과 수신측은 계속 대기 상태에서 서로의 신호를 기다리고 있을 뿐이다. 이것을 해결하기 위하여 초읽기 타이머(countdown timer)를 사용한다.

-송신자는 패킷이 송신될 때 타이머를 시작하고, 응답이 도착하면 타이머를 멈추고, 타이머가 끝날 때까지 응답이 오지 않으면 재전송을 해야 한다.

-송신 측에서 ACK를 받았을 때, 그 신호가 최근에 전송된 패킷에 대한 응답인지 아니면 그 이전에 전송된 다른 패킷에 대한 응답인지 구분하기 위해서 ACK 패킷에 확인 응답 필드를 추가 시킨다. 그리고 그 필드에 순서 번호를 넣는 것이다.

-패킷의 순서 번호가 0과 1을 왔다갔다 하기 때문에 rdt 3.0을 얼터네이팅 비트(alternating bit)프로토콜 이라고 한다.

3.4.2 파이프라인된 신뢰적인 데이터 전송 프로토콜

-stop-and-wait프로토콜의 경우 실제 네트워크 상에서 그 효율이 엄청나게 낮다. 거리가 먼 두 곳일 경우 보내는 작업을 수행한 다음 그 패킷이 그 먼 거리를 갈 동안 기다리고, 수신측이 처리할 동안 기다리고, ACK/NAK신호가 그 먼 거리를 올 동안 기다려야 한다. 수신측도 마찬가지이다.

-이 문제를 해결하기 위하여 파이프라이닝 방식을 사용한다. 확인 응답을 기다릴 것 없이 다중 패킷을 전송하는 것이다. 물론 이 파이프라이닝 방식을 적용하기 위해서는 순서 번호의 범위가 증가되어야 하고, 송신측과 수신측이 한 패킷 이상을 버퍼링해야 한다.

3.4.3 Go-Back-N(GBN)

-GBN 프로토콜에서는 송신자가 확인 응답을 기다리지 않고 다중 패킷들을 전송할 수 있다. 그러나 응답이 오지 않은 패킷의 최대 혀용수 N보다는 크지 않게 해야 한다.

-가장 오래된 미응답 패킷의 번호를 base라 하고, 아직 사용되지 않은 가장 작은 번호를 nextseqnum이라 하면, 순서번호의 범위는 4개로 나누어 진다. 0에서 base-1까지는 전송된 후 응답이 된 패킷의 번호이고, base에서 nextseqnum-1까지는 전송했지만 아직 응답이 오지 않은 패킷의 번호이다. 그리고 nextseqnum에서 base+N-1까지는 패킷을 보내야 할 때 바로 사용할 수 있는 번호이고 base+N부터는 지금 당장 보낼수는 없는 번호들이다.

-N은 윈도우 크기라고 하고, GBN은 슬라이딩 윈도우 프로토콜이라고 한다.

 *GBN에서 송신자는 세가지 타입의 이벤트에 응답해야 한다.
1.상위계층의 호출 시에, 송신자는 윈도우가 가득 찼는지 확인해야 한다. 가득 차 있지 않다면 패킷이 생성되고 송신하면 된다.(그리고 nextseqnum은 한칸 이동하게 된다.) 가득 차 있다면 송신자는 상위 계층으로 데이터를 반환하거나 버퍼링하는등 송신을 지연시킨다.
2.ACK을 수신 했을 경우, 순서 번호 n의 ACK를 수신했을 경우 n까지의 모든 패킷을 올바르게 수신되었다고 생각할 수 있다.(그리고 윈도우와 base는 한칸 이동하게 된다.) 이것은 축적 확인 응답이라 한다.
3.타임 아웃 이벤트 : 타이머가 종료(타임아웃)되면, 송신자는 이전에 전송되었지만 아직 응답되지 않은 모든 패킷들을 다시 송신한다. 

-수신자의 동작을 간단하게 하기 위하여 순서가 틀린 패킷들은 전부 버린다. 따라서 따로 버퍼링할 필요가 없다.


3.4.4 선택적 반복 ( Selective Repeat, SR)

-GBN프로토콜에서는 stop-and-wait 프로토콜에서의 채널 이용률 문제를 해결할 수 있다. 하지만 윈도우크기가 크고, 대역폭-지연 결과가 크면 많은 패킷들이 파이프라인에 속하게 되고 불필요한 재전송이 많이 일어날 수 있다. 

-SR에서는 수신자에게서 오류가 발생한 패킷들만들 송신자가 재전송하도록 한다. 

-수신자는 정확하게 도착한 패킷의 ACK을 반드시 보내야 한다. 만약 그 패킷이 순서에 맞지 않는 것이라 할 지라도. 이전 패킷을 받았다고 응답을 하지 않으면, 송신자는 그 이전 패킷을 계속 보낼수 밖에 없다.




발견법(heuristic, 휴리스틱)은 경험에 기반하여 문제를 해결하거나 학습하거나 발견해 내는 방법을 말한다. 전산학 등 과학분야에서는 한정된 시간 내에 수행하기 위해 최적의 해 대신 현실적으로 만족할 만한 수준의 해를 구하는 방법이다. 형용사구로 발견적 방법(heuristic method, 휴리스틱 기법)라고도 한다.

출처 : 위키백과




간단하게 설명하자면,

휴리스틱은 어떤 문제를 푸는데 있어서 가장 좋은 방법이 아닌, 어느정도 인정할 만한 풀이 방법을 얻는 방법이다.


위의 위키백과 링크에서 컴퓨터 공학부분을 보면

컴퓨터 공학에서 발견법은 해결법이 정확히 해결되는지에 대한 문제를 무시하고 일반적으로 좋은 해결법이나 보다 간단한 해결법으로 풀고자 하는 문제 해결법이다. 예를 들어 상업적인 컴퓨터 바이러스 검색 소프트웨어들은 발견법으로 특정 속성이나 특징들을 찾아 바이러스나 나쁜 소프트웨어를 찾아낸다. 하지만 잠재적으로 정확도가 대신 떨어 질 수 있다.

 

즉, 그 해결법이 정확한, 완벽한, 증명된 해결법인지는 설명하지 않고,
일반적이고, 간단한 해결법을 찾는 것이다.

휴리스틱은 어림짐작이나, 추정이나, 직관적인 생각으로 이루어질 수 있다.

*누군가가 어떤 문제를 푸는 한 해결법을 생각해 내었지만, 그 방법이 수학적으로(=이론적으로) 올바른 해결법인지에 대해서 증명할 수 없다면, 그 해결법은 휴리스틱한 해결법이라고 할 수 있다.
하지만 그 해결법에 대해서 수학적으로 증명할 수 있다면, 그 해결법은 더 이상 휴리스틱한 방법이 아니게 된다.



이 휴리스틱 기법은 백신에서도 사용한다.
기존에 발견된 바이러스의 특징을 사용해서 변형된 바이러스를 찾아내는 것이다.
물론 기존 방법에 비해서 정확도가 떨어진다.



+ Recent posts