Trình biên dịch

Làm phần mềm ít ai không biết đến cái gọi là trình biên dịch, tuy nhiên cũng đặc thù từng công việc mà mức độ hiểu biết về trình biên dịch có khác nhau.
Tôi làm về hệ thống nhúng (rất không muốn dùng từ này thay từ embedded trong tiếng Anh, nhưng cũng phải dùng cho đậm đà bản sắc dân tộc), là mảng công việc rất rất cần hiểu sâu sắc về trình biên dịch, nhưng đáng buồn là giờ tôi mới tìm hiểu, thôi thì chậm hơn là không.

Trong công việc phần mềm, thì trình biên dịch được hiểu ngắn gọn là phần mềm chuyển từ mã nguồn do lập trình viên viết ra, biến thành mã máy (trong trường hợp dotNET hay Java chắc phải hiểu khác chút).

Trình biên dịch thường là do các công ty phát triển môi trường phát triển (IDE) cho lập trình viên viết ra, nổi bật như Microsoft, với trường hợp này trình biên dịch tích hợp trong môi trường phát triển nên lập trình viên cũng không cần để ý quá nhiều. Bên cạnh đó các trình biên dịch mã nguồn mở cũng chả kém cạnh, mà đứng đầu là GCC.

Có thể tham khảo về các thể loại trình biện dịch trên Wiki, với trình biên dịch cho ngôn ngữ C thì chỗ này.

Trình biên dịch phải được phát triển rất cẩn thận, vì nếu trình biên dịch mà có lỗi thì ảnh hưởng rất lớn trong việc phát triển các phần mềm dùng trình biên dịch đó. Nếu xuất hiện tình huống lỗi phần mềm đang phát triển, mà nó lại do cái lỗi kia của trình biên dịch thì đúng là ác mộng. Tuy nhiên trên thực tế lỗi của trình biên dịch vẫn như sao trời mùa hạ, ví dụ danh sách lỗi dược báo cáo của GCC chẳng hạn, biết làm sao được nó cũng chỉ là phần mềm thôi mà. Cách đấy hơn 2 năm, tôi cũng đã từng ăn quả đắng khi trình biên dịch cho hệ thống firmware bị lỗi khi biên dịch phép tính 64bit, do không thể đợi lỗi này được xử lý ở trình biên dịch, mà phải đi vòng (workaround) bằng cách thay thế toàn bộ tính toán 64bit bằng một thư viện mới xử lý thông qua trình toán 32bit.

Công việc từ trước đến này tôi chỉ dùng GCC, ngoài việc hỗ trợ nhiều ngôn ngữ, nó còn hỗ trợ hầu hết các platform, thành ra tôi luôn nghĩ nó là “độc cô cầu bại” trong thế giới công việc nhúng. Nhưng ai có ngờ lời xưa đã chứng, đâu ra lại xuất hiện 1 thằng clang đã có chiều hướng đè bẹp GCC? Tôi chưa thử so sách xem chất lượng mã máy được biên dịch ra thế nào, còn về tốc độ biên dịch thì GCC hít khói. Nói về clang thì nó chỉ là mặt tiền (bước phân tích mã nguồn) của một thứ đang sợ hơn là LVMM, dự án này bắt đầu từ nghiên cứu của Chris Lattner. Cầu thủ này được Apple thuê hơn 10 năm, trong thời gian đó thì clang xuất hiện và thay thế GCC trong các môi trường phát triển của Apple. Sau khi không đá cho Apple nữa mà chuyển sang chơi ô tô với Elon Musk, nhưng chỉ đá được gần 6 tháng chắc thấy đá không vừa chân nên chuyển qua chơi AI với google.

Cưỡi ngựa xem hoa thế là đủ rồi, đã đến giờ “học đi đôi với hành”, để hiểu hơn về trình biên dịch thì cũng nên một lần trong đời thử viết 1 con compiler be bé xem nó ra cái gì. Để làm được cái “be bé” đó trước hết chắc phải đọc kỹ cái đống dưới.

BOOK.
[1] https://www.amazon.com/dp/0321486811/?tag=stackoverflow17-20
[2] https://www.amazon.com/dp/0471976970/?tag=stackoverflow17-20
[3] https://holub.com/goodies/compiler/compilerDesignInC.pdf

Other.
[1] https://www.quora.com/How-do-I-make-a-compiler-using-C-language
[2] https://holub.com/compiler/
[3] https://norasandler.com/2017/11/29/Write-a-Compiler.html
[4] http://scheme2006.cs.uchicago.edu/11-ghuloum.pdf
[5] https://softwareengineering.stackexchange.com/questions/165543/how-to-write-a-very-basic-compiler
[6] https://www.codeproject.com/articles/30353/designing-a-compiler

Câu chuyện từ khóa Volatile

Về từ khóa volatile thì có rất nhiều bài giải thích rồi, ví dụ như đây, đây đây nữa, tôi không muốn nhai đi nhai lại nhiều nữa.

Tuy nhiên vấn đề các tác giả đề cập đến thường là việc giá trị “biến thay đổi bất thường”, tôi không hiểu ý bất thường ở đây cụ thể là gì, bất thường đối với ai, nhưng có vẻ như là bất thường theo nghĩa trình biên dịch đọc code.
Để chắc bắp, nên tham khảo chính xác đặc tả C (or C++) xem nó nói gì, nhưng sờ vào đặc tả mới thấy nó không dễ đọc như tôi vẫn tưởng 😦

An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects. Therefore any expression referring to such an object shall be evaluated strictly according to the rules of the abstract machine, as described in 5.1.2.3.

Có thời gian nữa thì chắc nên nghiền ngẫm thêm chút vì thuật ngữ nghe là lạ, nhưng có thể tạm hiểu là từ khóa volatile để chỉ ra rằng biến đó có thể được thay đổi theo cách không rõ, không nhận biết được (mk, tiếng việt mình ngu quá, dài dòng vậy chứ có khi dùng từ “bất thường” là hợp lý nhất), cho nên việc tham chiếu biến đó phải tuyệt đối tuân thử đúng qui tắc máy :-o. Kết hợp thêm các ví dụ tham khảo thì tôi đang tạm hiểu ý là những chỗ đã liên quan đến từ khoá volatile thì phải tuyệt đối làm theo đúng từng mệnh lệnh mà mã nguồn đã được viết ra.
Dùng Google tìm kiếm thì có thể tóm tắt vài tình huống dưới, mà biến bị thay đổi một cách bất thường đối với trình biên dịch, làm cho nó không nhận thức được việc thay đổi đó.
– Trong chương trình có xử lý ngắt, vì xử lý ngắt tạo tình huống đặc biệt.
– Xử lý song song đa luồng, các luồng có sử dụng biến chung.
– Vùng nhớ sử dụng cho IO map.
Chính vì trình biên dịch không có khả năng (?) nhận thức, nhận biết được toàn bộ những thay đổi liên quan đến biến có mang từ khoá volatile, do đó nó phải tuân thủ từng dòng code chứ không được suy đoán, mà mục đích thường là để tối ưu khi biên dịch mã nguồn.
Tôi thì vẫn nghĩ chỉ có trường hợp 3 do trình biên dịch không thể đủ thông tin nên mới có thể làm sai khi tiến hành tối ưu code, chứ trường hợp interrupt hay xử lý đa luồng, thì rõ ràng mọi thứ trình biên dịch đều có thể nhận thức được, tôi không cho rằng cái đó là biến được thay đổi một cách bất thường. Tuy nhiên vì chưa có hiểu biết gì về cách tối ưu của trình biên dịch nên tôi cũng chỉ đưa ra nhận định chủ quan.

Sau khi đọc bài viết chỗ này, tôi đã thử 1 sampe code để test với gcc 6.3.0, dùng signal interrupt từ bàn phím, nhưng tối ưu hóa đủ mọi option vẫn không bị lỗi. Sau khi được tác giả gợi ý dùng fake interrupt bằng timer thì lại đúng là bị lỗi nếu không dùng volatile thật.
Dù sao chăng nữa thì tôi vẫn giữ quan điểm volatile chỉ cần trường hợp map IO do tác động thực sự từ yếu tố bên ngoài mà trình biên dịch có mắt cũng chả thấy được, à hoặc có thể một trường hợp là cố tình dump code theo ý người viết, mà thường thấy là tạo delay  cái này thường thấy khi lập trình cho vi điều khiển, do thư viện không hỗ trợ hàm delay, điều này cũng làm cho trình biên dịch phán đoán là đoán mã đó thừa và thực hiện tối ưu, do nó không hiểu “ngu ý” của người viết. Còn lại với những trường hợp mà bản thân trình biên dịch có đầy đủ thông tin nhưng vẫn biên dịch lỗi nếu không có volatile thì tôi nghĩ có khi phải xem xét lại bản thân trình biên dịch.

Tóm lại từ khóa volatile dùng để nói cho trình biên dịch đấy là vùng cấm, code thế nào thì hãy làm đúng như thế, mày mới chỉ biết 1 chứ chưa biết 2, phần mày đang biên dịch chỉ là 1 phần nhỏ trong hệ thống lớn, nên đừng có khôn lỏi vào chỗ đó, đừng dựa vào nhận định chủ quan mà tiến hành thay đổi code để thực hiện tối ưu.

Câu chuyện đến đây có lẽ là xong rồi, tuy nhiên có lẽ  ta dễ thấy có gì đó hơi không tự nhiên lắm, do nó chỉ bị lỗi khi yêu cầu trình biên dịch thực hiện tối ưu, vậy nếu trình biên dịch “ngây thơ” bảo gì làm nấy thì có lẽ là ta chẳng cần từ khóa volatile làm gì. Mà về tính năng tối ưu trong trình biên dịch thì tôi nghĩ nó chỉ phát triển sau này. Lúc xây dựng C không rõ trình biên dịch mà cụ Dennis Ritchie dùng có những tính năng gì (tôi không rõ ông làm thế nào để xây dựng ra C nên chỉ phán đoán thôi, nhưng dù sao chắc cũng phải vừa xây dựng đặc tả thì cũng phải song song xây dựng 1 trình biên dịch để kiểm thử).
Kiểm ra lại đặc cả ngôn ngữ C phiên bản đầu tiên thì chưa có thật, nó chỉ được thêm vào từ phiên bản số 2. Từ đó liệu ta có thể phán đoán là trong quá trình phát triển tính năng tối ưu code của trình biên dịch, nó lại yêu cầu ngược lại đặc tả phải thêm từ khóa volatile?

Như vậy “điều lệ” ban ra đã rõ ràng, tuy nhiên “chi bộ” Kernel Linux lại không tuân thủ, à cũng nói thêm là “chi bộ” này được “đồng chí” Tovard Linux thành lập từ 1990 (chú ý là “đồng chí” Ngô Thời Nhiệm không nằm trong chi bộ này). “chi bộ” này đã ra 1 “thông tư” nói không với volatile cơ bản có 2 điểm.
1. Trong mọi trường hợp trong kernel linux đều không thấy cần volatile.
2. Nếu cần thì đấy là BUG.
“Thông tư” đã viết rất rõ ràng nên ai muốn biết mời tham khảo. Tìm hiểu thêm về “chi bộ” này ta còn bắt gặp nhiều điểm bất thường khác nữa, phải chăng chính điều đó tạo nên đặc trưng cho Kernel Linux.

Tham khảo
http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html
http://publications.gbdirect.co.uk/c_book/

Cảm biến 3D – TOF

Từ khi ipornX Iphone X của Apple được giới thiệu, cảm biến 3D trở thành 1 hot keyword, làm cho nhà nhà đua nhau tích hợp 3D vào điện thoại, người người thi nhau mua điện thoại có cảm biến 3D. Ông trùm SONY về mảng điện tử một thời của Nhật, mà hiện giờ mảng cảm biến đang mang lại một trong những nguồn sống chính, đã nhanh chân mở ví ra mua luôn Softkinetic, một startup của Bỉ với tầm 77 nhân sự vào 2015.
Tôi vô tình cũng bị cuốn vào xu thế đó khi tham gia dự án làm platform & driver cho con hợi này. Do đó vừa học vừa viết lại đôi điểm cho đỡ quên, nội dung rút ra từ tài liệu [1] ở phần tham khảo. Có thể học thêm về TOF ở kho tài liệu của Texas Instrument [2], rất phong phú và chi tiết.

Trong vấn đề xử lý hình ảnh, việc thu và tái hiện lại hình 3D không phải vấn đề gì mới, trước TOF đã có 2 phương pháp được sử dụng để tái tạo hình ảnh 3D.
Stereo Vision : Sử dụng 2 camera để tái hiện lại 3D, vị trí của 1 điểm sẽ được xác định nhờ vị trí tương đối của nó đối với 2 camera. Phương pháp này sử dụng tương tự hệ thống mắt người.
stereo-vision
Nguyên lý Stereo Vision (Ảnh lấy trong tài liệu[1])

Structured-light: Phương pháp này sử dụng 1 chùm tia sáng với mô hình xác định trước (dạng lưới, quét ngang …) , để chiếu lên vật thể cần quan sát, thu lại hình ảnh khi tia sáng đập lên bề mặt vật thể để xây dựng lại hình ảnh 3D của nó.
structure-ligh
Nguyên lý Structured-light  (Ảnh lấy trong tài liệu[1])
Vậy TOF là gì? TOF là viết tắt của Time Of Flight, dựa trên nguyên lý đo khoảng cách bằng sóng điện từ (sóng ánh sáng ở dải mắt người không nhìn thấy). Trong hệ thống TOF, sử dụng 1 nguồn phát sóng ánh sáng, quan sát nguồn phản hồi từ đối tượng quan sát, bằng cách đo thời gian từ lúc phát ra đến lúc phản hồi thì sẽ tính được vị trí của đối tượng đó.
tof
Nguyên lý TOF (Ảnh lấy trong tài liệu[1])
Dễ thấy nguyên lý của TOF giống hệt như dùng sóng siêu âm để đo độ sâu đáy biển, tất nhiên từ lý thuyết đến thực tiễn là 1 khoảng cách không nhỏ về thời gian cũng như tiền bạc.

Bảng dưới đây cho thấy hình ảnh tổng quan của TOF khi so sánh với 2 kỹ thuật còn lại. Công nghệ thay đổi chóng mặt chả khác gì “chó chạy ngoài đồng” , nên cần chú ý rằng thông tin trong bảng này chỉ đúng với tầm thời điểm hiện tại (~2018).
tof

So sánh TOF với Stereo Vision và Structured-light (Ảnh lấy trong tài liệu[1])

Tham khảo:
[1] http://www.ti.com/lit/wp/sloa190b/sloa190b.pdf
[2] http://www.ti.com/3dtof
[3] https://en.wikipedia.org/wiki/Structured_light
[4] https://en.wikipedia.org/wiki/Time-of-flight_camera
[5] https://en.wikipedia.org/wiki/Computer_stereo_vision

3 định luật XYZ

Sau khi được nhà quí tộc Brahe để lại 1 khối lượng dữ liệu quan sát thiên văn hơn 30 năm, thì Kepler đã hoàn thành thuyết nhật tâm một cách có hệ thống bằng 3 định luật chuyển động thiên thể và những năm 1609 – 1619, lúc đấy ở Đại Việt ta bắt đầu thời kì Trịnh – Nguyễn phân tranh nên chắc chả ai có thời gian đâu mà quan tâm đến thiên với chả thể.
Tuy là tìm ra 3 định luật, nhưng Kepler cũng không hiểu “vì sao lại thế, tại vì sao lại thế, các thiên thể không chuyển động thế này mà lại là thế kia”. Người trong giang hồ phải chờ đến xuất hiện một quái kiệt mới “để tìm ra ngọn ngành”, người mà khiêm tốn nhận mình trông xa hơn vì được đứng trên vai những người khổng lồ, Newton đã đưa ra 3 định luật cơ bản, hình thành nên cơ học cổ điển hay còn gọi là cơ học Newton, cùng với định luật vạn vật hấp dẫn, đã giải thích thấu đáo tại sao qui luật chuyển động thiên thể. Cơ học Newton đã thống trị mọi lĩnh vực của Vật lý học cho đến đầu thế kỉ 19, khi mà mọi ngành nghiên cứu từ chuyển động của phân tử, đến những đối tượng to vật vã như thiên thể, hành tình đều được xây dựng theo các định luật cơ bản của Newton, mà đưa ra nhiều dự đoán đúng. Mô hình vật lý học trở nên thống nhất, rất đẹp đẽ.
Nói đến ngành nghiên cứu về tập hợp các phân tử tuân theo chuyển động cơ học, hay còn gọi là nhiệt động lực học, cũng cho ra đời 3 định luật nhiệt động lực học, trong đó từ định luật số 2 định nghĩa ra một khái niệm mới là entropy, mà nó còn dùng để định nghĩa lượng thông tin trong lý thuyết thông tin.

Tưởng chừng như “con thuyền Vật lý học cấp bến bình yên” như huân tước Kelvin (nhiều tài liệu dẫn tuyên bố này của Kelvin, tuy nhiên thực tế hình như không có thông tin chính thống), thì “2 gợn mây nhỏ” đã nổi lên thành 2 cơn giông tố làm rung chuyển và thay đổi hẳn bộ mặt ngành Vật lý. Trong cơn giông lượng tử, ta lại bắt gặp 3 định luật quang điện

Con số 3 chưa dừng ở đó, ta lại tiếp tục gặp 3 định luật về di truyền Mendel khi học sinh học hình như tầm năm lớp 9.
Hôm nay vô tình biết đến tồn lại 3 định luật hơi bị hay của Arthur C.Clarke, người nổi tiếng về những dự đoán của ông trong các tác phẩm khoa học viễn tưởng đã dần dần thành hiện thực. Nguyên văn của nó như sau:
1. When a distinguished but elderly scientist states that something is possible, he is almost certainly right. When he states that something is impossible, he is very probably wrong.
2. The only way of discovering the limits of the possible is to venture a little way past them into the impossible.
3. Any sufficiently advanced technology is indistinguishable from magic.

Tạm dịch nó như sau:
1. Khi một bậc lão thành cho rằng một chuyện gì đó là có thể xảy ra được thì ông ta hầu như chắc chắn đúng. Song khi vị này bảo rằng chuyện gì đó là không thể được, thì phần chắc là ông ta sai.
2. Cách duy nhất để xác định biên giới của cái có thể là mạo hiểm vượt qua lằn ranh đó để đi về hướng cái không thể.
3. Bất kỳ công nghệ tiên tiến nào đều không khác gì phép thần thông.

P/S: Áp dụng định luật Clarke ở trên, ta dễ dàng thấy được tuyên bố sau của Steve Wozniak là sai, thật là một định luật thú vị 🙂
http://genk.vn/dong-sang-lap-apple-tri-tue-nhan-tao-se-khong-bao-gio-du-thong-minh-de-dieu-khien-mot-chiec-o-to-20181001104135133.chn

Biên dịch Linux OS từ mã nguồn

Bắt đầu đi làm vào giữa 2009, tôi bắt đầu được tiếp xúc với Linux, nhưng trải qua gần 9 năm từ đó đến nay, hiểu biết về Linux rất ổn định như tham nhũng, không có gì thay đổi. Lý do thứ nhất là vì các dự án làm với Linux chỉ là sử dụng môi trường Linux để phát triển, nên cơ bản chỉ biết cái Makefile là xong, chẳng lúc nào cần mó tay một cách chỉnh chu thấu đáo vào các thứ như device driver, hay memory management …, để biết cái gì đủ hay ho mà kể chuyện. Thật ra là có một chút nhưng không ăn thua, mấy thứ cơ bản như system call, char driver, block driver … thì nó phổ cập cmnr, với lại khoảng cách giữa biết tên và biết để kể chuyện được nó cũng quá xa. Lý do thứ 2 là lười & nhác tìm hiểu.

Đang ôn tập lại chút kiến thức để chuẩn bị do dự án làm driver trên Linux, thì bắt gặp trang dưới (ko hiểu sao giờ mới biết, chắc lại do nhác & lười).
http://linuxfromscratch.org/lfs

Trước giờ hay có sở thích, là thử distribution (Linux OS) của Linux, hết Ubuntu đến Backtrack, với mục đích rất đáng sợ là để học sâu thêm về Linux nhưng cài xong  chiêm ngưỡng cái desktop xong  rồi thì sau đó là chỉ để duyệt web ~.~

Việc hay thử Linux OS, nó cũng bắt nguồn từ hồi mới ra trường, được bố mẹ bán hết lúa gạo lợn gà cho mua con hp pavilion, không nhớ chính xác tên nhưng giá là 12 hay 17 chai gì đấy. Đen đủi thế nào lúc ra lúc bắt đầu đi làm 1 năm thì bị trộm nó thó mất, lương thấp ăn chưa đủ nói gì đến mua lại máy. May thay ông anh trong dự án có con T40 thinkpad hỏng main đang đắp chiếu, bảo cầm về sửa mà dùng. Sau thay main cũ hết 1 triệu, cài luôn ubuntu, có hơi rùa bò tí những nó vẫn dùng để kết nối tốt với internet. Vì rùa bò nên nghĩ ra việc dùng các bản Linux OS cho máy cấu hình thấp, nhưng rồi cũng thấy chẳng ăn thua lắm nên mới sinh ra trò thử cài Ubuntu xong gỡ hết gói màu mè về giao diện ra thì tốc độ có thấy cải thiện kha khá. Từ đó có thêm trò ngược đời là cài xong Linux OS thì gỡ bớt gói không cần thiết ra, đôi khi không biết nên gỡ quá tay làm nó chẳng start up luôn được cả giao diện =]]. Dùng được hơn 1 năm thì T40 cũng đi vì cái màn hình hỏng.

Đến 2011, đi công tác ở Nhật, nhịn ăn nên cũng mua được con CF-W5MW8AJR Panasonic đồ cũ cùi bắp, mua xong cài luôn Ubuntu đè lên con Win Vista bản quyền luôn.
Riêng con này từ lúc mua ngoài làm mất thứ vớ vẩn thì cũng kiếm đc chút từ việc
data hiding, do muốn mua con len Nikon 50mm f/1.8G, nhưng lương chỉ đủ nuôi con nên đành kiếm tí việc đánh thêm, đỡ phạm đến phần tiền mua sữa cho con 😦

Nói dài dòng, nhưng tóm lại giờ có con CF5 cùi bắp, tính  cho mấy thằng em ở quê, nhưng chắc là nó không thèm lấy, mà công nhận đồ của Panasonic rất chất, nhẹ, pin trâu vẫn duy trì hơn tầm 1.5h, phím bấm cực đã không bị rung, ai dùng dòng Let’s Note của Panasonic rồi thì biết, chỉ có điều giá trên trời. Như  đề cập ở trên, tự dưng biết 1 dự án rất có tâm, hướng dẫn biên dịch hẳn Linux OS từ source code (có khi google đủ các kiểu + bỏ thời gian ra chắc cũng tự build được), tóm lại từ Linux kernel, đến các gói mã nguồn GNU & non-GNU …

Dù là việc biên dịch chỉ là việc chân tay, nhưng trải nghiệm 1 lần biên dịch ra OS từ mã nguồn nó cũng hay hay, dù sao cũng tạo hứng thú vượt qua lười & nhác để có thể bắt đầu tìm hiểu thêm chút về Linux. Thêm vào đó hi vọng do tự điều chỉnh được các gói cần thiết nên sẽ có được con OS nhỏ gọn để chạy với cái đồ cùi bắp như CF-W5MW8AJR.

Có 1 điểm chú ý khi bắt đầu biên dịch là nên chuẩn bị 1 con USB stick hoặc CD live có thể chạy live Linux OS nào đó (ex: ubuntu), để phòng trường hợp lỗi khi chia ổ cứng này nọ thì còn có cách mà xử lý.
Về phần dữ liệu quan trọng trong máy thì theo tôi không cần phải backup, vì nếu bị lỗi thì có cơ hội học cách cứu dữ liệu, nếu cứu không được thì coi như cái giá phải trả để nhớ bài học hơn =]].

Libc

Bắt đầu từ đoạn code nhỏ dưới viết bằng ngôn ngữ C. Ngoài dòng có chữ printf ra, thì các dòng khác được được biên dịch trực tiếp ra ASM và sang mã máy mà không cần thông qua thư viện nào hỗ trợ. Dĩ nhiên rồi cái nào cũng ra mã máy cả, nhưng printf có gì đặc biệt.

libc

Quay lại chút về ngôn ngữ C, được Dennis Ritchie xây dựng vào 1978, dựa trên ngôn ngữ B, đằng sau đó là 1 câu chuyện dài thú vị, nhưng giờ không phải lúc để kể. C là một ngôn ngữ lập trình, tất nhiên ai cũng biết rồi, tức là để tạo nên C sẽ có 1 loạt qui định về cấu trúc mã lệnh, từ khóa, toán tử … Bên cạnh đó có 1 thứ gần như luôn đi cùng đó là thư viện chuẩn của C, còn gọi là libc, quá quen thuộc với những ai lập trình C. Thư viện này được chuẩn hóa C POSIX library hẳn hỏi, và vẫn được bổ sung theo thời gian.

Thư viện này thuộc loại căn bản của C rồi, nên gần như nó luôn tồn tại sẵn làm người ta đôi lúc quên mất sự hiện diện của nó. Thực tế cũng giống như các thư viện khác, dựa vào đặc tả trên, nó cũng được code, biên dịch trước thành mã máy để liên kết vào chương trình nào dùng đến nó.
Trên môi trường GNU/Linux thì dùng glibc của GNU, trên android thì có bionic do google thực hiện để tránh cho Android đỡ dính đến copyleft licenses chừng nào có thể (trong khi đó vẫn dùng Linux Kernel → LOL), trên các hệ điều hành BSD ( ex: MacOS) cũng tự tạo BSD libc riêng của nó, ngoài ra còn nhiều trường hợp khác cũng viết lại thư viện này, để phù hợp hơn với yêu cầu hệ thống, ví dụ như đôi lúc không cần thiết phải dùng hết toàn bộ libc nhất là đối với môi trường hạn chế tài nguyên.

Trở lại vấn đề chút đoạn mã trên, vậy cái hàm printf trên nó là thuộc libc, chi tiết hơn là thư viện chuẩn vào ra (I/O) stdio.h. Nếu biên dịch trên GNU/Linux thì nó liên kết đến thư viện glibc trên đó để tạo ra mã máy.

Ngó qua chút xem 1 hàm “đơn giản” như printf thì có mã lệnh thế nào.
Official glibc repo ở đây, hàm printf nó ở chỗ này, rồi nhảy sang chỗ này, tổng cộng chỉ có “ít ỏi” gần 2500 dòng lệnh.

Đến đây có chút thú vị trên môi trường OS dùng nhân linux, do chỉ dùng glibc trên user space, nên thành ra ở kernel space không dùng được các hàm libc. Do đó lúc muốn printf thì làm sao giờ?, vậy là Linus viết luôn hàm printk thay thế, đúng theo triết lý, thấy ổ gà thì lấp.

Code refactoring

Từ 1 comment status của thằng bạn trên facebook, nhớ lại về nguyên lý thứ hai của nhiệt động lực học. À, mà sao lại nguyên lý thứ hai nhỉ, có nguyên lý thứ nhất không nhỉ?

Học từ hồi cấp 3, bắt đầu từ câu chuyện không thể chế tạo động cơ vĩnh cửu loại 2, tức là động cơ dùng 2 nguồn nhiệt để có thể biến nhiệt hoàn toàn thành công. Tuy không vi phạm định luật bảo toàn năng lượng, nhưng vẫn không làm được.

Hiệu suất lý tưởng để chuyển nhiệt biến thành công chỉ đạt được = (T2- T1)/T2; T1,T2 là nhiệt độ nguồn nóng & lạnh tính theo nhiệt giai Kelvin.
Tại sao lại thế? qui luật gì đã chi phối cái đó. Trong quá trình giải quyết cái đó thì ông cụ Rudolf Clausius đã mang đến một khái niệm gọi là Entropy (kí hiệu là S), bản chất là đặc trưng cho tính hỗn loạn của hệ thống. Chốt lại là qui luật trên sẽ tương đương với việc phát biểu: Entropy của hệ cô lập không thể giảm. Tức là tính hỗn loạn của hệ thống cô lập sẽ tăng hoặc ít nhất là giữ nguyên.
Câu chuyện tưởng đến đây là hết, thì hóa ra mới bắt đầu. Trong lý thuyết thông tin, Shannon định nghĩa lượng thông tin của hệ thống thông qua Entropy, xem ở đây. Hệ thống càng hỗn loạn thì càng chứa nhiều thông tin, hệ thống càng trật tự thì lượng thông tin chứa trong đó càng ít, nghe cũng có lý đấy chứ nhỉ!. Vậy là từ cái máy nhiệt lại liên hệ mật thiết với chủ đề nóng, vấn đề thông tin.

Cái nghề làm phần mềm chắc chắn cũng không ngoài cuộc, vì nguyên lý phổ quát mà, bao trùm từ vũ trụ bao la bát ngát ( xem Lược sử thời gian – Stephen Hawking, thì biết) đến trà đá vỉa hè (cục đá đang tan dần trong cốc trà, chính là biểu hiện của việc Entropy đang tăng). Vậy phần mềm có xu hướng càng ngày càng lộn xộn, và thực tế đúng như thế. Lúc bắt đầu dự án, nếu là dự án tử tế thì basic design, detail design chuẩn mực thật. Nhưng theo tháng năm, ta thêm tí mắm, lâu lâu cho chút muối vào, thi thoảng thêm tí tính năng để phần mềm lúc đầu đặc tính giống Chó nhưng lại muốn bắt đc cả Chuột, và dần dần nó trở thành 1 đống lộn xộn. Và đâu đó cũng có Sofware entropy thật.
Nhưng chú ý, điều đó chỉ đúng với hệ cô lập, và để phần mềm không trở nên thành 1 đống hổ lốn theo tháng năm thì phải tìm cánh phá vỡ tính “cô lập” của nó, một trong những cách đó là REFACTORING, quyển sách cần đọc, nó nằm ở đây.  Mặc dù  không khuyến khích, nhưng trước khi mua sách tử tế thì có thể xem tạm ở đây

Tóm lại từ nguyên lý thứ hai của nhiệt động lực học, ta rút ra rằng để software không bị xuống cấp, ta phải học cách refactoring?