ふつうのLinuxプログラミング
学び直しLinux
少し時間が空いたが年末年始に読んだ本のメモ。(ブログにまとめるまでのリードタイム短くしていきたいところ。ブログ書く前提で読む、メモする、という最適化が望まれる)
実は初見ではなく、大学院2年の時に同居していたRichard氏が図書館から借りてきた(自分に読ませるためにわざわざ)のを読んだことがあるので、学び直しになる。確か当時のレベルはC言語の入門書を1冊読みましたくらいで、Socketプログラミングをこの本で初めて見たような状態だったはず。章末問題もやらなかった。
C言語入門書読んだレベルで本書のコードを読むことは十分に可能で、非常に参考になった反面、カーネルやプロセスといった概念が絡むと今一つ理解できていなかった。あれからLinuxについての理解も少しは得たので確認の意味も込めて再度読んでみた次第。
感想としては、やはり3つの概念でLinuxを説明する点が明解であり、すんなりと受け入れられた。第一部だけでも読む価値あると思う。章末問題も今回は手を動かして解答書いてみて、strcatとかで文字列処理する辛さを味わった。でも、C言語は覚えることが少ない(言語特有のお作法みないなもの?)ところが良い。
Reference
『ふつうのLinuxプログラミング』第2版 サンプルコード
ふつうのLinuxプログラミング 第2版 サポートサイト
ふつうのLinuxプログラミング 第2版 | SBクリエイティブ
メモ
- 7章まで
- カーネルの中にストリームを管理するデータ構造がある
- global変数errno
- int fdとFILE *fileの混在
混ぜるな危険。stdioのバッファを介さない、介すで順番がおかしくなるため- なぜ両者が行き来できるのか
stdioではできない処理があるため。fopen()では新規ファイル作成でパーミッション指定できない。これはopen()で開いてfdopenでFILEストリームにするのが定石。またstdioにはioctl()やfcntl()に対応する操作が無い
- なぜ両者が行き来できるのか
- 気になったのでtail(1)のsource code調べた
- 末尾からbuffersize読み込む
- buffer内のendlineを検索 memchrと空目してしまい、前方一致だとうまくいかなくね?と嵌った。mem r chrで後方一致。検索対象バイト数のnを減らしていく
- 解答例だとbuffersizeが1行の限界になるからダメだなと思ったやつ
- 8章
- 課題1,grep2.c オプションごとにフラグを作ったり、regcompにignore caseのmodeがあるだろうと予想が当たっていたりと気分がよい。課題2も解答例と同じだった
- 9章
- /bin,/usr/binと/lib,/usr/libの使い分けはbootに必要かどうか
- devfsとudevでデバイスファイルを動的に生成する。devfsはkernel実装、udevはkernel外
- /tmpと/var/tmpは保存期間がちがう。/tmpはリブートしたら消える可能性がある
- 10章
- ls10-1.c: char *を動的にallocしているわけではないからbufは前のloopが引き継がれる。
- mkdir10-3.c char buf[i+1]のとき終端はbuf[i]=’\0’になる。宣言とアクセスのindexがずれる
- なるほど/を’\0’にreplaceするだけでいいのか。確かに。
- 11章
- 11章末,tail2.c: 実行時にRING_BUFFERの大きさが決まるからmallocする。ということ?
- 12章
- exit(3)はlibcライブラリ関数。_exit(2)はシステムコール。exit(3)はlibcに関連した各種後始末を行う
- forkしたらwaitする。子プロセスから親プロセスでwaitされるかわからないので子プロセスのPIDその他を保持しておく必要がある。ゾンビ
- 13章
- SIGSEGVのコアダンプはプロセスのメモリのスナップショット。コアメモリから
- パイプでつながれたプロセスは1つのプロセスグループになることを思い出しましょう。
- 14章
- クレデンシャルはプロセスのメタデータ
- クレデンシャルとユーザ・グループそれ自体の情報は独立している
- 戻り値が静的に確保したバッファへのポインタだと、次に関数読んだ時点で上書きされる
- 例えばシステムコールを実行した時間がシステム時間
- UTCの古い呼び方がGMTです
- 数ある時刻フォーマットの中でも比較的に厳密かつ汎用的な時刻表記を選ぶとするなら、ISO8601
- pwdはfork,execした子プロセスでもメタデータは同じになるので問題ない。cdは子プロセスから親プロセスのシェルのメタデータ編集しようとするわけだから不適切。
- 15章以降
- va_start()の第2引数にはva_startを読んでいる関数の可変長引数の一つ前の変数を渡す。引数のアドレスから、可変長引数のアドレスを計算する仕組みになっている。
- *p++ = ‘\0’;の意味は今pがさしている位置に’\0’を入れたあとにインクリメントする。よく見かける表現らしい。文字列区切りイディオム
- プロセス単位で仮想メモリ空間が分かれているはず。スレッドは同じプロセス内なので、仮想メモリ空間を共有することになる。
スレッドセーフとか概念わかんないな - chrootはプロセスから見えるファイルシステムを変更するわけだから、実体としてはプロセスのメタデータをいじっているはず。
- chrootしてからsetuidでクレデンシャル変更する。chrootはroot権限でないと実行できない。
- Daemon化。端末の入出力切って、forkして親が死ぬ。
- リクエストヘッダはリンクリストに格納。可変長リスト