20210725のLinuxに関する記事は8件です。

Raspi4 Case Fanを"きちんとPWM制御"するには?(その2, 調査段階)

TL;DR dtoverlay=pwm-fanが作れそう、だったけど時間切れ CPU温度で段階的に制御するためのrpi-poe-overlay.dts PWM制御するためのpwm-overlay.dts これを上手く合成できれば、、、ワンチャンありそうですね(残念ながら完成には至りませんでした) はじめに さて、前回の調査でFAN制御をするためにはraspi-config経由で起動時オプションを設定する、ということを確認した。 このraspberry piのFAN制御において、小さな疑問が生じた。 dtoverlay=gpio-fan 果たして、GPIO14を使ったFAN制御がなされる、というが、どこにデフォルトが書かれているのだろうか?この謎を追い求めるため、調査員はアマゾン…ではなくgithubを探索した・・・ が正攻法では見つからない。なかなか面白い問題にぶち当たった。 それは単純な落とし穴だった(ファイル数が多すぎるので見つからない) gpio-fan-overlay.dts というファイルが、arch/arm/boot/dts/overlays/以下にある。ここに確認したい情報の全てが入っていた。 しかしWebUIから表示しようとすると、"o"に達する前に読み込みが止まって見えない、おお、なんということだ!! ということで、こちらを確認してほしい https://github.com/raspberrypi/linux/blob/rpi-5.10.y/arch/arm/boot/dts/overlays/gpio-fan-overlay.dts * Requires: * - kernel configurations: CONFIG_SENSORS_GPIO_FAN=m; * - kernel rebuild; * - N-MOSFET connected to gpiopin, 2N7002-[https://en.wikipedia.org/wiki/2N7000]; * - DC Fan connected to N-MOSFET Drain terminal, a 12V fan is working fine and quite silently; * [https://www.tme.eu/en/details/ee40101s1-999-a/dc12v-fans/sunon/ee40101s1-1000u-999/] * * ┌─────────────────────┐ * │Fan negative terminal│ * └┬────────────────────┘ * │D * G │──┘ * [GPIO12]──────┤ │<─┐ 2N7002 * │──┤ * │S * ─┴─ * GND * この図面の、2N7002は単純な「トランジスタ」である。 つまり一言で結論を言うと。 FANを、GPIOでOn/Off制御することしか、考えられていない そう、もともと「これじゃ制御できないんじゃ・・・」という話、これは正解だった!!!ソフトの対応が足りておりません!! Kernelから制御するための救いは無いんですか? ⇒ (今のところは)ない。 では、pwm制御する手段はもう作れないのか? そのものずばりな、pwm-fan.dts は無かったですね…。 その代わりに、overlaysを眺めていると、なかなかよさそうなものがあります… 救い1 POEのFAN制御 Raspberry piの rpi-poe-overlay.dts これは、RasPiのPower Over Ethernet HATについているFANを制御するためのoverlay。 救い2 PWM制御 pwm-overlay.dts これは、RasPiのPWMを制御するためのoverlay。 ということは、これらを組み合わせれば、CPU温度に応じたPWMでのFAN制御がなんとかなりそうな気がするのですが。 というところで、4連休終了で、タイムオーバー!!もうちょっと!!もうちょっとなのですが。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

httpサーバを手っ取り早く立てる

概要 開発時 http サーバが欲しくなる以下のような状況について記載します。 静的htmlファイルなどを file:/// を使わずブラウザで開きたい。 CGI(php) をとりあえず動かしたい。 リバースプロキシサーバ(nginx)をとりあえず動かしたい。 ここ最近数ヶ月のうちに、2つ目と3つ目の方法が必要になり、調べてました。せっかくなので記事化しておく。 対象環境 Linux。メジャーな distribution なら大差ないはず。 手段 静的htmlファイルなどを開くためのhttpサーバを立てる python3 の http.server モジュールを使う。 $ python3 -m http.server 8000 Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ... http://localhost:8000/ に接続。 index.html が無ければディレクトリ一覧も出るので便利。 CGI(php) をとりあえず動かしたい。 php が使える。 $ php -S 0.0.0.0:8000 [Sun Jul 25 18:52:46 2021] PHP 7.4.3 Development Server (http://0.0.0.0:8000) started http://localhost:8000/ に接続。 ディレクトリ一覧は出せないので、一覧を自力で書くか、routerを定義する必要がある。 router の書き方については、以下の stackoverflow に書かれている回答が役に立ちました。 リバースプロキシサーバ(nginx)をとりあえず動かしたい リバースプロキシサーバが必要になりました。仕方ないですね。docker で nginx を立てましょう。 まずは、最も単純な、8000 番ポートに nginx サーバを立てる方法。python3 -m http.server 8000 と大体同じ。 docker run --name my-nice-nginx --rm \ -v $PWD:/usr/share/nginx/html:ro \ -d -p 8000:80 nginx 終了するには、docker kill my-nice-nginx だけでok。--rm 付けていますし。 設定ファイルを書き換えるには、以下のように設定ファイルをマウントする。 docker run --name my-nice-nginx --rm \ -v $PWD/nginx/html:/usr/share/nginx/html:ro \ -v $PWD/nginx/nginx.conf:/etc/nginx/nginx.conf:ro \ -v $PWD/nginx/conf.d:/etc/nginx/conf.d:ro \ -v $PWD/nginx/log:/var/log/nginx/:rw \ -d --net host nginx ポートフォワーディングで(80から8000に変更するような)ポート変更の対応をすると、リバースプロキシとしてnginxを使いたいときに、dockerの設定が大変になる。 ここは --net host してしまって、nginx 側の設定でlistenするポートを置き換えると手を抜ける。conf.d/default.conf の変更も忘れずに。 本番環境はちゃんとカプセル化しましょう。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Linux: 曜日情報を取得する方法

たまに必要となるのでメモ。 実施環境: Linux [testuser@testhost ~]$ uname -a Linux testhost 4.18.0-147.8.1.el8_1.x86_64 #1 SMP Thu Apr 9 13:49:54 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux [testuser@testhost ~]$ echo $SHELL /bin/bash 曜日によって実施する処理を変える等、曜日情報を取得したい場合はたまに存在します。 そのような場合は、dateコマンドのフォーマットに特定の文字列を指定することで取得できます。 %wを指定した場合、日曜日から0,1,2,3,4,5,6となる数値情報で取得できます。 Linux [testuser@testhost ~]$ date Tue Jul 13 21:44:44 JST 2021 [testuser@testhost ~]$ date +"%w" 2 [testuser@testhost ~]$ date -d "sunday" +"%w" 0 [testuser@testhost ~]$ date -d "monday" +"%w" 1 [testuser@testhost ~]$ date -d "saturday" +"%w" 6 %uを指定した場合、月曜日から1,2,3,4,5,6,7となる数値情報で取得できます。 Linux [testuser@testhost ~]$ date Tue Jul 13 21:48:25 JST 2021 [testuser@testhost ~]$ date +"%u" 2 [testuser@testhost ~]$ date -d "sunday" +"%u" 7 [testuser@testhost ~]$ date -d "monday" +"%u" 1 [testuser@testhost ~]$ date -d "saturday" +"%u" 6 文字列で取得したい場合は、%aまたは%Aを指定します。 ここで表示される文字列は、ロケール設定に依存します。 Linux [testuser@testhost ~]$ date Tue Jul 13 21:51:34 JST 2021 [testuser@testhost ~]$ date +"%a" Tue [testuser@testhost ~]$ date +"%A" Tuesday
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Linuxまとめ

用語一覧 用語             意味                      CLI(Command Line Interface) コマンドプロンプトやMacならターミナル(黒い画面)に文字を打ち、処理を行う GUI(Graphical User Interface) マウスでポチポチ操作 シェル LinuxのCLIを提供するソフトウェア シンボリックリンク リンク先のパス名を記載しただけのファイル、ファイルを移動したり削除すると使えなくなる テキストファイル 文字通りテキスト(文字列)が書かれたファイル バイナリファイル 画像ファイルや音声ファイル、Linexコマンドの実行ファイル(/bin/catなど) 正規表現 条件に合う文字列集合体を表現するための記法、* {} $ などの記号(メタ文字)が使われる メタ文字 本来の意味とは違う特別な意味を持たせた文字 コマンドの使い方を忘れたら ①--helpを使う ex) rm --helpでオプションも確認することが出来る ②manコマンド(manual)を使う ex) man bash よく使うコマンド やりたい事          コマンド          Vim(テキストエディタの一種)について テキストエディタとは Windowsでいう「メモ帳」などのように文字列を編集するために使うソフトのこと 2つのモードについて ノーマルモード(コマンドを実行する)と インサートモード(テキストの入力を行う)がある。 sudo vi ファイル名 でVimを起動した直後はノーマルモードで、 インサートモードに切り替えるにはa ノーマルモードに切り替えるにはEscキー Vimでよく使うコマンド やりたい事             コマンド               ファイルを編集 sudo vi ファイル名 右に移動 l 左に移動 h 上に移動 k 下に移動 j 保存せずに終了(編集した場合) :q! 保存せずに終了(何も編集していない場合) :q 保存する :w 保存して終了 :wq インサートモードに切り替え a ノーマルモードに切り替え Escキー
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

linuxコマンド メモ

基本 表示 ls [オプション] -a 全部出力 -l 詳しく出力 コピー cp [オプション] コピー元 コピー先 -i 確認出す -r 再帰 -p 元の情報そのまま 移動、名前の変更 mv 移動元ファイル 移動先ファイル -i 確認出す 削除 rm ファイル名 -i 確認出す -f 強制 -r 再帰 ディレクトリ作成 mkdir ディレクトリ名 -p 階層で書くと一気に作る ディレクトリ削除 rmdir ディレクトリ名 -p 階層で書くと一気に削除 #ディレクトリ内が空の時しか削除できないので安全 ファイルの中身を表示 cat ファイル名 -n 行番号を表示 ファイルの中身を表示 less ファイル名 /単語 検索 q 抜ける ファイル検索 find パス -name ファイル名 コマンドのパス表示 where コマンド名 コマンドのヘルプ参照 コマンド --help コマンドのマニュアル参照 man コマンド リダイレクト ls > ls-output-file エラー出力リダイレクト ls sonzaisinai-file 2> ls-output-file grep grep [オプション] 検索条件 [指定ファイル] ファイル内末尾参照 tail [オプション] ファイル名 -n 表示行数指定 -f リアルタイムで更新 テキストの中身をソート sort [オプション] ファイル名 -r 逆ソート -k n n列目のデータをソート -n 数値としてソート(デフォルトでは辞書順ソートのため) 比較 diff [オプション] ファイル1 ファイル2 -u 詳しく表示 -c 詳しく表示 管理 ユーザー useradd ユーザー名 usermod ユーザー名 userdel ユーザー名 グループ groupadd グループ名 groupmod グループ名 groupdel グループ名 パスワード登録・変更 passwd [ユーザー名] ユーザー変更 su - [ユーザー] #指定しなかったらroot sudo sudo コマンド 所有者の変更 chown ユーザー ファイル アクセス権の変更 chmod モード ファイル #モード:ユーザー グループ その他 シェルスクリプト おまじない #!/bin/bash コマンド ・ ・ ・ 実行可能権限に変更すること ネットワーク ipの確認 ip a ping ping [ホスト名] -c [回数] 経路の確認 traceroute [ホスト名] プロセス プロセスの確認 ps [オプション] -A 全部出力 l 詳しく出力 ファイル ディスク空き確認 df [オプション] -H 見やすくなる ディレクトリの容量確認 du
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

(思考実験) Raspi4 Case Fanを"きちんとPWM制御"するには?

TL;DR Raspberry Pi 4 Case Fanはソフト的にもPWM制御できていない(かもしれない)。 なお、この記事はRaspi買ってない人がソースコードベースで調べた結果なので、間違っているかもしれないし、その通りにやるともしかするとソフトやハードにダメージがあるかもしれません。その前提でご確認ください。 gpio-fan だと、onとoffとか、レベル制御しかできない。 HWスペックとしてはPWM制御できると書いている。 もったいない!もったいない!! ここまでの調査メモ。 はじめに @nekokurono7 さんがなかなか興味深い記事を書いていた。 Raspberry Pi OSに搭載されたファン制御機能が怪しいので実験してみた1 Raspberry Pi OSに搭載されたファン制御機能が怪しいので実験してみた2 これについて、もう少しソフトウェア方面で追加検証をしてみるよう。 なお、私自身はRaspberry pi 4持っていないので、「多分こうなるんじゃないのかなー」レベルです。 公式ファンとはどういう物なのか? どういう商品なのか? Raspberry Piの記事がこちら。 ここにもしっかりと"ユーザーが選択したGPIO pinを介して、PWM制御ができる"と書いてある。 Fan speed control: Pulse width modulation control via user-selectable GPIO pin PWMでファン制御するとは? @sh_o さんのRaspberry Pi でPWM信号を使って5Vファンを制御するが非常にわかりやすい。 簡単に言うと以下となる。概念を雑に説明すると、PWMの信号を高速にHigh/Lowすると、これに合わせて電源-FAN-GNDが通電する。 電源(5V) GND PWM Raspi公式の設定方法では? raspberry-pi-4-case-fan 公式サイト に書いてある通り、Raspberry Pi Configuration toolから設定する。 Then open the Raspberry Pi Configuration tool: 1. Click on the Raspberry Pi icon in the top left corner and select Preferences then Raspberry Pi Configuration. 2. Select the Performance tab. 3. Next to Fan, click Enabled. 4. If you have connected your fan as shown above, the default of 14 for Fan GPIO does not need to be changed. 5. Select the Fan Temperature at which you want your fan to turn on. The default is 80°C, which will stop the Raspberry Pi throttling on difficult tasks without having the fan on all the time. Raspberry Pi Configuration toolのソースコードでは? raspi-config#L1278 ここの設定を見ると、要するにkernel のcommand line引数に以下を追加するに見える。むむむ... sed \$CONFIG -i -e "\$adtoverlay=gpio-fan,gpiopin=\$GPIO,temp=\$TEMP" Linux Kernelのソースコードでは? Raspberry pi 4のlinux kernelツリーは https://github.com/raspberrypi/linux gpio-fanのソースコードは https://github.com/raspberrypi/linux/blob/rpi-5.10.y/drivers/hwmon/gpio-fan.c drivers/hwmon/gpio-fan.c#L482 static const struct of_device_id of_gpio_fan_match[] = { { .compatible = "gpio-fan", }, {}, }; MODULE_DEVICE_TABLE(of, of_gpio_fan_match); このコードを追うと、疑問が出てくる... PWM制御方法が若干違う・・・かも? 起動時や設定変更時でファン速度が変わる場合、set_fan_speed()関数をcallする。 ここから、__set_fan_ctrl()が呼ばれる。 drivers/hwmon/gpio-fan.c#L128 /* Must be called with fan_data->lock held, except during initialization. */ static void set_fan_speed(struct gpio_fan_data *fan_data, int speed_index) { if (fan_data->speed_index == speed_index) return; __set_fan_ctrl(fan_data, fan_data->speed[speed_index].ctrl_val); fan_data->speed_index = speed_index; } drivers/hwmon/gpio-fan.c#L100 /* * Control GPIOs. */ /* Must be called with fan_data->lock held, except during initialization. */ static void __set_fan_ctrl(struct gpio_fan_data *fan_data, int ctrl_val) { int i; for (i = 0; i < fan_data->num_gpios; i++) gpiod_set_value_cansleep(fan_data->gpios[i], (ctrl_val >> i) & 1); } あれ…… これ、指定されたindexに合わせて、GPIOでレベル指定して制御しているだけに見える・・・ ちょっと待ってあれ? gpio-fanのdocumentを読んでみる 最近のデバイスドライバは、Documentation/devicetreeの下にも簡易的にだがマニュアルがある。 gpio_fan { compatible = "gpio-fan"; gpios = <&gpio1 14 1 &gpio1 13 1>; gpio-fan,speed-map = <0 0 3000 1 6000 2>; alarm-gpios = <&gpio1 15 1>; }; このドライバは今回のような1本の信号線上でパルス信号を送るのではなく、複数のGPIO信号線でレベル指定してそれをICでPWM化/DC-ACするパターンなのでは…? 例えば、buffaloのGPIO fan制御とかはこのパターンに見える... (名前は、リニア制御方式、でいいのかな?) つまりどうやって動いていたように見えるのか? 簡単にいうと「PWM制御できるハードを、On/Offのレベル制御でしかつかっていない」ですね…。  もったいない、もったいない。 GPIO 停止 LOW 全力 HIGH どうやったらPWM制御になりそうか(予想) 使うべきドライバは"pwm-fan" gpio-fanではなく、pwm-fanを使うと制御できそう。 pwm-fan.txt PWM制御はHW?SW? SoftでPWM制御もできる話にはなっているけど、そんなことlinux動作中にやると普通に厳しいので、HW制御を前提にする。 BCM2711のdata sheetを見る限り、Channel0/1は分離していないので、片方で設定をすればよさそう。 bcm2711.dtsi#L274 pwm1: pwm@7e20c800 { compatible = "brcm,bcm2835-pwm"; reg = <0x7e20c800 0x28>; clocks = <&clocks BCM2835_CLOCK_PWM>; assigned-clocks = <&clocks BCM2835_CLOCK_PWM>; assigned-clock-rates = <10000000>; #pwm-cells = <2>; status = "disabled"; }; 接続先はGPIOのどこにする? ー> 18とかかなあ… まず、linux kernel側のdevice tree設定で、GPIO40/41はPWM定義されている。これを真似して、PWM0を定義しないとダメっぽい。 bcm2711.dtsi#L799 pwm1_0_gpio40: pwm1_0_gpio40 { pin-pwm { pins = "gpio40"; function = "alt0"; bias-disable; }; }; bcm2711-rpi-4-b.dts#L213 &pwm1 { pinctrl-names = "default"; pinctrl-0 = <&pwm1_0_gpio40 &pwm1_1_gpio41>; status = "okay"; }; device treeに付け足すべきは? 多分、こんな感じになると思うんだけど、、、 ここからは現物がないので妄想ですね。 pwm-fan { compatible = "pwm-fan"; #cooling-cells = <2>; pwms = <&pwm1 1 1250000>; cooling-levels = <16 128 192 240>; }; pwmsの引数 - https://www.kernel.org/doc/Documentation/devicetree/bindings/pwm/pwm.txt 1 : た、たぶんこちらは1chに設定でいいはず。 1250000: nano sec。PWMのperiod(1サイクルの長さ)。 (設定なし): PWM_POLARITY_INVERTEDが指定できるらしい 数字はかなり適当に、3000 rpm中に16分割で制御で、1.3ミリ秒間隔。もーっとおそくても(時間が長くても)いいかもしれない。 60 * 1,000,000,000 ns / 3000 rpm / 16 = 1,250,000 まとめ 実ハードウェアが無い状況で調べたことなので、間違っているかもしれません。興味のある方はこのあたり、夏休みの課題でチャレンジしてもいいかもしれませんね! 以上になります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

新しいLinuxの教科書のすゝめ(学習アプトプットを添えて)

はじめに 本記事は「Qiitaエンジニアフェスタ:今までに買って良かった技術書」に参加しています。 ベタベタですが最近熟読している「新しいLinuxの教科書」を紹介させてください。 (kindle版は7/25時点では半額になっています、激アツ?) なぜ今Linuxなのか 本記事を読んでくださる方には釈迦に説法ですが、昨今はクラウドを使うにも、ローカルでDockerを走らせるにも、Linuxとのお付き合いが避けては通れないのではないでしょうか? 私は趣味でプログラミングを行っていますが、今までLinuxに関することは困ったらその都度場当たり的な対処方法をググってよし!で終わらせており、本質的な理解からは逃げてしまっていました。 しかしそろそろ逃げている場合じゃないな!と一念発起し、まずは評価の高い「新しいLinuxの教科書」をガッツリ勉強してみようと考え、学習に勤しんでいます。☕️ 読んでみてどうなの? 初心者の私にも分かりやすく、基礎的なことから知識を積み上げさせてくれます。 (どうでも良いですけど、Twitterで見かける積み上げアピールは苦手です) そもそもLinuxのディストリビューションとは何なのかから始まり、シェルはなんぞや、vimの:qは絶対覚えるんや、コマンドのオプションの与え方は繋げられるんじゃ!など、Linuxを触る上で知っておきたいポイントを懇切丁寧に教えてくれます。痒いところに手が届く解説の丁寧さ…!ありがとたい…! やっとこさDockerで良く使う-itオプションが、なんで-i -tじゃなくても良いか得心しました?(自分のレベルの低さが露呈) 一通り読み終わった頃には、本が付箋だらけになりました…。まだまだ自分の血肉にはなっていないため、これからも手元に置きながら実践を繰り返していきたいと思います。 読書のアウトプット✨ 本書中盤で手厚く語られるシェルスクリプトを実践してみようと思い、簡単な作例を作ってみました。主に使用している内容・コマンドは以下の通りです。 基本的な制御構文 if while case コマンド sed grep 題材としては「Pythonのクローズドな開発環境をpyenv+venvで構築する対話型スクリプト」です。この時点で刺さる人が少なそうですが、まあ練習なので、私個人が嬉しければ良いのです…? スクリプトは下記に保存してあります。学習2日目でこれぐらいはサクッと書けるようになるのですが、これはやはり基礎からしっかりと解説してくれる本書のおかげかな、と思います。おすすめ。※大丈夫、1円も貰ってませんよ https://github.com/tenkoh/create-python-venv 以上ですー。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

inode ってなんのためにあるの?

枯渇するとファイルが作れなくなる inode は、 どんな役割を果たしているんでしょうか。 ここでは inode がどのように使われるものなのかまとめました。 これを読めば「なぜinodeが枯渇するとファイルが追加できないのか」についても理解できると思います。 はじめに inode はファイル・ディレクトリに関連して作られるものです。 むしろ、ファイル・ディレクトリの実態といってもいいです。 そしてファイルの書き込み・読み込み時に参照・作成・更新されます。 inode を理解するために、パーティション内のレイアウトを見てみましょう。 ファイルシステム と inode ファイルシステムによって inode とそれにまつわるデータ領域も様々ですが、 ここでは vsfs (very simple file system) という(説明上よく使われる)シンプルなファイルシステムを使って説明します。 vsfs は参考欄に載せたドキュメントでも使用されています。 vsfs を通して、 UNIX での基本的なファイル管理を確認します。 他のファイルシステムには XFS, ZFS, ext2, ext3, ext4, ReiserFS, FAT, NTFS などがあります。 ハードディスクはパーティションに分かれ、パーティションはブロックという単位に分かれます。 そのブロックは、 vsfs では次の5領域に分類されます。 上から順に、パーティションの先頭から並んでいると考えてください。 また、パーティション内での各領域の(感覚的な)割合を数値で記載しています。 細かいことは書きませんが、 データ領域 が一番大きく、 inode 領域 が次に大きいです。 その他はすごく小さいです。 領域 説明 割合 スーパーブロック パーティションの管理情報を格納。 2% inode ビットマップ inode 領域の使用・不使用をビットマップで管理。 2% データ ビットマップ データ領域の使用・不使用をビットマップで管理。 2% inode 領域 inode を保存する領域。 10% データ 領域 データを保存する領域。 84% スーパーブロック パーティションの最初のブロックをスーパーブロックに割り当てます。 スーパーブロックには、次のようなパーティション全体の管理情報を格納しています。 ファイルシステム識別子 (ここでは vsfs) 1ブロックのサイズ inode の数 inode 領域 の開始位置 inode ビットマップ inode 領域をブロックに分けて、使用されているかされていないかをビットで表すビットマップ領域です。 たとえば inode 領域が 5 つのブロックから構成されているとします。 1ブロック4KBとして、1セクタを256B、1つのinodeは1セクタに収まるものとすると、 inode の数は 5x4K/256=80 です。 すると 80ビットを inode ビットマップ として管理できればよいことになります。 inode領域の、 inode のために予約された 80個 それぞれの領域を、使用されているのかいないのか、 0, 1 を並べてわかるようにするのが inode ビットマップ です。 このビットマップを管理することで、 ビットマップ領域を確認するだけで、次に書き込める領域、空いている領域を見つけることができます。たとえば500GBのハードディスクだったら、500GBをすべてチェックしなくてもわかるわけですから、I/Oを格段に減らせます。 データビットマップ inode と同じように、 データ領域もビットマップで管理します。 inode 領域 inode が格納されます。 inode には例として次の情報が保存されます。 いわゆるファイル・ディレクトリのメタデータです。 「画像ファイルで使われている色情報」のようなファイル・ディレクトリの中身は保存されません。 ファイルサイズ ブロック数 パーミッション 時刻情報 データが格納されているブロック位置情報 inode に含まれる情報の一部は、 stat コマンド で見ることができます。 # Amazon Linux にて [kenjiotsuka@sample]~% stat a.out File: ‘a.out’ Size: 9904 Blocks: 24 IO Block: 4096 regular file Device: ca50h/51792d Inode: 526920 Links: 1 Access: (0775/-rwxrwxr-x) Uid: ( 500/kenjiotsuka) Gid: ( 501/kenjiotsuka) Access: 2021-07-07 09:29:59.116589605 +0900 Modify: 2021-07-07 09:29:55.092364079 +0900 Change: 2021-07-07 09:29:55.096364304 +0900 Birth: - inode に格納される情報も、 ファイルシステムによって変わってきます。 たとえば ext4 の inode は、 ext4_inode という構造体を使って表され(参考: GitHub fs/ext4/ext4.h)、 ext2 や ext3 とは異なります。 inode そのものについては Linux マニュアル にも説明があります。 重要なのは、データが格納されているブロック位置情報を持っているということです。 データ領域 ファイルに含まれる実際のデータが格納されます。ディレクトリの場合は、そのディレクトリに含まれるファイルの ファイル名とそのinode番号を格納します。 ファイルの読み書き と inode ファイルの読み書きを知ると、 inode の必要性が理解できます。 vsfsでのファイルの読み込み・書き込みの例を書きました。 inode で効率化されていることがわかるはずです。 読み込み vsfs 上のファイル /a/b/c を読み込む場合のステップは次のようになります。 まずルートディレクトリを参照します。 ルートディレクトリの inode番号は固定されています。 多くの場合は2だそうです。 ルートディレクトリの inode を参照して データのあるブロック番号を取得します。 データ領域からルートディレクトリの情報を取得します。 データの中から、 ディレクトリ /a の inode番号 を取得します。 ディレクトリ /a の inode を参照します。 ディレクトリ /a のデータのあるブロック番号を取得します。 データ領域からディレクトリ /a の情報を取得します。 データの中から、 ディレクトリ /a/b の inode番号 を取得します。 ディレクトリ /a/b の inode を参照します。 ディレクトリ /a/b のデータのあるブロック番号を取得します。 データ領域からディレクトリ /a/b の情報を取得します。 データの中から、 ファイル /a/b/c の inode番号 を取得します。 ファイル /a/b/c の inode を参照します。 ファイル /a/b/c のデータのあるブロック番号を取得します。 データ領域からファイル /a/b/c の情報を取得します。 読み込みだけでこれだけの作業が必要になります。 コスト高なので、多くのファイルシステムではキャッシュなどを活用して、I/Oを減らしています。 書き込み vsfs 上の新規ファイル /a/b/d を書き込む場合のステップは次のようになります。 まずルートディレクトリを参照します。 ルートディレクトリの inode番号は固定されています。 多くの場合は2だそうです。 ルートディレクトリの inode を参照して データのあるブロック番号を取得します。 データ領域からルートディレクトリの情報を取得します。 データの中から、 ディレクトリ /a の inode番号 を取得します。 ディレクトリ /a の inode を参照します。 ディレクトリ /a のデータのあるブロック番号を取得します。 データ領域からディレクトリ /a の情報を取得します。 データの中から、 ディレクトリ /a/b の inode番号 を取得します。 ディレクトリ /a/b の inode を参照します。 ディレクトリ /a/b のデータのあるブロック番号を取得します。 パーミッションに問題がないかチェックします。 inode ビットマップを参照して、 ファイルが書き込めるのかをチェックします。 データビットマップを参照して、 ファイルはどこに書き込めるのかをチェックします。 チェックしたinode領域、データ領域にファイル /a/b/d とそのメタ情報を書き込みます。 /a/b/d について inode ビットマップを更新します。 /a/b/d について データビットマップを更新します。 /a/b のデータ領域を更新します。 /a/b のinode領域を更新します。 書き込みの回数は1回ではありません。 だいぶコストがかかります。 効率を上げるためにバッファリングを行って、まとめてディスクに書き込むこともあります。 また、電源切断などによりステップの途中で中断した時に、データが中途半端になってしまわないように、ジャーナリングという仕組みを導入しているファイルシステムもあります(ext3, ext4 など)。 その他 なぜinodeが枯渇するとファイルが追加できないのか 上のフローでわかる通り、ファイルを作るということは、inode を新たに追加するということです。 ですから、 inode に空きがなければファイルが作れません。 また、 inode の領域は、ファイルシステムのフォーマット時に分割され、 その後でデータが書き込めるようになります。 そのため inode の領域がいっぱいになった後で inode 領域を拡張するのは難しいです。 一応、ファイルシステムの中には inode 領域を拡張できるものもあります。 inode の名前はいったいどこから inode は index node という名前に由来します。 (これは想像ですが) 要するにパーティション内のファイルに目次をつけておかないと、ファイルを探して取得できないので index node という名前が生まれたのだと思います。 まとめ inode は ... パーティション内の ファイル・ディレクトリのメタデータ です。 ファイルの参照では、ファイルのデータ位置を知るために必要です。 ファイルの作成では、ファイルの管理情報として作成・更新されます。 (inode に「ファイルの中身の保存場所も格納されています」と書きましたが、実際にはinodeに加えて多段インデックスを使うなど、ここで紹介したよりも複雑な管理になっています。) 参考 vsfs File System Implementation https://student.cs.uwaterloo.ca/~cs350/F16/notes/filesys-2up.pdf inode Linux manual - inode(7) GitHub fs/ext4/ext4.h
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む