Linux Tutorial #5 GCC 확장 속성 (Attributes)

문연수·2021년 5월 18일
0

Linux Tutorial

목록 보기
6/25
post-thumbnail

리눅스 커널은 C 언어 표준만으로 작성되어 있지 않다. 인라인 어셈블리, 다양한 GCC 확장 속성(함수, 자료형, 레이블, etc.) 등을 통해 구현되어 있다. 위 사진은 arch/x86/include/asm/vdso/gettimeofday.c 의 파일 내용(커널 버전 5.12.2) 이다. 보면 알겠지만, 분명 C 언어 로 작성되어 있지만 이질감이 느껴진다. 특히 57 행의 __attribute__69 행의 __always_inline 은 확실하게 비표준 이다. 이러한 속성(Attributes) 들은 모두 GCC 에서 제공해주는 기능으로 컴파일러에게 코드에 대한 약간에 힌트를 준다. 이러한 힌트를 바탕으로 컴파일러는 더 좋은 결과물을 만들어 낼 수 있다.

1. GNU GCC 컴파일러 속성 지정자

리눅스 커널은 속성 지정자(attribute specifier)를 제공하며 다음의 형태를 가진다: __attribute__((attribute-list)). 이는 마치 지정자(specifier) 와 같이 동작한다. 대표적인 C 표준 지정자로 extern, unsigned 등이 있다. attribute-list 에는 다음과 같은:

  • Type 속성
  • Function 속성
  • Label 속성
  • Enumerator 속성
  • Statement 속성

종류가 있다.

리눅스 커널에서는 이러한 다양한 속성의 지정자를 미리 매크로로 정의해두었다:
이는 include/linux/compiler_attributes.h 헤더파일의 내용 중의 일부이다. 이 밖에도 다양한 매크로가 있기 떄문에 한번쯤 살펴 보는 것을 추천한다.

2. Type 속성

Type 속성을 통해 데이터 타입에 속성을 부여할 수 있다.

 // 일반적인 변수의 선언
 int x = 0; 

 // __attribute__ 를 이용한 속성 지정: 16 바이트 단위로 정렬
 int y __attribute__((aligned(16))) = 0; 

위 예제는 일반적인 CBasic type 이였으나, 구조체(User-defined data type)에도 적용이 가능하다:

struct user_defined {
	int data_type[10];
} __attribute__((aligned(16)));

이렇게 16 바이트 단위로 정렬하라는 속성을 주는 것이 가능하다. 구조체의 aligningundefined 이기 때문에 이러한 속성은 undefined behavior (UB) 를 없애고, 컴파일러의 동작 방식을 구체적으로 명시해주는 장점이 있다.

3. Function 속성

Function 속성은 함수에 속성을 부여한다.

void __f(void) { /* do something */ }
void f(void) __attribute__((weak, alias("__f")));

위 명세(alias)는 함수에 대한 별칭을 생성하며 이는 반드시 지정되어야 한다.
weak 속성은 함수를 전역대신 약한 기호로 방출한다. 보통 사용자 코드에서 재정의 될 수 있는 라이브러리 함수에 대해 선언 되어진다.

4. Label 속성

Label 속성은 레이블(분기 위치)에 대해 속성을 부여한다.
대표적으로 unused, hot, cold 등이 존재한다.

  • unused : 이 특징은 프로그램이 생성한 코드가 사용하지 않는 레이블을 포함할 수도 있다는 것을 알리며, 이는 -Wall 과 함께 컴파일 되어진다. 사람이 작성한 코드에 사용하는 것은 부적합할지라도, #ifdef 조건을 포함하는 레이블로 분기하는 코드의 경우 유용할 수 있다.
  • hot : 레이블에 붙은 hot 속성은 컴파일러에게 다른 레이블의 경로보다 해당 레이블의 경로를 따라갈 가능성이 높은 것을 알리는데 사용되어진다.
  • cold : 레이블에 붙은 cold 속성은 다른 레이블에 비해 더 실행될 가능성이 적다는 것을 알린다.

5. Enumerator 속성

Enumerator 속성은 열거형에 대한 속성을 지정한다. 여기에는 현재(현재 필자의 GCC 버전인 9.3.0 을 기준으로) deprecated 속성 밖에 없다.

enum E {
	oldval __attribute__((deprecated)),
    newval
};

deprecated 속성은 소스 파일 내에서, 해당 속성이 지정된 열거형 사용 시 경고를 발생 시킨다. 이후 버전 프로그램에서 제거되어야 하는 열거형을 나타낼 때 유용하다.

6. Statement 속성

Statement 속성은 구문에 대해 속성을 부여한다. Enumerator 속성과 마찬가지로 아직 fallthrough 속성 밖에 없다.

switch (cond)
{
case 1:
	bar(1);
    __attribute__((fallthrough));
case 2:
	...

말 그대로 fallthrough (빠져버리는) 구문이다. 이 속성이 지정되면 컴파일러에게 다른 case 레이블로 빠져버릴 수 있다는 것과, switch 문 이 의도적으로 빠질 수 있게 설계되어 있으므로, -Wimplicit-fallthrough 경고가 필요 없다는 것을 알린다.


그 밖에도 다양한 속성들이 있지만 내용이 너무 방대하여 설명과 속성들을 일부 생략하였다. 자세한 내용은 필자가 아래에 적어둔 출처 를 통해서 그 내용을 확인하라.

출처

[사이트] https://gcc.gnu.org/onlinedocs/gcc-9.3.0/gcc/C-Extensions.html#C-Extensions
[책] 리눅스 커널 소스 해설: 기초입문 (정재준 저)
[책] C: A Reference Manual (Fifth Edition) (Samuel P. Harbison III, Guy L. Steele Jr. 저)
[책] C Programming: A Modern Approach (Second Edition) (K.N.KING 저)

profile
2000.11.30

0개의 댓글