システムプログラム(第6回): marshaling/unmarshaling

                                       筑波大学 システム情報系 情報工学域
                                       新城 靖
                                       <yas@cs.tsukuba.ac.jp>

このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~syspro/2022/2022-06-29/marshaling.html
あるいは、次のページから手繰っていくこともできます。
http://www.coins.tsukuba.ac.jp/~syspro/2022/
http://www.coins.tsukuba.ac.jp/~yas/

marshaling/unmarshaling

プログラム中のデータ項目とネットワーク上を流れるメッセージに対応づける。
marshaling (整列化)
メモリ中からデータ項目を集めて、ネットワークでメッセージとして 転送するのに適した形式にまとめる。
unmarshaling (非整列化)
逆。
英語の綴りは、l が1つのものと2つのもの(イギリス綴り)がある。教科書によって違う。

プロセスAがメモリ中のデータを1個にまとめてネットワークに送り出す。プロセスBが受け取り元に戻す
図? marshalingとunmarshaling

4個の要素からなる構造体を整列化して送信している。 整列化する基本的な方法 ネットワークからデータを受け取ると、先頭から解釈して元のデータを再現す る。

ネットワーク上を流れている時には、整列化された データの先頭にはネットワークのヘッダが付加されている。

整数のmarshaling

分散プログラムでは、メッセージを送信するプロセスと受信するプロセスが異 なる CPU で実行されることがある。整数をmarshalingする時には、次のような 点を考慮する必要がある。

バイト・オーダ

整数を送るだけでも、バイトオーダに気をつける必要がある。

C言語で扱える整数

C言語で扱える整数の例(コンパイラによって異なる)。 (現在のコンピュータのほとんどは、バイト単位でアドレスを付けているので、 1バイトの整数については、バイトオーダの問題はない。)

2バイト、または、4バイトの整数をメモリに保存する方法 : メモリの下位番地に上位バイトを置くか下位バイトを置くか

リトルエンディアン
下位番地に下位バイトを置く。x86 (Intel Pentium/Core, AMD Athlon/Phenom)。
ビッグエンディアン。
下位番地に上位バイトを置く。PowerPC, SPARC, m68k
PowerPC は、両方切り替え可能だが、ビッグエンディアンで使うことが多い。 ARM は、 両方切り替え可能だが、リトルエンディアンで使うことが多い。

◆0x2000番地に0x12345678を保存/saving 0x12345678 to the address 0x2000

main()
{
    int *p;
        p = (int *)0x2000;
        *p = 0x12345678;
}
        .globl  _main
        .align  4, 0x90
_main:
        pushq   %rbp
        movq    %rsp, %rbp
        movl    $305419896, 8192
        popq    %rbp
        ret

0x12345678を2000番地に保存する。
図? バイト・オーダ(byte order)

バイト・オーダが異なることも考慮した整数の送受信

現在、ネットワーク・バイト・オーダとしては、ビッグエンディアンが広く 使われている。

バイトオーダを変換するライブラリ関数

名前 方向 ビット数
uint32_t htonl(uint32_t hostlong) ホストからネットワークへ変換 32ビット
uint16_t htons(uint16_t hostshort) ホストからネットワークへ変換 16ビット
uint32_t ntohl(uint32_t netlong) ネットワークからホストへ変換 32ビット
uint16_t ntohs(uint16_t netshort) ネットワークからホストへ変換 16ビット

htonl() を使った整数の送信

uint32_t hostlong, netlong;
hostlong = 0x12345678 ;
netlong = htonl( hostlong );
send(conn, &netlong, sizeof(netlong), 0);

snprintf()/strtol()

snprintf() で文字列に直して送り、strtol() や atoi() でもどす方法もある。 文字列文化。インターネットのアプリケーションでよく使われる。

送信側:

    char buf[BUFSIZE];
    hostlong = 0x12345678 ;    
    snprintf(buf,BUFSIZE,"%d\n",hostlong );
    send(conn, buf, strlen(buf), 0);
思ったほど遅くはない。

注意:sscanf() は、整数をデコードするために使う分には問題ないが、 文字列を受け取るために使うとバッファ・オーバーフローが生じる可能性があるので、 使わない方がよい。

文字列のmarshaling


Last updated: 2022/06/07 15:57:26
Yasushi Shinjo / <yas@cs.tsukuba.ac.jp>