日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
「深入淺出」Linuxntohl函數(shù)使用方法詳解(linuxntohl函數(shù))

深入淺出:linux ntohl函數(shù)使用方法詳解

東山網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián),東山網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為東山超過千家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)營(yíng)銷網(wǎng)站建設(shè)要多少錢,請(qǐng)找那個(gè)售后服務(wù)好的東山做網(wǎng)站的公司定做!

網(wǎng)絡(luò)字節(jié)序和主機(jī)字節(jié)序的轉(zhuǎn)換是網(wǎng)絡(luò)編程中不可避免的問題。ntohl函數(shù)是Linux中處理字節(jié)序轉(zhuǎn)換的重要函數(shù)之一。本文將深入淺出地講解ntohl函數(shù)的使用方法。

一、關(guān)于字節(jié)序

在計(jì)算機(jī)系統(tǒng)中,數(shù)據(jù)類型是以數(shù)值形式存儲(chǔ)在內(nèi)存中的。然而,在網(wǎng)絡(luò)傳輸中,數(shù)據(jù)需要以二進(jìn)制流的形式進(jìn)行傳輸。由于不同的系統(tǒng)和處理器所使用的字節(jié)序(大端序或小端序)不同,為了確保數(shù)據(jù)在網(wǎng)絡(luò)傳輸過程中能夠被正確地讀取,需要進(jìn)行字節(jié)序的轉(zhuǎn)換。

網(wǎng)絡(luò)字節(jié)序是一種特定的字節(jié)序,用于在網(wǎng)絡(luò)中傳輸數(shù)據(jù)。網(wǎng)絡(luò)字節(jié)序采用大端字節(jié)序,在其中,高位字節(jié)存儲(chǔ)在低地址中,低位字節(jié)存儲(chǔ)在高地址中。

主機(jī)字節(jié)序則根據(jù)處理器的不同,有可能采用大端字節(jié)序,也有可能采用小端字節(jié)序。在大端字節(jié)序中,高位字節(jié)存儲(chǔ)在低地址,低位字節(jié)存儲(chǔ)在高地址;而在小端字節(jié)序中,則是恰恰相反。

例如,對(duì)于十六進(jìn)制數(shù)0x12345678,在不同的字節(jié)序中所對(duì)應(yīng)的內(nèi)存存儲(chǔ)方式如下:

大端字節(jié)序:0x12 0x34 0x56 0x78

小端字節(jié)序:0x78 0x56 0x34 0x12

在網(wǎng)絡(luò)編程中,需要使用一些函數(shù)將主機(jī)字節(jié)序轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)序,或者將網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換成主機(jī)字節(jié)序,這就是ntohl函數(shù)發(fā)揮作用的時(shí)候了。

二、ntohl函數(shù)的介紹

ntohl函數(shù)的作用就是將網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換成主機(jī)字節(jié)序。ntohl函數(shù)在頭文件中被定義,它的原型如下:

unsigned long int ntohl (unsigned long int x);

該函數(shù)將一個(gè)網(wǎng)絡(luò)字節(jié)序的32位整數(shù)x轉(zhuǎn)換成一個(gè)主機(jī)字節(jié)序的32位整數(shù)。函數(shù)返回一個(gè)主機(jī)字節(jié)序的32位整數(shù)。

在ntohl函數(shù)的實(shí)現(xiàn)中,將x強(qiáng)轉(zhuǎn)成了unsigned char*類型,并按照網(wǎng)絡(luò)字節(jié)序的順序?qū)?個(gè)字節(jié)的數(shù)據(jù)寫入一個(gè)32位整數(shù)中,然后將其返回。

在ntohl函數(shù)中,大端字節(jié)序和小端字節(jié)序的數(shù)據(jù)處理方法是完全一致的,因此ntohl函數(shù)的使用與系統(tǒng)的字節(jié)序無(wú)關(guān)。

三、ntohl函數(shù)的使用

下面的代碼片段演示了如何使用ntohl函數(shù)將網(wǎng)絡(luò)字節(jié)序的IP地址轉(zhuǎn)換成字符串:

“`

#include

#include

#include

#include

int mn() {

uint32_t ip = 0x7f000001;

uint8_t *p = (uint8_t*) &ip;

struct in_addr ip_addr;

memcpy(&ip_addr, &ip, sizeof(ip_addr));

char ip_str[INET_ADDRSTRLEN];

memset(ip_str, ‘\0’, INET_ADDRSTRLEN);

inet_ntop(AF_INET, &ip_addr, ip_str, INET_ADDRSTRLEN);

printf(“The IP address is: %s\n”, ip_str);

printf(“The IP address in host byte order is: %lu\n”, (unsigned long) ntohl(ip));

return 0;

}

“`

在這個(gè)代碼片段中,我們定義了一個(gè)32位的IP地址ip,這個(gè)IP地址是在網(wǎng)絡(luò)字節(jié)序下存儲(chǔ)的。我們使用了ntohl函數(shù)將它轉(zhuǎn)化為主機(jī)字節(jié)序,并輸出了它的十進(jìn)制形式。

需要注意的是,在使用ntohl函數(shù)時(shí),需要將網(wǎng)絡(luò)字節(jié)序的數(shù)據(jù)以某種形式存儲(chǔ)在內(nèi)存中,才能對(duì)其進(jìn)行處理。例如在上述代碼片段中,我們將數(shù)字變量ip強(qiáng)制轉(zhuǎn)換為一個(gè)unsigned char指針,并使用memcpy函數(shù)將其值復(fù)制到了一個(gè)struct in_addr類型的變量中,以便于inet_ntop函數(shù)將其轉(zhuǎn)化為字符串形式。

四、

成都網(wǎng)站建設(shè)公司-創(chuàng)新互聯(lián)為您提供網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)頁(yè)設(shè)計(jì)及定制高端網(wǎng)站建設(shè)服務(wù)!

大端的計(jì)算機(jī)用語(yǔ)

端模式(Endian)的這個(gè)詞出自JonathanSwift書寫的《格列佛游記》。這本書根據(jù)將雞蛋敲開的方法不同將所有的人分為兩類,從圓頭開始將雞蛋敲開的人被歸為BigEndian,從尖頭開始將雞蛋敲開的人被歸為L(zhǎng)ittileEndian。小人國(guó)的內(nèi)戰(zhàn)就源于吃雞蛋時(shí)是究竟從大頭(Big-Endian)敲開還是從小頭(Little-Endian)敲開。在計(jì)算機(jī)業(yè)BigEndian和LittleEndian也幾乎引起一場(chǎng)戰(zhàn)爭(zhēng)。在計(jì)算機(jī)業(yè)界,Endian表示數(shù)據(jù)在存儲(chǔ)器中的存放順序。下文舉例說明在計(jì)算機(jī)中大小端模式的區(qū)別。

如果將一個(gè)32位的整數(shù)0x存放到一個(gè)整型變量(int)中,這個(gè)整型變量采用大端或者小端模式在內(nèi)存中的存儲(chǔ)由下表所示。為簡(jiǎn)單起見,本書使用OP0表示一個(gè)32位數(shù)據(jù)的更高字節(jié)MSB(Most Significant Byte),使用OP3表示一個(gè)32位數(shù)據(jù)更低字節(jié)LSB(Least Significant Byte)。 ;地址偏移 ;大端模式 ;小端模式 0x00 12(OP0) 78(OP3) 0x01 34(OP1) 56(OP2) 0x02 56(OP2) 34(OP1) 0x03 78(OP3) 12(OP0) 如果將一個(gè)16位的整數(shù)0x1234存放到一個(gè)短整型變量(short)中。這個(gè)短整型變量在內(nèi)存中的存儲(chǔ)在大小端模式由下表所示。 ;地址偏移 ;大端模式 ;小端模式 0x00 12(OP0) 34(OP1) 0x01 34(OP1) 12(OP0) 由上表所知,采用大小模式對(duì)數(shù)據(jù)進(jìn)行存放的主要區(qū)別在于在存放的字節(jié)順序,大端方式將高位存放在低地址,小端方式將高位存放在高地址。采用大端方式進(jìn)行數(shù)據(jù)存放符合人類的正常思維,而采用小端方式進(jìn)行數(shù)據(jù)存放利于計(jì)算機(jī)處理。到目前為止,采用大端或者小端進(jìn)行數(shù)據(jù)存放,其孰優(yōu)孰劣也沒有定論。

有的處理器系統(tǒng)采用了小端方式進(jìn)行數(shù)據(jù)存放,如Intel的奔騰。有的處理器系統(tǒng)采用了大端方式進(jìn)行數(shù)據(jù)存放,如IBM半導(dǎo)體和Freescale的PowerPC處理器。不僅對(duì)于處理器,一些外設(shè)的設(shè)計(jì)中也存在著使用大端或者小端進(jìn)行數(shù)據(jù)存放的選擇。

因此在一個(gè)處理器系統(tǒng)中,有可能存在大端和小端模式同時(shí)存在的現(xiàn)象。這一現(xiàn)象為系統(tǒng)的軟硬件設(shè)計(jì)帶來(lái)了不小的麻煩,這要求系統(tǒng)設(shè)計(jì)工程師,必須深入理解大端和小端模式的差別。大端與小端模式的差別體現(xiàn)在一個(gè)處理器的寄存器,指令集,系統(tǒng)總線等各個(gè)層次中。 從軟件的角度上,不同端模式的處理器進(jìn)行數(shù)據(jù)傳遞時(shí)必須要考慮端模式的不同。如進(jìn)行網(wǎng)絡(luò)數(shù)據(jù)傳遞時(shí),必須要考慮端模式的轉(zhuǎn)換。有過Socket接口編程經(jīng)驗(yàn)的程序員一定使用過以下幾個(gè)函數(shù)用于大小端字節(jié)序的轉(zhuǎn)換。

¨ #define ntohs(n) //16位數(shù)據(jù)類型網(wǎng)絡(luò)字節(jié)順序到主機(jī)字節(jié)順序的轉(zhuǎn)換

¨ #define htons(n) //16位數(shù)據(jù)類型主機(jī)字節(jié)順序到網(wǎng)絡(luò)字節(jié)順序的轉(zhuǎn)換

¨ #define ntohl(n) //32位數(shù)據(jù)類型網(wǎng)絡(luò)字節(jié)順序到主機(jī)字節(jié)順序的轉(zhuǎn)換

¨ #define htonl(n) //32位數(shù)據(jù)類型主機(jī)字節(jié)順序到網(wǎng)絡(luò)字節(jié)順序的轉(zhuǎn)換

其中互聯(lián)網(wǎng)使用的網(wǎng)絡(luò)字節(jié)順序采用大端模式進(jìn)行編址,而主機(jī)字節(jié)順序根據(jù)處理器的不同而不同,如PowerPC處理器使用大端模式,而Pentuim處理器使用小端模式。

大端模式處理器的字節(jié)序到網(wǎng)絡(luò)字節(jié)序不需要轉(zhuǎn)換,此時(shí)ntohs(n)=n,ntohl =n;而小端模式處理器的字節(jié)序到網(wǎng)絡(luò)字節(jié)必須要進(jìn)行轉(zhuǎn)換,此時(shí)ntohs(n) = __swab16(n),ntohl =__swab32(n)。__swab16與__swab32函數(shù)定義如下所示。 #define ___swab16(x)

{

__u16 __x = (x);

((__u16)(

(((__u16)(__x) & (__u16)0x00ffU) > 8)));

}

#define ___swab32(x)

{

__u32 __x = (x);

((__u32)(

(((__u32)(__x) & (__u32)0x000000ffUL) > 8) |

(((__u32)(__x) & (__u32)0xff000000UL) >> 24)));

} PowerPC處理器提供了lwbrx,lhbrx,stwbrx,sthbrx四條指令用于處理字節(jié)序的轉(zhuǎn)換以優(yōu)化__swab16和__swap32這類函數(shù)。此外PowerPC處理器中的rlwimi指令也可以用來(lái)實(shí)現(xiàn)__swab16和__swap32這類函數(shù)。在LinuxPowerPC中,定義了一系列有關(guān)字節(jié)序轉(zhuǎn)換的函數(shù),其詳細(xì)定義在./include/a-powerpc/byteorder.h文件中。

程序員在對(duì)普通文件進(jìn)行處理也需要考慮端模式問題。在大端模式的處理器下對(duì)文件的32,16位讀寫操作所得到的結(jié)果與小端模式的處理器不同。讀者單純從軟件的角度理解上遠(yuǎn)遠(yuǎn)不能真正理解大小端模式的區(qū)別。事實(shí)上,真正的理解大小端模式的區(qū)別,必須要從系統(tǒng)的角度,從指令集,寄存器和數(shù)據(jù)總線上深入理解,大小端模式的區(qū)別。 除了4.2.1節(jié)中,軟件上對(duì)不同端模式編程上的差異,處理器在硬件上也由于端模式問題在設(shè)計(jì)中有所不同。從系統(tǒng)的角度上看,端模式問題對(duì)軟件和硬件的設(shè)計(jì)帶來(lái)了不同的影響,當(dāng)一個(gè)處理器系統(tǒng)中大小端模式同時(shí)存在時(shí),必須要對(duì)這些不同端模式的訪問進(jìn)行特殊的處理。

PowerPC處理器主導(dǎo)網(wǎng)絡(luò)市場(chǎng),可以說絕大多數(shù)的通信設(shè)備都使用PowerPC處理器進(jìn)行協(xié)議處理和其他控制信息的處理,這也可能也是在網(wǎng)絡(luò)上的絕大多數(shù)協(xié)議都采用大端編址方式的原因。因此在有關(guān)網(wǎng)絡(luò)協(xié)議的軟件設(shè)計(jì)中,使用小端方式的處理器需要在軟件中處理端模式的轉(zhuǎn)變。而Pentium主導(dǎo)個(gè)人機(jī)市場(chǎng),因此多數(shù)用于個(gè)人機(jī)的外設(shè)都采用小端模式,包括一些在網(wǎng)絡(luò)設(shè)備中使用的PCI總線,F(xiàn)lash等設(shè)備,這也要求硬件工程師在硬件設(shè)計(jì)中注意端模式的轉(zhuǎn)換。

本書中的小端外設(shè)是指這種外設(shè)中的寄存器以小端方式進(jìn)行存儲(chǔ),如PCI設(shè)備的配置空間,NOR FLASH中的寄存器等等。

對(duì)于有些設(shè)備,如DDR顆粒,沒有以小端方式存儲(chǔ)的寄存器,因此從邏輯上講并不需要對(duì)端模式進(jìn)行轉(zhuǎn)換。在設(shè)計(jì)中,只需要將雙方數(shù)據(jù)總線進(jìn)行一一對(duì)應(yīng)的互連,而不需要進(jìn)行數(shù)據(jù)總線的轉(zhuǎn)換。

如果從實(shí)際應(yīng)用的角度說,采用小端模式的處理器需要在軟件中處理端模式的轉(zhuǎn)換,因?yàn)椴捎眯《四J降奶幚砥髟谂c小端外設(shè)互連時(shí),不需要任何轉(zhuǎn)換。

而采用大端模式的處理器需要在硬件設(shè)計(jì)時(shí)處理端模式的轉(zhuǎn)換。大端模式處理器需要在寄存器,指令集,數(shù)據(jù)總線及數(shù)據(jù)總線與小端外設(shè)的連接等等多個(gè)方面進(jìn)行處理,以解決與小端外設(shè)連接時(shí)的端模式轉(zhuǎn)換問題。

在寄存器和數(shù)據(jù)總線的位序定義上,基于大小端模式的處理器有所不同。

一個(gè)采用大端模式的32位處理器,如基于E500內(nèi)核的MPC8541,將其寄存器的更高位m(mostsignificant bit)定義為0,更低位l(lease significantbit)定義為31;而小端模式的32位處理器,將其寄存器的更高位定義為31,低位地址定義為0。

與此向?qū)?yīng),采用大端模式的32位處理器數(shù)據(jù)總線的更高位為0,更高位為31;采用小端模式的32位處理器的數(shù)據(jù)總線的更高位為31,更低位為0。如圖4.5所示。 OP0 OP1 OP2 OP3 OP0 OP1 OP2 OP0 ;圖4.5大小端模式處理器的寄存器的定義 ;大端模式處理器寄存器位序定義 ;小端模式處理器寄存器位序定義 大小端模式處理器外部總線的位序也遵循著同樣的規(guī)律,根據(jù)所采用的數(shù)據(jù)總線是32位,16位和8位,大小端處理器外部總線的位序有所不同。

¨ 大端模式下32位數(shù)據(jù)總線的m是第0位,MSB是數(shù)據(jù)總線的第0~7的字段;而l是第31位,LSB是第24~31字段。小端模式下32位總線的m是第31位,MSB是數(shù)據(jù)總線的第31~24位,l是第0位,LSB是7~0字段。

¨ 大端模式下16位數(shù)據(jù)總線的m是第0位,MSB是數(shù)據(jù)總線的第0~7的字段;而l是第15位,LSB是第8~15字段。小端模式下16位總線的m是第15位,MSB是數(shù)據(jù)總線的第15~7位,l是第0位,LSB是7~0字段。

¨ 大端模式下8位數(shù)據(jù)總線的m是第0位,MSB是數(shù)據(jù)總線的第0~7的字段;而l是第7位,LSB是第0~7字段。小端模式下8位總線的m是第7位,MSB是數(shù)據(jù)總線的第7~0位,l是第0位,LSB是7~0字段。

由上分析,我們可以得知對(duì)于8位,16位和32位寬度的數(shù)據(jù)總線,采用大端模式時(shí)數(shù)據(jù)總線的m和MSB的位置都不會(huì)發(fā)生變化,而采用小端模式時(shí)數(shù)據(jù)總線的l和LSB位置也不會(huì)發(fā)生變化。

為此,大端模式的處理器對(duì)8位,16位和32位的內(nèi)存訪問(包括外設(shè)的訪問)一般都包含第0~7字段,即MSB。小端模式的處理器對(duì)8位,16位和32位的內(nèi)存訪問都包含第7~0位,小端方式的第7~0字段,即LSB。

由于大小端處理器的數(shù)據(jù)總線其8位,16位和32位寬度的數(shù)據(jù)總線的定義不同,因此需要分別進(jìn)行討論在系統(tǒng)級(jí)別上如何處理端模式轉(zhuǎn)換。

在一個(gè)大端處理器系統(tǒng)中,需要處理大端處理器對(duì)小端外設(shè)的訪問。

1.1.2.1 大端處理器對(duì)32位小端外設(shè)進(jìn)行訪問大端處理器采用32位總線與小端外設(shè)進(jìn)行訪問時(shí),大端處理器的32位數(shù)據(jù)總線的第0~7位用來(lái)處理OP0,第8~15位用來(lái)處理OP1,第16~23位用來(lái)處理OP2,第24~31位用來(lái)處理OP3。而32位的小端設(shè)備使用數(shù)據(jù)總線的第31~24位用來(lái)處理OP0,第23~16位用來(lái)處理OP1,第15~8位用來(lái)處理OP2,第7~0位用來(lái)處理OP3。

大端處理器,如MPC8541,使用stw,sth,stb和lwz,lhz,lbz指令對(duì)32位的外部設(shè)備進(jìn)行訪問。在這些指令結(jié)束后,存放在外部設(shè)備的數(shù)據(jù)將被讀入MPC8541的通用寄存器中。為保證軟件的一致性,當(dāng)訪問結(jié)束后,存放在通用寄存器的字節(jié)序,即OP0,OP1,OP2和OP3必須要和存放在小端外設(shè)的字節(jié)序一致。此時(shí)在使用大端處理器的數(shù)據(jù)總線連接小端外設(shè)時(shí)必須要進(jìn)行一定的處理,按照某種拓?fù)浣Y(jié)構(gòu)連接以保證軟件的一致性。大端處理器數(shù)據(jù)總線與小端外設(shè)進(jìn)行連接的拓?fù)浣Y(jié)構(gòu)如圖4.6所示。 OP0 OP1 OP2 OP 0 ;大端處理器的32位數(shù)據(jù)總線 ;小端設(shè)備的32位總線接口 ;圖4.6 大端處理器與小端外設(shè)的32位連接 OP0 OP1 OP2 OP3 如圖4.6所示,采用大端處理器訪問小端設(shè)備時(shí),將各自的OP0~OP3字段直接相連。在大端處理器的32位數(shù)據(jù)總線的更高位為0,更低位為31;而小端設(shè)備的更高位為31,更低位為0。因此硬件工程師在進(jìn)行信號(hào)連接時(shí)需要將采用大端處理器的0~31位分別與小端設(shè)備的31~0位一一對(duì)應(yīng),進(jìn)行互連。

1.1.2.2 大端處理器對(duì)8,16位小端外設(shè)進(jìn)行訪問大端處理器使用8位,16位數(shù)據(jù)總線對(duì)8位,16位的小端外設(shè)進(jìn)行連接。對(duì)于32位處理器,用來(lái)連接外設(shè)的總線一般是32位。因此體系結(jié)構(gòu)工程師在進(jìn)行大端處理器總線設(shè)計(jì)時(shí)有兩種選擇,是采用32位總線的高端部分(第0~15字段)還是低端部分(第16~31字段)連接小端設(shè)備。PowerPC處理器使用32位總線的高端部分,即數(shù)據(jù)總線的第0~15位連接16位的小端設(shè)備,使用0~7位連接8位的小端設(shè)備。

PowerPC處理器采用16位總線與16位的小端外設(shè)進(jìn)行訪問時(shí),PowerPC處理器的16位數(shù)據(jù)總線的第0~7位用來(lái)處理OP0,第8~15位用來(lái)處理OP1。而16位的小端設(shè)備使用數(shù)據(jù)總線的第15~8位用來(lái)處理OP0,第7~0位用來(lái)處理OP1。

PowerPC處理器采用8位總線與8位的小端外設(shè)進(jìn)行訪問時(shí),PowerPC處理器的8位數(shù)據(jù)總線的第0~7字段用來(lái)處理OP0。而8位的小端設(shè)備使用數(shù)據(jù)總線的第7~0位用來(lái)處理OP1。大端處理器與小端外設(shè)的連接關(guān)系如圖4.7所示。 OP0 OP1 OP0 OP ;大端處理器的8/16位數(shù)據(jù)總線 ;小端設(shè)備的8/16位總線接口 ;圖4.7 大端處理器與小端外設(shè)的8/16位連接 OP0 OP 與32位總線接口類似,PowerPC處理器可以使用stw,sth,stb和lwz,lhz,lbz指令對(duì)32位的外部設(shè)備進(jìn)行訪問,并將數(shù)據(jù)存放在相應(yīng)的通用寄存器中。當(dāng)訪問結(jié)束后,存放在通用寄存器的字節(jié)序,即OP0,OP1必須要和存放在小端外設(shè)的字節(jié)序一致。

PowerPC處理器對(duì)8位的小端外設(shè)進(jìn)行訪問時(shí),一個(gè)總線周期只能訪問8位數(shù)據(jù),如果處理器使用stw或者lwz指令訪問8位的小端設(shè)備內(nèi)的32位數(shù)據(jù)時(shí),在數(shù)據(jù)總線上將OP0,OP1,OP2和OP3依次傳遞到PowerPC的通用寄存器中。

PowerPC處理器對(duì)16位的小端外設(shè)進(jìn)行訪問時(shí),一個(gè)總線周期只能訪問16位數(shù)據(jù),如果處理器使用stw或者lwz指令訪問16位的小端設(shè)備內(nèi)的32位數(shù)據(jù)時(shí),在數(shù)據(jù)總線上將OP0~1和OP2~3依次傳遞到PowerPC的通用寄存器中。

PowerPC處理器使用sth或者lhz指令訪問16位的小端設(shè)備時(shí),16位的小端設(shè)備將數(shù)據(jù)的第15~0位,傳遞到PowerPC處理器的總線的第0~15位,然后再將數(shù)據(jù)最終傳遞給相應(yīng)的通用寄存器。這里有許多讀者會(huì)感到困惑,因?yàn)闉榱吮WC軟件的一致性,PowerPC處理器使用lhz指令訪問16位的小端設(shè)備的16位寄存器時(shí),需要將結(jié)果保存在通用寄存器的第16~31位,而不是0~15位。究竟PowerPC處理器是如何將系統(tǒng)總線中0~15位的數(shù)據(jù)搬移到寄存器的第16~31位中的呢?為此我們需要對(duì)lhz指令進(jìn)行分析。 lhz rD,d(rA)

if rA = 0 then b ← 0

else b ← (rA)

EA ← b + EXTS(d)

rD ← (24)0 || MEM(EA,1) 由lhz指令的以上描述得知lhz指令將來(lái)自數(shù)據(jù)總線上的OP0與OP1直接存入寄存器的第16~31位,而將第0~15位直接清零。

PowerPC處理器使用stb或者lbz指令訪問8位的小端設(shè)備時(shí),8位的小端設(shè)備將數(shù)據(jù)的第7~0位,傳遞到PowerPC處理器的總線的第0~7位,然后再將數(shù)據(jù)最終傳遞給相應(yīng)的通用寄存器,lbz指令的描述如下所示。 lbz rD,d(rA)

if rA = 0 then b ← 0

else b ← (rA)

EA ← b + EXTS(d)

rD ← (24)0 || MEM(EA,1) 由lhz指令的以上描述得知lhz指令將來(lái)自數(shù)據(jù)總線上的OP0直接存入寄存器的第24~31位,而將第0~23位清零。

文章二:

大端(big-endian)和小端(little-endian)

:36 ;補(bǔ):x86機(jī)是小端(修改分區(qū)表時(shí)要注意),單片機(jī)一般為大端 今天碰一個(gè)關(guān)于字節(jié)順序的問題,雖然看起來(lái)很簡(jiǎn)單,但一直都沒怎么完全明白這個(gè)東西,索性就找了下資料,把它弄清楚. 因?yàn)楝F(xiàn)行的計(jì)算機(jī)都是以八位一個(gè)字節(jié)為存儲(chǔ)單位,那么一個(gè)16位的整數(shù),也就是C語(yǔ)言中的short,在內(nèi)存中可能有兩種存儲(chǔ)順序big-endian和 litte-endian.考慮一個(gè)short整數(shù)0x3132(0x32是低位,0x31是高位),把它賦值給一個(gè)short變量,那么它在內(nèi)存中的存 ;儲(chǔ)可能有如下兩種情況:

大端字節(jié)(Big-endian):

—>>>>>>>>;內(nèi)存地址增大方向

short變量地址

0x1000 0x1001

_____________________________| || 0x31 | 0x32|_______________ | ________________

高位字節(jié)在低位字節(jié)的前面,也就是高位在內(nèi)存地址低的一端.可以這樣記?。ù蠖?>;高位->;在前->;正常的邏輯順序)

小端字節(jié)(little-endian):

—>>>>>>>>;內(nèi)存地址增大方向

short變量地址

0x1000 0x1001

_____________________________| || 0x32 | 0x31|________________ | ________________低位字節(jié)在高位字節(jié)的前面,也就是低位在內(nèi)存地址低的一端.可以這樣記?。ㄐ《?>;低位->;在前->;與正常邏輯順序相反)

可以做個(gè)實(shí)驗(yàn)

在windows上下如下程序

#include

#include

void main(void)

{ short test; FILE* fp; test = 0x3132; //(31ASⅡC碼的’1’,32ASⅡC碼的’2’)

if ((fp = fopen (c:\\test.txt,wb)) == NULL)

assert(0); fwrite(&test,sizeof(short),1,fp); fclose(fp);

}

然后在C盤下打開test.txt文件,可以看見內(nèi)容是21,而test等于0x3132,可以明顯的看出來(lái)x86的字節(jié)順序是低位在前.如果我們把這段 ;同樣的代碼放到(big-endian)的機(jī)器上執(zhí)行,那么打出來(lái)的文件就是12.這在本機(jī)中使用是沒有問題的.但當(dāng)你把這個(gè)文件從一個(gè)big- endian機(jī)器復(fù)制到一個(gè)little-endian機(jī)器上時(shí)就出現(xiàn)問題了.

如上述例子,我們?cè)赽ig-endian的機(jī)器上創(chuàng)建了這個(gè)test文件,把其復(fù)制到little-endian的機(jī)器上再用fread讀到一個(gè) short里面,我們得到的就不再是0x3132而是0x3231了,這樣讀到的數(shù)據(jù)就是錯(cuò)誤的,所以在兩個(gè)字節(jié)順序不一樣的機(jī)器上傳輸數(shù)據(jù)時(shí)需要特別小 ;心字節(jié)順序,理解了字節(jié)順序在可以幫助我們寫出移植行更高的代碼.

正因?yàn)橛凶止?jié)順序的差別,所以在網(wǎng)絡(luò)傳輸?shù)臅r(shí)候定義了所有字節(jié)順序相關(guān)的數(shù)據(jù)都使用big-endian,BSD的代碼中定義了四個(gè)宏來(lái)處理:

#define ntohs(n) //網(wǎng)絡(luò)字節(jié)順序到主機(jī)字節(jié)順序 n代表net,h代表host,s代表short

#define htons(n) //主機(jī)字節(jié)順序到網(wǎng)絡(luò)字節(jié)順序 n代表net,h代表host,s代表short

#define ntohl(n) //網(wǎng)絡(luò)字節(jié)順序到主機(jī)字節(jié)順序 n代表net,h代表host,l代表 long

#define htonl(n) //主機(jī)字節(jié)順序到網(wǎng)絡(luò)字節(jié)順序 n代表net,h代表host,l代表 long

舉例說明下這其中一個(gè)宏的實(shí)現(xiàn):#define sw16(x) \ ((short)(\ (((short)(x) & (short)0x00ffU) > 8)))

這里實(shí)現(xiàn)的是一個(gè)交換兩個(gè)字節(jié)順序.其他幾個(gè)宏類似.

我們改寫一下上面的程序

#include

#include

#define sw16(x) \

((short)(\ (((short)(x) & (short)0x00ffU) > 8)))

// 因?yàn)閤86下面是低位在前,需要交換一下變成網(wǎng)絡(luò)字節(jié)順序

#define htons(x) sw16(x)

void main(void)

{ short test; FILE* fp;

test = htons(0x3132); //(31ASⅡC碼的’1’,32ASⅡC碼的’2’) if ((fp = fopen (c:\\test.txt,wb)) == NULL)

assert(0); fwrite(&test,sizeof(short),1,fp); fclose(fp);

}

如果在高字節(jié)在前的機(jī)器上,由于與網(wǎng)絡(luò)字節(jié)順序一致,所以我們什么都不干就可以了,只需要把#define htons(x) sw16(x)宏替換為 #define htons(x) (x).

一開始我在理解這個(gè)問題時(shí),總在想為什么其他數(shù)據(jù)不用交換字節(jié)順序?比如說我們write一塊buffer到文件,最后終于想明白了,因?yàn)槎际莡nsigned char類型一個(gè)字節(jié)一個(gè)字節(jié)的寫進(jìn)去,這個(gè)順序是固定的,不存在字節(jié)順序的問題,夠笨啊.. 文章三:

big-endian和little-endian這兩個(gè)術(shù)語(yǔ)來(lái)自Jonathan Swift在十八世紀(jì)的嘲諷作品Gulliver’s Travels。Blefuscu帝國(guó)的國(guó)民被根據(jù)吃雞蛋的方式劃分為兩個(gè)部分:一部分在吃雞蛋的時(shí)候從雞蛋的大端(bigend)開始,而另一部分則從雞蛋的小端(little end)開始。

x86的CPU使用的是LE(Windows中稱為“主機(jī)字節(jié)序”),而SocksAddr中使用的則是BE(就是“網(wǎng)絡(luò)字節(jié)序”),所以在使用網(wǎng)絡(luò)編程時(shí)需要使用htns,htnl,nths,nthl來(lái)倒字節(jié)序。

其實(shí)對(duì)匯編熟了就清楚了,慘,我的匯編很慘的LE little-endian 更符合人的思維的字節(jié)序 地址低位存儲(chǔ)值的低位 地址高位存儲(chǔ)值的高位 怎么講是更符合人的思維的字節(jié)序,是因?yàn)閺娜说闹挥^感來(lái)說 低位值小,就應(yīng)該放在內(nèi)存地址小的地方,也即內(nèi)存地址低位 反之,高位值就應(yīng)該放在內(nèi)存地址大的地方,也即內(nèi)存地址高位 BE big-endian 最直觀的字節(jié)序 地址低位存儲(chǔ)值的高位 地址高位存儲(chǔ)值的低位 為什么說直觀,不要考慮對(duì)應(yīng)關(guān)系 只需要把內(nèi)存地址從左到右按照由低到高的順序?qū)懗?把值按照通常的高位到低位的順序?qū)懗?兩者對(duì)照,一個(gè)字節(jié)一個(gè)字節(jié)的填充進(jìn)去 例子:在內(nèi)存中雙字0x(DWORD)的存儲(chǔ)方式 內(nèi)存地址LEBEMSDN中關(guān)于LE和BE的解釋Byte Ordering Byte ordering Meaning big-endian The most significant byte is on the left end of a word. little-endian The most significant byte is on the right end of a word. 這里這個(gè)最重要的字節(jié)可以解釋成值的更高位,如果換成是錢的話就是最值錢的那一位 比如我有1234元人民幣,最值錢的是1000元,最不值錢的是4元,那么這個(gè)1就是最重要的字節(jié)

Big endian machine: It thinks the first byte it reads is the biggest.Little endian machine: It thinks the first byte it reads is the littlest.舉個(gè)例子,從內(nèi)存地址0x0000開始有以下數(shù)據(jù)0x0000 0x120x0001 0x340x0002 0xab0x0003 0xcd如果我們?nèi)プx取一個(gè)地址為0x0000的四個(gè)字節(jié)變量,若字節(jié)序?yàn)閎ig-endian,則讀出結(jié)果為0x1234abcd;若字節(jié)序位little-endian,則讀出結(jié)果為0xcdab3412.如果我們將0x1234abcd寫入到以0x0000開始的內(nèi)存中,則結(jié)果為 big-endian little-endian0x0000 0x12 0xcd0x0001 0x23 0xab0x0002 0xab 0x340x0003 0xcd 0x12x86系列CPU都是little-endian的字節(jié)序。

關(guān)于linux ntohl函數(shù)的介紹到此就結(jié)束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關(guān)注本站。

創(chuàng)新互聯(lián)(cdcxhl.com)提供穩(wěn)定的云服務(wù)器,香港云服務(wù)器,BGP云服務(wù)器,雙線云服務(wù)器,高防云服務(wù)器,成都云服務(wù)器,服務(wù)器托管。精選鉅惠,歡迎咨詢:028-86922220。


當(dāng)前標(biāo)題:「深入淺出」Linuxntohl函數(shù)使用方法詳解(linuxntohl函數(shù))
文章地址:http://m.5511xx.com/article/cdogcee.html