gcc의 __attribute__((bitwise))에 관한 질문
글쓴이: 시로코 / 작성시간: 화, 2007/06/19 - 1:21오후
리눅스 커널 소스(2.6.21.x)의 include/linux/types.h에 보면
#ifdef __CHECKER__ #define __bitwise__ __attribute__((bitwise)) #else #define __bitwise__ #endif #ifdef __CHECK_ENDIAN__ #define __bitwise __bitwise__ #else #define __bitwise #endif typedef __u16 __bitwise __le16; typedef __u16 __bitwise __be16; typedef __u32 __bitwise __le32; typedef __u32 __bitwise __be32; #if defined(__GNUC__) && !defined(__STRICT_ANSI__) typedef __u64 __bitwise __le64; typedef __u64 __bitwise __be64; #endif typedef __u16 __bitwise __sum16; typedef __u32 __bitwise __wsum;
이렇게 __attribute__((bitwise))로 자료형이 정의된 것을 볼 수 가 있습니다.
__le16, __be16의 이름으로 봐서는 16비트 리틀 엔디안, 16비트 빅 엔디안 변수라는 것 같은데.
리눅스 커널 내에서도 대부분 코드들이 uint32_t를 사용하지 않고 __le16, __be16을 쓰고 있었습니다.
실제로 __attribute__((bitwise))는 어떤 효과를 가지는지 궁금합니다.
Forums:
GCC 속성 확장 중의
GCC 속성 확장 중의 하나이겠거니 생각했는데 아니로군요. "__attbibute__((bitwise))"로 검색한 결과 중 하나를 따라가다 보니 다음과 같은 내용들을 알 수 있었습니다.
리눅스 소스에 ~linux/Documentations/sparse.txt라는 파일이 있습니다. 문서 제목은 "Using sparse for typechecking"입니다. sparse는 "semantic parser"에서 따온 이름으로, 그 패키지 안에 들어있는 sparse라는 이름의 프로그램은 static analyzer라고 합니다.
sparse.txt 문서의 내용처럼, 커널 소스에서 "make C=1"이나 "make C=2"라고 명령을 주면 C 소스 파일에 대해 sparse 프로그램을 실행합니다. 그 때 "CHECKFLAGS=-D__CHECKER__ -D__CHECK_ENDIAN__" 옵션을 함께 주면 소스 코드에서 "__attribute__((bitwise))"가 활성화 된 상태로 sparse 프로그램이 이를 분석하게 됩니다. 그래서 "__attribute__((bitwise))" 속성이 일치하지 않는 변수 할당 등을 발견하면 다음과 같은 식의 메시지를 출력합니다.
리누스가 sparse를 작성하기 시작한 건 소스 내에서 사용자 메모리 공간에 대한 포인터와 커널 메모리 공간에 대한 포인터가 섞여 쓰이는 문제를 해결하기 위해서였다고 합니다. 컴파일러로는 탐지하기 힘든 코딩 상의 오류이죠. ~linux/include/linux/compiler.h에 그 내용이 들어가 있습니다. 그리고 이후 그걸 확장해서 엔디안 검사까지 하도록 확장된 듯 합니다.
----
$PWD `date`
$PWD `date`
답변
답변 감사드립니다.
그러면 엔디안 검사까지 한다면 __be64에 값을 넣으면 메모리에도 빅 엔디안 형식으로 들어간다는 것인가요? 현재 인텔 프로세서는 변수에 값을 넣으면 모두 리틀 엔디안으로 들어가는데, __be64, __le64가 이해가 잘 안됩니다.
__be64라고 타입을
__be64라고 타입을 선언했다고 해서 그 변수에는 알아서 빅엔디안으로 들어가는 건 아닙니다. 당연히
cpu_to_xxx()
등을 통해 적절히 변환을 해줘야 합니다. 말씀드린 '엔디안 검사'라는 건 그렇게 적절히 변환하는 과정을 실수로 빠뜨린 경우를 잡아주는 거라고 할 수 있습니다. 가령 다음과 같은 경우이죠.----
$PWD `date`
$PWD `date`
댓글 달기