Linux/Linux Network

리눅스 네트워크 도입 - 1

Hans_S_92 2022. 6. 23. 01:07

- 네트워크 계층

메모리캐시

 커널은 메모리 블록을 할당하고 해제하기 위해 kmalloc 함수와 kfree 함수를 사용한다. C언어의 malloc과 free와 거의 유사하다. 커널 컴포넌트가 동일한 데이터 스트럭처 타입의 여러 인스턴스를 할당하는 것은 흔한 일이다. 할당과 해제가 자주 일어날 것으로 예상될 때 관련된 커널 컴포넌트 초기화 루틴은 대개 할당을 위한 특별한 메모리 캐시를 할당한다. 메모리 블록이 해제되면 초기에 할당받았던 해당 캐시 공간으로 반환한다. 커널이 네트워크 데이터를 전용 메모리 캐시에 저장하는 몇가지 예는 다음과 같다.

  1. 소켓 버퍼 디스크립터 이 캐시는 net/core/sk_buff.c 파일의 skb_init의 의해 할당되고 sk_buff 버퍼 디스크립터를 할당하는데 사용함. sk_buff 구조체는 네트워크 서브시스템 중 할당과 반환이 가장 많이 사용하는 변수 중 하나다.
  2. 인접 프로토콜 매핑 각각의 인접 프로토콜 L3-L2 간 주소 매핑 정보를 저장하는 데이터 스트럭처 할당을 위해 메모리 캐시를 사용한다.
  3. 라우팅 테이블 라우팅 코드는 라우트를 정의하기 위해 2개의 데이터 스트럭처를 위한 메모리 캐시를 사용한다.

커널에서 다루는 메모리 함수는 다음과 같다.

  • kmem_cache_create, kmem_cache_destory 함수들은 캐시를 생성하고 소멸시킨다.
  • kmem_cache_alloc, kmem_cache_free 캐시를 할당하거나 해제한다. 대개 상위 레벨에서 할당과 해제를 관리하는 래퍼에 의해 호출

캐시와 해시 테이블

캐시를 사용하는 것은 성능을 향상시키는 방법 중 하나다. 네트워크 코드에서도 라우팅 테이블 캐시 등을 위해 L3-L2 매핑용 캐시( ARP 캐시)를 사용한다. 캐시는 대개 해시 테이블을 사용해 개발한다. 커널에는 단방향 리스트나 양방향 리스트와 같은 데이터 타입이 있어서 간단하게 해시 테이블을 만들 수 있다.


참조 카운트

삭제된 데이터 스트럭처에 대한 모음으로 커널 내의 컴포넌트들은 자신들이 데이터 스트럭처에 대한 참조를 저장하거나 풀어줄 때마다 참조 카운트를 각각 늘이거나 줄인다. 커널 컴포넌트 중 데이터 스트럭처 참조 카운트를 필요로 하는 것들은 참조 카운트를 늘리거나 줄이기 위해 xxx_hold, xxx_release 라는 이름을 각각 사용한다. 참조 카운트의 증감이 버그로 인하여 유지 되지 않으면 다음과 같다.

 

  1. xxx_release하는 것을 잃어버린다면 커널은 해당 데이터 구조체를 해제하지 못한다. 점진적으로 메모리가 소진된다.
  2. xxx_hold하는 것을 잃어버린다면 참조에 대한 숫자가 고려돼지 않기에 이미 해제됀 데이터의 참조를 갖게된다. 커널 패닉을 발생시킬 수 있다.

가비지 컬렉션

가상 메모리를 사용할 수 없는 커널에서는 특히 낭비가 없어야 한다. 대부분의 커널 서브시스템은 사용되지 않거나 오래된 데이터 구조체 인스턴스가 사용하고 있는 메모리를 회수할 수 있는 가비지 컬렉션 방법을 가지고 있다.

 

  1. 비동기적 ( Asynchronous ) 이벤트와 관련이 없다. 타이머가 주기적으로 데이터 스트럭처를 살펴보고 삭제해도 될 만하다고 판단된 메모리를 삭제하는 루틴을 수행한다. 대개 참조 카운트가 없는가를 기준으로 판단
  2. 동기적 ( Synchronous ) 메모리가 부족하여 타이머에 의해 수행되는 비동기적 가비지 컬렉션을 기다리기 어려울 경우 즉각적으로 메모리를 확보해야 하는 경우에 해당한다.

벡터 정의

어떠한 경우에는 데이터 스트럭처 정의의 마지막에 추가적인 코드 블록을 포함하기도 한다.\

struct abc {
	int abc;
	car *name[20];
 ...
	char placeholder[0];
}

추가적인 블록이 placeholder로 시작한다. placeholder가 크기 0인 벡터로 정의됐다. 이는 abc가 추가적인 블록과 같이 메모리를 할당받을 때 placeholder는 그 블록의 시작을 가리키는 것이다. 추가적인 블록이 없을 경우 placeholder 단지 스트럭처의 끝을 가리키는 포인터다.(메모리를 사용하지 않는다.)

⇒ 구조체 변수에 다른 구조체의 시작점을 넣는다는 건가? 맞는 말 같은데