目次
1.コンセプト" >1.コンセプト
単語の長さ" >単語の長さ
2. 配置ルール" >2. 配置ルール
3. バイト アライメントの数を制限するにはどうすればよいですか? " >3. バイト アライメントの数を制限するにはどうすればよいですか?
1.デフォルト" >1.デフォルト
2.#pragma Pack(n)" >2.#pragma Pack(n)
四、为什么要对齐?" >四、为什么要对齐?
五、举例" >五、举例
例1:os基本数据类型占用的字节数" >例1:os基本数据类型占用的字节数
例2:结构体占用的内存大小–默认规则" >例2:结构体占用的内存大小–默认规则
例3:调整结构体大小" >例3:调整结构体大小
例5:#pragma pack(8)" >例5:#pragma pack(8)
例6:汇编代码" >例6:汇编代码
六、汇总实力" >六、汇总实力
ホームページ システムチュートリアル Linux Linuxのバイトアライメントについて

Linuxのバイトアライメントについて

Feb 05, 2024 am 11:06 AM
linux Linuxチュートリアル Linuxシステム Linuxコマンド シェルスクリプト overflow 埋め込みLinux 良い約束 Linux を始める Linux学習

最近、プロジェクトに取り組んでいたところ、問題が発生しました。 ARM 上で実行されている ThreadX が DSP と通信するとき、メッセージ キューを使用してメッセージを配信します (最終的な実装では、割り込みと共有メモリ メソッドが使用されます)。しかし、実際に動作させてみると、ThreadX が頻繁にクラッシュすることが判明しました。調査の結果、問題は、メッセージを渡す構造がバイト アラインメントを考慮していないという事実にあることがわかりました。

C言語におけるバイトアライメントの問題点を整理して共有したいと思います。

1.コンセプト

バイト アラインメントは、メモリ内のデータの位置に関係します。変数のメモリ アドレスがその長さの正確な整数倍である場合、その変数は自然に位置合わせされていると言われます。たとえば、32 ビット CPU では、整数変数のアドレスが 0x00000004 であると仮定すると、自然に整列されます。

まずビット、バイト、ワードとは何かを理解してください

############名前### ###英語名### ###意味### ###############少し### ###少し### 1 バイナリ ビットを 1 ビットと呼びます #########バイト### ###バイト### 8 バイナリ ビットは 1 バイトと呼ばれますコンピュータがトランザクションを一度に処理するために使用する固定長

単語の長さ

ワード内のビット数、つまり現代のコンピューターのワード長は、通常 16、32、または 64 ビットです。 (一般に、N ビット システムの語長は N/8 バイトです。)

異なる CPU は、一度に異なる数のデータ ビットを処理できます。32 ビット CPU は一度に 32 ビット データを処理でき、64 ビット CPU は一度に 64 ビット データを処理できます。ここでのビット語長を参照してください。

いわゆる語長のことをワードと呼ぶこともあります。 16 ビット CPU では、1 ワードはちょうど 2 バイトですが、32 ビット CPU では、1 ワードは 4 バイトです。キャラクターを単位とすると、その上にダブルキャラクター(2キャラクター)とクアッドキャラクター(4キャラクター)があります。

2. 配置ルール

標準データ型の場合、そのアドレスはその長さの整数倍である必要があるだけです。非標準データ型は次の原則に従って整列されます: 配列: 基本データ型に従って整列されます。最初のデータ型は、以下の通りです。 Union: 含まれるデータ型の最大長によって整列されます。構造: 構造内の各データ型は整列している必要があります。

3. バイト アライメントの数を制限するにはどうすればよいですか?

1.デフォルト

デフォルトでは、C コンパイラは、自然な境界条件に従って各変数またはデータ単位にスペースを割り当てます。一般に、デフォルトの境界条件は次の方法で変更できます。

2.#pragma Pack(n)

· #pragma Pack (n) ディレクティブを使用すると、C コンパイラは n バイトずつ整列します。 · カスタム バイト アライメントをキャンセルするには、ディレクティブ #pragma Pack () を使用します。

#pragma Pack(n) は、変数を n バイトのアライメントに設定するために使用されます。 n バイトのアライメントは、変数が格納される開始アドレスのオフセットには 2 つの状況があることを意味します。

    n が変数によって占有されるバイト数以上の場合、オフセットはデフォルトのアライメントを満たしている必要があります
  1. n が変数の型が占めるバイト数より小さい場合、オフセットは n の倍数となり、デフォルトのアライメントを満たす必要はありません。

構造体の合計サイズにも制約があります。n がすべてのメンバー変数の型が占めるバイト数以上の場合、構造体の合計サイズは次の数値でなければなりません。最大のスペースを占める変数が占めるスペースの倍数、それ以外の場合は n の倍数でなければなりません。

3.__属性

さらに、次のメソッドがあります: · __attribute((aligned (n)))。これは、作用される構造体のメンバーを n バイトの自然な境界に位置合わせします。構造内のいずれかのメンバーの長さが n より大きい場合、最大のメンバーの長さに応じて位置合わせされます。 ·

attribute ((packed)) は、コンパイル中に構造体の最適化された配置をキャンセルし、実際に占有されているバイト数に従って構造を配置します。

3.Assembly.align

アセンブリ コードは通常、.align を使用してバイト アラインメント ビット数を指定します。

.align: データの配置を指定するために使用されます。形式は次のとおりです:

リーリー

未使用のストレージ領域を特定の配置の値で埋めます。最初の値は配置 (4、8、16、または 32) を表します。2 番目の式の値は、埋められた値を表します。

四、为什么要对齐?

操作系统并非一个字节一个字节访问内存,而是按2,4,8这样的字长来访问。因此,当CPU从存储器读数据到寄存器,IO的数据长度通常是字长。如32位系统访问粒度是4字节(bytes), 64位系统的是8字节。当被访问的数据长度为n字节且该数据地址为n字节对齐时,那么操作系统就可以高效地一次定位到数据, 无需多次读取,处理对齐运算等额外操作。数据结构应该尽可能地在自然边界上对齐。如果访问未对齐的内存,CPU需要做两次内存访问。

字节对齐可能带来的隐患:

代码中关于对齐的隐患,很多是隐式的。比如在强制类型转换的时候。例如:

unsigned int i = 0x12345678;
unsigned char *p=NULL;
unsigned short *p1=NULL;

p=&i;
*p=0x00;
p1=(unsigned short *)(p+1);
*p1=0x0000;
ログイン後にコピー

最后两句代码,从奇数边界去访问unsignedshort型变量,显然不符合对齐的规定。在x86上,类似的操作只会影响效率,但是在MIPS或者sparc上,可能就是一个error,因为它们要求必须字节对齐.

五、举例

例1:os基本数据类型占用的字节数

首先查看操作系统的位数Linuxのバイトアライメントについて

在64位操作系统下查看基本数据类型占用的字节数:

#include 

int main()
{
    printf("sizeof(char) = %ld\n", sizeof(char));
    printf("sizeof(int) = %ld\n", sizeof(int));
    printf("sizeof(float) = %ld\n", sizeof(float));
    printf("sizeof(long) = %ld\n", sizeof(long));                                      
    printf("sizeof(long long) = %ld\n", sizeof(long long));
    printf("sizeof(double) = %ld\n", sizeof(double));
    return 0;
}
ログイン後にコピー
Linuxのバイトアライメントについて

例2:结构体占用的内存大小–默认规则

考虑下面的结构体占用的位数

struct yikou_s
{
    double d;
    char c;
    int i;
} yikou_t;
ログイン後にコピー

执行结果

sizeof(yikou_t) = 16
ログイン後にコピー

在内容中各变量位置关系如下:

其中成员C的位置Linuxのバイトアライメントについて还受字节序的影响,有的可能在位置8

编译器给我们进行了内存对齐,各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量类型所占用的字节数的倍数, 且结构的大小为该结构中占用最大空间的类型所占用的字节数的倍数。

对于偏移量:变量type n起始地址相对于结构体起始地址的偏移量必须为sizeof(type(n))的倍数结构体大小:必须为成员最大类型字节的倍数

char: 偏移量必须为sizeof(char) 即1的倍数
int: 偏移量必须为sizeof(int) 即4的倍数
float: 偏移量必须为sizeof(float) 即4的倍数
double: 偏移量必须为sizeof(double) 即8的倍数
ログイン後にコピー

例3:调整结构体大小

我们将结构体中变量的位置做以下调整:

struct yikou_s
{
    char c;
    double d;
    int i;
} yikou_t;
ログイン後にコピー

执行结果

sizeof(yikou_t) = 24
ログイン後にコピー

各变量在内存中布局如下:

Linuxのバイトアライメントについて

当结构体中有嵌套符合成员时,复合成员相对于结构体首地址偏移量是复合成员最宽基本类型大小的整数倍。

例4:#pragma pack(4)

#pragma pack(4)

struct yikou_s
{
    char c;
    double d;
    int i;
} yikou_t;
sizeof(yikou_t) = 16
ログイン後にコピー

例5:#pragma pack(8)

#pragma pack(8)

struct yikou_s
{
    char c;
    double d;
    int i;
} yikou_t;
sizeof(yikou_t) = 24
ログイン後にコピー

例6:汇编代码

举例:以下是截取的uboot代码中异常向量irq、fiq的入口位置代码:Linuxのバイトアライメントについて

六、汇总实力

有手懒的同学,直接贴一个完整的例子给你们:

#include 
main()
{
struct A {
    int a;
    char b;
    short c;
};
 
struct B {
    char b;
    int a;
    short c;
};
struct AA {
   // int a;
    char b;
    short c;
};

struct BB {
    char b;
   // int a;
    short c;
}; 
#pragma pack (2) /*指定按2字节对齐*/
struct C {
    char b;
    int a;
    short c;
};
#pragma pack () /*取消指定对齐,恢复缺省对齐*/
 
 
 
#pragma pack (1) /*指定按1字节对齐*/
struct D {
    char b;
    int a;
    short c;
};
#pragma pack ()/*取消指定对齐,恢复缺省对齐*/
 
int s1=sizeof(struct A);
int s2=sizeof(struct AA);
int s3=sizeof(struct B);
int s4=sizeof(struct BB);
int s5=sizeof(struct C);
int s6=sizeof(struct D);
printf("%d\n",s1);
printf("%d\n",s2);
printf("%d\n",s3);
printf("%d\n",s4);
printf("%d\n",s5);
printf("%d\n",s6);
}
ログイン後にコピー
#########キャラクター### ###言葉###

以上がLinuxのバイトアライメントについての詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

VSCODEに必要なコンピューター構成 VSCODEに必要なコンピューター構成 Apr 15, 2025 pm 09:48 PM

VSコードシステムの要件:オペレーティングシステム:オペレーティングシステム:Windows 10以降、MACOS 10.12以上、Linux Distributionプロセッサ:最小1.6 GHz、推奨2.0 GHz以上のメモリ:最小512 MB、推奨4 GB以上のストレージスペース:最低250 MB以上:その他の要件を推奨:安定ネットワーク接続、XORG/WAYLAND(Linux)

VSCODEは拡張子をインストールできません VSCODEは拡張子をインストールできません Apr 15, 2025 pm 07:18 PM

VSコード拡張機能のインストールの理由は、ネットワークの不安定性、許可不足、システム互換性の問題、VSコードバージョンが古すぎる、ウイルス対策ソフトウェアまたはファイアウォール干渉です。ネットワーク接続、許可、ログファイル、およびコードの更新、セキュリティソフトウェアの無効化、およびコードまたはコンピューターの再起動を確認することにより、問題を徐々にトラブルシューティングと解決できます。

Apr 16, 2025 pm 07:39 PM

NotePadはJavaコードを直接実行することはできませんが、他のツールを使用することで実現できます。コマンドラインコンパイラ(Javac)を使用してByteCodeファイル(filename.class)を生成します。 Javaインタープリター(Java)を使用して、バイトコードを解釈し、コードを実行し、結果を出力します。

Linuxアーキテクチャ:5つの基本コンポーネントを発表します Linuxアーキテクチャ:5つの基本コンポーネントを発表します Apr 20, 2025 am 12:04 AM

Linuxシステムの5つの基本コンポーネントは次のとおりです。1。Kernel、2。Systemライブラリ、3。Systemユーティリティ、4。グラフィカルユーザーインターフェイス、5。アプリケーション。カーネルはハードウェアリソースを管理し、システムライブラリは事前コンパイルされた機能を提供し、システムユーティリティはシステム管理に使用され、GUIは視覚的な相互作用を提供し、アプリケーションはこれらのコンポーネントを使用して機能を実装します。

vscodeの使用方法 vscodeの使用方法 Apr 15, 2025 pm 11:21 PM

Visual Studio Code(VSCODE)は、Microsoftが開発したクロスプラットフォーム、オープンソース、および無料のコードエディターです。軽量、スケーラビリティ、および幅広いプログラミング言語のサポートで知られています。 VSCODEをインストールするには、公式Webサイトにアクセスして、インストーラーをダウンロードして実行してください。 VSCODEを使用する場合、新しいプロジェクトを作成し、コードを編集し、コードをデバッグし、プロジェクトをナビゲートし、VSCODEを展開し、設定を管理できます。 VSCODEは、Windows、MacOS、Linuxで利用でき、複数のプログラミング言語をサポートし、マーケットプレイスを通じてさまざまな拡張機能を提供します。その利点には、軽量、スケーラビリティ、広範な言語サポート、豊富な機能とバージョンが含まれます

vscodeはMacに使用できますか vscodeはMacに使用できますか Apr 15, 2025 pm 07:36 PM

VSコードはMacで利用できます。強力な拡張機能、GIT統合、ターミナル、デバッガーがあり、豊富なセットアップオプションも提供しています。ただし、特に大規模なプロジェクトまたは非常に専門的な開発の場合、コードと機能的な制限がある場合があります。

vscodeとは何ですか?vscodeとは何ですか? vscodeとは何ですか?vscodeとは何ですか? Apr 15, 2025 pm 06:45 PM

VSコードは、Microsoftが開発した無料のオープンソースクロスプラットフォームコードエディターと開発環境であるフルネームVisual Studioコードです。幅広いプログラミング言語をサポートし、構文の強調表示、コード自動完了、コードスニペット、および開発効率を向上させるスマートプロンプトを提供します。リッチな拡張エコシステムを通じて、ユーザーは、デバッガー、コードフォーマットツール、GIT統合など、特定のニーズや言語に拡張機能を追加できます。 VSコードには、コードのバグをすばやく見つけて解決するのに役立つ直感的なデバッガーも含まれています。

GITの倉庫アドレスを確認する方法 GITの倉庫アドレスを確認する方法 Apr 17, 2025 pm 01:54 PM

gitリポジトリアドレスを表示するには、次の手順を実行します。1。コマンドラインを開き、リポジトリディレクトリに移動します。 2。「git remote -v」コマンドを実行します。 3.出力と対応するアドレスでリポジトリ名を表示します。

See all articles