私は以前にネットワークプログラミングを扱ったことがあります。しかし、これはネットリンクソケットへの私の最初の進出です。
私は「コネクタ」タイプの netlink ソケットを研究することにしました。他のカーネル コンポーネントと同様に、対応するユーザー コンポーネントもあります。Linux カーネルには、ucon.cというサンプル プログラムがあり、これを使用して、前述のコネクタ netlink ソケットに基づいてユーザー空間プログラムを構築できます。
そこで、ここでは、プログラムの理解を確認したい部分と、論理に従っていないプログラムの部分を特定したいと思います。十分な話。どうぞ。私が間違っているところはどこでも訂正してください。
私が理解している限り、netlink ソケットは同じマシン上のプロセスを接続するために使用される IPC メソッドであるため、プロセス ID が識別子として使用されます。また、netlink メッセージは理想的にはマルチキャストできるため、netlink ソケットが必要とするもう 1 つの識別子はメッセージ グループです。同じメッセージ グループに接続されているすべてのコンポーネントは、実際には関連しています。したがって、IPv4 の場合はsockaddrの代わりにsockaddr_inを使用しますが、ここでは上記の識別子を含むsockaddr_nlを使用します。
ここで、カーネルの TCP/IP スタックを使用しないため、netlink メッセージの場合、netlinkパケットはrawと見なすことができます(間違っている場合はここで訂正してください)。したがって、ネットリンク パケットが通過する唯一のカプセル化は、nlmsghdrとして定義されたネットリンク メッセージ ヘッダーです。
さて、プログラムの ucon に移ります。まず、コネクタプロトコルを使用main()
して NETLINK ファミリ ソケットを作成します。次に、前述の netlink socketaddress 構造体に関連情報を入力します。ここで少し実験的にするために、connector.h ファイルにエントリを追加しました。ここで私の最初の質問です。
コネクタ メッセージには、connector.h で定義された特定のタイプがあります。このコネクタのメッセージ構造は、完全に netlink の内部にあるものですよね? 同様に、netlink に関する限り、これはペイロード以外のすべてです。右?
続けて、netlink メッセージ ヘッダー構造内のnl-groupフィールドは正確には何を意味するのでしょうか? 定義には、この名前の要素は実際には含まれていません。では、ネットリンク メッセージ ヘッダーの特定のフィールドを埋めるためにオーバーレイ技術を使用しているのでしょうか? もしそうなら、対応は正確には何ですか?どこにも見つからないようです。
したがって、ソケット アドレスをソケットにバインドした後、10,000 個の一意のコネクタ ベースのデータを送信します。これは、netlink に関する限り、純粋なペイロードです。しかし、これらのメッセージに関する限り奇妙なのは、それらのすべてが同じシーケンス番号を持っているように見えることです。
次に進むと、netlink_sendサブルーチンで、上記でバインドされたソケットを介してこれらのパケットを送信することに気づきます。このサブルーチンは、さまざまな netlink ヘルパー マクロを使用して、送信するデータを操作します。上で述べたように、このmain()
関数は 10,000 個のデータを送信します。それぞれの長さは 0 であり、ack フィールドが 0 であるため確認応答は必要ありません (ここで間違っている場合は訂正してください)。したがって、各「パケット」は、何も含まれていないコネクタ メッセージ ヘッダーにすぎません。右?
ここで驚くべきことは、グローバル変数であるため、netlink_Send 関数が main() と同じシーケンス番号を使用することです。ただし、main() でのポスト インクリメントの後、現在は「1」です。したがって、基本的に私たちのネットリンクの話は、シーケンス番号「1」から始まります。それでいいですか?
linux/netlink.h で定義されているいくつかのヘルパー マクロを調べて、このプログラムで直接的または間接的に使用されているものについて、私の理解を要約しようと思います。
#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(NLMSG_HDRLEN))
そのため、このマクロは最初に netlink メッセージ ヘッダーの長さを調整し、次にペイロードの長さをそれに追加します。この場合、netlink ペイロードは、独自のペイロードを持たないコネクタ ヘッダーです。私たちの場合、このマイクロは次のように使用されます
nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh));
ここで、私が理解していないのは、netlink メッセージの実際のペイロードです。上記の場合、コネクタ メッセージ ヘッダーのサイズ (コネクタ メッセージ自体には独自のペイロードが含まれていないため) からポインタ (netlink メッセージの最初のバイト、したがって netlink メッセージ ヘッダーを指している) を引いたものです。そして、このポインターは (他のポインター変数と同様に) 機械語のサイズに等しく、私の場合は 4 バイトです。これをコネクタ メッセージ ヘッダーから差し引くのはなぜですか?
その後、他の IPv4 ソケットと同様に、この netlink ソケットを介してメッセージを送信します。上記の質問に関して、皆さんからのご連絡をお待ちしております。私の投稿はかなり長いので、実際の質問の前にいくつかの文を含めると役立ちます. しかし、それが私だけでなく人々に役立つことを願っています。
よろしく。