Sunday, 12 October 2008

Segmentation fault

Quoted from wikipedia:

A segmentation fault (often shortened to segfault) is a particular error condition that can occur during the operation of computer software. A segmentation fault occurs when a program attempts to access a memory location that it is not allowed to access, or attempts to access a memory location in a way that is not allowed (for example, attempting to write to a read-only location, or to overwrite part of the operating system). Systems based on processors like the Motorola 68000 tend to refer to these events as address or bus errors.

Segmentation is one approach to memory management and protection in the operating system. It has been superseded by paging for most purposes, but much of the terminology of segmentation is still used, "segmentation fault" being an example. Some operating systems still have segmentation at some logical level although paging is used as the main memory management policy.

On Unix-like operating systems, a process that accesses invalid memory receives the SIGSEGV signal. On Microsoft Windows, a process that accesses invalid memory receives the STATUS_ACCESS_VIOLATION exception, and usually a window asking the user to send an error report to Microsoft appears.

------------

Well, worth learning huh?

That's the error I got when running Matt to align 3 pdb structures. Omg, how can I fix such a mass of c library without no knowledge about the language? Hehe, the final way is nothing other than emailing the author. OMG, I' ve just remember that the author was not at the same institute when he wrote this any longer. OMG, then... what to do next???

Tuesday, 12 August 2008

Linux loadable kernel modules (LKM)

15. Giới thiệu các modules

15.1 Trình phiên dịch thi hành (Executable interpreters)

Bạn phải có ít nhất một trình phiên dịch thi hành gắn vào kernel cơ sở, vì để load một LKM phiên dịch thi hành (executable interpreter LKM), bạn cần phải thực thi một lệnh, và do đó, cần có chương trình để phiên dịch lệnh thực thi này.

Trình này gần như hiển nhiên là ELF, vì hầu hết các lệnh thực thi trong hệ thống Linux là ELF.

Trước khi ELF tồn tại trên Linux, dạng lệnh thực thi thông thường là a.out. Có một thời gian ngắn, các hệ thống nửa-ELF/nửa-a.out khá thông dụng. Một số vẫn còn tồn tại.

15.1.1. binfmt_aout: EI cho dạng a.out

a.out là định dạng thực thi phổ biến trong những ngày đầu của Linux và từng là định dạng duy nhất của Linux. Cho đến ngày nau, tên mặc định của các file xuất thực thi của một trình biên dịch GNU (GNU compiler) là a.out (bất kể chúng có định dạng gì).

Nếu bạn thử chạy một file thực thi a.out mà không cần EI, lệnh hệ thống exec sẽ không thực hiện được và báo lỗi "cannot execute binary file".

Không có tham số LKM

Ví dụ:


modprobe binfmt_aout


15.1.2 binfmt_elf: EI cho định dạng ELF

ELF là định dạng thực thi thông thường trên các hệ thống Linux.

Gần như không thể nào không có EI này trong kernel cơ sở của bạn (nếu không còn lý do nào khác thì: insmod là một file thực thi dạng ELF!). Tuy nhiên, về lý thuyết, có thể bỏ nó ra khỏi kernel cơ sở và đưa nó vào như một LKM.

Không có tham số LKM.

VD:

modeprobe binfmt_elf

15.1.3 binfmt_java: EI cho Java bytecode

Java là một ngôn ngữ lập trình hướng đối tượng khá hiện đại. Những chương trình Java truyền thống được biên dịch thành các "Java bytecode", nghĩa là cần phiên dịch bởi một trình phiên dịch Java bytecode. Điếm quan trọng đối với ngôn ngữ hướng đối tượng mới này là các file đối tượng hoàn toàn linh động: chúng có thể được chạy trên mọi hệ thống, miễn là hệ thống đó có một trình phiên dịch bytecode.

Trong khi dự tính ban đầu là trình phiên dịch bytecode sẽ chạy như một chương trình người dùng, với LKM này, bạn có thể làm cho kernel linux phiên dịch file thực thi Java như bất kỳ một file thực thi nào khác. Và vì vậy, bạn có thể chạy một chương trình biên dịch từ Java cũng như chương trình biên dịch từ C, tức là gõ tên chương trình tại dấu đợi lệnh của giao diện dòng lệnh.

Thực tế, lợi ích của ngôn ngữ bytecode trung gian vẫn chưa được chứng minh. Và thường, Java được biên dịch hẳn thành một file thực thi truyền thống như ELF. Nếu làm như vậy, bạn sẽ không cần tới binfmt_java.

Không có tham số LKM.

VD:
modeprobe binfmt_java

15.2. Block device drivers

15.2.1. floppy: floppy disk driver

Đây là driver thiết bị cho ổ đĩa mềm. Bạn sẽ cần đến driver này để có thể truy xauất một đĩa mềm. Tài liệu về LKM này được ghi trong README.fd đặt trong linux/drivers/block directory.

Lưu ý rằng nếu bạn boot từ đĩa mềm hay có hệ thống file root trên một đĩa mềm, bạn phải đưa driver này vào kernel cơ sở.

[ ... ]

15.2.2 loop: loop device driver

Module này cho phép bạn tổ chức một filesystem được lưu trữ dưới dạng file thông thường (trong một filesystem khác). File này được gọi là backing file.

Một ứng dụng của việc này là kiểm tra một filesystem ISO 9660 trước khi ghi chính thức lên một CD. Bạn xây dựng một filesystem trong một file thông thường 650MB. File này sẽ được đưa vào một chương trình ghi đĩa CD. Nhưng bạn có thể định nghĩa một loopback device dựatre6n file này như một backing file và sau đó tổ chức filesytem từ backing file.

Bạn cũng có thể dùng loop device để chuyển các tập hợp file qua một hệ thống mạng. Nó giống như một file .tar, chí khác là bạn không cần phải gói và mở gói. Bạn chỉ cần tổ chức lại file nguyên thủy.

Một số người dùng các loop device trên một hệ thống khi thì chạy WIndows, khi thì chạy Linux, để có thể duy trì hệ thống Linux thông qua hệ thống Windows: đặt một root filesystem vào một file trong hệ FAT để windows có thể truy xuất, sau đó tổ chức hệ thống Linux thông qua một loop device khi Linux đang chạy.

Bạn có thể giữ filesystem mã hóa hoặc nén, hoặc bất cứ cách biến đổi nào, trong một backing file. Loop device mã hóa khi bạn ghi vào, và giãi mã khi bạn truy xuất. Một chiến lược khác khá phổ biến để mã hóa và nén một filesystem là sử dụng một định dạng filesystem đã nén hoặc mã hóa, chẳng hạn như Cfs, Tcfs, Stegfs.

Một hệ thống mã hóa được dựa trên một hàm chuyển (transfer function). Có hai hàm chuyển sẵn có trong một loop module: identify (dùng cho trường hợp mã hóa thông thường: những gì bạn thấy trong loop device chính xác là những gì có trong backing file) và hàm mã hóa XOR đơn giản. Một module độc lập khác có thể bổ sung vào bất kỳ chức năng chuyển nào bằng cách gọi hàm loop_register_transfer() trong loop module.

Tuesday, 5 August 2008

Linux loadable kernel modules (LKM)

4. Công cụ LKM

Chương trình cần để load, unload và thực hiện các tác vụ khác với LKM nằm trong gói modutils. Bạn có thể tìm thấy gói này trong thư mục modutils tại đây

Gói này chứa những chương trình sau giúp bạn sử dụng LKM:

insmod gắn một LKM vào kernel
rmmod gỡ một LKM khỏi kernel
depmod xác định sự phụ thuộc lẫn nhau giữa các LKM
kerneld chương trình kernel daemon
ksyms thể hiện các symbol được kernel xuất ra để các LKM mới sử dụng
lsmod liệt kê các LKM đang được load
modinfo thể hiện nội dung của phần .modinfo trong file object LKM
modprobe gắn hoặc gỡ một LKM hay một bộ các LKM một cách thông minh. Ví dụ, nếu bạn phải load A trước khi load B, modprobe sẽ tự động load A rồi mới load B.

Thay đổi trên kernel thường yêu cầu kèm theo thay đổi trên modutils, vì vậy hãy chắc chắn bạn đang sử dụng phiên bản mới nhất của modutils khi bạn nâng cấp kernel. modutils luôn luôn tương thích ngược (hoạt động với các kernel cũ hơn).

Cảnh báo: modprobe sẽ khởi động insmod với vị trí cố định trong code là /sbin/insmod. Có thể có những PATH không được modutils sử dụng để tìm kiếm chương trình. Vì vậy hãy chỉnh sửa code của modutils trước khi bạn xây dựng, hoặc bảo đảm bạn sẽ cài đặt chương trình vào các thư mục truyền thống.

Linux loadable kernel modules (LKM)

vietnamized and note-taking version of Linux Loadable Kernel Module HOWTO

3.Tạo LKM


Một LKM nằm trong một file đối tượng ELF (thường được đặt tên theo dạng serial.o) Thông thường bạn lưu tất cả file object LKM trong một thư mục nhất định (gần file image của kernel cơ sở). Khi dùng chương trình insmod để chèn một LKM vào kernel, bạn cần đưa vào tên của file đối tượng đó.

Đối với các LKM là một phần của linux, bạn xây dựng chúng cùng lúc với việc tạo image của kernel cơ sở. Đọc file README trong cây thư mục chứa source Linux. Ngắn gọn, sau khi tạo image cho kernel cơ sở với một lệnh (chẳng hạn như make zImage, bạn sẽ tạo tiếp tất cả các LKM với lệnh

make modules

Lệnh này sẽ cho ra một loạt các file đối tượng LKM *.o trong cây thư mục chứa source Linux. (Trong những phiên bản cũ của Linux, sẽ có link trong thư mục modules trỏ đến tất cả các file này. Những LKM này đã sẵn sàng để được load, nhưng có thể bạn sẽ muốn cài đặt chúng trong những thư mục thích hợp hơn.

Một trong những công việc cần làm để cấu hình kernel (lúc xây dựng) là chọn những phần nào của kernel để đưa vào kernel cơ sở và những phần nào để tạo LKM độc lập. Trong quá trình cấu hình cơ bản theo dạng hỏi-trả lời ( make config ), với mỗi phần tuỳ chọn của kernel, bạn sẽ được chọn Y - để tích hợp vào kernel cơ sở, hay M - để tạo module độc lập, hay N - bỏ qua hoàn toàn. Những cách cấu hình khác cũng tương tự.

Như đã giải thích trong phần 2.3, bạn chỉ nên đưa vào kernel cơ sở những phần tối thiểu, và bỏ qua những phần chắn chắn là bạn không cần tới. Không mất mát gì nhiều nếu bạn tạo một LKM mà bạn không dùng tới. Chỉ là một ít thời gian biên tập (compile), một ít không gian lưu trữ, và khả năng lỗi trong module đó làm cản trở quá trình xây dựng kernel.

Cũng trong bước cấu hình, bạn phải chọn có sử dụng symbol versioning hay không. Lựa chọn này ảnh hường đến cả việc xây dựng kernle cơ sở lẫn LKM, và bạn nhất thiết phải chọn đúng. (Xem phần 6).

Wednesday, 23 July 2008

Linux loadable kernel modules (LKM)

vietnamized ^_^ and note-taking version of Linux Loadable Kernel Module HOWTO

1. Lời nói đầu

2. Giới thiệu Linux loadable kernel modules

Khi muốn bổ sung code vào một linux kernel, phương thức cơ bản nhất là đưa các file source vào source tree của kernel và biên tập lại (recompile) kernel. Và thực chất, quá trình cấu hình kernel chủ yếu là việc lựa chọn những file source để biên tập.

Có một cách khác để bổ sung code vào linux kernel trong quá trình vận hành. Một bộ code được bổ sung theo cách này được gọi là loadable kernel module. Các module này có thể có nhiều chức năng, thông thường rơi vào 1 trong 3 dạng: (1) driver thiết bị, (2) driver filesystem, (3) lệnh hệ thống (system calls). Một số chức năng nhất định (bao gồm các chức năng trên) được kernel tách biệt nhằm tránh sự đan cài phức tạp của chúng đối với những phần khác trong kernel.

2.1 Thuật ngữ

Loadable kernel module thường được gọi tắt là kernel module, hay module. Tuy nhiên, những cách gọi này rất dễ gây nhầm lẫn vì có rất rất nhiều dạng gói phần mềm cũng được gọi là module.

Một nhầm lẫn phổ biến về LKM là cho rằng đó là một phần riêng biệt nằm bên ngoài kernel và giao tiếp với kernel khi cần thiết. Tuy nhiên, LKM, khi được load lên, thực sự là một phần của kernel. Cách gọi chính xác cho phần kernel gắn kết với image khi boot (tức là toàn bộ kernel, trừ các LKM) là kernel cơ sở (base kernel), và LKM giao tiếp với kernel cơ sở.

Trong một số HĐH khác, khái niệm tương đương với LKM của linux là phần mở rộng kernel.

Vậy thì 'linux' là gì? Linux là tên gọi cho 2 khu vực rất khác nhau:
1. kernel và các yếu tố liên quan được phân phối dưới dạng một gói phần mềm, bởi Linux Torvald.
2. hệ thống các hệ điều hành dựa trên linux kernel

Trong phạm vi đang được nói đến, linux cần được hiểu theo nghĩa thứ 1. Mặc dù LKM luôn là một phần của kernel, LKM không nhất thiết là linux. Chẳng hạn, nếu kernel của bạn được bổ sung bằng một LKM driver đi kèm thiết bị, đó là một kernel linux được điều chỉnh chút đỉnh.

2.2. Lịch sử của LKM

LKM chỉ xuất hiện từ Linux 1.2 (1995). Những LKM ngày nay ban đầu cũng là một phần của kernel cơ sở.

Các driver thiết bị (hay đại loại vậy) luôn là các phần rời rạc. Khi khái niệm LKM được phát minh, người ta chỉ cần điều chỉnh chút ít để biến các thành phần rời rạc này thành những LKM thực sự. Tuy nhiên, công việc này cũng mất khá nhiều thời gian vì cần phải thực hiện trên từng thành phần một. Từ khoảng năm 2000 trở đi, hầu như mọi thứ có thể chuyển thành LKM đều có thêm lựa chọn LKM cho người dùng.

2.3. Khi nào cần LKM?

Người dùng thường có nhiều lựa chọn giữa việc gắn kết một thành phần rời vào kernel cơ sở hoặc dưới dạng LKM. LKM có rất nhiều ưu điểm so với việc gắn chết một thành phần vào kernel cơ sở, và thường luôn được lựa chọn bất cứ khi nào có thể.

Với LKM, bạn không cần xây dựng lại kernel quá thường xuyên, tiết kiệm thời gian và hạn chế khá nhiều sai sót trong giai đoạn tái xây dựng và cài đặt lại kernel cơ sở. Một khi đã có một kernel cơ sở tốt, bạn nên để nó yên càng lâu càng tốt.

Một lợi điểm khác của LKM là chúng giúp bạn chẩn đoán các trục trặc của hệ thống. Khi có lỗi (chẳng hạn do một driver thiết bị) trong kernel cơ sở, toàn bộ hệ thống sẽ ngưng hoạt động, không thể boot được, và bạn cũng không thể biết thành phần nào trong kernel cơ sở gây ra vấn đề. Tuy nhiên, nếu driver đó nằm trong một LKM, kernel cơ sở vẫn có thể chạy và chỉ gặp vấn đề khi load lên LKM bị lỗi.

LKM cũng giúp tiết kiệm tài nguyên nhớ, vì chúng chỉ được gọi khi thực sự cần thiết. Tất cả các thành phần của kernel cơ sở phải sẵn sàng trong mọi lúc, và phải nằm trong vùng nhớ thực, không phải vùng nhớ ảo.

LKM giúp cho việc bảo trì và sửa sai được nhanh chóng. Để có hiệu lực, các thay đổi trên một filesystem driver nằm trong kernel cơ sở yêu cầu toàn bộ hệ thống phải khởi động lại. Với LKM của filesystem driver đó, chỉ cần vài dòng lệnh để thay đổi, và không cần khởi động lại toàn hệ thống để xem hiệu quả những thay đổi đó.

LKM không chậm hơn các module trong kernel cơ sở. Việc gọi lên một LKM chỉ đơn giản là trỏ đến vị trí của LKM đó trên bộ nhớ.

Dĩ nhiên bạn buộc phải đưa một số module vào kernel cơ sở. Đó là những thành phần giúp cho hệ thống hoạt động được cho đến lúc có thể gọi ra LKM, ví dụ như driver của ổ đĩa chứa roort filesystem.

2.4. LKM không thể làm gì?

Có một xu hướng cho rằng LKM cũng giống như các chương trình người dùng. Thật sự chúng có nhiều điểm chung, nhưng LKM hoàn toàn không phải là chương trình người dùng, mà là một phần của kernel, có thể hoạt động khá tự do trong hệ thống, và do đó, cũng rất dễ làm sụp đổ hệ thống.

2.5. LKM được sử dụng trong trường hợp nào?

Có 6 lĩnh vực chính sử dụng LKM:
* Driver thiết bị. MỘt driver thiết bị được thiết kế cho một thành phần phần cứng cụ thể. Kernel sử dụng chúng đề giao tiếp với thành phần phần cứng đó mà không cần biết rõ cách thức phần cứng hoạt động. Ví dụ: driver cho ổ đĩa ATA, driver cho card mạng Ethernet tương thích với NE2000... Để sử dụng một thiết bị bất kì, kernel phải chứa driver của thiết bị đó.

* Filesystem driver. Một filesystem driver phiên dịch nội dung của filesystem (điển hình là nội dung của một ổ đĩa) thành file, thư mục hay các đơn vị quản lý đại loại như vậy. Có rất nhiều cách lưu trữ file và thư mục trên ổ đĩa, trên server, ... Với mỗi cách lưu trữ, cần có một filesystem driver.

* Lệnh hệ thống. Các chương trình trong khu vực người dùng sử dụng các lệnh hệ thống để gọi lên các dịch vụ cần thiết từ kernel. Hầu hết các lệnh hệ thống được tích hợp trong hệ thống và khá chuẩn mực, nên luôn được gắn vào kernel cơ sở. Nhưng nếu bạn tự tạo ra những lệnh hệ thống mới, hoặc muốn thay đổi một số cách thức hoạt động của linux và muốn đè lên các lệnh hệ thống sẵn có, bạn có thể cài đặt chúng vào kernel dưới dạng LKM.

* TTY line disciplines. Về cơ bản, đây là các hình thức nâng cao chất lượng (???) của driver cho các thiết bị đầu cuối (terminal device)

* Các trình phiên dịch có thể thi hành. Một trình phiên dịch có thể thi hành gọi lên và thi hành lệnh. Linux được thiết kế để có thể thi hành các lệnh dưới nhiều dạng khác nhau, và mỗi dạng cần có trình phiên dịch tương ứng.