6月 30th, 2010

バイトオーダー? 朏 64bit移? メボ

Posted in Linux by admin

圏 考:Linuxアプリケーションぜ 64ビット・システムへの移植
http://www.ibm.com/developerworks/jp/linux/library/l-port64/

 上記URLにも掲載されていますが、アプリケーションを64bit移? する際の注? 点がいぜ つかあります。このうち、ネットワークプログラミングに頻出するバイトオーダーの? 朏 に関してメモを残します。簡単に? うと、ビッグエンディアン方? のネットワークバイトオーダーをLinuxのリトルエンディアン方? のバイトオーダーに? 朏 する際に使用する関? “ntohl”, “htonl”は、64bit Linux環? では正しく変朏 されないという事象の? 書です。以? 、サンプルプログラムと? 行結果を残します。

§ x86 64bit

# uname -m
x86_64
# cat test.c
#include <stdio .h>
#include <byteswap .h>

int main(){

	printf("int: %d\n", sizeof(int));
	printf("long: %d\n", sizeof(long));
	printf("int*: %d\n\n", sizeof(int*));

	int i = 0x12345678;
	long l = 0x0123456789abcdef;
	long m = 0x0123456789abcdef;
	char* c = (char *)&i;
	char* d = (char *)&l;
	char* e = (char *)&m;

	if (*(char *)&i == 0x12){
		printf ("Big endian\n\n");
	} else if(*(char *)&i == 0x78){
		printf ("Little endian\n\n");
	}

	printf("[1]int org:\t%X : %X : %X : %X\n" , c[0] , c[1] , c[2] , c[3]);
	i = htonl( i );
	printf("[2]int htonl:\t%X : %X : %X : %X\n\n" , c[0] , c[1] , c[2] , c[3]);

	printf("[3]long org:\t%X : %X : %X : %X : %X : %X : %X : %X\n" , \
		d[0] , d[1] , d[2] , d[3], d[4], d[5], d[6], d[7]);
	l = bswap_64( l );
	printf("[4]long bswap_64:\t%X : %X : %X : %X : %X : %X : %X : %X\n\n" , \
		d[0] , d[1] , d[2] , d[3], d[4], d[5], d[6], d[7]);

	printf("[5]long org:\t%X : %X : %X : %X : %X : %X : %X : %X\n" , \
		e[0] , e[1] , e[2] , e[3], e[4], e[5], e[6], e[7]);
	m = htonl( m );
	printf("[6]long htonl:\t%X : %X : %X : %X : %X : %X : %X : %lX\n" , \
		e[0] , e[1] , e[2] , e[3], e[4], e[5], e[6], e[7]);

	return 0;
}
# gcc test.c && ./a.out
int: 4
long: 8
int*: 8

Little endian

[1]int org:	78 : 56 : 34 : 12
[2]int htonl:	12 : 34 : 56 : 78

[3]long org:		FFFFFFEF : FFFFFFCD : FFFFFFAB : FFFFFF89 : 67 : 45 : 23 : 1
[4]long bswap_64:	1 : 23 : 45 : 67 : FFFFFF89 : FFFFFFAB : FFFFFFCD : FFFFFFEF

[5]long org:	FFFFFFEF : FFFFFFCD : FFFFFFAB : FFFFFF89 : 67 : 45 : 23 : 1
[6]long htonl:	FFFFFF89 : FFFFFFAB : FFFFFFCD : FFFFFFEF : FFFFFFFF : FFFFFFFF : FFFFFFFF : FFFFFFFF

 [5][6]で示した結果のように、64bit環? においぜ “htonl”関数では正しぜ バイトオーダーの? 朏 がされていないのが゜ かります。”htonl”、”ntohl”は、4バイト整数の? 朏 に使用され、同様に、”htons”、”ntohs”は、2バイト整数に使用されますが、64bit環? ぜ 8バイトデータサイズとなるlong型やポインターには使用出来ないからです。[3][4]のように正しく変朏 する為には、Linux上でぜ “bswap_64″マクボ (/usr/include/bits/byteswap.h)を使用します。以? のように、データサイズが4バイトを超えない32bit環? では問題なぜ 動作します。

§ i686 32bit

# uname -m
i686
# cat test.c
#include <stdio .h>
#include <byteswap .h>

int main(){

	printf("int: %d\n", sizeof(int));
	printf("long: %d\n", sizeof(long));
	printf("int*: %d\n\n", sizeof(int*));

	int i = 0x12345678;
	long l = 0x12345678;
	long m = 0x12345678;
	char* c = (char *)&i;
	char* d = (char *)&l;
	char* e = (char *)&m;

	if (*(char *)&i == 0x12){
		printf ("Big endian\n\n");
	} else if(*(char *)&i == 0x78){
		printf ("Little endian\n\n");
	}

	printf("[1]int org:\t%X : %X : %X : %X\n" , c[0] , c[1] , c[2] , c[3]);
	i = htonl( i );
	printf("[2]int htonl:\t%X : %X : %X : %X\n\n" , c[0] , c[1] , c[2] , c[3]);

	printf("[3]long org:\t%X : %X : %X : %X\n" , d[0] , d[1] , d[2] , d[3]);
	l = bswap_32( l );
	printf("[4]long bswap_32:\t%X : %X : %X : %X\n\n" , d[0] , d[1] , d[2] , d[3]);

	printf("[5]long org:\t%X : %X : %X : %X\n" , e[0] , e[1] , e[2] , e[3]);
	m = htonl( m );
	printf("[6]long htonl:\t%X : %X : %X : %X\n" , e[0] , e[1] , e[2] , e[3]);

	return 0;
}
# gcc test.c && ./a.out
int: 4
long: 4
int*: 4

Little endian

[1]int org:	78 : 56 : 34 : 12
[2]int htonl:	12 : 34 : 56 : 78

[3]long org:		78 : 56 : 34 : 12
[4]long bswap_32:	12 : 34 : 56 : 78

[5]long org:	78 : 56 : 34 : 12
[6]long htonl:	12 : 34 : 56 : 78
You can leave a comment, or trackback from your own site. RSS 2.0

One comment

  1. FirstKennith says:

    I see you don’t monetize your site, don’t waste your traffic, you can earn additional cash every month because you’ve got hi quality content.
    If you want to know how to make extra bucks, search for: Mrdalekjd methods for $$$

    10月 4th, 2017 at 12:37:51

Leave a comment