'Linux/Kernel Programming'에 해당하는 글 3건

리눅스 클럭 관련 코드를 뜯어보던 중,

부끄럽게도 처음보는 함수를 발견,

        unsigned int __r, __b = (base);                                 \
         if (!__builtin_constant_p(__b) || __b == 0 ||                   \
             (__LINUX_ARM_ARCH__ < 4 && (__b & (__b - 1)) != 0)) {       \
                 /* non-constant divisor (or zero): slow path */         \
                 __r = __do_div_asm(n, __b);


무엇에 쓰는 물건인고 하여 구글신께 조공을 드렸더니 떡하니 답을 주심 -ㅅ-;

__builtin_constant_p(__b) : __b라는 파라미터가 상수인가를 검사
                                         gcc builtin 함수로 지원됨

유사한 기능을 하는 빌트인 함수들이 많이 있군 -ㅅ-
중간에도 나와있으나 위와 같은 빌트인 함수들은 c 에서만 사용가능하다네요.

자세한 내용은 아래를 참조,

============================================================

출처 : http://gcc.gnu.org/onlinedocs/gcc-4.3.2/gcc/Other-Builtins.html

5.49 Other built-in functions provided by GCC

GCC provides a large number of built-in functions other than the ones mentioned above. Some of these are for internal use in the processing of exceptions or variable-length argument lists and will not be documented here because they may change from time to time; we do not recommend general use of these functions.

The remaining functions are provided for optimization purposes.

GCC includes built-in versions of many of the functions in the standard C library. The versions prefixed with __builtin_ will always be treated as having the same meaning as the C library function even if you specify the -fno-builtin option. (see C Dialect Options) Many of these functions are only optimized in certain cases; if they are not optimized in a particular case, a call to the library function will be emitted.

Outside strict ISO C mode (-ansi, -std=c89 or -std=c99), the functions _exit, alloca, bcmp, bzero, dcgettext, dgettext, dremf, dreml, drem, exp10f, exp10l, exp10, ffsll, ffsl, ffs, fprintf_unlocked, fputs_unlocked, gammaf,gammal, gamma, gammaf_r, gammal_r, gamma_r, gettext, index, isascii, j0f, j0l, j0, j1f, j1l, j1, jnf, jnl, jn, lgammaf_r, lgammal_r, lgamma_r, mempcpy, pow10f, pow10l, pow10, printf_unlocked, rindex, scalbf, scalbl, scalb,signbit, signbitf, signbitl, signbitd32, signbitd64, signbitd128, significandf, significandl, significand, sincosf, sincosl, sincos, stpcpy, stpncpy, strcasecmp, strdup, strfmon, strncasecmp, strndup, toascii, y0f, y0l, y0, y1f, y1l, y1, ynf,ynl and yn may be handled as built-in functions. All these functions have corresponding versions prefixed with __builtin_, which may be used even in strict C89 mode.

The ISO C99 functions _Exit, acoshf, acoshl, acosh, asinhf, asinhl, asinh, atanhf, atanhl, atanh, cabsf, cabsl, cabs, cacosf, cacoshf, cacoshl, cacosh, cacosl, cacos, cargf, cargl, carg, casinf, casinhf, casinhl, casinh, casinl,casin, catanf, catanhf, catanhl, catanh, catanl, catan, cbrtf, cbrtl, cbrt, ccosf, ccoshf, ccoshl, ccosh, ccosl, ccos, cexpf, cexpl, cexp, cimagf, cimagl, cimag, clogf, clogl, clog, conjf, conjl, conj, copysignf, copysignl, copysign, cpowf,cpowl, cpow, cprojf, cprojl, cproj, crealf, creall, creal, csinf, csinhf, csinhl, csinh, csinl, csin, csqrtf, csqrtl, csqrt, ctanf, ctanhf, ctanhl, ctanh, ctanl, ctan, erfcf, erfcl, erfc, erff, erfl, erf, exp2f, exp2l, exp2, expm1f, expm1l, expm1,fdimf, fdiml, fdim, fmaf, fmal, fmaxf, fmaxl, fmax, fma, fminf, fminl, fmin, hypotf, hypotl, hypot, ilogbf, ilogbl, ilogb, imaxabs, isblank, iswblank, lgammaf, lgammal, lgamma, llabs, llrintf, llrintl, llrint, llroundf, llroundl, llround, log1pf,log1pl, log1p, log2f, log2l, log2, logbf, logbl, logb, lrintf, lrintl, lrint, lroundf, lroundl, lround, nearbyintf, nearbyintl, nearbyint, nextafterf, nextafterl, nextafter, nexttowardf, nexttowardl, nexttoward, remainderf, remainderl, remainder,remquof, remquol, remquo, rintf, rintl, rint, roundf, roundl, round, scalblnf, scalblnl, scalbln, scalbnf, scalbnl, scalbn, snprintf, tgammaf, tgammal, tgamma, truncf, truncl, trunc, vfscanf, vscanf, vsnprintf and vsscanf are handled as built-in functions except in strict ISO C90 mode (-ansi or -std=c89).

There are also built-in versions of the ISO C99 functions acosf, acosl, asinf, asinl, atan2f, atan2l, atanf, atanl, ceilf, ceill, cosf, coshf, coshl, cosl, expf, expl, fabsf, fabsl, floorf, floorl, fmodf, fmodl, frexpf, frexpl, ldexpf,ldexpl, log10f, log10l, logf, logl, modfl, modf, powf, powl, sinf, sinhf, sinhl, sinl, sqrtf, sqrtl, tanf, tanhf, tanhl and tanl that are recognized in any mode since ISO C90 reserves these names for the purpose to which ISO C99 puts them. All these functions have corresponding versions prefixed with __builtin_.

The ISO C94 functions iswalnum, iswalpha, iswcntrl, iswdigit, iswgraph, iswlower, iswprint, iswpunct, iswspace, iswupper, iswxdigit, towlower and towupper are handled as built-in functions except in strict ISO C90 mode (-ansi or -std=c89).

The ISO C90 functions abort, abs, acos, asin, atan2, atan, calloc, ceil, cosh, cos, exit, exp, fabs, floor, fmod, fprintf, fputs, frexp, fscanf, isalnum, isalpha, iscntrl, isdigit, isgraph, islower, isprint, ispunct, isspace, isupper,isxdigit, tolower, toupper, labs, ldexp, log10, log, malloc, memchr, memcmp, memcpy, memset, modf, pow, printf, putchar, puts, scanf, sinh, sin, snprintf, sprintf, sqrt, sscanf, strcat, strchr, strcmp, strcpy, strcspn, strlen, strncat,strncmp, strncpy, strpbrk, strrchr, strspn, strstr, tanh, tan, vfprintf, vprintf and vsprintf are all recognized as built-in functions unless -fno-builtin is specified (or -fno-builtin-function is specified for an individual function). All of these functions have corresponding versions prefixed with __builtin_.

GCC provides built-in versions of the ISO C99 floating point comparison macros that avoid raising exceptions for unordered operands. They have the same names as the standard macros (isgreater, isgreaterequal, isless, islessequal, islessgreater, and isunordered) , with __builtin_ prefixed. We intend for a library implementor to be able to simply #define each standard macro to its built-in equivalent. In the same fashion, GCC provides isfinite and isnormal built-ins used with __builtin_ prefixed.

— Built-in Function: int __builtin_types_compatible_p (type1, type2)

You can use the built-in function __builtin_types_compatible_p to determine whether two types are the same.

This built-in function returns 1 if the unqualified versions of the types type1 and type2 (which are types, not expressions) are compatible, 0 otherwise. The result of this built-in function can be used in integer constant expressions.

This built-in function ignores top level qualifiers (e.g., const, volatile). For example, int is equivalent to const int.

The type int[] and int[5] are compatible. On the other hand, int and char * are not compatible, even if the size of their types, on the particular architecture are the same. Also, the amount of pointer indirection is taken into account when determining similarity. Consequently, short * is not similar to short **. Furthermore, two types that are typedefed are considered compatible if their underlying types are compatible.

An enum type is not considered to be compatible with another enum type even if both are compatible with the same integer type; this is what the C standard specifies. For example,enum {foo, bar} is not similar to enum {hot, dog}.

You would typically use this function in code whose execution varies depending on the arguments' types. For example:

          #define foo(x)                                                  \
({ \
typeof (x) tmp = (x); \
if (__builtin_types_compatible_p (typeof (x), long double)) \
tmp = foo_long_double (tmp); \
else if (__builtin_types_compatible_p (typeof (x), double)) \
tmp = foo_double (tmp); \
else if (__builtin_types_compatible_p (typeof (x), float)) \
tmp = foo_float (tmp); \
else \
abort (); \
tmp; \
})

Note: This construct is only available for C.

— Built-in Function: type __builtin_choose_expr (const_exp, exp1, exp2)

You can use the built-in function __builtin_choose_expr to evaluate code depending on the value of a constant expression. This built-in function returns exp1 if const_exp, which is a constant expression that must be able to be determined at compile time, is nonzero. Otherwise it returns 0.

This built-in function is analogous to the `? :' operator in C, except that the expression returned has its type unaltered by promotion rules. Also, the built-in function does not evaluate the expression that was not chosen. For example, if const_exp evaluates to true, exp2 is not evaluated even if it has side-effects.

This built-in function can return an lvalue if the chosen argument is an lvalue.

If exp1 is returned, the return type is the same as exp1's type. Similarly, if exp2 is returned, its return type is the same as exp2.

Example:

          #define foo(x)                                                    \
__builtin_choose_expr ( \
__builtin_types_compatible_p (typeof (x), double), \
foo_double (x), \
__builtin_choose_expr ( \
__builtin_types_compatible_p (typeof (x), float), \
foo_float (x), \
/* The void expression results in a compile-time error \
when assigning the result to something. */ \
(void)0))

Note: This construct is only available for C. Furthermore, the unused expression (exp1 or exp2 depending on the value of const_exp) may still generate syntax errors. This may change in future revisions.

— Built-in Function: int __builtin_constant_p (exp)

You can use the built-in function __builtin_constant_p to determine if a value is known to be constant at compile-time and hence that GCC can perform constant-folding on expressions involving that value. The argument of the function is the value to test. The function returns the integer 1 if the argument is known to be a compile-time constant and 0 if it is not known to be a compile-time constant. A return of 0 does not indicate that the value is not a constant, but merely that GCC cannot prove it is a constant with the specified value of the -O option.

You would typically use this function in an embedded application where memory was a critical resource. If you have some complex calculation, you may want it to be folded if it involves constants, but need to call a function if it does not. For example:

          #define Scale_Value(X)      \
(__builtin_constant_p (X) \
? ((X) * SCALE + OFFSET) : Scale (X))

You may use this built-in function in either a macro or an inline function. However, if you use it in an inlined function and pass an argument of the function as the argument to the built-in, GCC will never return 1 when you call the inline function with a string constant or compound literal (see Compound Literals) and will not return 1 when you pass a constant numeric value to the inline function unless you specify the -O option.

You may also use __builtin_constant_p in initializers for static data. For instance, you can write

          static const int table[] = {
__builtin_constant_p (EXPRESSION) ? (EXPRESSION) : -1,
/* ... */
};

This is an acceptable initializer even if EXPRESSION is not a constant expression. GCC must be more conservative about evaluating the built-in in this case, because it has no opportunity to perform optimization.

Previous versions of GCC did not accept this built-in in data initializers. The earliest version where it is completely safe is 3.0.1.

— Built-in Function: long __builtin_expect (long exp, long c)

You may use __builtin_expect to provide the compiler with branch prediction information. In general, you should prefer to use actual profile feedback for this (-fprofile-arcs), as programmers are notoriously bad at predicting how their programs actually perform. However, there are applications in which this data is hard to collect.

The return value is the value of exp, which should be an integral expression. The semantics of the built-in are that it is expected that exp == c. For example:

          if (__builtin_expect (x, 0))
foo ();

would indicate that we do not expect to call foo, since we expect x to be zero. Since you are limited to integral expressions for exp, you should use constructions such as

          if (__builtin_expect (ptr != NULL, 1))
error ();

when testing pointer or floating-point values.

— Built-in Function: void __builtin_trap (void)

This function causes the program to exit abnormally. GCC implements this function by using a target-dependent mechanism (such as intentionally executing an illegal instruction) or by calling abort. The mechanism used may vary from release to release so you should not rely on any particular implementation.

— Built-in Function: void __builtin___clear_cache (char *begin, char *end)

This function is used to flush the processor's instruction cache for the region of memory between begin inclusive and end exclusive. Some targets require that the instruction cache be flushed, after modifying memory containing code, in order to obtain deterministic behavior.

If the target does not require instruction cache flushes, __builtin___clear_cache has no effect. Otherwise either instructions are emitted in-line to clear the instruction cache or a call to the __clear_cache function in libgcc is made.

— Built-in Function: void __builtin_prefetch (const void *addr, ...)

This function is used to minimize cache-miss latency by moving data into a cache before it is accessed. You can insert calls to __builtin_prefetch into code for which you know addresses of data in memory that is likely to be accessed soon. If the target supports them, data prefetch instructions will be generated. If the prefetch is done early enough before the access then the data will be in the cache by the time it is accessed.

The value of addr is the address of the memory to prefetch. There are two optional arguments, rw and locality. The value of rw is a compile-time constant one or zero; one means that the prefetch is preparing for a write to the memory address and zero, the default, means that the prefetch is preparing for a read. The value locality must be a compile-time constant integer between zero and three. A value of zero means that the data has no temporal locality, so it need not be left in the cache after the access. A value of three means that the data has a high degree of temporal locality and should be left in all levels of cache possible. Values of one and two mean, respectively, a low or moderate degree of temporal locality. The default is three.

          for (i = 0; i < n; i++)
{
a[i] = a[i] + b[i];
__builtin_prefetch (&a[i+j], 1, 1);
__builtin_prefetch (&b[i+j], 0, 1);
/* ... */
}

Data prefetch does not generate faults if addr is invalid, but the address expression itself must be valid. For example, a prefetch of p->next will not fault if p->next is not a valid address, but evaluation will fault if p is not a valid address.

If the target does not support data prefetch, the address expression is evaluated if it includes side effects but no other code is generated and GCC does not issue a warning.

— Built-in Function: double __builtin_huge_val (void)

Returns a positive infinity, if supported by the floating-point format, else DBL_MAX. This function is suitable for implementing the ISO C macro HUGE_VAL.

— Built-in Function: float __builtin_huge_valf (void)

Similar to __builtin_huge_val, except the return type is float.

— Built-in Function: long double __builtin_huge_vall (void)

Similar to __builtin_huge_val, except the return type is long double.

— Built-in Function: double __builtin_inf (void)

Similar to __builtin_huge_val, except a warning is generated if the target floating-point format does not support infinities.

— Built-in Function: _Decimal32 __builtin_infd32 (void)

Similar to __builtin_inf, except the return type is _Decimal32.

— Built-in Function: _Decimal64 __builtin_infd64 (void)

Similar to __builtin_inf, except the return type is _Decimal64.

— Built-in Function: _Decimal128 __builtin_infd128 (void)

Similar to __builtin_inf, except the return type is _Decimal128.

— Built-in Function: float __builtin_inff (void)

Similar to __builtin_inf, except the return type is float. This function is suitable for implementing the ISO C99 macro INFINITY.

— Built-in Function: long double __builtin_infl (void)

Similar to __builtin_inf, except the return type is long double.

— Built-in Function: double __builtin_nan (const char *str)

This is an implementation of the ISO C99 function nan.

Since ISO C99 defines this function in terms of strtod, which we do not implement, a description of the parsing is in order. The string is parsed as by strtol; that is, the base is recognized by leading `0' or `0x' prefixes. The number parsed is placed in the significand such that the least significant bit of the number is at the least significant bit of the significand. The number is truncated to fit the significand field provided. The significand is forced to be a quiet NaN.

This function, if given a string literal all of which would have been consumed by strtol, is evaluated early enough that it is considered a compile-time constant.

— Built-in Function: _Decimal32 __builtin_nand32 (const char *str)

Similar to __builtin_nan, except the return type is _Decimal32.

— Built-in Function: _Decimal64 __builtin_nand64 (const char *str)

Similar to __builtin_nan, except the return type is _Decimal64.

— Built-in Function: _Decimal128 __builtin_nand128 (const char *str)

Similar to __builtin_nan, except the return type is _Decimal128.

— Built-in Function: float __builtin_nanf (const char *str)

Similar to __builtin_nan, except the return type is float.

— Built-in Function: long double __builtin_nanl (const char *str)

Similar to __builtin_nan, except the return type is long double.

— Built-in Function: double __builtin_nans (const char *str)

Similar to __builtin_nan, except the significand is forced to be a signaling NaN. The nans function is proposed by WG14 N965.

— Built-in Function: float __builtin_nansf (const char *str)

Similar to __builtin_nans, except the return type is float.

— Built-in Function: long double __builtin_nansl (const char *str)

Similar to __builtin_nans, except the return type is long double.

— Built-in Function: int __builtin_ffs (unsigned int x)

Returns one plus the index of the least significant 1-bit of x, or if x is zero, returns zero.

— Built-in Function: int __builtin_clz (unsigned int x)

Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined.

— Built-in Function: int __builtin_ctz (unsigned int x)

Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined.

— Built-in Function: int __builtin_popcount (unsigned int x)

Returns the number of 1-bits in x.

— Built-in Function: int __builtin_parity (unsigned int x)

Returns the parity of x, i.e. the number of 1-bits in x modulo 2.

— Built-in Function: int __builtin_ffsl (unsigned long)

Similar to __builtin_ffs, except the argument type is unsigned long.

— Built-in Function: int __builtin_clzl (unsigned long)

Similar to __builtin_clz, except the argument type is unsigned long.

— Built-in Function: int __builtin_ctzl (unsigned long)

Similar to __builtin_ctz, except the argument type is unsigned long.

— Built-in Function: int __builtin_popcountl (unsigned long)

Similar to __builtin_popcount, except the argument type is unsigned long.

— Built-in Function: int __builtin_parityl (unsigned long)

Similar to __builtin_parity, except the argument type is unsigned long.

— Built-in Function: int __builtin_ffsll (unsigned long long)

Similar to __builtin_ffs, except the argument type is unsigned long long.

— Built-in Function: int __builtin_clzll (unsigned long long)

Similar to __builtin_clz, except the argument type is unsigned long long.

— Built-in Function: int __builtin_ctzll (unsigned long long)

Similar to __builtin_ctz, except the argument type is unsigned long long.

— Built-in Function: int __builtin_popcountll (unsigned long long)

Similar to __builtin_popcount, except the argument type is unsigned long long.

— Built-in Function: int __builtin_parityll (unsigned long long)

Similar to __builtin_parity, except the argument type is unsigned long long.

— Built-in Function: double __builtin_powi (double, int)

Returns the first argument raised to the power of the second. Unlike the pow function no guarantees about precision and rounding are made.

— Built-in Function: float __builtin_powif (float, int)

Similar to __builtin_powi, except the argument and return types are float.

— Built-in Function: long double __builtin_powil (long double, int)

Similar to __builtin_powi, except the argument and return types are long double.

— Built-in Function: int32_t __builtin_bswap32 (int32_t x)

Returns x with the order of the bytes reversed; for example, 0xaabbccdd becomes 0xddccbbaa. Byte here always means exactly 8 bits.


— Built-in Function: int64_t __builtin_bswap64 (int64_t x)

Similar to __builtin_bswap32, except the argument and return types are 64-bit.




출처 : http://chlrbgh0.tistory.com/archive/201006

'Linux > Kernel Programming' 카테고리의 다른 글

atomic_t in Linux Kernel  (0) 2010.03.06
asmlinkage, __attribute__  (0) 2010.03.02

WRITTEN BY
RootFriend
개인적으로... 나쁜 기억력에 도움되라고 만들게되었습니다.

,
typedef struct {  int counter;} atomic_t;

형식은 리소스 카운터 용도로 사용한다.ATOMIC_INIT() 매크로로 값을 초기화한다.
64비트형을 따로 쓰는 아키텍처에서는 ATOMIC64_INIT()을 쓴다.
일부 아키텍처에서는 atomic_t와 atomic64_t 두 가지 형식을 제공하지만, x86 형식에서는
atomic_t만 지원한다. 대신 atomic_32.h와 atomic_64.h 헤더 파일로 나누어 32비트와 64비트
커널에 따라 정의를 달리 쓰지만, 어느 쪽이든 32비트 부호형(32bit signed) 정수로 선언하므로
사실상 같다.(i386 아키텍처는 현재 2.6.20 이상의 커널에서 쓰이지 않으며 x86으로 변경되었다. i386은 현재 심볼 링크 형태로만 그 흔적이 남아있다)
atomic_read(), atomic_set(), atomic_inc(), atomic_dec() 등의 다양한 매크로로 값을 조작한다.
접미어 _t를 붙이는 형식은 데이터 추상화(ADT, Abstract Data Type)를 위해 C 언어에서 자주 쓰는 방법이다.

typedef int atomic_t;정도로 써도 될텐데, 그렇게 하지 않는다.
struct으로 감싼 것과 아닌 것의 차이가 뭘까? typedef int로 선언하면 ++ 연산을 이용할 수 있고,
이는 설계자가 의도하지 않은 코드 작성이 된다.
이를 막고 안전하게 atomic_inc() 등으로 접근하라는 의도가 코드에 포함된 설계다.
i++이나 atomic_int(i)나 차이가 뭐가 크다고? 생각할지도 모르겠다. i++은 i = i + 1의 형태이고
 이는 값 읽어오기, 연산, 저장의 과정으로 이뤄진다.
atomic_inc()의 구현은 각 아키텍처별 어셈블리어로 되어 있다. 어셈블리 명령 단 하나로
구현하였다. CPU를 어떻게 쪼개든 어셈블리 명령 하나(보통 incl 명령)는 반드시 실행된다.
이는 CPU에서 실행할 수 있는 최소 단위(atomic) 명령이기 때문이다.

커널 2.6.22 이전까지의 코드나 2.6.22 이후 일부 아키텍처(xtensa 등)에서는 atomic_t를
volatile int로 선언한다.
typedef struct {
      volatile int counter;
}atomic_t;
이전까지는 volatile로 선언했으나 2.6.23 이후 버전은 int로만 선언한다.<Professional Linux Kernel Architecter>(Wrox, 2008)에서도 volatile int로 소개하는데, 이는 틀린 내용이다.
(책은 커널 2.6.24를 기준으로 설명한다지만, 해당 부분의 원고는 아마도 2.6.22 이하 버전일 때
작성했다고 추측한다)
volatile int가 int로 바뀐 이유는 무엇일까?
atomic_read() 동작 방식 때문이다. 컴파일러 최적화를 이용하면 레지스터에 저장된 값을
재사용하게 되고, 이는 레지스터에서 어떤 값이든 읽을 수 있음을 뜻한다.
루프를 처리하는 데 atomic_t 형식의 값을 외부 코드에서 변경하게 되면 코드는 엉망이 되고
만다. barrier()를 써서 이런 버그를 피할 수 있지만, 이는 루프에서 사용하는 모든 레지스터 값을
 다시 읽어와야 한다(reload). 이는 성능 측면에서 바람직하지 않으며, 이런 동작이 모든 아키텍처
에서 꼭 필요한 것도 아니다. 루프 안에서 barrier()를 써야 한다는 불필요한 의존성도 제거하고,
atomic_t 루프 외부에서 값을 변경할 수 있다고 생각해 버리자는 의도.



출처 : http://stnzone.com/gboard/bbs/board.php?bo_table=rss&wr_id=12696

'Linux > Kernel Programming' 카테고리의 다른 글

__builtin_constant_p  (0) 2010.08.31
asmlinkage, __attribute__  (0) 2010.03.02

WRITTEN BY
RootFriend
개인적으로... 나쁜 기억력에 도움되라고 만들게되었습니다.

,
리눅스 커널 코드를 분석하다보면 분명 작성된 언어는 C언어인데 처음보는 낯선 키워드등 분석이 잘 안되는 경우가 있습니다.

이는 메크로함수나 함수 포인터 등 #define으로 새로 정의되어 사용되는 키워드들 때문에 가독성이 떨어지기 때문입니다.
 
그 중 한 예로 리눅스의 스케줄링을 담당하는 schedule() 함수를 보면,

asmlinkage void __sched schedule(void)

이렇게 함수가 구성되어 있습니다.

이를 하나씩 살펴 보겠습니다.

asmlinkage는 어셈블리와 링크가 가능하다는 뜻 즉, 어셈블리어로 짜여진 코드에서 이 함수를 호출 할 수 있다는 뜻입니다.

__sched 이 키워드는 linux/include/linux/sched.h에 정의 되어 있습니다.

#define __sched __attribute__((__section__(".sched.text")))

다음과 같은 형태로 정의되어 있는데 ( 점점 더 복잡하게 되는 것 같습니다. )

__attribute__ 는 윈도우의 #pragma 와 비슷한 것으로 c의 표준은 아닙니다.

#pragma는 cl컴파일러에서 작동하며, __attribute__는 gcc컴파일러에서 작동하며 사용되는 용도는 비슷합니다.

__attribute__ 키워드의 대표적인 예로는

typedef struct
{
char a;
int b;
}asdf;

이런 구조체가 있을때 sizeof(asdf) 라고 하면 결과는 8이 나옵니다.

int a = sizeof(char)+sizeof(int);

printf("%d\n", a);

라고 했을 때 결과는 5가 나옵니다.

이는 packing(natural boundary)때문에 일어나는 현상입니다.

이를 정확한 값을 얻고 싶다면

typedef struct
{
char a;
int b;
}__attribute__(packed) asdf;

이렇게 하면 정확한 값이 나옵니다.  (윈도우에서는 #pragma pack(1) 라고 하면 됩니다.)

이 외에 __attribute__(x) 안에 들어갈 수 있는 것은 여러가지가 있습니다.

그럼 다시 돌아와서 살펴 보도록 하겠습니다.
 
__attribute__((__section__(".sched.text")))

이 키워드는 ".sched.text라는 섹션을 만들어서 그 섹션안에 schedule()함수의 내용을 넣어라" 라는 뜻이 됩니다.

이렇게 함으로써 얻을 수 있는 이점으로 섹션은 build 타임에 relocation이 가능하게 되는데,
 
초기화 역할을하는 특정 섹션을 만들어 그 안에 넣은 후 사용하다가 더이상 필요 없을 시 이 섹션을 날려 버립니다.

이런 방식으로 메모리 공간을 아낄 수 있습니다.
 
리눅스에서는 보통 커널공간이 1GB이고, 유저공간이 3GB입니다.(설정에 따라 달라질 수는 있습니다.)

만약 task_struct등 커널 오브젝트의 증가나 컨택스트 스위칭 등 커널 자원을 소비하는 작업을 할 때 커널 공간이 부족하다면 시스템 운영상 곤란 할 것입니다.

실제로 start_kernel() 함수도

asmlinkage void __init start_kernel(void)

#define __init __attribute__ ((__section__ (".text.init")))

이렇게 정의되어 있습니다.

즉 .text.init섹션에 start_kernel함수의 내용을 넣었다가 초가화가 끝나고 나면 이 섹션을 날리면서 메모리 공간을 절약합니다.

이렇게 리눅스에서는 커널공간을 효율적으로 관리하고 있습니다.

관련된 pdf파일을 첨부합니다. 관련된 내용은 아주 조금 있지만 전반적으로 읽어두면 커널을 이해하는데 조금 도움이 될듯합니다.




출처 : http://teamcrak.tistory.com/130

'Linux > Kernel Programming' 카테고리의 다른 글

__builtin_constant_p  (0) 2010.08.31
atomic_t in Linux Kernel  (0) 2010.03.06

WRITTEN BY
RootFriend
개인적으로... 나쁜 기억력에 도움되라고 만들게되었습니다.

,