κ°μ π
λΉ μλμκ³Ό 리ν μλμμ κ΄ν΄ μ 무μμ μ ν μ μλ μν©κ³Ό κ°κ°μ ν΄λΉνλ ν¬μΈν° μ°μ° μμ λ₯Ό μ’ ν©μ μΌλ‘ μ 리νλλ‘ νλ€.
μλμ(Endianness)μ μ»΄ν¨ν°μ λ©λͺ¨λ¦¬μ κ°μ 1μ°¨μ 곡κ°μ μ¬λ¬ κ°μ μ°μλ λμμ λ°°μ΄νλ λ°©λ²μ λ»νλ©°, λ°μ΄νΈλ₯Ό λ°°μ΄νλ λ°©λ²μ λ°μ΄νΈ μμ(Byte-order)λΌκ³ νλ€. μλμμ λ³΄ν΅ ν° λ¨μκ° μμ λμ€λ λΉ μλμ(Big-Endian)κ³Ό μμ λ¨μκ° μμ λμ€λ 리ν μλμ(Little-Endian)μΌλ‘ λλ μ μμΌλ©°, λ κ²½μ°μ μνμ§ μκ±°λ λ λͺ¨λ μ§μνλ κ²μ λ―Έλ€ μλμ(Middle-Endian)μ΄λΌ λΆλ₯Έλ€.
- Big-Endian: μ΅μμ λ°μ΄νΈ(MSB)λΆν° μ°¨λ‘λ‘ μ μ₯νλ λ°©μ (μ¬λμ΄ μ½κ³ μ°λ λ°©μκ³Ό λΉμ·ν¨)
- Little-Endian: μ΅νμ λ°μ΄νΈ(LSB)λΆν° μ°¨λ‘λ‘ μ μ₯νλ λ°©μ
μμ π
μλ₯Ό λ€μ΄, λ©λͺ¨λ¦¬μ 0x12345678μ λμ νλ€κ³ νμ λ, λΉ μλμκ³Ό 리ν μλμ κ°κ° μλμ κ°μ΄ μ μ₯λλ€.
λΉ μλμμ μ¬λμ΄ μ«μλ₯Ό μ¬μ©νλ κ²κ³Ό κ°μ΄ ν° λ¨μμ λ°μ΄νΈκ° μμ μ€λ λ°©λ²μ΄κ³ 리ν μλμμ λ°λλ‘ μμ λ¨μμ λ°μ΄νΈκ° μμ μ€λ λ°©λ²μ΄λ€.
#include <stdio.h>
int main(void) {
unsigned long value = 0x12345678;
unsigned char* ptr = &value;
int i;
for (i = 0; i < 4; i++) {
fprintf(stdout, "value[%d] = 0x%x\n", i, *ptr++);
}
unsigned long long value2 = 0x12345678abcdefab;
ptr = &value2;
for (i = 0; i < sizeof(value2); i++) {
fprintf(stdout, "value2[%d] = 0x%x\n", i, *ptr++);
}
return 0;
}
μμ μ½λλ₯Ό μ»΄νμΌνμ¬ Mac OS νκ²½μμ μ€ννλ©΄ μλμ κ°μ κ²°κ³Όλ₯Ό μ»μ μ μλ€.
~/Workspaces/study/languages/modernc/endian $ ./endian
value[0] = 0x78
value[1] = 0x56
value[2] = 0x34
value[3] = 0x12
value2[0] = 0xab
value2[1] = 0xef
value2[2] = 0xcd
value2[3] = 0xab
value2[4] = 0x78
value2[5] = 0x56
value2[6] = 0x34
value2[7] = 0x12
0x12345678μμ MSBλ 0x12, LSBλ 0x78μ΄λ©°, LSBκ° μ²μ λμ€λ κ²μΌλ‘ 보μ 리ν μλμ λ°©μμΌλ‘ Byte-ordering
μ νκ³ μλ κ²μ μ μ μλ€. unsigned long long
μ κ²½μ°λ‘ νμΈν μ μλ―μ΄ 4λ°μ΄νΈλ 8λ°μ΄νΈ λ¨μλ‘ byte-ordering λλ κ²μ΄ μλλΌ ν΄λΉ λ°μ΄ν° νμ
μ λ°λΌ λ¬λΌμ§λ κ²μ μ μ μλ€.
μ₯/λ¨μ π
κ°λ μ± π
Big-Endianμ μννΈμ¨μ΄μ λλ²κ·Έλ₯Ό νΈνκ² ν΄μ£Όλ κ²½ν₯μ΄ μλ€. μ¬λμ΄ μ«μλ₯Ό μ½κ³ μ°λ λ°©λ²κ³Ό κ°κΈ° λλ¬Έμ λλ²κΉ κ³Όμ μμ λ©λͺ¨λ¦¬μ κ°μ 보기 νΈνλ€. μλ₯Ό λ€μ΄, 0x59654148μ Big-EndianμΌλ‘ νννλ©΄ 0x59, 0x65, 0x41, 0x48 λ±μΌλ‘ λ©λͺ¨λ¦¬μ μμλλ‘ ννλλ€.
λ°λλ‘ Little-Endianμ λ©λͺ¨λ¦¬μ μ μ₯λ κ°μ νμ λ°μ΄νΈλ€λ§ μ¬μ©ν λ λ³λμ κ³μ°μ΄ νμ μλ€λ μ₯μ μ΄ μλ€. μλ₯Ό λ€μ΄, 32λΉνΈ μ«μμΈ 0x2Aλ 리ν μλμΈμΌλ‘ νννλ©΄ 2A 00 00 00μ΄ λλλ°, μ΄ ννμμ μμ λ λ°μ΄νΈ λλ ν λ°μ΄νΈλ§ λΌμ΄λ΄λ©΄ νμ 16λΉνΈ λλ 8λΉνΈλ₯Ό λ°λ‘ μ»μ μ μλ€. λ°λ©΄ 32λΉνΈ λΉ μλμ νκ²½μμλ νμ 16λΉνΈλ 8λΉνΈ κ°μ μ»κΈ° μν΄ λ³μ μ£Όμμ 2λ°μ΄νΈ λλ 3λ°μ΄νΈλ₯Ό λν΄μΌ νλ€.
컀λ λ΄ μΈν°νμ΄μ€ π
컀λμ byte order
μ λν μμ‘΄μ±μ ν΄κ²°νκΈ° μν΄ Type Identifier
, Conversion Macro
λ±μ μ 곡νκ³ μλ€. include/uapi/linux/types.h
ν€λ νμΌ λ΄μμλ μλμ κ°μ΄ μλμ λ³λ‘ νμ
λ€μ΄ μ μλμ΄ μλ κ²μ μ μ μλ€. μ¬κΈ°μ uapi λλ ν 리λ 컀λμ userspace APIλ₯Ό ν¬ν¨νκ³ μλ€.
(μ°Έκ³ . https://stackoverflow.com/questions/18858190/whats-in-include-uapi-of-kernel-source-project)
νμ μ μ π
/*
* Below are truly Linux-specific types that should never collide with
* any application/library that wants linux/types.h.
*/
#ifdef __CHECKER__
#define __bitwise__ __attribute__((bitwise))
#else
#define __bitwise__
#endif
#define __bitwise __bitwise__
typedef __u16 __bitwise __le16;
typedef __u16 __bitwise __be16;
typedef __u32 __bitwise __le32;
typedef __u32 __bitwise __be32;
typedef __u64 __bitwise __le64;
typedef __u64 __bitwise __be64;
typedef __u16 __bitwise __sum16;
typedef __u32 __bitwise __wsum;
bitwise μμ±(λ¨μν μ μλ‘μ¨ μ¬μ©λλ κ²μ μ ννλλ° μ¬μ©)μΌλ‘ μ μλμ΄ μλ Type Identifiers λ€μ΄λ€. bitwise μμ±μ sparse μ νΈλ¦¬ν°(static analyzer)κ° λ³μμ λν μ°μ°μ μννκΈ° μ μ λ‘컬 νλ‘μΈμλ‘ λ³νλ μ μλλ‘ λ³΄μ₯νλ€.
Byte Order μμλ΄κΈ° π
μλμ κ°μ΄ κ°λ¨ν user-space νλ‘κ·Έλ¨μ μμ±νμ¬ νμ¬ μμ€ν μ λ°μ΄νΈ μ€λλ₯Ό μμλΌ μ μλ€.
union {
int i;
char c[sizeof(int)];
} foo;
main() {
foo.i = 1;
if (foo.c[0] == 1)
printf("Little endian\n");
else
printf("Big endian\n");
}
λ€μμ μκ°λλ 맀ν¬λ‘λ λ³ν νμ κ°λ€μ λ°ννλ€.
#include <linux/kernel.h>
__u16 le16_to_cpu(const __le16);
__u32 le32_to_cpu(const __le32);
__u64 le64_to_cpu(const __le64);
__le16 cpu_to_le16(const __u16);
__le32 cpu_to_le32(const __u32);
__le64 cpu_to_le64(const __u64);
__u16 be16_to_cpu(const __be16);
__u32 be32_to_cpu(const __be32);
__u64 be64_to_cpu(const __be64);
__be16 cpu_to_be16(const __u16);
__be32 cpu_to_be32(const __u32);
__be64 cpu_to_be64(const __u64);
ν¬μΈν°μ λν λ³νμ pλ₯Ό λΆμ¬μ μλμ κ°μ΄ μ¬μ©νλ©°, νμ¬ μ¬μ© μ€μΈ νλ‘μΈμ μλμ νκ²½μ λ§κ² λ³νν΄μ£Όλ 맀ν¬λ‘λ μλμ κ°μ΄ μ 곡νκ³ μλ€.
#include <linux/kernel.h>
void le16_to_cpus(__u16 *);
void le32_to_cpus(__u32 *);
void le64_to_cpus(__u64 *);
void cpu_to_le16s(__u16 *);
void cpu_to_le32s(__u32 *);
void cpu_to_le64s(__u64 *);
void be16_to_cpus(__u16 *);
void be32_to_cpus(__u32 *);
void be64_to_cpus(__u64 *);
void cpu_to_be16s(__u16 *);
void cpu_to_be32s(__u32 *);
void cpu_to_be64s(__u64 *);
__u16 le16_to_cpup(const __le16 *);
__u32 le32_to_cpup(const __le32 *);
__u64 le64_to_cpup(const __le64 *);
__le16 cpu_to_le16p(const __u16 *);
__le32 cpu_to_le32p(const __u32 *);
__le64 cpu_to_le64p(const __u64 *);
__u16 be16_to_cpup(const __be16 *);
__u32 be32_to_cpup(const __be32 *);
__u64 be64_to_cpup(const __be64 *);
__be16 cpu_to_be16p(const __u16 *);
__be32 cpu_to_be32p(const __u32 *);
__be64 cpu_to_be64p(const __u64 *);