Ubuntu 24.02で論理ボリュームの拡張

M1 MacBook AirにVMware Fusionインストしましたが、Ubuntuのインストールでデフォルトで割り当てるディスク容量は20GBで、さらに実際の論理ボリュームに割り当てられるのはその半分の10GB、デスクトップ環境にしただけで、すでに85%ぐらい消費しているのですぐに足りなくなるので拡張します。

Ubuntuの20.02からはLVMが標準になってるらしく、LVMは一言で言うと物理ボリュームと論理ボリュームの対応づけを柔軟に行える仮想化されたボリューム管理システムです。物理的に多くのサーバーでは複数のディスクが存在するだろうし、論理ボリュームという概念で複数の異なるディスクを同じ論理ボリュームにすることも当然必要になるから。

作業の参照は、

https://www.myit-service.com/blog/ubuntu-lvm/

<現状と関連するコマンド>

最初にディスクUTYでの見え方は、VMwareでディスク容量を30GBの物理ドライブにしただけで、そのうちの11GBだけがBlock Device(論理ボリューム)に割り当てられています

スクリーンショット 2024-05-17 13.28.22.png

 

・ディスク拡張に関連するコマンドと拡張前の状態

$ growpart

resize2fsと共にパーティションサイズの拡張に使われるらしけど、今回は使っていない

$ lsblk

list block devices、現在利用できるブロックデバイス(block device : Linuxにはブロックデバイスとキャラクターデバイスがありますが、一言で言えばファイルデバイス)の表示させる

スクリーンショット 2024-05-17 12.52.49.png

$ parted

パーティションの作成や削除などに使う、以下はparted起動してprint all実行の結果

スクリーンショット 2024-05-17 13.18.01.png

$ pvdisplay

物理ボリュームの詳細を表示する

スクリーンショット 2024-05-17 13.31.44.png

$ gparted

グラフィカルなインターフェースのpartedコマンド

スクリーンショット 2024-05-17 13.11.33.png

$ lvextend

LVM(RedHatではLVM2が標準らしいがUbuntuではLVMしかインストされていない)で論理ボリュームを拡張するコマンド

$ resize2fs

マウント状態で論理ボリューム変更を反映します

 

<拡張作業>

① 最初に仮想マシン(Ubuntu)の停止状態で、「仮想マシン」 →「設定」でディスク容量拡張しておく、今回は20 -> 30GBにしていますが元々が20GBのうちで論理ボリュームには10GBしか割り当てられていないから少なすぎ

② Ubuntu立ち上げて、GPartedで “->|”のアイコンで、対象のボリューム(/dev/nvme0n1p3)をリサイズします

③ $ lsblkでパーテションの割り付け確認して余裕容量を確認、残らず割り当てるにはlvextendコマンドで100%指定すればいいだけですが

④ $ sudo lvextend -L 27G /dev/ubuntu-vg/ubuntu-lv

で27.3GBの内27GBを割り当てします

⑤ $ sudo resize2fs /dev/ubuntu-vg/ubuntu-lv

変更反映のためにresize2fsを実行、マウント状態で実行できます(出来なかったら変えられない)

⑥ $ df

で確認、めでたくボリューム拡張が反映されました、

スクリーンショット 2024-05-17 13.44.21.png

 

admin

apple silicon版のVMwareにarm64版のUbuntu

VMwareも個人使用は無償のアナウンスがBroadcomからあったので、M1 MacBook AirにVMとUbuntuを入れてみた。これもIntel macからの移行の一つになるのかな

・VMwareのインスト

https://9to5mac.com/2024/05/14/vmware-fusion-pro-13-free-for-personal-use/

このリンクからアカウント取得してダウンロード、何回か弾かれてChromeで成功、多分混んでただけで、次の日の朝にやってみたらすんなりだったから

インストールでファイルが見つからないと言われる時の解決方法。

https://www.dev2qa.com/how-to-fix-file-not-found-error-when-launching-vmware-fusion-on-mac-os/

以前にVMwareインストールはしてないと思うけど、同じ対応(VMwareライブラリの削除)でインストできた。

・Ubuntuのインスト

Arm用のデスクトップ版は無いから、サーバー版をダウンロード、インストしてデスクトップ関連のソフトをアップデートする、このやり方だとあくまでOSの種類はサーバーに見えている

$ sudo apt install ubuntu-desktop

ただしこれは時間が相当に掛かる、一時間以上かかった

$ sudo reboot

で起動して、timezoneの変更

$ sudo timedatectl set-timezone Asia/Tokyo

これでとりあえずデスクトップ版のUbuntuは使えるようになったけど、macとのファイル共有にはVMware Toolsを入れないといけないのだけれども、方法が?

 

P.S. 2024.5.19

VMware toolsはなくとも、過去のUbuntuインスト時のやり方で共有できました。ディレクトリ名などは微妙に異なっていますが(Desktop -> デスクトップ)、

https://isehara-3lv.sakura.ne.jp/blog/2021/08/13/vmwareでゲストosとのフォルダ共有/

 

admin

Valgrind(メモリリークチェックツール)

Rustのドキュメントの中に出てきたキーワードですが、Valgrindなるツールがあるらしいので触ってみた。

M1 Macにはインストールできないので、久々にVMのUbuntuにインストールしてみた。

ついでにRustもインストール。

<Rust on Ubuntu>

参考サイト、

https://qiita.com/yoshiyasu1111/items/0c3d08658560d4b91431

$ curl –proto ‘=https’ –tlsv1.2 -sSf https://sh.rustup.rs | sh

ただしcurlがcurl: (23) Failure writing output to destinationのエラーを吐くので、

$ sudo snap remove curl

$ sudo apt install curl

でcurl再インストールしたらできました、この理屈は以下のようなものかと、

https://qiita.com/ynott/items/c7362ab3fdcee3fb0972

 

<Valgrindのインストール>

https://valgrind.org/info/

wikipediaによるとvalgrind自身はvmになっていて、バイナリを中間言語に変換して実行するらしいから、実行速度はかなり低下する(数分の1)けれども、メモリリークテストにとってはそれほど問題とならないという理屈のようです。バイナリを中間言語に変換するので、コンパイラが何であってもバイナリさえあれば実行可能です。

Linux(VM上のUbuntu)にソースからインストールしてみた、

————————————————

ダウンロードした最新のtar.bz2ファイルを

tar -jxvf valgrind-3.23.0.tar.bz2

展開されたソースフィイルに移動して、

$ ./configure

$ make 

$ sudo make install

インストールできたら動作確認、

main.rsというシンプルなRustのファイルを作って、

fn main() {

  println!("Hello, world!");

}

これをコンパイルしてmainファイル作成して以下を実行すると、

$ valgrind ls -l
==10251== Memcheck, a memory error detector
==10251== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==10251== Using Valgrind-3.23.0 and LibVEX; rerun with -h for copyright info
==10251== Command: ls -l
==10251== 
合計 3700
-rwxrwxr-x 1 hoge hoge 3780776  5月 12 12:37 main
-rw-rw-r-- 1 hoge hoge      44  5月 12 12:36 main.rs
==10251== 
==10251== HEAP SUMMARY:
==10251==     in use at exit: 20,365 bytes in 9 blocks
==10251==   total heap usage: 140 allocs, 131 frees, 109,770 bytes allocated
==10251== 
==10251== LEAK SUMMARY:
==10251==    definitely lost: 0 bytes in 0 blocks
==10251==    indirectly lost: 0 bytes in 0 blocks
==10251==      possibly lost: 0 bytes in 0 blocks
==10251==    still reachable: 20,365 bytes in 9 blocks
==10251==         suppressed: 0 bytes in 0 blocks
==10251== Rerun with --leak-check=full to see details of leaked memory
==10251== 
==10251== For lists of detected and suppressed errors, rerun with: -s
==10251== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Rustなので問題は出ませんが、次にC++で意図的にリークが発生するような以下のソースでは、

#include <stdlib.h>
int main()
{
 char *x = new char[100];
 return 0;
}

以下のようにエラー(LEAK SUMMARY:)が発生します、この実行は実はintel MacOSにValgrindインストールして行ってますが、

% valgrind --tool=memcheck ./memory
==23180== Memcheck, a memory error detector
==23180== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==23180== Using Valgrind-3.23.0.GIT-lbmacos and LibVEX; rerun with -h for copyright info
==23180== Command: ./memory
==23180== 
--23180-- run: /usr/bin/dsymutil "./memory"
warning: no debug symbols in executable (-arch x86_64)
==23180== Syscall param map_with_linking_np(link_info) points to uninitialised byte(s)
==23180==    at 0x100067D2E: __map_with_linking_np (in /usr/lib/dyld)
==23180==    by 0x10001C88A: dyld4::setUpPageInLinkingRegions(dyld4::RuntimeState&, dyld4::Loader const*, unsigned long, unsigned short, unsigned short, bool, dyld3::Array const&, dyld3::Array const&) (in /usr/lib/dyld)
==23180==    by 0x10001C221: invocation function for block in dyld4::Loader::setUpPageInLinking(Diagnostics&, dyld4::RuntimeState&, unsigned long, unsigned long long, dyld3::Array const&) const (in /usr/lib/dyld)
==23180==    by 0x10001BF94: dyld4::Loader::setUpPageInLinking(Diagnostics&, dyld4::RuntimeState&, unsigned long, unsigned long long, dyld3::Array const&) const (in /usr/lib/dyld)
==23180==    by 0x10001CA08: dyld4::Loader::applyFixupsGeneric(Diagnostics&, dyld4::RuntimeState&, unsigned long long, dyld3::Array const&, dyld3::Array const&, bool, dyld3::Array const&) const (in /usr/lib/dyld)
==23180==    by 0x100022212: dyld4::JustInTimeLoader::applyFixups(Diagnostics&, dyld4::RuntimeState&, dyld4::DyldCacheDataConstLazyScopedWriter&, bool) const (in /usr/lib/dyld)
==23180==    by 0x100009DBC: dyld4::prepare(dyld4::APIs&, dyld3::MachOAnalyzer const*) (in /usr/lib/dyld)
==23180==    by 0x1000092FE: (below main) (in /usr/lib/dyld)
==23180==  Address 0x1048e7d00 is on thread 1's stack
==23180==  in frame #1, created by dyld4::setUpPageInLinkingRegions(dyld4::RuntimeState&, dyld4::Loader const*, unsigned long, unsigned short, unsigned short, bool, dyld3::Array const&, dyld3::Array const&) (???:)
==23180== 
==23180== 
==23180== HEAP SUMMARY:
==23180==     in use at exit: 9,441 bytes in 176 blocks
==23180==   total heap usage: 186 allocs, 10 frees, 10,173 bytes allocated
==23180== 
==23180== LEAK SUMMARY:
==23180==    definitely lost: 4,388 bytes in 135 blocks
==23180==    indirectly lost: 48 bytes in 1 blocks
==23180==      possibly lost: 600 bytes in 3 blocks
==23180==    still reachable: 4,405 bytes in 37 blocks
==23180==         suppressed: 0 bytes in 0 blocks
==23180== Rerun with --leak-check=full to see details of leaked memory
==23180== 
==23180== Use --track-origins=yes to see where uninitialised values come from
==23180== For lists of detected and suppressed errors, rerun with: -s
==23180== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 124 from 39)

Rustではあまり出番がなさそうですが、c++では使えるツールのようです。

 

admin

関連型(associated types)(@Rust)

ジェネリクスと関連し、ジェネリクスとの使い分けも必要ですが、関連型という記法があります。

https://zenn.dev/shinyay/articles/hello-rust-day040

のコードから、関連型で全体を構成してみました。

できるだけ固有の型記述を排除するために、impl Positionの中ではi32指定とするのではなく&Self::X or Yを使っています。

fn main() {
    // associated types
    //
    let point = Point(x, y);

    println!("Point X:{}, Y:{}", &x, &y);
    println!("Exist?:{}", point.exist(&x, &y));

    println!("Point-X:{}", point.v_axis());
    println!("Point-X:{}", point.h_axis());

    new_point(&point);
}

struct Point(i32, i32);

trait Position {
    type X;         // to use associated types
    type Y;

    fn exist(&self, _: &Self::X, _: &Self::Y) -> bool;
    fn h_axis(&self) -> i32;
    fn v_axis(&self) -> i32;
}

impl Position for Point {
    type X = i32;
    type Y = i32;

    fn exist(&self, x: &Self::X, y: &Self::Y) -> bool {
        (&self.0 == x) && (&self.1 == y)
    }

    fn h_axis(&self) -> Self::X {
        self.0
    }

    fn v_axis(&self) -> Self::Y {
        self.1
    }
}

fn new_point<Z: Position>(point: &Z) {                          // you don't need specify X and Y anymore
    println!("POINT:({},{})", point.v_axis(), point.h_axis())   // like "fn new_point<X, Y, Z>(point: &Z) where Z: Position<X, Y>"
}

使い分けですが、この例のようなシンプルなトレイトとSelfが一対一対応(トレイトに実装される型が一種類の時)の場合には、関連型を使う方がコードが読みやすいだろうと思います。もしi32以外に例えばf64の実装もあるというような複数実装の時には素直にジェネリクスを使うしかありません。

 

admin

空トレイトを境界条件として使う(@Rust)

トレイトが何らの機能を持っていなくとも境界条件として使えるというサンプルコードです。

https://doc.rust-jp.rs/rust-by-example-ja/generics/bounds/testcase_empty.html

のコードにYellowトレイトを追加しています。

struct Cardinal;
struct BlueJay;
struct Turkey;

trait Red {}
trait Blue {}
trait Yellow {}

impl Red for Cardinal {}
impl Blue for BlueJay {}
impl Yellow for Turkey {}

// These functions are only valid for types which implement these
// traits. The fact that the traits are empty is irrelevant.
fn red<T: Red>(_: &T)   -> &'static str { "red" }
fn blue<T: Blue>(_: &T) -> &'static str { "blue" }
fn yellow<T: Yellow>(_: &T) -> &'static str { "yellow" }

fn main() {
    let cardinal = Cardinal;
    let blue_jay = BlueJay;
    let turkey   = Turkey;

    // `red()` won't work on a blue jay nor vice versa
    // because of the bounds.
    println!("A cardinal is {}", red(&cardinal));
    println!("A blue jay is {}", blue(&blue_jay));
    println!("A turkey is {}", yellow(&turkey));
}

このソースではライフタイム指定(‘static)はしなくとも動作します。

 

admin

ジェネリック境界(@Rust)

ジェネリクスにおいてジェネリクスの型に制限を与えることですが、

https://doc.rust-jp.rs/rust-by-example-ja/generics/bounds.html

のコードから変更してtriangleの処理もできるように変更しています。あと三角形の面積の計算の仕方が変なのでそこも変更。

ここではジェネリクスにトレイトHasArea型を満たすことという条件で「境界」を決めています。

またprint_debugに引き渡す引数にはDebugが実装されていなければならないので、struct TriangleとRectangleにはDebug実装のための(#[derive(Debug)])が必須です。

// A trait which implements the print marker: `{:?}`.
use std::fmt::Debug;

trait HasArea {
    fn area(&self) -> f64;
}

impl HasArea for Rectangle {
    fn area(&self) -> f64 {
        self.length * self.height
    }
}

impl HasArea for Triangle {
    fn area(&self) -> f64 {
        (self.length * self.height) / 2.0
    }
}

#[derive(Debug)]
struct Rectangle {
    length: f64,
    height: f64,
}

#[derive(Debug)]
struct Triangle {
    length: f64,
    height: f64,
}

// The generic `T` must implement `Debug`. Regardless
// of the type, this will work properly.
fn print_debug(t: &T) {
    println!("{:?}", t);
}

// `T` must implement `HasArea`. Any type which meets
// the bound can access `HasArea`'s function `area`.
fn area<t>(t: &T) -> f64
where
    T: HasArea,
{
    t.area()
}

fn main() {
    let rectangle = Rectangle {
        length: 3.0,
        height: 4.0,
    };
    let triangle = Triangle {
        length: 3.0,
        height: 5.0,
    };

    print_debug(&rectangle);
    println!("Area: {}", area(&rectangle));

    print_debug(&triangle);
    println!("Area: {}", area(&triangle));
}

 

admin

 

スマートポインターの独自実装(@Rust)

Box<T>のようなスマートポインターの独自実装がRustドキュメントの中に出てきます。Box<T>は一番基本的なスマートポインターで他にもいくつか存在しますが、

https://doc.rust-jp.rs/book-ja/ch15-02-deref.html

もともとスマートポインターはRust固有ではなくC++でもありますが、定義は『通常のポインタのように振る舞うだけでなく、追加のメタデータと能力があるデータ構造』とありますが、追加のメタデータと能力とは以下のサンプルコードで示される参照外しは一例かと思います。もともとC++におけるスマートポインターも目的とするところはほぼ同じ。

以下のコードはリンクからのコードですが、独自のMyBox(Box相当)でBoxのメソッドの一つであるnew()を実装すれば、引数の値をヒープエリアに割り当ててくれます。ただし、DerefをMyBoxメソッドに対して実装しないとせっかくMyBoxで割り当てたメモリエリアの参照ができないので、以下のコードはコンパイルできません。

hello関数と呼出の例は、もしMyBoxにDerefが実装されていないと呼び出しが煩雑になるよという例を示すためで、もしDeref実装がないと以下のような読みづらいコードを書かないといけないようです。

hello(&m); –> hello(&(*m)[..]);

これは、

https://qiita.com/moyamoyac/items/5aea471d6676625dcd62

で記述されているように、以下の三段階の変換が組み込まれたコードなのでぱっと見分かりづらい。

mMyBox<String>
*mString
&(*m)[..]&str

 

use std::ops::Deref;

struct MyBox<T>(T);

impl MyBox<T> {      // original smart pointer
    fn new(x: T) -> MyBox {
        MyBox(x)
    }
}

impl Deref for MyBox {    // deref coercion
    type Target = T;    // to define return value type T for the Deref "Target"
                        // in the DeRef trait : fn deref(&self) -> &Self::Target;

    fn deref(&self) -> &T {
        &self.0
    }
}

fn hello(name: &str) {          // "&" is needed to get a known size of the argument at compile-time
    println!("Hello, {}!", name);
}

fn main() {
    let x = 5;
    let y = MyBox::new(x);

    assert_eq!(5, x);
    assert_eq!(5, *y);  // to success compile, Deref definition should be defined

    println!("x = {}, y = {}", x, *y);

    let m = MyBox::new(String::from("Rust"));
    hello(&m);
}

 

admin

車の中に三日放置で変形

夏に近づいたせいか、車内の温度は相当上昇するようで、土曜日にデモのため持ち出したホーバークラフト、今日取り出してみるとファンのホルダーがグダグダに変形しています。

PLAの耐熱温度は60℃ぐらいらしいから、車内だと今でも直射日光浴びる場所だとアウトの模様。この先意識しておかないと、

ABSだと耐熱性は問題なくとも、形状安定性特にファンのホルダーのようなそこそこ寸法精度が必要とされる場所には向いていないと思う。

 

admin

ホバークラフト(ver.2)

ようやくver.2を製作した、

改良点は、

① プロペラを水平(可変はできる)取り付けで横方向の推力が出ないようにした

② プロペラの風の抜けをよくできるような取り付け形状に改良

③ micro:bitを水平に取り付けてコンパス機能を使えるようにした

④ 金属ネジとか使わないで、かつコネクタも軽量化して、全体で二割ぐらいは軽量化

ver.1のようにファンが傾いていないから、割と安定してホバリングしている。

プロペラ駆動力(回転数)の調整でどこまで移動や回転が制御できるかはこれから、

<micro:bit制御用のコード>

・本体用

https://github.com/chateight/hober

ここでファンに与える電圧(回転数)を変えれば動きが制御できるはず

・コントローラー用

https://github.com/chateight/hober_ctl

 

<モーター駆動回路図>

 

 

admin

関数呼び出しと戻り値がクロージャーの場合(@Rust)

https://kudohamu.hatenablog.com/entry/2015/09/26/084621

で、以下のようなコードが出てきて、なぜhoge()()と()が二重になるのかなと思いましたが、

fn main(){
    println!("{}", hoge()());
}

fn hoge() -> Box<dyn Fn() -> String> {
    Box::new(|| -> String {
        String::from("ほげー!")
    })
}

Geminiで質問すると、

hoge()だけだと関数呼び出すだけで、hoge()()としないと戻り値であるクロージャーの実行はできないと以下のように言われました。

まとめ:

hoge()() は、hoge 関数を呼び出し、その結果として得られたクロージャを呼び出すという二つの操作をまとめて実行しています。

「関数の戻り値としてのクロージャーを実行するなら二重括弧を使う」ということのようです

したがって、以下のように冗長に記述もできます。

    let abc = hoge();
    println!("{}", abc());

同じことは、クロージャーを戻り値にしている

https://isehara-3lv.sakura.ne.jp/blog/2024/04/05/クロージャーを戻り値にするrust/

のコードでも言えて、

    let fn_plain = create_fn(); // return a closure
    
    fn_plain();

と

    create_fn()();

は等価です

 

admin