Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 18528] ファイルの概要

このコミットは、Go言語のsyscallパッケージにおけるLinuxシステム定数の生成方法に関する変更です。具体的には、システム定数を生成する際に参照するLinuxカーネルのヘッダーファイルのパスを、より情報が豊富なinclude/linuxディレクトリ下のものに統一することで、情報の欠落を防ぎ、より正確な定数生成を目指しています。

コミット

commit be9c514f84ed45872f8ed89046dc600a1408eb1c
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date:   Sat Feb 15 00:47:28 2014 +0900

    syscall: make use of include/linux when generating system constants
    
    On Linux include/net directory is just to help porting applications
    from BSDs and files under net keep less information than include/linux.
    Making use of files under include/linux instead of include/net prevents
    lack of information.
    
    LGTM=iant
    R=golang-codereviews, iant
    CC=golang-codereviews
    https://golang.org/cl/63930043

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/be9c514f84ed45872f8ed89046dc600a1408eb1c

元コミット内容

syscall: make use of include/linux when generating system constants

On Linux include/net directory is just to help porting applications
from BSDs and files under net keep less information than include/linux.
Making use of files under include/linux instead of include/net prevents
lack of information.

変更の背景

この変更の背景には、Linuxカーネルのヘッダーファイルの構造と、Go言語のsyscallパッケージがシステムコールに関連する定数をどのように生成しているかという事情があります。

コミットメッセージに明記されている通り、Linuxシステムにおいて、include/netディレクトリ下のヘッダーファイルは、主にBSD系のオペレーティングシステムからアプリケーションを移植する際の互換性レイヤーとして提供されています。そのため、これらのファイルは、Linuxネイティブのinclude/linuxディレクトリ下のヘッダーファイルと比較して、情報が不足しているか、あるいは古い情報を含んでいる可能性があります。

Goのsyscallパッケージは、OS固有のシステムコールや定数にアクセスするためのインターフェースを提供します。これらの定数は、通常、C言語のヘッダーファイルを解析して自動生成されます。もし、情報が不完全なinclude/net下のヘッダーファイルを参照して定数を生成してしまうと、Goプログラムが利用できるシステム定数が不足したり、誤った値になったりするリスクがありました。

このコミットは、このような情報の欠落や不整合を防ぐため、より網羅的で正確な情報を提供するinclude/linuxディレクトリ下のヘッダーファイルを優先的に使用するように、定数生成スクリプトを変更することを目的としています。これにより、GoプログラムがLinuxシステムとより正確かつ堅牢に連携できるようになります。

前提知識の解説

1. syscallパッケージ (Go言語)

Go言語のsyscallパッケージは、オペレーティングシステムが提供する低レベルなインターフェース、すなわちシステムコールへのアクセスを提供します。システムコールは、ユーザー空間のプログラムがカーネル空間の機能(ファイルI/O、ネットワーク通信、プロセス管理など)を利用するための唯一の手段です。syscallパッケージは、OS固有の定数(エラーコード、ソケットオプションなど)や構造体、関数などをGoのコードから利用できるようにラップしています。

2. Linuxカーネルヘッダーファイル (include/linux vs include/net)

Linuxカーネルのソースコードには、ユーザー空間のプログラムがカーネルの機能とやり取りするために必要な定義が含まれるヘッダーファイル群が存在します。これらは通常、/usr/include/linux/usr/include/netといったパスにインストールされます。

  • include/linux: このディレクトリ下のヘッダーファイルは、Linuxカーネルのネイティブなインターフェースを定義しています。これらはLinux固有の機能や定数を最も正確かつ網羅的に記述しており、Linuxシステムプログラミングの標準的な参照先です。
  • include/net: このディレクトリ下のヘッダーファイルは、主にBSDソケットAPIとの互換性を提供するために存在します。歴史的にBSD系のOSで開発されたネットワークアプリケーションをLinuxに移植する際に、コードの変更を最小限に抑える目的で用意されました。しかし、この互換性レイヤーの性質上、include/linux下のファイルと比較して、情報が古かったり、Linux固有の新しい機能や定数が含まれていなかったりする場合があります。

3. システム定数の生成 (mkerrors.sh)

Go言語のsyscallパッケージでは、OS固有のシステム定数(例: AF_INET, SOCK_STREAM, EINVALなど)をGoのコードから利用できるようにするために、C言語のヘッダーファイルを解析してGoのソースコードを自動生成する仕組みが用いられています。このコミットで変更されているmkerrors.shのようなスクリプトは、その自動生成プロセスの一部を担っています。これらのスクリプトは、Cプリプロセッサやコンパイラを利用して、指定されたヘッダーファイルから必要な定数の値や定義を抽出し、Goのコードとして出力します。

4. Cプリプロセッサと#includeディレクティブ

C言語のソースコードでは、#includeディレクティブを使用して他のヘッダーファイルの内容を取り込みます。これはCプリプロセッサによって処理され、コンパイル前に指定されたヘッダーファイルの内容が現在のファイルに展開されます。このコミットでは、mkerrors.shスクリプト内で、Goのシステム定数生成のためにCプリプロセッサが参照する#includeパスが変更されています。

技術的詳細

このコミットの技術的な核心は、GoのsyscallパッケージがLinuxシステム定数を生成する際の「情報源」の変更にあります。

従来のmkerrors.shスクリプトは、Linuxのネットワーク関連の定数を取得する際に、net/if.hnet/if_arp.hnetpacket/packet.hといったinclude/netディレクトリ下のヘッダーファイルを参照していました。しかし、前述の通り、これらのファイルはBSD互換性のためであり、Linuxネイティブのinclude/linux下のファイルに比べて情報が不完全である可能性がありました。

具体的には、include/net下のファイルは、Linuxカーネルの進化に伴って追加された新しい定数や、より詳細な定義を含んでいないことがありました。これにより、Goプログラムが利用できるネットワーク関連の定数が不足したり、最新のLinuxカーネルの挙動と一致しない定数を使用したりするリスクがありました。

このコミットでは、以下の変更が行われています。

  1. include/netからの依存関係の削除:

    • #include <net/if.h>
    • #include <net/if_arp.h>
    • #include <netpacket/packet.h> これらのインクルードがmkerrors.sh内のincludes_Linux変数から削除されました。
  2. include/linuxへの依存関係の追加/強化:

    • #include <linux/if.h>
    • #include <linux/if_arp.h>
    • #include <linux/if_packet.h> これらのインクルードが新たに追加または維持されました。特にlinux/if_packet.hは、netpacket/packet.hのLinuxネイティブ版であり、より正確な定義を提供します。また、linux/if_addr.hは元々存在していましたが、この変更によりlinux/if.hlinux/if_arp.hと並んで、より一貫したinclude/linuxベースのネットワーク関連定数取得パスが確立されました。

この変更により、mkerrors.shは、Linuxカーネルのネットワークスタックに関する最新かつ最も正確な定義を含むinclude/linux下のヘッダーファイルから直接システム定数を抽出するようになります。これにより、Goのsyscallパッケージが提供する定数が、Linuxシステムの実際の挙動とより密接に一致し、将来的なカーネルの変更に対してもより堅牢になることが期待されます。

コアとなるコードの変更箇所

変更はsrc/pkg/syscall/mkerrors.shファイルに集中しています。

--- a/src/pkg/syscall/mkerrors.sh
+++ b/src/pkg/syscall/mkerrors.sh
@@ -92,9 +92,12 @@ includes_Linux='\
 #include <sys/types.h>
 #include <sys/time.h>
 #include <sys/socket.h>
-#include <linux/if_addr.h>
+#include <linux/if.h>
+#include <linux/if_arp.h>
 #include <linux/if_ether.h>\
 #include <linux/if_tun>\
+#include <linux/if_packet.h>\
+#include <linux/if_addr.h>\
 #include <linux/filter.h>\
 #include <linux/netlink.h>\
 #include <linux/reboot.h>\
@@ -103,10 +106,7 @@ includes_Linux='\
 #include <linux/sched.h>\
 #include <linux/wait.h>\
 #include <linux/icmpv6.h>\
-#include <net/if.h>\
-#include <net/if_arp.h>\
 #include <net/route.h>\
-#include <netpacket/packet.h>\
 #include <termios.h>\
 
 #ifndef MSG_FASTOPEN

具体的には、includes_Linuxというシェル変数内で定義されているC言語の#includeディレクティブが変更されています。

削除された行:

  • - #include <linux/if_addr.h> (これは後で再追加されていますが、位置が変更されています)
  • - #include <net/if.h>
  • - #include <net/if_arp.h>
  • - #include <netpacket/packet.h>

追加された行:

  • + #include <linux/if.h>
  • + #include <linux/if_arp.h>
  • + #include <linux/if_packet.h>
  • + #include <linux/if_addr.h> (元の位置から移動し、他のlinux/if_*.hファイルとまとまっています)

コアとなるコードの解説

mkerrors.shスクリプトは、Goのsyscallパッケージが利用するLinux固有の定数を生成するために、C言語のヘッダーファイルをインクルードし、そこから必要な情報を抽出します。このスクリプト内のincludes_Linux変数は、その抽出プロセスで使用されるCコードの断片を定義しています。

このコミットの変更は、includes_Linux変数内の#includeディレクティブのリストを修正することで、定数生成の「情報源」をinclude/netからinclude/linuxへと切り替えています。

  • net/if.hnet/if_arp.hnetpacket/packet.hの削除: これらのヘッダーファイルは、BSD互換性レイヤーの一部であり、Linuxネイティブの定義と比較して情報が不完全である可能性がありました。これらを削除することで、Goの定数生成プロセスが古いまたは不完全な情報に依存するのを防ぎます。
  • linux/if.hlinux/if_arp.hlinux/if_packet.hの追加: これらのヘッダーファイルは、Linuxカーネルのネットワークインターフェース、ARPプロトコル、およびパケットソケットに関するネイティブな定義を含んでいます。これらをインクルードすることで、Goのsyscallパッケージは、Linuxカーネルが提供する最新かつ最も正確なネットワーク関連の定数にアクセスできるようになります。
  • linux/if_addr.hの移動: このファイルは元々include/linux下にありましたが、他のlinux/if_*.hファイルと論理的にまとめる形で再配置されました。これにより、関連するヘッダーファイルのグループ化が改善され、コードの可読性と保守性が向上します。

この変更により、mkerrors.shが生成するGoのシステム定数は、Linuxカーネルの実際の定義とより密接に一致するようになり、GoプログラムがLinuxのネットワーク機能とより堅牢に連携できるようになります。これは、特にネットワークプログラミングにおいて、Goアプリケーションの安定性と互換性を向上させる上で重要な意味を持ちます。

関連リンク

  • Go CL 63930043: https://golang.org/cl/63930043
    • これは、このコミットに対応するGoのコードレビューシステム(Gerrit)上のチェンジリストです。コミットの詳細な議論、レビューコメント、および関連する変更履歴を確認できます。

参考にした情報源リンク

  • Linuxカーネルのソースコード(特にinclude/linuxinclude/netディレクトリの構造)
  • Go言語のsyscallパッケージのドキュメント
  • C言語の#includeディレクティブとプリプロセッサに関する一般的な情報
  • BSDソケットAPIとLinuxソケットAPIの比較に関する情報 (Web検索)
  • Go言語のシステム定数生成メカニズムに関する情報 (Web検索)
  • mkerrors.shスクリプトの役割と機能に関する情報 (Goソースコードの分析)
  • git diffコマンドの出力から変更点を分析する方法I have generated the detailed technical explanation in Markdown format, following all the specified instructions and including all the required sections. The output is ready to be displayed.