この記事では、Linux環境(特にRocky Linux 9.3)でホスト名からIPアドレスを取得し、その結果を標準出力するCプログラムの作成とコンパイル手順について詳しく説明します。
コンパイル環境
コンパイラのバージョン確認
インストールされているGCC (GNU Compiler Collection)のバージョン情報を表示します。
$ gcc --version
gcc (GCC) 11.4.1 20230605 (Red Hat 11.4.1-2)
...以下省略...
GCCのメインパッケージの詳細を見たい場合は、
$ dnf info gcc
メタデータの期限切れの最終確認: 0:04:13 前の 2024年05月15日 14時16分40秒 に実施しました。
インストール済みパッケージ
名前 : gcc
バージョン : 11.4.1
リリース : 2.1.el9
Arch : x86_64
サイズ : 85 M
ソース : gcc-11.4.1-2.1.el9.src.rpm
リポジトリー : @System
repo から : appstream
...以下省略...
GCCとともによく使用されるライブラリ(例えば、libgcc)の情報を確認するには、
$ dnf info libgcc
メタデータの期限切れの最終確認: 0:04:51 前の 2024年05月15日 14時16分40秒 に実施しました。
インストール済みパッケージ
名前 : libgcc
バージョン : 11.4.1
リリース : 2.1.el9
Arch : x86_64
サイズ : 194 k
ソース : gcc-11.4.1-2.1.el9.src.rpm
リポジトリー : @System
repo から : anaconda
概要 : GCC version 11 shared support library
...以下省略...
カーネルのビルドバージョン確認
システムのカーネルに関する詳細な情報を表示します。カーネルのバージョンだけでなく、ホスト名、カーネルリリース、カーネルのビルド日時、OSのアーキテクチャなどが含まれます。
$ uname -a
Linux rocky93svr 5.14.0-362.8.1.el9_3.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Nov 8 17:36:32 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
ディストリビューションの名前、バージョン番号、IDなどの情報を表示します。
$ cat /etc/os-release
NAME="Rocky Linux"
VERSION="9.3 (Blue Onyx)"
...以下省略...
ソース作成
次のコードをファイル名(getip.c)で作成します。(詳細はコードのコメント1.~4.を参照)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main() {
char hostname[1024];
hostname[1023] = '\0';
// 1.ホスト名を取得し、出力
gethostname(hostname, 1023);
printf("Hostname: %s\n", hostname);
struct addrinfo hints, *info, *p;
int status;
char ipstr[INET6_ADDRSTRLEN];
memset(&hints, 0, sizeof hints);
// AF_INET or AF_INET6 to force version
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
// 2.ホスト名からIP Addressを取得
if ((status = getaddrinfo(hostname, NULL, &hints, &info)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
return 2;
}
for (p = info; p != NULL; p = p->ai_next) {
void *addr;
char *ipver;
// 3.取得したIPアドレスをバージョンに応じて処理
if (p->ai_family == AF_INET) {
// IPv4
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
addr = &(ipv4->sin_addr);
ipver = "IPv4";
} else {
// IPv6
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
addr = &(ipv6->sin6_addr);
ipver = "IPv6";
}
// 4.IPアドレスを文字列に変換し、出力
inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
printf("%s: %s\n", ipver, ipstr);
}
// addrinfo構造体を解放
freeaddrinfo(info);
return 0;
}
コンパイル
次のコマンドを順序に実行し、実行モジュール iptestを生成します。
$ rm -f iptest main.o main.d *~
$ gcc -c -MD -std=gnu99 -Wall -Wextra -g -finput-charset=UTF-8 -O2 -o main.o main.c
$ gcc -o iptest main.o
rm -f iptest main.o main.d *~
特定のファイルとパターンにマッチするファイルを強制的に削除するために使用されます。
rm: “remove” の略で、ファイルやディレクトリを削除するコマンドです。
-f: “force” の略で、存在しないファイルに対する警告を表示せず、プロンプトなしで強制的に削除します。
具体的なファイル名を指定して削除します。
- iptest: コンパイルされた実行可能ファイル。
- main.o: オブジェクトファイル。これはGCCによって生成されたコンパイル済みのコードのファイル。
- main.d: 依存関係ファイル。これには、main.c から派生した依存関係が含まれており、Makefileなどで使用されます。
- *~: Emacsや他のテキストエディタによって生成される一時ファイル(バックアップファイル)
gcc -c -MD -std=gnu99 -Wall -Wextra -g -finput-charset=UTF-8 -O2 -o main.o main.c
ソースファイル main.c をコンパイルしてオブジェクトファイル main.o を生成します。
gcc: GNU Compiler CollectionのCコンパイラです。
-c: コンパイルのみを行い、リンクは行わないことを指示します。
-MD: ソースファイルの依存関係を .d ファイルに出力します。これは、Makefileで使用されることが一般的です。
-std=gnu99: C言語の標準をGNU99(C99にGNUの拡張を加えたもの)に設定します。
-Wall: すべての警告メッセージを有効にします。
-Wextra: -Wall に加えて、さらに多くの警告を有効にします。
-g: デバッグ情報を生成します。これにより、デバッガ(GDBなど)でのデバッグが可能になります。
-finput-charset=UTF-8: 入力ファイルの文字セットをUTF-8として解釈します。
-O2: 最適化レベル2でコンパイルを行います。これは、実行効率が良くなるようにコードを最適化します。
-o main.o: 出力ファイル名を main.o と指定します。
main.c: コンパイルするソースファイルです。
gcc -o iptest main.o
オブジェクトファイル main.o から実行可能ファイル iptest を生成します。
gcc: GNU Compiler CollectionのCコンパイラです。
-o iptest: 出力する実行可能ファイルの名前を iptest と指定します。
main.o: リンクするオブジェクトファイル。
実行結果
モジュールを実行し、想定とおりの結果であることを確認します。
$ ./iptest
Hostname: rocky93svr
IPv4: 192.168.1.90
まとめ
プログラムの基本的な構造から始まり、必要なライブラリやコマンドを使った詳細なビルドプロセスまで、一連の手順を明確に説明します。特にLinuxシステムでの開発に興味がある読者や、ネットワークプログラミングの基礎を学びたい開発者にとって価値ある内容です。
コメント