大尾端 小尾端和 htons函数

本文深入探讨了大小尾端的概念及其在计算机体系结构中的作用,通过实例展示了如何判断机器的体系结构,并解释了在不同体系结构下进行网络编程时使用htons函数的重要性。
提到体系结构时,经常遇到大小尾端的概念,这里做个总结。
    big endian:大尾端,也称大端(高位)优先存储。
    little endian:小尾端,也称小端(低位)优先存储。
   如下00000000 00000000 00000000 00000001的存储
       
    大尾端: 00000000 00000000 00000000 00000001
           addr+0    addr+1     addr+2   addr+3     //先存高有效位(在低地址)
    小尾端: 00000001 00000000 00000000 00000000
           addr+0    addr+1     addr+2   addr+3     //先存低有效位(在低地址)

   故要判断机器的体系结构是大尾端还是小尾端,以下程序可以完成任务:

#include <</span>stdio.h>
int main()
{
    int tt = 1;
    char *c = (char*)(&tt);
    if(*c == 1)
    {
        printf("litte endian\n");
    }
    else
    {
        printf("big endian\n");
    }
    return 0;
}

在Linux和Windows网络编程时需要用到htons和htonl函数,用来将主机字节顺序转换为网络字节顺序。

在Intel机器下,执行以下程序

int main()
{
   printf("%d /n",htons(16));
      return 0;
}

得到的结果是4096,初一看感觉很怪。
解释如下,数字16的16进制表示为0x0010,数字4096的16进制表示为0x1000。 由于Intel机器是小尾端,存储数字16时实际顺序为1000,
存储4096时实际顺序为0010。因此在发送网络包时为了报文中数据为0010,需要经过htons进行字节转换。如果用IBM等大尾端机器,则没有这种字节顺序转换,但为了程序的可移植性,也最好用这个函数。

另外用注意,数字所占位数小于或等于一个字节(8 bits)时,不要用htons转换。这是因为对于主机来说,大小尾端的最小单位为字节(byte)。


16    -  00000000 00001000 
4096 - 00001000 00000000


当前使用的内核版本是5.4.281,原始tipc函数 static u16 tipc_build_gap_ack_blks(struct tipc_link *l, void *data) { struct sk_buff *skb = skb_peek(&l->deferdq); struct tipc_gap_ack_blks *ga = data; u16 len, expect, seqno = 0; u8 n = 0; if (!skb) goto exit; expect = buf_seqno(skb); skb_queue_walk(&l->deferdq, skb) { seqno = buf_seqno(skb); if (unlikely(more(seqno, expect))) { ga->gacks[n].ack = htons(expect - 1); ga->gacks[n].gap = htons(seqno - expect); if (++n >= MAX_GAP_ACK_BLKS) { pr_info_ratelimited("Too few Gap ACK blocks!\n"); goto exit; } } else if (unlikely(less(seqno, expect))) { pr_warn("Unexpected skb in deferdq!\n"); continue; } expect = seqno + 1; } /* last block */ ga->gacks[n].ack = htons(seqno); ga->gacks[n].gap = 0; n++; exit: len = tipc_gap_ack_blks_sz(n); ga->len = htons(len); ga->gack_cnt = n; return len; } panic位置在skb_queue_walk 5298: f940035a ldr x26, [x26] 529c: f9403fe0 ldr x0, [sp, #120] 52a0: eb1a001f cmp x0, x26 52a4: 540006c0 b.eq 537c <tipc_link_build_proto_msg+0x5a4> // b.none 52a8: f9406740 ldr x0, [x26, #200] 52ac: b9400818 ldr w24, [x0, #8] 52b0: 5ac00b18 rev w24, w24 52b4: 12003f05 and w5, w24, #0xffff 52b8: 17ffffe6 b 5250 <tipc_link_build_proto_msg+0x478> 中52a8: f9406740 ldr x0, [x26, #200] 官方5.8版本新增了修改https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/net/tipc/link.c?h=linux-5.8.y&id=d7626b5acff9227e2a65da636a53e09bdafdc0aa 参考这个提交,最小程度修改原始代码解决panic问题 将原始代码修改为static u16 tipc_build_gap_ack_blks(struct tipc_link *l, void *data) { struct sk_buff *skb, *tmp; struct tipc_gap_ack_blks *ga = data; u16 len, expect, seqno = 0; u8 n = 0; skb = skb_peek(&l->deferdq); if (!skb) goto exit; expect = buf_seqno(skb); /* Use skb_queue_walk_safe to prevent use-after-free */ skb_queue_walk_safe(&l->deferdq, skb, tmp) { seqno = buf_seqno(skb); if (unlikely(more(seqno, expect))) { ga->gacks[n].ack = htons(expect - 1); ga->gacks[n].gap = htons(seqno - expect); if (++n >= MAX_GAP_ACK_BLKS) { pr_info_ratelimited("Too few Gap ACK blocks!\n"); goto exit; } } else if (unlikely(less(seqno, expect))) { pr_warn("Unexpected skb in deferdq!\n"); continue; } expect = seqno + 1; } // Safely add the last consecutive block if (seqno && n < MAX_GAP_ACK_BLKS) { ga->gacks[n].ack = htons(seqno); // Last valid sequence number ga->gacks[n].gap = 0; n++; } exit: len = tipc_gap_ack_blks_sz(n); ga->len = htons(len); ga->gack_cnt = n; return len; } 请判断这段代码有没有解决panic问题,是否引入新的逻辑问题。 if段改为if (seqno && n < MAX_GAP_ACK_BLKS) 后,如果不赋值ga->gacks[n].ack是否会有问题
08-28
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值