OpenBSD/riscV64

Table of Contents

timeout

前回やった、時間切れを引き起こすコマンドがどうなってるか調べてみる。 軽くmanすると、-f を付けてあげると子供に波及しなくなる。-s signalで、お望み の信号を送出出来る。それでも終了しない頑固な奴には、-k timeで、time時間だけ 更に猶予を与えてから、伝家の宝刀のKILLを発出する。あのトランプ爺の手口そっくり だな。

pid = fork();
if (pid == -1)
        err(1, "fork");
else if (pid == 0) {
        /* child process */
        signal(SIGTTIN, SIG_DFL);
        signal(SIGTTOU, SIG_DFL);

        execvp(argv[0], argv);
        warn("%s", argv[0]);
        _exit(errno == ENOENT ? 127 : 126);
}
:
set_interval(first_kill);
:
        } else if (sig_term) {
                if (!foreground)
                        killpg(pgid, killsig);
                else
                        kill(pid, (int)sig_term);

                if (do_second_kill) {
                        set_interval(second_kill);
                        second_kill = 0;
                        sig_ign = killsig;
                        killsig = SIGKILL;
                } else

指定されたコマンドを起動。そのコマンドを first_kill 時間だけ実行。 その後、killを実行。まだ生きていて、最終通告時間が設定されてたら、強権発動 。

STANDARDS
     The timeout utility is compliant with the IEEE Std 1003.1-2024
     (“POSIX.1”) specification.

HISTORY
     The timeout utility first appeared in GNU Coreutils 7.0 and has been
     available since OpenBSD 7.0.

このコマンドはIEEEの提案 (compliantって、人の言いなりたなるって意味も有るぞ) で標準になった。つられて、GNUも同調。OpenBSDにも 波及した。IEEEってトランプ爺の国だからね。国際化って美辞麗句だけど、俺の言う 事を黙って聞けって事よ。

IEEE栄誉賞の賞金はノーベル賞超えの200万ドル

この賞金の原資は誰が提供してる? それは、技術のルールを決めて覇者になりたい メーカーに決っているだろう(俺がルールだ、って漫画にも出てくるな)。少額な投資で多大なリターンが約束されますから。

riscv Regster

gp,tpってのがABIで規定されてるけど、どんな用途が目的? 昔のCPUには無かったぞ。

A: はい、あなたの理解はかなり正確です。RISC-Vの`gp`(`x3`)と`tp`(`x4`)は、それぞれ以下のような役割で使用されることが多いです。

### 🔹 `gp`(Global Pointer、x3)

  • 用途: グローバル変数へのアクセス高速化
  • 主な利用場面:
    • コンパイラ(GCCなど)は、`.sdata`(small data)や`.sbss`(small BSS)セクションの**中小規模のグローバル変数**を、`gp`を基点とした**オフセットアクセス**で行います。
    • 通常のグローバル変数のうち、サイズが小さくアクセス頻度が高いものは、このようにして効率的にアクセスされます。

#### ✅ 具体例:

int gcounter = 0;

このような変数が`.sdata`に置かれると、 アセンブリでは以下のように`gp`からのオフセットでアクセスされることがあります。

lw a0, offset(gp) # 例: lw a0, 16(gp)

#### 📌 備考:

  • `gp`の初期値は、OSのリンカスクリプト(`ld`)によって決定される`.sdata`セクションの**中心あたり**。
  • アクセス範囲は ±2048バイト(12ビット即値)に制限されます。これを超えると通常のグローバル変数アクセス(`auipc+ld/st`)に切り替えられます。

### 🔹 `tp`(Thread Pointer、x4)

  • 用途: スレッドローカルストレージ(TLS)やスレッドコンテキストの基点
  • 主な利用場面:
    • **マルチスレッド環境**で、スレッドごとに独立なデータ(例: errno、TLS変数、スレッド管理構造など)を扱うための基準ポインタ。
    • OSカーネルやランタイム(glibc、muslなど)は、`tp`を使って現在スレッドのPCBやTLS領域の先頭を指すように設定します。

#### ✅ 具体例:

  • ユーザ空間のTLS変数:

_thread int localvar;

は、RISC-VのABIに従って`tp`を基準にしたオフセットアクセスにコンパイルされます。

  • カーネル空間でも:
    • `tp` = currentスレッドのPCBのアドレス
    • PCBの中にカーネルスタックや各種スケジューラ情報が格納されており、`tp`を通してアクセス

### 💡まとめ

レジスタ 名称 主な用途 アクセス例
---- -------------- -------------------------- -------------------
`gp` Global Pointer `.sdata/.sbss`中の変数への高速アクセス `lw a0, offset(gp)`
`tp` Thread Pointer TLS変数、スレッド固有情報(PCBなど)の参照基点 `lw a0, offset(tp)`

### 余談

  • ARMやx86\64でも似た用途のレジスタがあります(例:x86\64では`fs`や`gs`がTLSに使われます)。
  • RISC-Vでは、TLSモデルとして IE (initial exec)LE (local exec) モデルが用いられますが、いずれも`tp`をベースとするアクセスが行われます。

OpenBSD/riscV64

riscvでちゃんとしたOSを動作させたい。それにはOpenBSDに限る。稼動ホストは 前回のインチキ・コンペで好成績だったLubuntuにする。

Let's install OpenBSD/riscv64 on QEMU (on windows)

Setup an OpenBSD RISCV64 VM in QEMU (on openbsd)

sakae@lu:rv$ cat MKDISK
qemu-img create -f qcow2 riscv64.img 8G
sakae@lu:rv$ cat INS
qemu-system-riscv64 \
 -M virt -m 1G -bios fw_jump.bin -kernel u-boot.bin \
 -device virtio-net-device,netdev=net -netdev user,id=net \
 -device virtio-blk-device,drive=sd -drive file=miniroot76.img,if=none,id=sd \
 -device virtio-blk-device,drive=hd -drive file=riscv64.img,if=none,id=hd

訳あってOpenBSD 7.6を入れてみた。 起動時にモニター画面になるけど、viewメニューから、シリアルを選択すると、見慣れ たインストール画面が出てくるぞ。

インストール先は、上記ではhdとなってるが、それ はsd1になるんで、sd1を指定する事。httpから本体を入れるんだけど、その筆頭は、あ の北陸の大学を提示してきた。ちゃんとローカライズしてるのね。いつもはCDから なんで、気がつかなかった。

sakae@lu:rv$ cat boot
qemu-system-riscv64 \
 -M virt -m 1G -bios fw_jump.bin -kernel u-boot.bin \
 -device virtio-net-device,netdev=net \
 -netdev user,hostfwd=tcp::2022-:22,id=net \
 -device virtio-blk-device,drive=hd \
 -drive file=riscv64.img,if=none,id=hd \
 -nographic

こちらは常用するbootスクリプトだ。ネットは外側から接続可能としてある。 普段はコンソール画面だけど、非常用って事です。

デフォではgdbが用意されていないので、pkgから入れた。

rv$ gdb a.out
GNU gdb (GDB) 9.2
 :
Breakpoint 1, main () at t.c:4
4               printf("hello riscV\n");
(gdb) disassemble
Dump of assembler code for function main:
   0x00000001197ed7f8 <+0>:     addi    sp,sp,-16
=> 0x00000001197ed7fa <+2>:     sd      ra,8(sp)
   0x00000001197ed7fc <+4>:     sd      s0,0(sp)
   0x00000001197ed7fe <+6>:     addi    s0,sp,16
   0x00000001197ed800 <+8>:     auipc   a0,0xfffff
   0x00000001197ed804 <+12>:    addi    a0,a0,-760 # 0x1197ec508
   0x00000001197ed808 <+16>:    auipc   ra,0x0
   0x00000001197ed80c <+20>:    jalr    184(ra) # 0x1197ed8c0 <printf@plt>
   0x00000001197ed810 <+24>:    li      a0,0
   0x00000001197ed812 <+26>:    ld      ra,8(sp)
   0x00000001197ed814 <+28>:    ld      s0,0(sp)
   0x00000001197ed816 <+30>:    addi    sp,sp,16
   0x00000001197ed818 <+32>:    ret
End of assembler dump.

一応動作してる。objdump -d は、まだ未実装らしいので、llvm-objdump を利用して くれとの事。

RISC-Vについて学ぶ-後編

my OpenBSD

自前のカーネルを作ってみる。

makeoptions DEBUG="-g"

何はともあれ、設定に入れておく事。

rv# time make
  :
ld -T ld.script -X --warn-common -nopie -o bsd ${SYSTEM_HEAD} vers.o ${OBJS}
text    data    bss     dec     hex
4629672 194060  667896  5491628 53cbac
mv bsd bsd.gdb
ctfstrip -S -o bsd bsd.gdb
   70m35.52s real    47m47.74s user    18m34.00s system

qemu上でのセルフ・ビルドです。

rv$ ls *.o | wc
     652     652    7054
rv$ ls -l bsd*
-rwxrwx---  1 root  wobj   5667334 Jun 25 06:14 bsd*
-rwxrwx---  1 root  wobj  23987358 Jun 25 06:14 bsd.gdb*

ファイル数が少な目になる様に調整。

rv# du -sh /usr/obj/sys/arch/riscv64/compile/RISCV64/
151M    /usr/obj/sys/arch/riscv64/compile/RISCV64/

そのおかげか、コンパイル現場は、こんな容量だった。

rv# grep '##' /sys/conf/GENERIC
##option                CRYPTO          # Cryptographic framework
##option                QUOTA           # UFS quotas
##option                EXT2FS          # Second Extended Filesystem
##option                NFSCLIENT       # Network File System client
##option                NFSSERVER       # Network File System server
##option                CD9660          # ISO 9660 + Rock Ridge file system
##option                INET6           # IPv6
##pseudo-device pf              # packet filter
##pseudo-device pflog           # pf log if
##pseudo-device pfsync          # pf sync if
##pseudo-device pflow           # pflow export if

こんな具合にOSの機能を削った。失敗するとmake cleanしてからやり直し。削るなら こちらの方が無難だろう。configした時に、検出してくれる可能性が高いからね。 まあ、デバイス・ツリーの剪定だからね。

rv# grep '##' /sys/arch/riscv64/conf/RISCV64
##radeondrm*    at pci?
##drm*          at radeondrm?
##wsdisplay*    at radeondrm?
##iwm*          at pci?         # Intel WiFi Link 7xxx
   :
## wi*          at uhub?                # WaveLAN IEEE 802.11DS
## udsbr*               at uhub?                # D-Link DSB-R100 radio
##radio*                at udsbr?               # USB radio

頑張ればUSBの所をもっと削れるだろうけど、程々にしといた。

rv# ls -l /bsd*
-rwx------  2 root  wheel   5667334 Jun 25 06:38 /bsd
-rwx------  2 root  wheel   5667334 Jun 25 06:38 /bsd.booted
-rwx------  1 root  wheel   8763415 Jun 24 14:01 /bsd.org
-rw-------  1 root  wheel  12349853 Jun 23 07:16 /bsd.rd
rv# uname -a
OpenBSD rv.my.domain 7.6 RISCV64#1 riscv64

後は、Lubuntu側に、下記を配置するだけだな。 /usr/obj/sys/arch/riscv64/compile/RISCV64/bsd.gdb

break

Lubuntuには、OpenBSD 7.6のソースが鎮座してて、amd64,i386のカーネルをbreakできる 様にしてるんで、今度はriscV64だ。起動スクリプトに -s を付けておいてBSDを起動。 それから、おもむろにgdbを起動する。

sakae@lu:RISCV64$ riscv64-unknown-elf-gdb bsd.gdb
GNU gdb (SiFive GDB-Metal 10.1.0-2020.12.7) 10.1
  :
Reading symbols from bsd.gdb...
cpu_idle_cycle () at /usr/src/sys/arch/riscv64/riscv64/machdep.c:204
204     }
(gdb) bt
#0  cpu_idle_cycle () at /usr/src/sys/arch/riscv64/riscv64/machdep.c:204
#1  0xffffffc0004ebb52 in sched_idle (v=0xffffffc000894780 <cpu_info_primary>)
    at /usr/src/sys/kern/kern_sched.c:194
#2  0xffffffc00020fdec in proc_trampoline ()
Backtrace stopped: frame did not save the PC
  :
(gdb) bt
#0  sys_execve (p=0xffffffc051ff6008, v=0xffffffc04c775f78,
    retval=<optimized out>) at /usr/src/sys/kern/kern_exec.c:259
#1  0xffffffc00020fc30 in mi_syscall (p=0xffffffc051ff6008,
    code=<optimized out>, argp=0xffffffc04c775f78, retval=<optimized out>,
    callp=<optimized out>) at /usr/src/sys/sys/syscall_mi.h:179
#2  svc_handler (frame=0xffffffc04c775ec0)
    at /usr/src/sys/arch/riscv64/riscv64/syscall.c:57
#3  0xffffffc0002708f4 in do_trap_user (frame=0xffffffc04c775ec0)
    at /usr/src/sys/arch/riscv64/riscv64/trap.c:149
#4  0xffffffc000223f92 in cpu_exception_handler_user ()
Backtrace stopped: frame did not save the PC

sys_execve でも停止するか確認した。frame 2,3,4がマシン依存性のあるコード なんだな。frame 1は、 mi_syscall となってる。miはマシン・インディペンデント (被依存)を示している。mdは依存ね。

(gdb) bt
#0  sys_execve (p=0xffff800023938018, v=0xffff800023925bb0,
    retval=0xffff800023925b30) at /usr/src/sys/kern/kern_exec.c:259
#1  0xffffffff81ee33d8 in mi_syscall (p=0xffff800023925b30,
    code=-140736891561040, argp=0x5d55b1dd41f9336a, retval=<optimized out>,
    callp=<optimized out>) at /usr/src/sys/sys/syscall_mi.h:179
#2  syscall (frame=0x5d55b1dd41f9336a)
    at /usr/src/sys/arch/amd64/amd64/trap.c:577
#3  0xffffffff822fa134 in Xsyscall ()

こちらは参考までに、amd64の場合。

一方、起動したOS上では、Ctl+a c でqemuのモニターに入る事ができる(出る時は、 もう一度Ctl+a c)。

rv$ (qemu) info registers

CPU#0
 V      =   0
 pc       ffffffc000349d74
 mhartid  0000000000000000
 mstatus  0000000a000000a2
 hstatus  0000000200000000
 vsstatus 0000000a00000000
 mip      0000000000000000
 mie      00000000000002a8
 mideleg  0000000000001666
 hideleg  0000000000000000
 medeleg  0000000000f0b509
 hedeleg  0000000000000000
 mtvec    0000000080000408
 stvec    ffffffc000223e38
 vstvec   0000000000000000
 mepc     ffffffc00048a3fc
 sepc     ffffffc000349d74
 vsepc    0000000000000000
 mcause   0000000000000009
 scause   8000000000000005
 vscause  0000000000000000
 mtval    0000000000000000
 stval    0000000000000000
 htval    0000000000000000
 mtval2   0000000000000000
 mscratch 0000000080034000
 sscratch 0000000000000000
 satp     8000000000080b9d
x0/zero  0000000000000000 x1/ra    ffffffc0004ebb52 x2/sp    ffffffc04c724e50 x3/gp    ffffffc00082cd38
 x4/tp    ffffffc000894780 x5/t0    0000000000000001 x6/t1    ffffffc00020ff74 x7/t2    0000003e86fcbb18
 x8/s0    ffffffc04c724e60 x9/s1    ffffffffffffffff x10/a0   0000000000000000 x11/a1   0000000000000000
 x12/a2   0000000000000000 x13/a3   0000000000000000 x14/a4   fffffffffffffffc x15/a5   ffffffc000348eb0
 x16/a6   0000000000000001 x17/a7   ffffffc04c75bd80 x18/s2   ffffffc0006439bd x19/s3   ffffffc00087e600
 x20/s4   ffffffc051ffef00 x21/s5   ffffffc00082e188 x22/s6   ffffffc00082cab2 x23/s7   0000000000000001
 x24/s8   fffffffffffffffe x25/s9   0000000000000003 x26/s10  ffffffc000894780 x27/s11  0000000000000000
 x28/t3   0000000c0c71c2ec x29/t4   0000000000000059 x30/t5   00000000051eb850 x31/t6   00000000028f5c28
 f0/ft0   416cd6d010000000 f1/ft1   416cd6d000000000 f2/ft2   0000000000000000 f3/ft3   0000000000000000
 f4/ft4   0000000000000000 f5/ft5   0000000000000000 f6/ft6   0000000000000000 f7/ft7   0000000000000000
 f8/fs0   0000000000000000 f9/fs1   0000000000000000 f10/fa0  0000000000000000 f11/fa1  0000000000000000
 f12/fa2  0000000000000000 f13/fa3  0000000000000000 f14/fa4  0000000000000000 f15/fa5  0000000000000000
 f16/fa6  0000000000000000 f17/fa7  0000000000000000 f18/fs2  0000000000000000 f19/fs3  0000000000000000
 f20/fs4  0000000000000000 f21/fs5  0000000000000000 f22/fs6  0000000000000000 f23/fs7  0000000000000000
 f24/fs8  0000000000000000 f25/fs9  0000000000000000 f26/fs10 0000000000000000 f27/fs11 0000000000000000
 f28/ft8  0000000000000000 f29/ft9  0000000000000000 f30/ft10 0000000000000000 f31/ft11 0000000000000000

CSR'sを見ると、カーネルはS-modeで動作してるっぽいな。正式にはコード嫁。

gp,tp

gp,tpがどんな風に利用されてるか簡単に調べてみる。C言語の中にasm構文を埋め込む のはOpenBSDの方々は嫌い(でも若干は利用してる)のようなんでオイラーは嬉しい。マシン依存部分。

rv$ cd /sys/arch/riscv64/riscv64/
rv$ grep gp *.S
exception.S:    sd      gp, (TF_GP)(sp)
exception.S:    la      gp, __global_pointer$
exception.S:    ld      gp, (TF_GP)(sp)
locore.S:       lla     gp, __global_pointer$
locore.S:       lla     gp, __global_pointer$
locore.S:       lla     gp, __global_pointer$
locore.S:       lla     gp, __global_pointer$
rv$ grep tp *.S
cpuswitch.S:    ld      a5, CI_CURPCB(tp)
cpuswitch.S:    sd      tp, P_CPU(a1)           // Store curcpu
cpuswitch.S:    sd      a5, CI_CURPCB(tp)
cpuswitch.S:    sd      a1, CI_CURPROC(tp)
cpuswitch.S:    call    pmap_set_satp
exception.S:    sd      tp, (TF_TP)(sp)
exception.S:    ld      tp, (TRAPFRAME_SIZEOF)(sp)
exception.S:    sd      tp, (TRAPFRAME_SIZEOF)(sp)
exception.S:    ld      tp, (TF_TP)(sp)
exception.S:    /* Check for astpending */
exception.S:    ld      a1, CI_CURPROC(tp)
locore.S:       ld      tp, CI_SELF(a1)
locore.S:       csrw    satp, s2
locore.S:       csrw    satp, a2

tpの方は地道に追跡しないと詳細不明だけど、それっぽい利用をしてるみたいだ。 gpの方は、すっきりしてるね。

rv$ nm bsd | grep __global_pointer
ffffffc00082cd38 D __global_pointer$
rv$ readelf -a bsd|grep __global_pointer
Symbol table '.symtab' contains 15094 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
  2738: ffffffc00082cd38     0 NOTYPE  GLOBAL DEFAULT    5 __global_pointer$

リンカーが作り出したシンボルなのかな? Section Headers:を見ると、 .sdata あたりに なるっぽい。でも、りよう してる場所が無いぞ。何故だ?

ChatGPTとあれこれやりながら調査したけど、gpを利用していない、形式的に設定 だけして、お茶を濁しているって結論になった。

speed test

3.5Gのriscv DISKのバックアップをi386マシンにした。ここでもriscv64が動作 するはずなんで、コンパイルの時間を計測。

rv$ time make
cc -g -O0  -MD -MP  -c cmp.c
cc -g -O0  -MD -MP  -c ls.c
cc -g -O0  -MD -MP  -c main.c
cc -g -O0  -MD -MP  -c print.c
cc -g -O0  -MD -MP  -c util.c
cc -g -O0  -MD -MP  -c utf8.c
cc   -o ls cmp.o ls.o main.o print.o util.o utf8.o -lutil
    1m55.05s real     1m10.51s user     0m36.47s system

Lubuntuな環境にあるriscv64確認。

rv$ time make
cc -g -O0  -MD -MP  -c cmp.c
 :
cc   -o ls cmp.o ls.o main.o print.o util.o utf8.o -lutil
    0m14.60s real     0m05.41s user     0m07.55s system

KVMと言うamd64な石。

ad$ time make
cc -g -O0  -MD -MP  -c cmp.c
 :
cc   -o ls cmp.o ls.o main.o print.o util.o utf8.o -lutil
    0m00.60s real     0m00.19s user     0m00.32s system

容量比べ

amd64とriscV64のバイナリーサイズの比較。amd64

ad$ ls -l /bin/tar /bin/sh /usr/bin/vi
-r-xr-xr-x  3 root  bin  797712 Sep 30  2024 /bin/sh*
-r-xr-xr-x  3 root  bin  453304 Sep 30  2024 /bin/tar*
-r-xr-xr-x  3 root  bin  364000 Sep 30  2024 /usr/bin/vi*

こちらは、riscV64。

rv$ ls -l /bin/tar /bin/sh /usr/bin/vi
-r-xr-xr-x  3 root  bin  617680 Sep 30  2024 /bin/sh*
-r-xr-xr-x  3 root  bin  334728 Sep 30  2024 /bin/tar*
-r-xr-xr-x  3 root  bin  290048 Sep 30  2024 /usr/bin/vi*

比較対称は適当に選んだもの。公平な選択と思ってくれ。統計のサンプリング理論を 持ち出すまでもなく、riscV64の方がコンパクトだな。

USB-HDD

TVに取り付けている、録画用のHDDをアクオスが認識しなくなった。放っておくと 普通に使える事がある。そんな不安定な状況を経て、とうとう認識しなくなった。 もう5年ぐらいなるんで、寿命だろう。

USB 3.2(Gen 1)接続な4TByteのHDDを購入。14K円だった。普通録画で500時間、4KBSで 350時間見当らしい。見たら消すって運用をすれば、2TByteで十分と思うんだけど、 どうよ。大事なのを保存しときたいらしいんで4Tになった。でも、データの移動は できないからなあ。オイラー的には無駄だと思うんだけど。2Tだと10K円ぐらい。バッファロー強いですねぇ。 今迄使ってたのもバッファロー製でしたよ。

取り外したHDDが本当に死んでいるか、OpenBSDなマシンに接続して確認。結果は、 全く認識しなかった。もう粗大ゴミで出すしかないな。長年ご苦労様でした。

今迄使ってた河豚板のHDDが認識されなくなっちゃったんで点検。from dmesg

sd1 at scsibus4 targ 1 lun 0: <USB-HS, SAMSUNG SP1604N, 0.01> serial.0411002a000001112523
sd1: 152627MB, 512 bytes/sector, 312581808 sectors
WARNING: R/W mount of /mnt denied.  Filesystem is not clean - run fsck
sd1(umass0:1:0): Check Condition (error 0x70) on opcode 0x28
    SENSE KEY: Media Error
     ASC/ASCQ: Unrecovered Read Error
sd1(umass0:1:0): Check Condition (error 0x70) on opcode 0x28
    SENSE KEY: Media Error
     ASC/ASCQ: Unrecovered Read Error

この所の暑さのせいでHDDもやる気が失せたのかな?

ob$ doas fsck /dev/sd1d
CANNOT READ: BLK 3400
THE FOLLOWING DISK SECTORS COULD NOT BE READ: 3404,
BAD SUMMARY INFORMATION
CONTINUE? yes

 ** Last Mounted on /mnt
 ** Phase 1 - Check Blocks and Sizes
 ** Phase 2 - Check Pathnames
 ** Phase 3 - Check Connectivity
 ** Phase 4 - Check Reference Counts
 ** Phase 5 - Check Cyl groups
FREE BLK COUNT(S) WRONG IN SUPERBLK
SALVAGE? yes

280050 files, 83939288 used, 187158349 free (20013 frags, 23392292 blocks, 0.0% fragmentation)

MARK FILE SYSTEM CLEAN? yes

 ***** FILE SYSTEM WAS MODIFIED *****

README

獣医さんがゆく なんて本を読んだ。

医者の免許は、厚生労働省ってのは知ってたけど、獣医さんは、農林水産省と 環境省のコラボだそうだ。競馬はJRAなんで関連で農林水産省ってのは頷ける。 いや、競馬なんてより、畜産の方がずっと範囲が広い。じゃ、環境省は何で からんで来る? 利権か? 野生動物も含めた世界を扱かう必要が声高に なってきているので、連名になったそうだ。

獣医と言えば、町の動物病院が身近だろう。犬よりも猫の方が人気ってのは 知っていたけど、大学で学ぶのは犬だけだそうだ。ってか、動物界を代表して 馬、牛、豚、うさぎ、犬と、もう1種(何だっけ、忘れた)の6種を勉強するそうだ。 後は、十把一絡で、推測してください、らしい。そんなアバウトな事でいいのか?

家畜って、凄い英語なのね。

Translate from Japanese to English:

家畜

livestock

名詞
 1. livestock (家畜)
 2. domestic animals (家畜)
 3. cattle (牛, 家畜)

これemacsからググるへの解い合わせ結果。奴らの脳味噌って、直接的な解釈なんだなあ。 リスが冬籠りの為に、ドングリを備蓄するのと一緒な発想。まあ、妥当なネーミングだ わな。こんな単語を獣医さん本で知れるってのが楽しいぞ。

獣医さんは、動物園とか水族館にも居る。ダチョウを診察する時は、頭にすっぽりと 袋をかぶせてしまうと、手もとえ足も出なくなるそうだ。奴らの足蹴りは凶器ですから。 鳥は恐竜の末裔。獣医さんの一部な方は、恐竜医でもあるわけか。


This year's Index

Home