virtual disk
Table of Contents
VScode and WindowTerminal
前回Rust本を購入してしまったものだから、本に合わせて環境構築してみる。 場所は、Ubuntu/WSL2だ。まずはターミナルって事で、MS推薦のやつを入れた。 年寄には、色がつらいんで、RGBにした。フォントサイズもデフォでは11らしい ので、JSONファイルの中のプロファイル項で
{ "guid": "{2c4de342-38b7-51cf-b940-2309a097f518}", "hidden": true, "name": "Ubuntu", "font": { "size": 16 }, "source": "Windows.Terminal.Wsl" },
こんな風にした。全く若者向けの設定で困ったものだ。 VScodeについては、こんなのが有った。 Linux 用 Windows サブシステムで Visual Studio Code の使用を開始する これも若者設定になってる。
さすがにググルと設定の変更方法がすぐに見付かった。フォントサイズと配色を変更 したよ。にしてもGUIって泥沼だと思うぞ。配色は、ほなららのテーマを選ぶのね。 そのテーマも自作できたりして、見栄を競う世界が待ってる。オイラーみたいにCUIの 住民からしたら無駄の極みと思うぞ。
件の本にもVScodeのスナップショットが出てくるんだけど、これがまた見難い。闇夜の 烏を提示して心眼で読めってか。配慮が足りないと思うぞ。せめて背景が白ぐらいを 選んで欲しいものだ。
困ったものついでに、rustにはreplが無い。goにも無いか。でも、lispやschemeには 有るぞ。haskell(= ghc)にも、ghciって言うりっぱなreplが存在する。ならばrustでも ってなるのは当然の事。どうやら、これがそうらしい。 A Rust REPL
user-agent for Ubunts/WSL2
いきおい余ってウブを入れちゃったので、各種ブラウザーのユーザー・エージェントを 採取してみた。
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Mozilla/5.0 (X11; Linux x86_64; rv:133.0) Gecko/20100101 Firefox/133.0 URL/Emacs Emacs/29.3 (TTY; x86_64-pc-linux-gnu) w3m/0.5.3+git20230121 curl/8.5.0
chromeって専用サイトからDLして、それをapt installするのね。週間アップデートは、 どうやるのが正解? リポジトリィを登録しておいて、apt upgradeかな。firefoxは普通 にインストール出来るけど、$HOME直下にsnapなんてのが作成される。そこが第二の$HOME になるみたいだ。一応、環境分離ってか分断される訳ね。 emacsは現行の物より、ちと古い。LTS 24.04だと、その時代に固定されるんだな。
SCSI
ここからは、純粋なBSDの話として、仮想にまつわるあれこれを、仮想Diskを中心 に調べてみる。
まずは、暗号diskの所で、MAKEDEV なんてのが出ていたので、MAKEDEV(8)してみた。
Special device names all Creates special files for all devices on amd64. ramdisk Ramdisk kernel devices. std Creates the ‘standard’ devices (console, klog, kmem, ksyms, mem, null, stderr, stdin, stdout, tty, zero) which are absolutely necessary for the system to function properly. local Creates configuration-specific devices, by invoking the shell file MAKEDEV.local. Disks cd* ATAPI and SCSI CD-ROM drives, see cd(4). fd* Floppy disk drives (3 1/2", 5 1/4"), see fd(4). rd* “rd pseudo-disks, see rd(4). sd* SCSI disks, including flopticals, see sd(4). vnd* “file pseudo-disk devices, see vnd(4). wd* “winchester disk drives (ST506, IDE, ESDI, RLL, ...), see wd(4).
これぐらいが興味の有る所でしょうか。そのうちのsdを調べてみる。
Small Computer System Interface
/usr/share/misc/scsimodes とか、scsi(8)を参照しながら、scsi deviceと意思疎通してみましょう。ここまで来る と病気だな。
現在の河豚板のマウント状況。
eq$ df -h Filesystem Size Used Avail Capacity Mounted on /dev/rd0a 1.5M 1.0M 509K 68% / /dev/sd1a 1.1G 1.1G 8.6M 100% /sysmedia /dev/vnd5a 1.1G 1.1G 4.3M 100% /fuguita mfs:79663 5.4G 2.2G 2.9G 43% /ram /dev/sd1d 129G 37.3G 92.0G 29% /mnt
sd1がSCSI接続されたデバイスと判明したんで、この素性を確認してみる。
eq$ doas scsi -f /dev/rsd1c -c "12 0 0 0 64 0" -i 0x64 "s8 z8 z16 z4" USB-HS SAMSUNG SP1604N 0.01
そして、検算。sd0はThinkPadに内蔵されてるSSD。sd1はUSBで接続してるドライブ。こ こに河豚板がはいっている。たまたま両者がコリア製だったのね。安いからね。
eq$ dmesg|grep SAMS sd0 at scsibus1 targ 0 lun 0: <ATA, SAMSUNG MZ7LN256, EMT0> naa.5002538d00000000 sd1 at scsibus2 targ 1 lun 0: <USB-HS, SAMSUNG SP1604N, 0.01> serial.0411002a000001112523eq$ dmesg|grep SAMS
ああ仮想マシンで暗号化した事も有ったな。同じ事をやってみる。
hoge# df -h Filesystem Size Used Avail Capacity Mounted on /dev/sd1a 975M 480M 446M 52% / hoge# scsi -f /dev/rsd1c -c "12 0 0 0 64 0" -i 0x64 "s8 z8 z16 z4" OPENBSD SR CRYPTO 006 hoge# dmesg | grep sd sd0 at scsibus1 targ 0 lun 0: <VirtIO, Block Device, > sd0: 1024MB, 512 bytes/sector, 2097152 sectors sd1 at scsibus3 targ 1 lun 0: <OPENBSD, SR CRYPTO, 006> sd1: 1023MB, 512 bytes/sector, 2096560 sectors root on sd1a (5576836c7209b6a6.a) swap on sd1b dump on sd1b hoge# scsi -f /dev/rsd0c -c "12 0 0 0 64 0" -i 0x64 "s8 z8 z16 z4" VirtIO Block Device
隠れsd0にもアクセス出来た。このsd0が暗号化されてて、bootの途中でパスフレーズに より復号化されるんだな。それがsd1となって、ユーザーから見えるんだな。sd0,sd1で 微妙にセクター数が異なるぞ。
昔、あのぶ太いケーブルの取り回しに苦労したな。それを皆が嫌ったものだから、 USBが発達したんだな、ってのは素人の邪推。そもそもケーブルがぶっ太いのは、多数の 信号線が有るから。多数の信号だと、信号同士で干渉しちゃって速度を上げられない。 信号に遅い速いのバラツキが出て(いわゆるスキュー問題)、やはり速度を上げられない、なんて問題が出た。 ならば、パラレル転送よりシリアル転送の方が、いいんでないかい。これが技術的 な問題になったんだったな。
old time
Q: DISKメディアを交換できるタイプの 古 DISK装置について質問します。 基準メディアを装着して、キャッツ・アイ調整と称する作業を行なった記憶が あります。これは何を目的とした調整だったのでしょうか?
A: 「キャッツ・アイ調整」という名称から推測すると、古いディスク装置(特にフロッピーディスクや光磁気ディスクなどのメディア交換が可能なタイプ)における読み取り・書き込みヘッドの**アライメント(位置調整)**を行う作業を指している可能性が高いです。
### キャッツ・アイ調整の目的
- ヘッドの位置調整 ヘッドがディスク上のデータトラックに正確に位置するように調整することで、正確なデータの読み書きを可能にします。トラック間のズレが発生すると、データが正しく読み取れなくなります。
- 信号強度の最大化 読み取りヘッドがディスク上のデータ信号を最適にキャプチャできるよう、信号の強度や波形を観測しながら調整を行います。これにより、エラー率を下げることができます。
- 基準メディアを使った標準化 基準メディア(工場出荷時に正確にフォーマットされたディスク)を使用して調整することで、装置がメーカー規定の動作を再現できるようにします。これにより、他の装置で作成されたディスクも問題なく読み書きできる互換性が確保されます。
- 異常な動作の修正 使用中にヘッド位置がズレたり、機械的な経年劣化で調整が必要になった場合、キャッツ・アイ調整によって正常な動作を取り戻すことができました。
### キャッツ・アイの由来 「キャッツ・アイ」という名称は、おそらく**調整中に観測される信号の形状や光学的なパターン**が、猫の目に似ていることからつけられた俗称だと考えられます。このような調整は、特定の波形や信号を監視しながら行うことが多く、波形の見た目が「猫の目」に見えたのではないでしょうか。
### 関連する装置や作業
- 5.25インチや8インチフロッピーディスク装置 古いコンピュータではフロッピーディスクのヘッド調整がよく行われました。
- **オシロスコープ**を用いて波形を観測 調整時には、オシロスコープを使用して信号の波形や強度を確認する作業が一般的でした。
- 磁気ヘッドクリーニング ヘッドが汚れている場合、調整前に清掃を行う必要がありました。
もし具体的な装置名や時代背景について教えていただければ、さらに詳しく調べてお答えできます!
Q: 磁気テープ装置では、スキュー調整と言う作業も良く実施しました。これは、 どんな目的だったのでしょうか?
A: 磁気テープ装置における**スキュー調整**は、主に以下の目的で行われる作業です。
—
### スキュー調整の目的
- トラック間のタイミング整合性の確保 磁気テープには複数のトラック(並列データライン)が記録されており、すべてのトラックから同時にデータを正しく読み取るためには、各トラックのヘッドが正確に同期している必要があります。 **スキュー**とは、トラックごとに読み取りタイミングがズレる現象を指します。このズレを調整し、同期を確保するのがスキュー調整の主な目的です。
- 機械的な歪みや摩耗の補正 テープ装置は長時間の使用や経年劣化により、機械部品の摩耗や物理的なズレが発生することがあります。これにより、テープがヘッドに対して斜めに走行したり、トラック間のタイミングが狂うことがあります。スキュー調整によってこれを補正します。
- テープ移動の安定性向上 磁気テープがヘッドを通過する際の**テンション(張力)**や**ガイドローラーの角度**に起因する不安定な動きを修正します。これにより、トラック位置のズレを最小化し、安定した読み書きを実現します。
- データエラーの低減 トラック間でタイミングがズレると、データの読み取りエラー(パリティエラーなど)が発生しやすくなります。特に高速で動作する磁気テープ装置では、微小なズレでもデータの完全性に大きな影響を与えるため、スキュー調整が重要です。
—
### スキュー調整の具体的な作業
- 基準テープの使用 工場出荷時に正確に記録された**基準テープ**を装置にセットし、各トラックの信号タイミングを確認します。
- 波形観測 オシロスコープや専用のタイミングモニタを使用し、複数トラックの信号が同時に出力されているかをチェックします。波形が一致しない場合、物理的または電子的に調整します。
- ヘッド位置と角度の調整
- 磁気ヘッドの高さ、角度、テープへの接触面を調整します。
- トラック間の信号のタイミングを一致させるように調整します。
- テープ走行経路の確認 テープガイド、キャプスタン、ピンチローラーなどの部品の位置や角度が正しいか確認し、不整合があれば調整します。
—
### スキュー調整が必要になる主な原因
- テープ媒体の劣化 長期間使用されたテープは伸びや縮みが生じ、トラック間の物理的な位置がズレます。
- 装置の摩耗や物理的変形 テープを繰り返し読み書きする中で、ヘッドやテープガイドが摩耗し、位置がズレることがあります。
- 温度や湿度の影響 テープ媒体や装置の機械部品は、環境条件により変形する場合があります。これによりスキューが発生することがあります。
—
### 調整の効果
- データの**信頼性**が向上し、エラーの発生頻度が減少。
- 他の磁気テープ装置との**互換性**を維持。
- **データ復旧**の成功率が向上。
スキュー調整は、磁気テープ装置の性能とデータの安全性を確保するうえで非常に重要なメンテナンス作業でした。
vmd
仮想マシンを動作させるには、vmdはダエモン君が必要。このダエモン君を表に 引っぱり出す起動オプションが有るみたい。
-d Do not daemonize and log to stderr. -v Verbose mode. Multiple -v options increase the verbosity.
-v ひとつだと有益な情報が出てこないので、-vv にした。
eq$ doas /usr/sbin/vmd -d -vv vmd: startup : vm/amd: loadfile_bios: loaded BIOS image vm/amd: pic_set_elcr: setting level triggered mode for irq 3 vm/amd: pic_set_elcr: setting level triggered mode for irq 5 vm/amd: amd: launching vioblk0 vm/amd: virtio_dev_launch: sending 'd' type device struct vm/amd: virtio_dev_launch: sending vm message for 'amd' vm/amd/vioblk: vioblk_main: got viblk dev. num disk fds = 1, sync fd = 15, async fd = 17, capacity = 0 seg_max = 126, vmm fd = 5 vm/amd/vioblk0: vioblk_main: initialized vioblk0 with raw image (capacity=2097152) vm/amd/vioblk0: vioblk_main: wiring in async vm event handler (fd=17) vm/amd/vioblk0: vm_device_pipe: initializing 'd' device pipe (fd=17) vm/amd/vioblk0: vioblk_main: wiring in sync channel handler (fd=15) vm/amd/vioblk0: vioblk_main: telling vm amd device is ready vm/amd/vioblk0: vioblk_main: sending heartbeat vm/amd: virtio_dev_launch: receiving reply vm/amd: virtio_dev_launch: device reports ready via sync channel vm/amd: vm_device_pipe: initializing 'd' device pipe (fd=16) vm/amd: pic_set_elcr: setting level triggered mode for irq 6 vm/amd: run_vm: starting 1 vcpu thread(s) for vm amd : vm/amd: fw_cfg_handle_dma: selector 0x0004 vm/amd: i8259_write_datareg: master pic, reset IRQ vector to 0x8 vm/amd: i8259_write_datareg: slave pic, reset IRQ vector to 0x70 vm/amd: fw_cfg_handle_dma: selector 0x000f vm/amd: fw_cfg_select: unhandled selector f : vm/amd: fw_cfg_select_file: accessing file etc/screen-and-debug vm/amd: vcpu_process_com_lcr: set baudrate = 115200 vm/amd: vcpu_process_com_lcr: set baudrate = 115200 : ここら辺で仮想マシンが起動する。次はshutdownのフェーズに突入だ。 vm/amd: vmmci_ack: vm 3 requested shutdown vm/amd: vmd: vm 3 shutdown vm/amd/vioblk0: handle_sync_io: vioblk pipe dead (EV_READ) vm/amd/vioblk0: dev_dispatch_vm: pipe dead (EV_READ) vmm: vmm_sighdlr: handling signal 20 vmm: vmm_sighdlr: terminated vm amd (id 1) vmm: vm_remove: vmm vmm_sighdlr removing vm 1 from running config vmm: vm_stop: vmm vmm_sighdlr stopping vm 1 vmd: vm_remove: vmd vmd_dispatch_vmm removing vm 1 from running config vmd: vm_stop: vmd vmd_dispatch_vmm stopping vm 1
これとソースを突き合わせてみれば、色々と見えてくるだろうけど、大変そうなので 先に進む事にする。
dev/pv
こちらは識者に勧められたもの。準仮想を担う根幹なドライバー。何か世の中の 仮想を一手に引き受けている感じだな。
VIRTIO(4) Device Drivers Manual VIRTIO(4) NAME virtio – VirtIO support driver SYNOPSIS virtio* at fdt? virtio* at pci? flags 0x00 DESCRIPTION The virtio driver provides support service for paravirtualized devices using the VirtIO protocol. Such devices are provided by bhyve, KVM, QEMU, VirtualBox, and vmm(4). Currently there are drivers for the following virtio devices: vio(4) VirtIO network device vioblk(4) VirtIO disk viocon(4) VirtIO console device viogpu(4) VirtIO GPU device viomb(4) VirtIO memory ballooning driver viornd(4) VirtIO random number device vioscsi(4) VirtIO SCSI adapter vmmci(4) vmm(4) control interfaece
見るなら、こちらですかね。
vnd, vnconfig
いや、diskに的を絞れば、まだ有るぞ。 vnconfig(8) は、普通のファイルをデバイスに見立ててくれる便利な機構だ。 便利なんで河豚板にも、採用されてる。 下記の例はOpenBSDのインストール用ISOファイルをデバイスに見立てる。そして そのデバイスをマウントして、ファイル・システムに参加させてる例だ。
eq$ doas vnconfig vnd0 /mnt/my/ISO/i386Inst76.iso eq$ doas mount -t cd9660 /dev/vnd0c /CVS eq$ tree /CVS /CVS |-- 7.6 | |-- TRANS.TBL | `-- i386 | |-- BUILDINFO : : | |-- xserv76.tgz | `-- xshare76.tgz |-- TRANS.TBL `-- etc |-- TRANS.TBL `-- boot.conf eq$ cat /CVS/etc/boot.conf set image /7.6/i386/bsd.rd
ふーん、ISOからブートした時は、ミニ・カーネルであるbsd.rdが動き出すんか。 じゃ、イメージ・ファイルはどうよ? vndのご協力によると、
ob$ file install76.img install76.img: x86 boot sector; partition 4: ID=0xa6, active, starthead 0, startsector 64, 921536 sectors ob$ ls /mnt 7.6/ boot bsd* bsd.rd* etc/
bsdとbsd.rdは同一の物。これをbootがメモリーに載せてくれるんだな。
use vnconfig
ちょっと使い方を確認。
eq$ doas vnconfig -v vnd3 /mnt/my/ISO/i386Inst76.iso vnd3: 461645824 bytes on /mnt/my/ISO/i386Inst76.iso eq$ doas vnconfig -l vnd0: not in use vnd1: not in use vnd2: not in use vnd3: covering /mnt/my/ISO/i386Inst76.iso on sd1d, inode 5845621 vnd4: not in use vnd5: covering /sysmedia/fuguita-7.6-amd64.ffsimg on sd1a, inode 4 eq$ doas vnconfig -u vnd3
河豚板も利用してた。sd1aに置いてあるイメージを、vnd5でアクセス出来る様に してるのね。vndは貴重な資源だから、利用が終了したら開放しておきましょう。 なお、上記ではvnd3を指定してるけど、省略可能、その場合はvnd0が自動で 利用される。
see code
久しぶりに、gdbします。
(gdb) bt #0 0x00000eb215a109cc in config ( file=0x790d17ca4540 "/mnt/my/ISO/i386Inst76.iso", dev=0xeb509d69c80 "vnd0", dp=0x0, key=0x0, keylen=0) #1 0x00000eb215a103fb in main (argc=1, argv=0x790d17ca43f0) at vnconfig.c:148
核心部分。dpはdisklabelらしい。
if ((fd = opendev(dev, O_RDONLY, OPENDEV_PART, &rdev)) == -1) { : memset(&vndio, 0, sizeof vndio); vndio.vnd_file = file; vndio.vnd_type = (dp && dp->d_type) ? dp->d_type : DTYPE_VND; vndio.vnd_secsize = (dp && dp->d_secsize) ? dp->d_secsize : DEV_BSIZE; vndio.vnd_nsectors = (dp && dp->d_nsectors) ? dp->d_nsectors : 100; vndio.vnd_ntracks = (dp && dp->d_ntracks) ? dp->d_ntracks : 1; vndio.vnd_key = (u_char *)key; vndio.vnd_keylen = keylen; /* * Configure the device */ rv = ioctl(fd, VNDIOCSET, &vndio);
結局は伝家の宝刀であるioctlの世話になってカーネル側でゴニョゴニョする訳ね。
vnconfig(8)
-t disktype Specify a disktype entry from the disktab(5) database. The vnd_dev will have the sector size, sectors per track, and tracks per cylinder values of the specified disktype. The defaults are 512-byte sectors, 100 sectors per track and 1 track per cylinder.
disktabは昔、充実してた覚えが有るんだけど、今は閑古鳥が鳴いてる状況だ。それから vnd(4)も見ておけってさ。
Makefile for Fuguita
河豚板はどの様にして製造されてるか? その秘伝のレシピがMakefileとして公開 されている。そしてその解説書も公開されている。 Makefileのターゲット
今回このMakefileに触れてmakeに対する認識を新たにした。どういう事か? ソースから コンパイルするには、通常GNUのconfigureを実行する。その結果Makefileが自動作成 される。初期の頃のMakefileは手軽に読めたし修正も容易だった。が、最近のそれは 読むのも修正するのも拒むぐらい面倒な代物に成り下ってしまった。そう、 将来は人がコードに関わらなくなる、プログラミング言語はXMLのような存在に の様な存在になって来ているんだな。
でも、それに異を唱えてmakeを上手に利用されているのが河豚板の製造システムだ。 Makefileはコンパイルの為のレシピだけじゃないよ! 上手に使えば、shell scriptの 集合体になるし、makeが提供してる .if とか .for を使って、仕事の流れも制御できるよと。 makeの固定観念を打破した、素晴らしい利用法だと思う。正に慧眼、目の付け所がいいね。
shell scriptの集合体と書いたが、その個別のスクリプトに相当するのが、ターゲットだ。 一つ例を挙げると、
#======================================== # generate LiveUSB from LiveDVD # IMGMB = 2048 # size of uncompressed LiveUSB in MB .PHONY: dvd2usb dvd2usb: pv $(FI).iso.gz | $(COMPRESS) -d -c > $(FI).iso dd if=/dev/zero bs=1m count=$(IMGMB) | pv -s $(IMGMB)M > $(FI).img vmctl start -cL -i1 -m2G -r $(FI).iso -d $(FI).img fi74 vmctl start -cL -i1 -m2G -d $(FI).img fi74 pv $(FI).img | $(COMPRESS) -9 -c > $(FI).img.gz
これはコメントにある様に、LiveDVDからLiveUSBを作成するスクリプトだ。自動化を 推し進める為、作者さんが、仮想マシンを利用する様に追加されたそうだ。make自体は ターゲット単位で管理されるので、どこに記述しようと知ったこっちゃない。
但し、makeはグローバル変数しかない。この変数は、利用しようと思った時に、確定 していなければならない。そんな訳なんで、グローバル変数だけは、最初に記述して おくのが筋だ。
# global definitions # PROJNAME = FuguIta VERSION != uname -r VER != uname -r | tr -d . # define and setup UEFI CD boot # if UEFI applications exist # .if exists(/usr/mdec/BOOTIA32.EFI) . if exists(/usr/mdec/BOOTX64.EFI) EFICD=1 EFICDBOOT_SIZE=350K EFICD_OPT=-e eficdboot MAKE_EFICD=$(MAKE) sysmedia/eficdboot . endif .endif
make独特の癖が一部で露出してるけど、すぐに慣れるだろう(例えば、!= は、マクロだ。右式に、`uname -r` と記述したのと同様な効果を発揮する)。
後make独特な機構として、あの仕事の前に、これをやっとけとか、変更が有った場合 これを続けてやれってのが有る。いわば、ターゲットに対する引数だな。
STAGE_DEPENDS += lib/usbfadm_postproc.sh.$(ARCH) staging.time: $(STAGE_DEPENDS) ./lib/010_extract.sh ./lib/020_modify_tree.sh touch staging.time
そして、最上階に位置((main)するのが、これ。
# final target # .PHONY: all livedvd liveusb all: $(MAKE) livedvd $(MAKE) liveusb # increase revision echo $$(($(REV)+1)) > rev.count # to reorder kernel at next compilation $(MAKE) kernreset livedvd: $(FI).iso.gz liveusb: $(FI).img.gz
allと言う仕事の単位(ターゲット)の定義。livedvdは、Fl.iso.gz が作成されてるって条件が必要。ゆえに下請け しますってことだ。なお、Flは何かと言うとグローバルに定義されてる、説明的な ファイル名だ(OpenBSDが提供する奴は、単純にinstall76.imgの様にアーキテクチャ名は 省略されてる)。
FIBASE = $(VERSION)$(VERSTAT)-$(ARCH)-$(DATE)$(REV) FI = $(PROJNAME)-$(FIBASE)
rust for emacs
冒頭でVScodeに触れた。ファイラー、エディター、ターミナルの3つの機能を1画面に 展開する作りになっている。そのせいか、それぞれの窓が中途半端で使い辛い。 大きな画面ならどうよ? と思って、42インチのTVに投影してみたけど、なんだかなあの 感触であった。
ならば使い慣れたemacsではどうよ? VScode難民の為の設定を公開されてる方が おられた。ありがたい事です。
;;;; for Rust (add-to-list 'exec-path (expand-file-name "/usr/local/bin")) (use-package rust-mode :ensure t :custom rust-format-on-save t) (use-package cargo :ensure t :hook (rust-mode . cargo-minor-mode)) (use-package lsp-mode :ensure t :hook (rust-mode . lsp) :bind ("C-c h" . lsp-describe-thing-at-point) :custom (lsp-rust-server 'rust-analyzer)) (use-package lsp-ui :ensure t)
設定はこれだけ(OpenBSD用なんで、clippyとかはpkgからの導入ゆえ、/usr/local/bin にしてる)。emacsのパッケージは自動で導入されるんで、手間入らずだ。
README
リナ普及を目指して、教科書が無料で公開されてる。
勉強したら実力判定の試験を受けてみましょう。目標が有るとやる気になるな。
dockerコンテナとは?仕組みや利用するメリット・基本的な使い方をわかりやすく解説!
2024年の更新は、これで最後です。来年も宜しくお願い致します。