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
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
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
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
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
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
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 và 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
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