Oasis – ระบบ Linux ขนาดเล็กที่ลิงก์แบบสแตติก
(github.com/oasislinux)- Oasis เป็น ระบบ Linux ขนาดเล็ก ที่มีลักษณะใกล้เคียง BSD มากกว่า โดยลิงก์ระบบพื้นฐานทั้งหมดแบบสแตติก และให้ความสำคัญกับโครงสร้างที่เรียบง่ายกับ build ที่ทำซ้ำได้
- ซอฟต์แวร์ทั้งหมดในระบบพื้นฐานจะถูก ลิงก์แบบสแตติก แม้แต่ display server อย่าง velox และเว็บเบราว์เซอร์ NetSurf ก็ถูกทำเป็นไบนารีแบบรวมทุกอย่างในตัว เพื่อลดปัญหาจากการอัปเกรดไลบรารี
- แพ็กเกจ build ด้วย samurai และสคริปต์ Lua แม้ต้นทุนการทำแพ็กเกจช่วงแรกจะสูง แต่มีเป้าหมายที่ build ซ้ำได้อย่างรวดเร็ว, ต้นทุนบำรุงรักษาต่ำ และ incremental build ข้ามขอบเขตแพ็กเกจ
- แทนที่จะใช้ package manager จะกำหนดไฟล์ที่จะรวมไว้ด้วย specifications และระบบ build จะบันทึก filesystem tree ผลลัพธ์ลงใน git repository เพื่อนำไปรวมกับ
/หรือดึงไปใช้บนเครื่องอื่นได้ - ผู้ติดตั้งต้องสามารถ build kernel เองและแก้ไขระบบเมื่อเกิดปัญหาได้ ส่วนซอฟต์แวร์ที่ยังขาดสามารถเสริมด้วย pkgsrc หรือ Nix
เป้าหมายและลักษณะของ Oasis
- Oasis เป็นระบบ Linux ขนาดเล็ก และแตกต่างจากระบบปฏิบัติการบน Linux ที่คุ้นเคยอยู่มาก โดยมีความใกล้เคียงกับ BSD มากกว่า
- แนวทางหลักมุ่งไปที่โครงสร้างขนาดเล็กและเรียบง่าย, การลิงก์แบบสแตติก, build ที่ทำซ้ำได้ และ dependency สำหรับ bootstrap ที่น้อยที่สุด
- แม้ตั้งใจให้ระบบปฏิบัติการทั้งชุดเป็นระบบที่สมบูรณ์ แต่แทนที่จะสร้างและดูแล repository แพ็กเกจหลายพันรายการขึ้นมาใหม่ จะรักษา ระบบพื้นฐานให้มีขนาดเล็กและโฟกัสชัดเจน
ระบบที่อิงการลิงก์แบบสแตติก
- ซอฟต์แวร์ทั้งหมดในระบบพื้นฐานจะถูก ลิงก์แบบสแตติก
- การลิงก์แบบสแตติกเป็นกลไกที่เรียบง่ายกว่าการลิงก์แบบไดนามิก และช่วยขจัดปัญหาการอัปเกรดไลบรารี
- ไบนารีที่ได้จะรวมทุกอย่างไว้ในตัวอย่างสมบูรณ์ จึงคัดลอกไปยังระบบอื่นได้ง่าย
วิธี build และ bootstrap
- ทุกแพ็กเกจ build ด้วย samurai และ build manifest สร้างจาก สคริปต์ Lua
- วิธีนี้ต้องใช้ต้นทุนการทำแพ็กเกจเริ่มต้นค่อนข้างมาก แต่ช่วยให้ต้นทุนการบำรุงรักษาต่ำ
- ข้อดีที่ระบบ build มอบให้มีดังนี้
- เวลา build ที่เกือบใกล้เคียงจุดเหมาะสมที่สุด
- build ที่คาดการณ์ได้และทำซ้ำได้
- dependency ณ เวลา build ที่ลดลง
- incremental build ข้ามขอบเขตแพ็กเกจ
- การ bootstrap ต้องใช้ระบบ POSIX, git, lua, curl, ยูทิลิตี sha256, ยูทิลิตีบีบอัดมาตรฐาน และ cross compiler
x86_64-linux-musl - ด้วยเงื่อนไขนี้ จึงทำให้ cross compile ได้ง่ายแม้บนระบบที่ไม่ใช่ Linux เช่น macOS หรือ OpenBSD
TLS, การจัดองค์ประกอบแพ็กเกจ และการตั้งค่าระบบ
- Oasis ใช้ BearSSL เป็น TLS และไลบรารีเข้ารหัสของระบบ
- BearSSL มีขนาดเล็กมากและเขียนมาอย่างดี แต่ยังไม่ได้ถูกใช้อย่างแพร่หลาย
- ใช้ libcurl ที่รองรับ BearSSL แบบ native และ libtls-bearssl ซึ่งเป็น implementation ทดแทน libtls ที่อิง BearSSL
- มีเพียง แพ็กเกจเสริม บางส่วนที่ต้องใช้ LibreSSL
- Oasis ไม่มี package manager
- แต่จะกำหนดด้วย specification ว่าจะรวมไฟล์ใดจากแพ็กเกจใดไว้ในระบบ
- ระบบ build จะบันทึก filesystem tree ผลลัพธ์ลงใน git repository
- tree นี้สามารถนำไปรวมกับ
/หรือดึงไปใช้บนเครื่องอื่นได้
/etcควรเรียบง่ายพอให้ผู้ดูแลระบบเข้าใจทั้งหมดและปรับแต่งได้อย่างเหมาะสม- ไฟล์ที่ซับซ้อนที่สุดในการตั้งค่าเริ่มต้นคือสคริปต์ init ของระบบ
/etc/rc.initซึ่งมี 16 บรรทัด
- ไฟล์ที่ซับซ้อนที่สุดในการตั้งค่าเริ่มต้นคือสคริปต์ init ของระบบ
ระบบแพ็กเกจอื่นและแนวทางเน้น ISO C
- Oasis ผสานกับระบบแพ็กเกจที่เป็นอิสระจาก OS ได้ดี
- สามารถขยายซอฟต์แวร์ที่ต้องการด้วย pkgsrc หรือ Nix ได้ โดยระบบพื้นฐานยังคงมีขนาดเล็กและโฟกัสชัดเจน
- หนึ่งในเป้าหมายหลักของ Oasis คือการ build ด้วย cproc
- cproc เข้มงวดกับมาตรฐาน ISO C มากกว่า gcc หรือ clang อย่างมาก
- cproc มีขนาดเล็กกว่า gcc หรือ clang มาก
- งานนี้ยัง อยู่ระหว่างดำเนินการ แต่แพ็กเกจ core ทั้งหมดและแพ็กเกจอื่นส่วนใหญ่สามารถ build ด้วย cproc ได้สำเร็จแล้ว
หลักการออกแบบ
- ความซับซ้อนของซอฟต์แวร์ควรวัดโดยรวม transitive dependency ทั้งหมด
- ไฟล์ executable ควรถูก ลิงก์แบบสแตติก
- องค์ประกอบซอฟต์แวร์ควรปรับแต่งหรือแก้ไขได้ง่าย
- ซอร์สของแพ็กเกจควรถูกอ้างอิงด้วย URL หรือ git submodule ไม่ควรถูกรวมเข้ามาโดยตรง
/etcควรเรียบง่ายพอให้เข้าใจได้ทั้งหมด- patch ควรถูกจัดระเบียบอย่างดี มีคำอธิบายที่ดี และ apply ได้อย่างสะอาดเสมอ
ประสบการณ์การติดตั้งและใช้งาน
- คู่มือติดตั้งอยู่ใน wiki
- Oasis ยังเป็นโปรเจกต์ที่ทะเยอทะยานและมีงานต้องทำอีกมาก ดังนั้นผู้ใช้ต้องสามารถ build kernel เองและแก้ไขระบบเมื่อเกิดปัญหาได้
- มี QEMU image ให้ลองใช้โดยไม่ต้องติดตั้งเอง
- archive มี root filesystem, Linux kernel และสคริปต์สำหรับรัน QEMU
./runรันในโหมดกราฟิก./run -sรันในโหมด serial
ซอฟต์แวร์พื้นฐานที่เลือกใช้
- Oasis ใช้ implementation ของไลบรารีและเครื่องมือที่เล็กกว่าและเรียบง่ายกว่าเมื่อเป็นไปได้
- ใช้ musl ไม่ใช่ glibc
- ใช้ sbase แทน coreutils
- ใช้ ubase แทน util-linux
- ใช้ pigz แทน gzip
- ใช้ mandoc แทน man-db
- ใช้ bearssl แทน openssl
- ใช้ oksh แทน bash
- ใช้ sdhcp แทน dhclient หรือ dhcpcd
- ใช้ vis แทน vim หรือ emacs
- ใช้ byacc แทน bison
- ใช้ perp และ sinit แทน sysvinit หรือ systemd
- ใช้ netsurf แทน chromium หรือ firefox
- ใช้ samurai แทน ninja
- ใช้ velox แทน Xorg
- ใช้ netbsd-curses แทน ncurses
- แพ็กเกจถูกจัดกลุ่มเป็น set เชิงตรรกะ และรายการทั้งหมดอยู่ในไดเรกทอรี pkg
- แม้จะไม่มีซอฟต์แวร์ที่ต้องการ ก็มีความเป็นไปได้ว่าจะติดตั้งได้ผ่าน pkgsrc หรือ Nix
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ตัวระบบเองอธิบายละเอียดได้ยาก แต่โดยรวมใช้งานได้ดี และ คอมมูนิตี้ ที่เจอใน IRC ก็เป็นมิตรมาก
ผมพยายามบิลด์ oasis ด้วย Bazel เพื่อทำอิมเมจ OS แบบ immutable ที่เอาไปรันเป็นโหนด Kubernetes ได้ และสำเร็จด้วยความช่วยเหลือนิดหน่อย
อยากลองจับมาใช้สำหรับรัน Atomic T ดู
ฟังดูเป็นโปรเจกต์ที่เจ๋งมาก
ถ้าลิงก์ทุกอย่างแบบ static ก็น่าจะทำให้อิมเมจพื้นฐานและหน่วยความจำตอนรันใหญ่ขึ้น เพราะมีสำเนาของ libc และไลบรารีร่วม อยู่เยอะไม่ใช่หรือ
ความเรียบง่ายของ static linking นั้นดี แต่ดูเหมือนจะขัดกับแนวคิดที่พยายามหลีกเลี่ยง “ความเทอะทะ” อยู่บ้าง
ผมมองว่านี่ไม่ใช่ความเทอะทะ แต่เป็น การแยกความรับผิดชอบ ที่ดีขึ้นมากกว่า ระบบที่ต้องคอยติดตาม dependency ของไลบรารีทั้งหมดทั้งจากมุมแพ็กเกจจิงและตอนรันต่างหากที่รู้สึกว่าเทอะทะกว่า แล้วแต่จุดตั้งต้นด้วย แต่สำหรับผม static linking สะอาดกว่า และหน่วยความจำที่เพิ่มขึ้นก็ไม่ได้เป็นเรื่องน่ากังวลนัก
เป้าหมายไม่ได้ใช่การประหยัดพื้นที่จัดเก็บด้วย static binary และจริง ๆ คาดว่าจะเสียพื้นที่มากขึ้นด้วยซ้ำ แต่ในบางกรณีพื้นที่จัดเก็บกลับลดลง เพราะสามารถลบ ไลบรารีใน /usr/lib ออกได้ ไม่แน่ใจเหตุผลที่แน่ชัด แต่อาจเป็นเพราะไม่ต้องเก็บไลบรารีขนาดใหญ่ที่มีฟังก์ชันจำนวนมากซึ่งโปรแกรมไม่ได้ใช้
สำหรับผม static binary เหมาะมาก ถ้าใช้ มัลติคอลไบนารี อย่าง busybox ในบางกรณีก็สามารถตัดไลบรารี “ร่วม” ออกได้ด้วย ไม่ได้เหมาะกับทุกคนหรอก แต่น่าจะขึ้นกับชุดโปรแกรมที่เจ้าของคอมพิวเตอร์ชอบใช้ หรือก็คือ dependency ที่โปรแกรมเหล่านั้นต้องการ เป็นหลัก
คงไม่อยากให้เครื่องมือ 100 ตัวลิงก์ Chromium ทั้งตัวแบบ static แต่ในระดับขนาดของไลบรารี C ทั่วไป มันไม่ได้ทำให้เทอะทะขึ้น เหตุผลที่ดิสโทร Linux ชอบไลบรารี dynamic คือสามารถแจกแพตช์อัปเดตจากจุดเดียวได้ โดยไม่ต้องบิลด์โปรแกรมที่พึ่งพามันทั้งหมดใหม่
ปัญหาหลักจริง ๆ ของระบบ Linux ที่ลิงก์แบบ static คือ การรองรับ GPU แอปที่ใช้ GPU จริง ๆ ต้องถูกลิงก์ใหม่ทั้งหมดให้รวมไดรเวอร์ GPU ที่จำเป็นเข้าไปด้วย
ส่วนเสียง ถ้าเป็น ALSA ก็โอเค เพราะมีการมิกซ์แบบอิง IPC/หน่วยความจำร่วมสำหรับอุปกรณ์เล่น/บันทึกเสียง (dmix/dsnoop) static linking จึงสมเหตุสมผล อินเทอร์เฟซ IPC ของ pulseaudio[012] นั้นเทอะทะ เป็นวิธีแก้เฉพาะหน้าจน ๆ และไม่เสถียรเมื่อเวลาผ่านไป จนเทียบกับความเสถียรแข็งแกร่งของ ALSA ที่ทำงานได้ดีพอพร้อมให้การเข้าถึงฮาร์ดแวร์ความหน่วงต่ำจากภายในโปรเซสจริง ๆ แล้วไม่น่าเชื่อถือ
X11 และ Wayland อิง IPC อยู่แล้ว จึงไม่มีปัญหาในจุดนี้
แต่สำหรับ GPU ดูเหมือนจะต้องมีชุดอินเทอร์เฟซ IPC/หน่วยความจำร่วมที่ได้แรงบันดาลใจจาก Wayland Vulkan 3D ต้องมี Wayland compositor ที่รองรับ 3D และอินเทอร์เฟซสำหรับงานคำนวณน่าจะเป็น dma-buffers แบบแชร์ที่แยกจาก Wayland compositor
ข้อดีของแนวทางนี้คือสามารถปลดปล่อยอินเทอร์เฟซระบบออกจาก ELF ที่ซับซ้อนอย่างสุดขั้วได้ เราสามารถเลือกฟอร์แมตไฟล์ปฏิบัติการที่เรียบง่ายมาก ๆ หรือก็คือฟอร์แมตไฟล์ปฏิบัติการสมัยใหม่ได้ แต่ยังต้องมีการรองรับจาก compiler และ linker เพื่อช่วยเรื่องการรองรับ legacy
ยังมีทางสายกลางด้วย คือทุกอย่างลิงก์แบบ static แต่ยกเว้นเฉพาะแอปที่ต้องใช้ไดรเวอร์ GPU และไดรเวอร์นั้นยังคงถูกจัดให้ในรูปแบบ shared library สำหรับจุดประสงค์นั้น ELF ถือว่าเกินความจำเป็นอย่างไร้เหตุผล
ประเด็นเรื่องไดรเวอร์ GPU เป็นจุดที่ดี ตอนนี้ก็น่าจะยังลิงก์แบบ static ไม่ได้ และในทางปฏิบัติคงเป็นการลิงก์แบบ static เฉพาะชั้นกลางบาง ๆ ที่ไปหาไดรเวอร์จริงตอน runtime มากกว่า
น่าสนใจ แต่สงสัยว่า กรณีใช้งาน คืออะไร
เช่น ข้อดีของการใช้คอมไพเลอร์ C อย่าง croc แทน TCC คืออะไร?
ไม่เคยรู้จัก Netsurf(https://www.netsurf-browser.org/); มาก่อน น่าทึ่งจริง ๆ แต่ดูเหมือนจะใช้ Duktape เป็นเอนจิน JS ดังนั้นประสิทธิภาพอาจเป็นปัญหาได้
อีกอย่าง cproc ใช้ QBE และ QBE กำลังค่อย ๆ เพิ่มแบ็กเอนด์อย่าง RISC-V อยู่ แต่เท่าที่รู้ tcc น่าจะไม่รองรับ
ลิงก์ที่ใช้งานได้: https://www.netsurf-browser.org
ลิงก์ในหน้านั้นเสียทั้งหมด
https://www.netsurf-browser.org/about/screenshots/
จากภาพหน้าจอ ดูเหมือนจะเรนเดอร์ BBC, เว็บไซต์ของตัวเอง และ Wikipedia ได้ เว็บไซต์อื่นก็อาจทำได้ แต่ดูจากภาพหน้าจออย่างเดียวบอกไม่ได้ สิ่งที่บอกได้คือสามเว็บไซต์นั้นทำงานได้ในหน้าต่างที่มีการตกแต่งหลากหลายแบบ
สงสัยว่ามีใครรู้ไหมว่า ขนาดติดตั้งพื้นฐาน อยู่ที่เท่าไร หาไม่เจอคำตอบจากที่ไหนเลย และลิงก์อิมเมจ QEMU ก็ดูเหมือนจะเสียอยู่ตอนนี้
อยากรู้ว่าเมื่อเทียบกับ Alpine ที่มีชุดแพ็กเกจคล้ายกันแล้วจะเป็นอย่างไร
เคยมีคอมเมนต์ที่ถูกลบไปแล้วบ่นว่าเข้าถึง GitHub ไม่ได้ถ้าปิด JavaScript ไว้ รีโพซิทอรี Oasis มีมิเรอร์อยู่บน sourcehut ด้วย ถ้าทางนั้นดีกว่า ก็อยู่ที่นี่
https://git.sr.ht/~mcf/oasis
michaelforney ยังเป็นคนทำ พอร์ต Wayland ของ st ด้วย: https://github.com/michaelforney/st
ต้นแบบก่อนหน้าของ oasis น่าจะเป็น https://dl.suckless.org/htmlout/sta.li
[1]: https://github.com/michaelforney/cproc
เจ๋งมาก ชอบแนวทางที่ไม่มีความเทอะทะ โดยเฉพาะตัวจัดการหน้าต่าง velox ระบบบิลด์ Samurai ก็ดูน่าสนใจทีเดียว
ยังไม่เข้าใจแน่ชัดว่า Samurai ทำงานอย่างไร และพูดตรง ๆ ก็ยังไม่รู้ว่าต่างจาก ninja อย่างไร แต่โปรเจกต์นี้เป็นสิ่งกระตุ้นทางปัญญาแบบที่ดูมีอะไรให้เรียนรู้เยอะมาก
ขอปรบมือดัง ๆ ให้ Michael Forney
เป็นตัวเลือกที่น่าสนใจ ในที่สุดก็มีอะไรที่ไม่ใช่แค่ดิสโทร Linux อีกตัวหนึ่งออกมา
อยากรู้การเปรียบเทียบระหว่างการใช้ musl กับ glibc แบบดั้งเดิม
ระหว่างสองตัวนี้มีความต่างด้านประสิทธิภาพไหม?
ช่วงนี้เห็น musl ถูกใช้มากขึ้นเรื่อย ๆ ทั้งในอีโคซิสเต็ม Rust และ Zig
โดยเฉพาะเมื่ออยากให้ไบนารี Linux ตัวเดียวทำงานได้ทั้งบนสาย RH และสาย Debian/Ubuntu หรือบนดิสโทรที่อายุคนละรุ่นกัน
และมีพฤติกรรมแปลก ๆ ที่ต้องเลี่ยงอยู่ค่อนข้างมาก
การลิงก์แบบสแตติกทำให้การลิงก์เจ็บปวดขึ้น โดยเฉพาะเกี่ยวกับ global constructor ซึ่งมักจำเป็นด้วยเหตุผลด้านความถูกต้องหรือประสิทธิภาพ นี่ไม่ใช่ปัญหาเฉพาะของ musl แต่มีคนจำนวนมากที่สนใจทั้งสองเรื่อง
ถ้าบิลด์บนระบบเก่าที่สุดที่ต้องการรองรับ การลิงก์แบบไดนามิกก็ทำงานได้ดีเช่นกัน ดีเพนเดนซีที่ไม่ใช่ libc และติดตั้งยุ่งยากสามารถจัดการด้วย relative rpath ได้ แต่ libstdc++ ควรคิดทบทวนอีกที
ข้อดีใหญ่ของ MUSL คือเมื่อเขียน OS ใหม่ การพอร์ตจะง่ายกว่ามาก
โปรเจกต์นี้ดูเหมือนยอมประนีประนอมคุณภาพโดยรวมเพื่อให้ขนาดเล็กลง
แม้แต่ BearSSL เองก็ระบุบนเว็บไซต์ว่าเป็นคุณภาพระดับเบตา: “Current version is 0.6. It is now considered beta-quality software” (https://bearssl.org/)
ถ้าเรียกฟังก์ชัน libc ไปทั่วแบบไม่ค่อยคิด และโค้ดเบสโดยรวมไม่ได้ถูกปรับแต่ง glibc อาจดีกว่า แต่โค้ดเบสขนาดเล็กของ musl มีข้อได้เปรียบเรื่องการเริ่มทำงานที่เร็วกว่าและการจูนละเอียด แม้ไม่ใช้การปรับแต่งขณะลิงก์ก็ตาม ถ้าใช้ก็ยังมีโอกาสได้ประโยชน์เพิ่มขึ้น
[0]: https://neosmart.net/blog/a-high-performance-cross-platform-...
แก้ไข: ลิงก์ที่ถูกต้องคืออันนี้: https://neosmart.net/blog/using-simd-acceleration-in-rust-to...
musl เป็น MIT จึงมีข้อจำกัดน้อยกว่า