元Linux向けアプリケーション開発者がおすすめする本「C言語によるスーパーLinuxプログラミング」の紹介

この記事は [Linuxアドベントカレンダー2021](https://qiita.com/advent-calendar/2021/linux) の23日目の記事なります。
前日の22日目は [@shohey1226](https://qiita.com/shohey1226) さんによる[「Online Linux Terminal - Wazatermを支える技術」](https://qiita.com/shohey1226/items/8c51593663050d37def2)でした。

# はじめに
現在はSREとして働いているため、Linuxアプリケーションやカーネルモジュール開発からは離れてしまいました。しかし、今でもカーネルおじさんと呼ばれるべく、Linux に触れる機会を自分で作っています。
さて、私が大学時代に特別講義で教わった飯尾淳先生の本で、C言語でLinux向けのアプリケーション開発をしていた頃に出会いたかったなと思った本です。近年、C言語によるアプリケーション開発は他の高級言語にとって変わられ、大学の講義でしか触ったこともない人が多いのではないでしょうか。
本記事では、**「Linux環境でC言語で書かれた各種ライブラリを使ったプログラミングでも色々できて楽しいんだよ」** という部分をお伝えできれば嬉しいと思います。

# 紹介する本について
紹介する本の詳細についてまとめておきます。発行から10年が経っていますが、面白いので読んでみて欲しいです。書かれた中での Kernel version は 2.6.32 ですので、今は5系なのでバージョンの数字からでも少し昔だなと思ってしまいますよね。

|タイトル|C言語によるスーパーLinuxプログラミング|
|-----------|------------|
|著者|飯尾淳|
|発行所|ソフトバンククリテエイティブ株式会社|
|発行|2011年6月10日 初版発行|
|ISBN-10|4797361204|
|ISBN-13|978-4-7973-6120-9|
|amazon link|[ここから購入しても私には1円も入らないので安心してください](https://www.amazon.co.jp/C%E8%A8%80%E8%AA%9E%E3%81%AB%E3%82%88%E3%82%8B-%E3%82%B9%E3%83%BC%E3%83%91%E3%83%BCLinux%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-C%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%AE%E6%B4%BB%E7%94%A8%E3%81%A8%E5%AE%9F%E8%A3%85%E3%83%BB%E9%96%8B%E7%99%BA%E3%83%86%E3%82%AF%E3%83%8B%E3%83%83%E3%82%AF-%E9%A3%AF%E5%B0%BE-%E6%B7%B3-ebook/dp/B06Y114CHD/ref=tmm_kin_swatch_0?_encoding=UTF8&qid=&sr=)|

# 個人的に面白い章
## 第3章：大規模プログラミングとライブラリの利用
この章では、大規模プログラミングについてソースコード分割の必要性について書かれています。ただそれだけだと面白くないのですが、C言語のビルド工程や makefile、ライブラリの活用方法の説明もあります。
特に動的リンクと動的ローディングは当時ソースコードを調べながら読んでいて楽しかったです。よくあるプラグインやアドオンの仕組みを実装しようと思うと、動的ローディングの知識は必須です。この章で簡単に違いを学んだ後で、第5章に動的ローディングの実際のソースコードを読みながら、深く学ぶことができたが非常に良かったです。インターフェース設計を行い、初期化処理、拡張機能の呼び出し、終了処理といった関数呼び出しなどを提供しておけば、安全に拡張できます。この辺りの知識は開発時に何気なく利用していたので、あの当時に深くきちんと理解していれば...と思いました。

## 第4章：プログラムの移植性
コンテナが安易に扱えるようになり、今となってはあまり考えることも少なくなりましたが、昔はC言語で作られたプログラムの移植性が大きな課題でした。OSの違いもそうですが、実行環境のことも意識しなくてはなりません。一般のOSでは当たり前のリロケータブルなライブラリは組み込みLinuxでは使用できませんし、対応するOSの幅を広げようと思うととても苦労していました。また、実行環境の際はOSのバージョン、ディストリビューション、インストールされているパッケージやライブラリについても意識しなくてはなりません。インストールされているライブラリのバージョンによっては、下位互換性がなくなり、構造体のメンバー構成が変わっているなんてこともありました。
また、Cコンパイラ特有の機能を使っていないか考える必要もあります。私が開発していた頃は gcc でクロスコンパイルして動作確認するという決まりがあって良かったなと思いました。
そういった時に必要になるマクロや Autotoolset、CMake について詳しく説明されています。`make`コマンドでは対応できないファイル数になる場合も多く、`autoconf`,`automake`などの詳しい流れ、CMakeの活用方法などが記載されています。


## 第15章：エンコードとデコード、文字列の解釈
この章では、エンコードとデコード、そしてそれに関する文字列を解釈する処理を行うライブラリについて紹介されています。具体的にはバーコードやQRコードなどの取扱い、URLのパース、MIMEのデコードなどがソースコードや実例とともに書かれております。

本を買った当時、QRコードライブラリを作って遊んだことを思い出しました。`qrencode.h`を用いて 読み取った文字列をとある法則で変換し３分割、RGBの3色でQRコードを生成し、組み合わせて画像化することで、よりセキュアで、画像としてのサイズを小さくした「カラー版QRコード」を作成してレポートとして提出しました。レポートを出した後で、[カラーコード](http://www.manbouchan.com/ip_studio/ip-colorcode/ccoder-01.html)を知った時は、自分の調査不足を呪ったものです。(超優秀な同期から教えてもらい、なんでも知っているなーと思ったのは別の話。)

また、設定ファイルに書かれた文字列を解釈する `dotconf.h` についても大変勉強になります。
`dotconf.h`を用いると、コメント、連続行、コマンドエスケープ、ヒアドキュメント、環境変数による設定の置換、設定ファイルのインクルードなど、非常に便利な機能が実装することなく利用できます。
設定ファイルを書いたことがある人が多いと思いますが、その解釈のされ方（文字列がどのように解釈され、どんな型で、どのような構造体に格納されているのか）について詳しくみたことがある人は少ないのではないでしょうか？ 空白による解釈のされ方の違いなどにも触れられています。実際に GNOME環境では GConfなどが使われていますが、それよりももっと気軽に利用できるライブラリです。

# 実際に触ってみたい方向け、安易な開発環境
実際にライブラリを使用したプログラミングをしてみようと思うと、ライブラリが更新されていたり、対応するdevパッケージが提供されていなかったり、難しいものも多々あると思います。この本で紹介されている環境は前述の通り、Kernel 2.6.32の頃のパッケージやライブラリになります。
ただ、基本的な仕組み、ビルド工程や移植性などの基本的な考え方は普遍なものだと思います。これから暇な時間に最新版の Ubuntu で10年近く前に書いたソースコードをコンパイルして、実行できるようにしてみたいと思いました。その時はまた別のQiitaの記事を書くと思います。

:::note info
qrencode.h は割と簡単に動きました。
qrencode.h のコメントを読んでみると 2017年まで開発されていたようです。ライブラリの呼び出し方が変わっていなくて嬉しいです。
:::

dockerで最新のUbuntuイメージをとってきて、起動。

```shell:やったことメモ
docker pull ubuntu
docker run -it ubuntu

apt-get update
apt-get install vim gcc libqrencode-dev

vim sample.c
gcc -o sample sample.c -lqrencode
./sample "Hello world"> sample.pbm
```


```c:sample.c
#include <qrencode.h>
#include <stdio.h>

int main(int argc, char* argv[]) 
{
  if (argc < 2)
  {
    fprintf(stderr, "Usage: %s STRING\n", argv[0]);
    return 1;
  }

  QRcode* qrcode = QRcode_encodeString8bit (argv[1], 0, QR_ECLEVEL_L);

  int width = qrcode->width;
  int x, y, i = 0;
  unsigned char* data = qrcode->data;

  printf("P1\n%d %d\n", width, width);
  for (y = 0; y < width; y++)
  {
    for (x = 0; x < width; x++, i++)
    {
      printf((data[i] & 1) ? "1 " : "0 ");
    }
    printf("\n");
  }
  return 0;
}
```
上記のsamaple.c は飯尾先生の本の中に記載されている `list1513.c`と同様の内容です。

作成した sample.pbm をコンテナホストと共有しているディレクトリに移す。MacOS なら `open ./sample.pbm` で開くことができます。読み込んでみてください。
![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145853/a4d18498-1241-adec-836a-79b7ab8e4bda.png)


# おわりに
さて、C言語によるスーパーLinuxプログラミングの紹介はいかがだったでしょうか？
C言語での開発をゴリ推ししたいわけではなく、プログラミング言語は特性に合わせて適材適所の言語選びをしていくものだと思います。C言語では、システム(OS)が提供するサービスを効果的に活用してアプリケーションを開発するシステムプログラミングにとても向いています。いきなり、カーネルモジュールを作ったり、Systemtapで処理を挟むような開発はハードルが高すぎると思いますので、まずはC言語で書かれてたライブラリをLinux環境で触ってみるところからスタートすると、楽しくなってくるのではないかな？と思います。

読書感想文だけで終わるつもりでしたが、簡単な実行環境とサンプルまで載せてしましました（文字数稼ぎとも言う）。本記事でC言語の各種ライブラリを使ったLinuxプログラミングに少しでも興味を持ってもらえたら嬉しいです。

[Linux アドベントカレンダー 2021](https://qiita.com/advent-calendar/2021/linux) の24日目は[@gracehime](https://qiita.com/gracehime)さんによる記事です。