Kho tháng 5/2008

Thứ bảy, 31 Tháng năm năm 2008 14:40:27 ICT

Buồn

Báo mấy ngày trước đăng Một nửa nhân loại đang sử dụng ĐTDĐ. Vậy là mình chính thức bị liệt vào nửa tối còn lại của thế giới.

Bốn năm nữa, ta sẽ nằm trong một góc tối còn lại của thế giới. Mười năm nữa biết đâu ta là điểm tối duy nhất còn lại của thế giới :D

Đời tăm tối (chắc tại tối ngày ngó cái xterm đen thùi)


Cập nhật 2 lần. Lần cuối: Tue Aug 08 11:22:15+0011 2017

Tác giả: pclouds | Liên kết tĩnh | Hâm

Thứ bảy, 31 Tháng năm năm 2008 14:23:24 ICT

Rác của tui ở đâu?

Các phiên bản trước đây của GNOME không tuân theo đặc tả trash-spec, chứa rác ở một số nơi. Với GNOME 2.22 (đúng hơn là nautilus), trash-spec được tuân thủ. Nghĩa là bạn sẽ thấy rác trước đây của mình "biến mất".

Rác theo trash-spec giờ được lưu trong $HOME/.local/share/Trash/files. Với các phân vùng khác, rác nằm trong $MOUNTPOINT/.Trash/files hoặc $MOUNTPOINT/.Trash-$UID/files. Lưu ý là kiểu ".Trash-username" không còn hoạt động, phải bắt buộc dùng UID. Thư mục "files" còn có thêm một thư mục họ hàng "info" ngang cấp, chứa thông tin về rác.


Cập nhật 2 lần. Lần cuối: Tue Aug 08 11:22:15+0011 2017

Tác giả: pclouds | Liên kết tĩnh | GNOME, Mánh và mẹo

Chủ nhật, 25 Tháng năm năm 2008 14:39:14 ICT

Scheme và trả về giá trị qua đối số

Cái “tội” Không hỗ trợ trả về giá trị qua đối số có vẻ như chẳng phải là tội, vì không có cách gì một thủ tục có thể đặt lại giá trị được truyền từ bên ngoài cả. Mất cả tuần lễ mò mẫm. Nhảm nhí quá.


Cập nhật 2 lần. Lần cuối: Tue Aug 08 11:22:15+0011 2017

Tác giả: pclouds | Liên kết tĩnh | Liễu

Thứ tư, 21 Tháng năm năm 2008 21:10:59 ICT

Dòng họ nhà Liễu

Để tránh tình trạng lộn xộn, không biết nên đọc Lisp là Líp-xì hay Xì-líp, vả lại chữ Lisp cũng hơi ngoại lai, quyết định chuyển sang tên tiếng Việt: Liễu. Mấy cái ngoặc của Lisp trông cũng thon thả mượt mà, đặt Liễu cũng... giống giống. Phân loại Liễu cũng được thêm để tránh lạm dụng phân loại Emacs.

Common Lisp nay có tên mới là Liễu Chung. Scheme cũng một họ Lisp, nay có tên là Liễu Kim.

Gambit-C là một phiên bản của Scheme, nay được gọi là Liễu Kim Giang. Gauche Scheme là Liễu Gấu.

Công nhận mình có khiếu đặt tên.


Cập nhật 3 lần. Lần cuối: Tue Aug 08 11:22:15+0011 2017

Tác giả: pclouds | Liên kết tĩnh | Liễu

Thứ ba, 20 Tháng năm năm 2008 18:35:19 ICT

DNS phân cấp với dnsmasq

Tình huống là bạn đang sử dụng DNS nội bộ của công ty, đồng thời nối với một mạng nội bộ khác (ví dụ qua VPN). Hai hệ thống mạng này đều cung cấp DNS với những domain nội bộ, làm sao sử dụng cả hai?

Giải pháp thêm tất tần tật vào /etc/resolve.conf sẽ không hoạt động do nó sẽ chỉ chọn một server. Nếu server đó không trả về kết quả, nó không truy vấn những server khác mà báo không tìm ra.

Dnsmasq có thể giải quyết khá đẹp trường hợp này bằng thông số "server" trong dnsmasq.conf. Một DNS server sẽ được chọn là DNS chính, lưu vào /etc/resolve.conf chẳng hạn. DNS server còn lại, giả sử cung cấp các tên miền riêng bắt đầu bằng abc.com, ta có thể thêm dòng sau vào dnsmasq.conf:

server=/abc.com/1.2.3.4

(Dĩ nhiên thay 1.2.3.4 bằng IP của server). Nghĩa là nếu có ai hỏi cái-gì-đấy.abc.com thì cứ nắm đầu thằng 1.2.3.4 mà réo, đừng réo DNS server chính. Đơn giản và hiệu quả.

Đây cũng là cách khá hay để làm firewall ở mức domain. Cứ domain bậy bạ là cho nó vào DNS server dỏm hết. Xong.


Cập nhật 2 lần. Lần cuối: Tue Aug 08 11:22:15+0011 2017

Tác giả: pclouds | Liên kết tĩnh | Mánh và mẹo, Linux

Thứ hai, 19 Tháng năm năm 2008 22:51:08 ICT

Gambit, Swig và Cairo

Tiến tục dấn thân vào bể khổ, quyết định (hết sức sai lầm) là tạo cái Cairo binding cho Gambit để có thể quậy Gambit tiếp. Sau thành công "nhập khẩu" một vài hàm Cairo, thấy cực quá nên quyết định (càng sai lầm hơn) chuyển hướng qua chương trình phát sinh binding, nhằm tạo Cairo binding tự động.

Những ngày đầu điên rồ (giờ nghĩ lại cũng chưa điên lắm), định viết luôn chương trình phân tích cú pháp C/C++ (thu thập đủ bộ lex/yacc cho C và C++) nhưng nghĩ lại, với khối lượng công việc khổng lồ cần làm, có lẽ làm tới Tết mười năm sau mới xong. Bỏ.

May nhớ ra Swig, công cụ chuyên dụng để tạo binding. Nhào vào tạo mần cái hỗ trợ Gambit (sai lầm KINH DỊ). Code swig dơ dã man. Swig về cơ bản tạo binding bằng cách phát sinh một mớ đoạn code C/C++ để sau đó gắn với ngôn ngữ mới, như một phần mở rộng.

Khổ thay thân ta, Gambit với những ưu điểm của FFI của mình, lại không hỗ trợ nói chuyện trực tiếp với C kiểu đó (đúng ra là cũng nói được, nhưng đòi hỏi phải viết đại loại là "Gambit assembly" dưới dạng C macro). Thành ra phải mần tất tần tật trong Scheme.

Mần thế cũng sướng, mỗi tội:

  • Hỗ trợ enum chưa có
  • Mấy cái hằng số phức tạp kiểu CAIRO_VERSION là bó chiếu
  • Không hỗ trợ trả về giá trị qua đối số
  • Không hỗ trợ con trỏ hàm

Hai cái đầu cũng châm chước được, hai cái cuối không có thì kì. Quyết định mới nhất (sai lầm thế kỉ!!) : thêm hai cái sau vào Gambit.

Có lẽ đó là quyết định sai lầm cuối cùng. Biết đâu quyết định cuối cuối cùng sẽ là... viết tay Cairo binding cho Gambit.

Điên quá xá.


Cập nhật 2 lần. Lần cuối: Tue Aug 08 11:22:15+0011 2017

Tác giả: pclouds | Liên kết tĩnh | Emacs, OSS

Thứ bảy, 03 Tháng năm năm 2008 14:58:21 ICT

Gambit-C "cho chó gặm"

Sau mấy ngày moi móc nội tạng Gambit-C, thấy hết sức thoả mãn. Nếu mà phần FFI(Foreign Function Interface) ngon ngon nữa (kèm theo hỗ trợ module) thì có thể chọn làm bản cài đặt Scheme "chuẩn".

Phần VM của Gambit-C rất hấp dẫn. Gambit-C coi C như là assembly (hoặc mã máy) và cài thêm một tí bên dưới, như garbage collector hay lập lịch cho các thread. Tập lệnh của Gambit C khá nhỏ. Vài lệnh để thao tác thanh ghi và stack. Vài lệnh để nhảy, hết (ít ra là hết những gì đã biết). Phần "nhảy" của Gambit-C cũng khá thú vị. Các đoạn code phát sinh nằm trong cùng một hàm to vĩ đại (gọi là "host"), lệnh nhảy chỉ đơn giản là "goto cái-gì-đó". Nếu phải dùng đến những hàm ngoài module đó, ví dụ như thư viện chuẩn R5RS, thì sẽ nhảy "liên-module" bằng cách... thoát khỏi hàm đó. Trước khi thoát, nó đặt biến ___pc để chỉ nơi cần đến, sau đó gambit dispatcher (sẽ nói bên dưới) sẽ gọi đến hàm C đó. Phần đầu hàm C sẽ có lệnh để "goto" đến đúng vị trí cần đến. Như vậy C stack sẽ luôn ở mức 1 hoặc 2 entry là cùng.

Đầu vào của một chương trình viết bằng Gambit là ___main_char() (hoặc một "main" khác, định nghĩa trong lib/os_base.c). Phần từ main() đến ___main_char() được phát sinh tự động bằng macro ___LINKFILE_DESCR (rốt cuộc gọi đến macro ___MAIN_PROC, trong gambit.h). Cái tên cũng đủ nói lên là macro này nằm trong tập tin "link" (được phát sinh bằng lệnh gambit-compiler -link). ___main_char() gọi ___main() (trong lib/main.c), rồi đến ___setup() (trong lib/setup.c). Chính ___setup() sẽ khởi động kernel (gọi đến handler_break, ___LBL(12) trong lib/_kernel.scm).

Mỗi module sẽ xuất ra một hàm, trả về struct ___mod_or_lnk, trong struct này chứa struct ___module_struct, chứa con trỏ đến ___label_struct, khai báo bên trong mỗi module. Struct này chứa chỉ dẫn gọi hàm "host" C nào... Hàm ___call() là hàm thực sự gọi đến các "host" này bằng một vòng lặp vô tận. Dispatcher nêu trên chính là ___call().

Do gì thì gì C cũng không thể giả làm CPU trăm phần trăm (ví dụ không thể phát sinh ngắt) nên vẫn cần một chút can thiệp từ phía "máy" (ảo). Do các lệnh C được thực hiện trực tiếp bởi CPU (Gambit không thông dịch từng lệnh một), nên Gambit-C thêm một số lệnh gọi "poll" vào phần mã phát sinh bằng C. Phần lệnh "poll" này (gọi đến hàm handler_stack_limit(), được cài đặt trong lib/_kernel.scm) có nhiệm vụ kiểm tra stack kiểm tra xem có ngắt nào được phát sinh không.

Phần xử lí thread của Gambit "khá" đơn giản. Có vẻ như thread chạy liên tục và chỉ chuyển thread khi chờ I/O, hoặc gọi các lệnh trực tiếp như (thread-yield!) hoặc (thread-stop). Nếu mà thread được lập lịch ngay trong phần poll luôn thì có lẽ mới đủ để gọi là preemptible thread. Chứ như vầy thì chỉ có thể coi là cooperative. Nhưng mà dù gì vậy cũng ngon rồi. Nói cho cùng Gambit-C vẫn chưa hỗ trợ nhiều CPU thật sự, nên có preemptible thread thì cũng vậy à. Những trường hợp này nên xem xét dùng termite.

Phần máy ảo của Gambit-C không có nhiều thứ lắm (nói chung là đủ hết rồi). Phần khai báo thông tin máy ảo nằm trong struct ___global_state_struct, phần thông tin khởi động trong ___setup_params_struct, tất cả nằm trong gambit.h (đúng hơn là gambit.h.in). GVM(Gambit Virtual Machine) hỗ trợ tối đa 25 thanh ghi, nhưng hiện chỉ định nghĩa 5 (và dùng 3 để truyền tham số). Có lẽ do quá nhiều thanh ghi (giả) sẽ ảnh hưởng đến tốc độ, nên mới hạn chế như thế.

Chưa biết Gambit có hỗ trợ Emacs ngon như Common Lisp/SLIME hay không. Nếu ngon là số dzách. Hông biết có nên thử phát sinh code LLVM cho Gambit không cà (thay vì phát sinh C). Có một số tối ưu được thiết kế riêng cho GCC, nên nếu chuyển qua backend khác thì sẽ mất các ưu điểm này.


Cập nhật 3 lần. Lần cuối: Tue Aug 08 11:22:15+0011 2017

Tác giả: pclouds | Liên kết tĩnh | Emacs

Thứ năm, 01 Tháng năm năm 2008 18:43:46 ICT

Gambit hello world

$ cat a.scm
(pretty-print (command-line))
$ gambit-compiler -c a.scm
$ gambit-compiler -link a.scm
$ gcc a_.c a.c -lgambc
$ ./a.out "Hello world"
("./a.out" "Hello world")
$ ls -l a*
-rw-r--r-- 1 pclouds root 393316 2008-05-01 18:44 a_.c
-rw-r--r-- 1 pclouds root   2244 2008-05-01 18:44 a.c
-rwxr-xr-x 1 pclouds root   9746 2008-05-01 18:45 a.out
-rwxr-xr-x 1 pclouds root     30 2008-05-01 18:42 a.scm

Gambit còn hỗ trợ chạy dạng script. Chi tiết xem tài liệu hướng dẫn sử dụng Gambit.


Cập nhật 2 lần. Lần cuối: Tue Aug 08 11:22:15+0011 2017

Tác giả: pclouds | Liên kết tĩnh | Emacs