エンディアン


レジスタ(AX)にメモリ設定時、AHに下位アドレスを、ALに上位アドレスを設定するシステムをリトルエンディアン、その逆をビッグエンディアンと言い、数値データのメモリ設定で、下位アドレスをデータの終了とするのをリトルエンディアン。上位アドレスをデータの終了とするのをビッグエンディアン。とう事です。X86はリトルエンディアンです。

ビッグエンディアンデータをリトルエンディアンシステムで取り扱ったサンプルです。
#include "stdio.h"
#include "byteswap.h"

void    main()
{
       char    big_endian[] = {0x01, 0x02, 0x03, 0x04};

       short   int     *a;
       long    int     *b;
       char    *c;

       printf("short %d byte\n", sizeof(*a));
       printf("long  %d byte\n\n", sizeof(*b));

       a = (short int *)big_endian;
       b = (long int *)big_endian;
       c = big_endian;

       printf("%02x%02x%02x%02x\n\n", *c, *(c + 1), *(c + 2), *(c + 3));

       printf("%08x\n", *a);
       printf("%08x\n\n", *b);

       printf("%08x\n", bswap_16(*a));
       printf("%08x\n", bswap_32(*b));
}

[root@localhost north]# ./endial
short 2 byte
long  4 byte

01020304

00000201
04030201

00000102
01020304
システム外のデータ(ファイル/通信等)をやり取りする場合、そのデータのエンディアンとシステムのエンディアンに依存したデータ参照となります。

ext2_iget()でext2のスーパブロックデータからinodeの各種設定を行います。スーパブロックデータはリトルエンディアンで、inodeの各種設定はシステムエンディアン依存のle16_to_cpu()でリトルエンディアンをシステムがビッグエンディアンならbswap()で修正します。
#if BYTE_ORDER == LITTLE_ENDIAN
#define le16_to_cpu(val) (val)
#define le32_to_cpu(val) (val)
#endif
#if BYTE_ORDER == BIG_ENDIAN
#define le16_to_cpu(val) bswap_16(val)
#define le32_to_cpu(val) bswap_32(val)
#endif

struct ext2_inode {
       __le16  i_mode;         /* File mode */
       __le16  i_uid;          /* Low 16 bits of Owner Uid */
       __le32  i_size;         /* Size in bytes */
       __le32  i_atime;        /* Access time */
       __le32  i_ctime;        /* Creation time */
       __le32  i_mtime;        /* Modification time */
       __le32  i_dtime;        /* Deletion Time */
       __le16  i_gid;          /* Low 16 bits of Group Id */
       __le16  i_links_count;  /* Links count */
       __le32  i_blocks;       /* Blocks count */
       __le32  i_flags;        /* File flags */
       union {
               struct {
                       __le32  l_i_reserved1;
               } linux1;
               struct {
                       __le32  h_i_translator;
               } hurd1;
               struct {
                       __le32  m_i_reserved1;
               } masix1;
       } osd1;                         /* OS dependent 1 */
       __le32  i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
       __le32  i_generation;   /* File version (for NFS) */
       __le32  i_file_acl;     /* File ACL */
       __le32  i_dir_acl;      /* Directory ACL */
       __le32  i_faddr;        /* Fragment address */
       union {
               struct {
                       __u8    l_i_frag;       /* Fragment number */
                       __u8    l_i_fsize;      /* Fragment size */
                       __u16   i_pad1;
                       __le16  l_i_uid_high;   /* these 2 fields    */
                       __le16  l_i_gid_high;   /* were reserved2[0] */
                       __u32   l_i_reserved2;
               } linux2;
               struct {
                       __u8    h_i_frag;       /* Fragment number */
                       __u8    h_i_fsize;      /* Fragment size */
                       __le16  h_i_mode_high;
                       __le16  h_i_uid_high;
                       __le16  h_i_gid_high;
                       __le32  h_i_author;
               } hurd2;
               struct {
                       __u8    m_i_frag;       /* Fragment number */
                       __u8    m_i_fsize;      /* Fragment size */
                       __u16   m_pad1;
                       __u32   m_i_reserved2[2];
               } masix2;
       } osd2;                         /* OS dependent 2 */
};

struct inode *ext2_iget (struct super_block *sb, unsigned long ino)
{
       struct ext2_inode_info *ei;
       struct buffer_head * bh;
       struct ext2_inode *raw_inode;
       struct inode *inode;
       long ret = -EIO;
       int n;

       inode = iget_locked(sb, ino);
       if (!inode)
               return ERR_PTR(-ENOMEM);
       if (!(inode->i_state & I_NEW))
               return inode;

       ei = EXT2_I(inode);
       ei->i_block_alloc_info = NULL;

       raw_inode = ext2_get_inode(inode->i_sb, ino, &bh);
       if (IS_ERR(raw_inode)) {
               ret = PTR_ERR(raw_inode);
               goto bad_inode;
       }

       inode->i_mode = le16_to_cpu(raw_inode->i_mode);
       inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);
       inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low);
       if (!(test_opt (inode->i_sb, NO_UID32))) {
               inode->i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16;
               inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16;
       }
       set_nlink(inode, le16_to_cpu(raw_inode->i_links_count));
       inode->i_size = le32_to_cpu(raw_inode->i_size);
       inode->i_atime.tv_sec = (signed)le32_to_cpu(raw_inode->i_atime);
       inode->i_ctime.tv_sec = (signed)le32_to_cpu(raw_inode->i_ctime);
       inode->i_mtime.tv_sec = (signed)le32_to_cpu(raw_inode->i_mtime);
       inode->i_atime.tv_nsec = inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0;
       ei->i_dtime = le32_to_cpu(raw_inode->i_dtime);

       if (inode->i_nlink == 0 && (inode->i_mode == 0 || ei->i_dtime)) {
               /* this inode is deleted */
               brelse (bh);
               ret = -ESTALE;
               goto bad_inode;
       }
       inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
       ei->i_flags = le32_to_cpu(raw_inode->i_flags);
       ei->i_faddr = le32_to_cpu(raw_inode->i_faddr);
       ei->i_frag_no = raw_inode->i_frag;
       ei->i_frag_size = raw_inode->i_fsize;
       ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
       ei->i_dir_acl = 0;
       if (S_ISREG(inode->i_mode))
               inode->i_size |= ((__u64)le32_to_cpu(raw_inode->i_size_high)) << 32;
       else
               ei->i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
       ei->i_dtime = 0;
       inode->i_generation = le32_to_cpu(raw_inode->i_generation);
       ei->i_state = 0;
       ei->i_block_group = (ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);
       ei->i_dir_start_lookup = 0;

       for (n = 0; n < EXT2_N_BLOCKS; n++)
               ei->i_data[n] = raw_inode->i_block[n];

       if (S_ISREG(inode->i_mode)) {
               inode->i_op = &ext2_file_inode_operations;
               if (ext2_use_xip(inode->i_sb)) {
                       inode->i_mapping->a_ops = &ext2_aops_xip;
                       inode->i_fop = &ext2_xip_file_operations;
               } else if (test_opt(inode->i_sb, NOBH)) {
                       inode->i_mapping->a_ops = &ext2_nobh_aops;
                       inode->i_fop = &ext2_file_operations;
               } else {
                       inode->i_mapping->a_ops = &ext2_aops;
                       inode->i_fop = &ext2_file_operations;
               }
       } else if (S_ISDIR(inode->i_mode)) {
               inode->i_op = &ext2_dir_inode_operations;
               inode->i_fop = &ext2_dir_operations;
               if (test_opt(inode->i_sb, NOBH))
                       inode->i_mapping->a_ops = &ext2_nobh_aops;
               else
                       inode->i_mapping->a_ops = &ext2_aops;
       } else if (S_ISLNK(inode->i_mode)) {
               if (ext2_inode_is_fast_symlink(inode)) {
                       inode->i_op = &ext2_fast_symlink_inode_operations;
                       nd_terminate_link(ei->i_data, inode->i_size,
                               sizeof(ei->i_data) - 1);
               } else {
                       inode->i_op = &ext2_symlink_inode_operations;
                       if (test_opt(inode->i_sb, NOBH))
                               inode->i_mapping->a_ops = &ext2_nobh_aops;
                       else
                               inode->i_mapping->a_ops = &ext2_aops;
               }
       } else {
               inode->i_op = &ext2_special_inode_operations;
               if (raw_inode->i_block[0])
                       init_special_inode(inode, inode->i_mode,
                          old_decode_dev(le32_to_cpu(raw_inode->i_block[0])));
               else 
                       init_special_inode(inode, inode->i_mode,
                          new_decode_dev(le32_to_cpu(raw_inode->i_block[1])));
       }
       brelse (bh);
       ext2_set_inode_flags(inode);
       unlock_new_inode(inode);
       return inode;
       
bad_inode:
       iget_failed(inode);
       return ERR_PTR(ret);
}
le16/le32/le64はshort/int/long、__attribute__((bitwise))のbitwiseはgccの機能でなく、sparceコマンドと称するパーサでle16_to_cpu()/le32_to_cpu()を介さないで参照されてないかをチェックするための属性のようです。
typedef __u16 __bitwise __le16;
typedef __u32 __bitwise __le32;
typedef __u64 __bitwise __le64;

typedef unsigned short __u16;
typedef unsigned int __u32;
typedef unsigned long __u64;

#ifdef __CHECK_ENDIAN__
#define __bitwise __bitwise__
#else
#define __bitwise
#endif

#ifdef __CHECKER__
#define __bitwise__ __attribute__((bitwise))
#else
#define __bitwise__
#endif

最終更新 2016/02/12 17:15:32 - north
(2011/12/27 16:49:01 作成)


検索

アクセス数
3586054
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。