Quay lại
01/05/2026 37 phút

Chương 26: Hệ điều hành

Cuối cùng cũng lắp xong—ít nhất là trong trí tưởng tượng—thứ trông có vẻ như là một chiếc máy tính hoàn chỉnh. Chiếc máy tính này có một bộ xử lý trung tâm (CPU), một ít bộ nhớ truy cập ngẫu nhiên (RAM), bàn phím, màn hình hiển thị dùng chung bộ nhớ với RAM, và một thiết bị lưu trữ dung lượng lớn nào đó. Mọi phần cứng đã đủ, và đôi mắt thèm thuồng đang nhìn chằm chằm vào công tắc cấp nguồn để khởi động bộ máy. Có lẽ dự án này sẽ gợi lên trong trí bạn quá trình chế tạo quái vật của Victor Frankenstein, hay lúc bác thợ mộc Geppetto đẽo gọt nên cậu bé người gỗ Pinocchio.

Nhưng chúng ta vẫn còn thiếu một thứ, và nó chẳng phải là sức mạnh của một tia sét hay sự thuần khiết của một điều ước gửi tới vì sao. Cứ thử đi: Hãy bật chiếc máy tính mới toanh này lên và nói cho tôi biết bạn thấy gì.

Khi màn hình nhấp nháy bật sáng, nó sẽ chỉ hiển thị một mớ rác ngẫu nhiên. Nếu bạn dùng bộ adapter đồ họa, sẽ có đủ các chấm màu lộn xộn chẳng ra hình thù gì. Còn với bộ adapter văn bản, bạn sẽ thấy toàn các ký tự ngẫu nhiên. Đúng như dự đoán. Bộ nhớ bán dẫn sẽ mất sạch nội dung khi bị cắt điện và bắt đầu ở trạng thái ngẫu nhiên, không thể đoán trước khi mới được cấp điện lại. Toàn bộ RAM được chế tạo cho bộ vi xử lý lúc này chứa toàn những byte ngẫu nhiên. Bộ vi xử lý sẽ bắt đầu thực thi những byte ngẫu nhiên này như thể chúng là mã máy. Sẽ chẳng có thảm họa nào xảy ra—chẳng hạn máy tính sẽ không phát nổ—nhưng nó cũng chẳng có ích gì.

Thứ chúng ta đang thiếu ở đây là phần mềm. Khi một bộ vi xử lý lần đầu được bật lên hoặc bị reset, nó bắt đầu thực thi mã máy tại một địa chỉ bộ nhớ cụ thể. Đối với Intel 8080, địa chỉ đó là 0000h. Trong một chiếc máy tính được thiết kế đàng hoàng, địa chỉ bộ nhớ đó phải chứa một lệnh mã máy (rất có thể là lệnh đầu tiên trong chuỗi rất nhiều lệnh) mà CPU sẽ thực thi ngay khi máy tính được bật.

Thế làm sao lệnh mã máy lại ở đó? Quá trình đưa phần mềm vào một chiếc máy tính mới được thiết kế là một trong những khía cạnh dễ gây bối rối nhất của dự án này. Một cách để làm điều đó là sử dụng bảng điều khiển tương tự như ở Chương 19, dùng để ghi các byte vào bộ nhớ truy cập ngẫu nhiên và sau đó đọc chúng ra:

Bảng điều khiển RAM 64KB


Khác với bảng điều khiển trước, cái này có thêm một công tắc tên Reset. Công tắc Reset được kết nối với đầu vào Reset của CPU. Chừng nào công tắc đó còn bật, bộ vi xử lý sẽ không làm gì. Khi bạn tắt công tắc, bộ vi xử lý bắt đầu thực thi mã máy tại địa chỉ 0000h.

Để dùng bảng điều khiển này, bạn bật công tắc Reset để khởi động lại bộ vi xử lý và bắt nó ngừng thực thi mã máy. Bạn bật công tắc Takeover để giành quyền kiểm soát bus địa chỉ và bus dữ liệu. Lúc này, bạn có thể dùng các công tắc từ A0 đến A15 để chỉ định một địa chỉ bộ nhớ 16-bit. Các bóng đèn từ D0 đến D7 sẽ cho bạn thấy nội dung 8-bit tại địa chỉ bộ nhớ đó. Để ghi một byte mới vào địa chỉ, bạn thiết lập byte này trên các công tắc từ D0 đến D7, rồi gạt công tắc Write bật lên và tắt xuống. Sau khi đã nhét xong các byte vào bộ nhớ, hãy tắt công tắc Takeover và tắt luôn công tắc Reset, bộ vi xử lý sẽ bắt đầu thực thi chương trình.

Đây chính là cách bạn nhập những chương trình mã máy đầu tiên vào chiếc máy tính mà bạn vừa chế tạo từ con số không. Đúng vậy, rườm ra quá trời. Khỏi phải bàn. Lúc này lúc kia mắc lỗi là điều hiển nhiên. Rồi ngón tay bạn phồng rộp và não bạn nhũn ra như cháo là một loại "tai nạn nghề nghiệp".

Nhưng điều khiến công sức đổ vào xứng đáng là khi bạn bắt đầu sử dụng màn hình video để hiển thị kết quả từ những chương trình nhỏ của mình. Một trong những đoạn mã đầu tiên bạn viết là một chương trình con dùng để chuyển đổi số thành ASCII. Ví dụ, nếu bạn viết một chương trình cho ra kết quả 4Bh, bạn không thể đơn giản là bê nguyên giá trị đó ghi vào bộ nhớ màn hình video được. Nếu làm thế, thứ bạn thấy trên màn hình sẽ là chữ K vì đó là ký tự tương ứng với mã ASCII 4Bh. Thay vào đó, bạn cần hiển thị hai ký tự ASCII: 34h (mã ASCII cho chữ số 4) và 42h (mã ASCII cho chữ B). Bạn đã từng thấy đoạn mã làm đúng việc đó rồi: đó là chương trình con ToAscii ở trang 398 trong Chương 24.

Một trong những ưu tiên hàng đầu có lẽ là vứt quách cái bảng điều khiển nực cười kia đi và điều đó đồng nghĩa với việc bạn phải viết một trình xử lý bàn phím (keyboard handler): một chương trình đọc các ký tự được gõ từ bàn phím, lưu chúng vào bộ nhớ, đồng thời ghi chúng lên màn hình. Việc chuyển các ký tự từ bàn phím lên màn hình đôi khi được gọi là dội lại (echoing), và nó tạo ra ảo giác về một sự kết nối trực tiếp giữa bàn phím và màn hình.

Bạn có thể sẽ muốn nâng cấp trình xử lý bàn phím này thành một thứ gì đó có thể thực thi các lệnh (command) đơn giản—tức là giao cho nó làm thêm vài việc hữu ích. Đoạn mã bạn viết để xử lý các lệnh này giờ đây được đặt tên là bộ xử lý lệnh (command processor). Để mọi thứ đơn giản lúc đầu, bạn chỉ dùng ba lệnh. Ba lệnh này tương ứng với chữ cái đầu tiên được gõ trên dòng:

  • W cho Write (Ghi)
  • D cho Display (Hiển thị)
  • R cho Run (Chạy)

Trình xử lý bàn phím của bạn sẽ thực thi các lệnh này khi bạn nhấn phím Enter để ra hiệu rằng bạn đã gõ xong.

Nếu dòng văn bản bắt đầu bằng chữ W, lệnh này có nghĩa là Ghi vài byte vào bộ nhớ. Dòng bạn gõ trên màn hình sẽ trông thế này:

W 1020 35 4F 78 23 9B AC 67

Lệnh này hướng dẫn bộ xử lý lệnh ghi các byte thập lục phân 35h, 4Fh, v.v., vào bộ nhớ bắt đầu từ địa chỉ 1020h. Để làm được, trình xử lý bàn phím cần phải chuyển đổi các mã ASCII thành byte—tức là quy trình đảo ngược của việc chuyển đổi ToAscii mà tôi đã trình bày ở trước.

Nếu dòng văn bản bắt đầu bằng chữ D, lệnh này có nghĩa là Hiển thị vài byte trong bộ nhớ. Dòng bạn gõ trên màn hình sẽ trông như thế này:

D 1030

Bộ xử lý lệnh sẽ đáp lại bằng cách hiển thị các byte được lưu trữ bắt đầu từ vị trí 1030h. Bạn có thể dùng lệnh Display để xem nội dung bên trong bộ nhớ.

Nếu dòng văn bản bắt đầu bằng chữ R, lệnh này có nghĩa là Chạy. Trông như này:

R 1000

Lệnh này có nghĩa "Chạy chương trình đang nằm ở địa chỉ bắt đầu từ 1000h." Bộ xử lý lệnh có thể lưu giá trị 1000h vào cặp thanh ghi HL và sau đó thực thi lệnh PCHL, lệnh này sẽ nạp giá trị từ cặp thanh ghi HL vào bộ đếm chương trình, về cơ bản chính là nhảy đến địa chỉ đó.

Làm cho trình xử lý bàn phím và bộ xử lý lệnh này hoạt động trơn tru là một cột mốc cực kỳ quan trọng. Một khi đạt được, bạn chẳng cần phải chịu tủi nhục khi dùng bảng điều khiển nữa. Nhập dữ liệu từ bàn phím dễ hơn, nhanh hơn và "sang" hơn nhiều.

Đương nhiên, bạn vẫn còn một vấn đề là toàn bộ mã bạn vừa nhập vào sẽ biến mất ngay khi tắt nguồn. Vì lẽ đó, bạn có thể sẽ muốn cất giữ toàn bộ đoạn mã mới này vào trong bộ nhớ chỉ-đọc, hay ROM. Ở thời kỳ sơ khai của các bộ vi xử lý như Intel 8080, việc lập trình các chip ROM ngay tại nhà đã khả thi. Chip bộ nhớ chỉ-đọc có thể lập trình (PROM - Programmable read-only memory) chỉ cho phép lập trình đúng một lần duy nhất. Chip bộ nhớ chỉ-đọc có thể lập trình và xóa được (EPROM - Erasable programmable read-only memory) có thể được lập trình rồi lập trình lại sau khi bị xóa sạch hoàn toàn bằng cách đem đi tắm tia cực tím.

ROM chứa trình xử lý bàn phím của bạn sau đó sẽ chiếm lấy không gian địa chỉ bắt đầu từ 0000h—vốn là chỗ trước kia RAM từng giữ. Tất nhiên là bạn vẫn giữ lại RAM, nhưng nó sẽ phải dọn lên ở một địa chỉ nào đó cao hơn trong không gian bộ nhớ.

Việc tạo ra bộ xử lý lệnh là một cột mốc quan trọng, không chỉ vì nó cung cấp một phương tiện nhanh hơn để đưa các byte vào bộ nhớ mà còn vì giờ đây chiếc máy tính đã trở nên có tính tương tác (interactive).

Một khi đã có bộ xử lý lệnh trong ROM, bạn có thể bắt đầu viết dữ liệu từ bộ nhớ sang ổ đĩa và đọc dữ liệu đó ngược trở lại vào bộ nhớ. Lưu trữ chương trình và dữ liệu trên đĩa an toàn hơn nhiều so với lưu trong RAM (nơi chúng sẽ biến mất nếu mất điện) và linh hoạt hơn nhiều so với việc lưu trong ROM.

Dần dà, bạn có thể sẽ muốn bổ sung thêm vài lệnh mới cho bộ xử lý lệnh. Ví dụ, lệnh S dùng để Store (Lưu) một phần bộ nhớ vào một nhóm các sector (cung từ) đĩa cụ thể, trong khi lệnh L sẽ Load (Tải) nội dung của các sector đĩa đó vào bộ nhớ.

Tất nhiên, bạn sẽ phải tự mình theo dõi xem mình đang lưu gì ở sector đĩa nào. Chắc bạn sẽ cần một cuốn sổ và cây bút chì cho việc này đấy. Và cẩn thận nhé: Bạn không thể cứ thế lưu một đoạn mã nằm ở một địa chỉ rồi sau đó lại nạp nó về bộ nhớ ở một địa chỉ khác và kỳ vọng nó sẽ chạy mượt mà đâu. Tất cả các lệnh JumpCall sẽ sai vì chúng vẫn đang trỏ về các địa chỉ cũ. Hơn nữa, có thể bạn sẽ có một chương trình dài hơn kích thước một sector trên đĩa, thế nên bạn sẽ phải chia nó ra để lưu vào nhiều sector. Một số sector trên đĩa có khi đã bị các chương trình hoặc dữ liệu khác xí chỗ rồi, vì vậy các sector trống để lưu một chương trình dài có thể sẽ không nằm liền kề nhau trên đĩa.

Rốt cuộc, bạn có thể sẽ phải thừa nhận rằng việc chép tay để theo dõi xem mọi thứ đang được lưu ở đâu trên đĩa là quá sức chịu đựng. Tới đây, bạn đã sẵn sàng cho một hệ thống tệp (file system) rồi đấy.

Hệ thống tệp là phần mềm giúp tổ chức dữ liệu thành các tệp. Một tệp hiểu đơn giản là một tập hợp các dữ liệu liên quan chiếm một hoặc nhiều sector trên đĩa. Quan trọng nhất, mỗi tệp được nhận diện bằng một cái tên giúp bạn nhớ xem tệp đó chứa gì. Bạn có thể coi ổ đĩa giống như một chiếc tủ đựng hồ sơ, trong đó mỗi tệp có một nhãn dán nhỏ xíu ghi tên của nó.

Một hệ thống tệp gần như luôn là một phần của một bộ phần mềm lớn hơn được gọi là hệ điều hành (operating system). Trình xử lý bàn phím và bộ xử lý lệnh mà chúng ta đang xây dựng trong chương này chắc chắn có thể tiến hóa thành một hệ điều hành. Nhưng thay vì phải lê bước qua quá trình tiến hóa dài đằng đẵng đó, chúng ta hãy ngó qua một hệ điều hành thật ngoài đời để xem nó làm những gì và hoạt động ra sao nhé.

Về mặt lịch sử, hệ điều hành quan trọng nhất dành cho các bộ vi xử lý 8-bit là CP/M, ban đầu là viết tắt của Control Program/Monitor nhưng sau đó được đổi tên thành Control Program for Microcomputers. Nó được viết vào giữa thập niên 1970 cho bộ vi xử lý Intel 8080 bởi Gary Kildall (1942–1994), người sau này đã thành lập nên Digital Research Incorporated (DRI).

CP/M được lưu trữ trên một ổ đĩa, nhưng phần lớn ổ đĩa vẫn trống rỗng để bạn thỏa sức lưu trữ các tệp của riêng mình. Hệ thống tệp của CP/M khá đơn giản, nhưng nó đáp ứng được hai yêu cầu tối quan trọng: Thứ nhất, mỗi tệp trên đĩa được xác định bằng một cái tên và tên này cũng được lưu luôn trên đĩa. Thứ hai, các tệp không cần phải chiếm các sector nằm cạnh nhau. Chuyện rất hay xảy ra là khi các tệp với đủ thứ kích thước được tạo ra và xóa đi, không gian trống trên đĩa sẽ bị phân mảnh. Khả năng của hệ thống tệp cho phép lưu trữ một tệp lớn vào các sector không liền kề là cực kỳ hữu dụng. Bảng đối chiếu giữa các tệp với các sector đĩa của chúng cũng được cất trên đĩa.

Dưới CP/M, mỗi tệp được định danh bằng tên có hai phần. Phần đầu được gọi là tên tệp (filename) có độ dài tối đa tám ký tự, còn phần thứ hai được biết đến là loại tệp (file type) hay phần mở rộng (extension) và có thể chứa tối đa ba ký tự. Có một vài loại tệp tiêu chuẩn. Ví dụ, TXT biểu thị một tệp văn bản (tức là tệp chỉ chứa toàn mã ASCII và có thể đọc được bởi con người chúng ta), và COM (viết tắt của command - lệnh) thì báo hiệu đây là một tệp chứa các lệnh mã máy 8080—tức là một chương trình.

Cái quy ước đặt tên tệp này dần được biết đến là 8.3 (đọc là tám-chấm-ba), ám chỉ con số tối đa tám chữ cái trước dấu chấm và ba chữ cái sau nó. Mặc dù các hệ thống tệp hiện đại đã bỏ giới hạn tám và ba ký tự này, nhưng kiểu quy ước đặt tên tệp chung chung này vẫn còn khá phổ biến.

Các máy tính xài CP/M thường trang bị một ROM chứa một đoạn mã nhỏ gọi là bootstrap loader, sở dĩ có tên gọi đó là vì đoạn mã này thực sự lôi phần còn lại của hệ điều hành lên bằng chính dây giày của nó (by its bootstraps). Trình bootstrap loader này sẽ nạp sector đầu tiên từ đĩa mềm vào bộ nhớ và chạy. Sector này lại chứa đoạn mã dùng để nạp nốt phần còn lại của CP/M vào bộ nhớ. Toàn bộ quy trình này được gọi là khởi động (booting) hệ điều hành, một thuật ngữ mà tới tận nay vẫn còn được xài phổ biến.

Bản thân CP/M được tổ chức theo cấu trúc phân cấp: Nằm ở tầng đáy là Hệ thống Đầu vào/Đầu ra Cơ bản, hay BIOS (phát âm là BY-ohss). Nó chứa đoạn mã trực tiếp truy cập vào phần cứng máy tính, bao gồm cả việc đọc và ghi các sector trên đĩa. Bất kỳ nhà sản xuất máy tính nào muốn chạy CP/M đều phải tự cung cấp BIOS riêng để phục vụ cho tổ hợp phần cứng đặc thù của họ.

Nấc tiếp theo trong hệ thống phân cấp là Hệ Điều hành Đĩa Cơ bản, hay BDOS (phát âm là BE-doss). Chức năng chính của BDOS là biến các sector đĩa (vốn do BIOS quản lý) thành tệp.

Khi CP/M đã được tải vào bộ nhớ, nó sẽ kích hoạt một chương trình mang tên Console Command Processor (CCP) để hiển thị một dấu nhắc (prompt) trên màn hình:

A>

Trong các máy tính có nhiều hơn một ổ đĩa, chữ A ám chỉ ổ đĩa đầu tiên, chính là nơi mà CP/M vừa được nạp lên. Prompt là tín hiệu báo cho bạn biết đã đến lúc gõ một cái gì đó và nhấn phím Enter. Hầu hết các lệnh để làm việc với tệp, chẳng hạn như liệt kê (DIR cho directory - thư mục), xóa (ERA), đổi tên (REN), và hiển thị nội dung (TYPE). Bất kỳ cái tên nào mà CP/M thấy lạ thì nó sẽ mặc định coi đó là một chương trình đang lẩn đâu đó trên ổ đĩa.

CP/M cũng thủ sẵn một bộ sưu tập các chương trình con mà các chương trình khác có thể dùng để đọc từ bàn phím, ghi ký tự lên màn hình video, lưu dữ liệu vào một tệp trên đĩa, và tải nội dung của tệp đó ngược trở lại vào bộ nhớ.

Các chương trình chạy dưới CP/M không cần phải trực tiếp truy xuất vào phần cứng máy tính bởi vì mảng BDOS của CP/M đã dùng mảng BIOS để điều khiển phần cứng rồi. Điều này có nghĩa là một chương trình được viết cho CP/M có thể chạy trên bất kỳ chiếc máy tính nào chạy CP/M mà chẳng cần biết tí gì về phần cứng bên dưới. Đây là một nguyên lý được gọi là độc lập thiết bị (device independence), và nó cực kỳ sống còn đối với sự phát triển của phần mềm thương mại. Về sau, những chương trình kiểu vậy được biết đến rộng rãi với cái tên ứng dụng (application) hay app.

Một bộ sưu tập các chương trình con do một hệ điều hành cung cấp được biết đến với tên gọi là giao diện lập trình ứng dụng (application programming interface), hay API. Trong một thế giới lý tưởng, một gã lập trình viên viết chương trình ứng dụng chỉ cần biết mỗi API là đủ và chẳng cần quan tâm xem API đó được triển khai ra sao hay phần cứng mà nó truy cập là gì. Nhưng ở đời thực thì đôi khi có thêm chút kiến thức lại tỏ ra khá hữu ích.

Đối với người dùng máy tính, một hệ điều hành chính là giao diện người dùng (user interface), hay UI. Trong trường hợp của CP/M, đó là giao diện dòng lệnh (command-line interface - CLI) được triển khai bởi CCP. Còn đối với một lập trình viên, hệ điều hành đồng thời cũng là API—bộ sưu tập các chương trình con được dọn sẵn cho một chương trình ứng dụng xài.

Với CP/M, các chương trình con này có một điểm truy cập chung nằm ở vị trí 0005h trong bộ nhớ, và một chương trình sẽ gọi một trong những chương trình con này bằng cách thực hiện một lệnh gọi đến vị trí bộ nhớ đó:

CALL 0005h

Hoặc ngắn gọn là:

CALL 5

Được gọi là giao diện "Call 5"!

Một thủ tục cụ thể được chỉ định bởi giá trị của thanh ghi C. Dưới đây là vài ví dụ:

Thanh ghi C | Hàm CP/M Call 5
------------+----------------------------------------------------
01h         | Đầu vào bảng điều khiển (đọc một ký tự từ bàn phím)
------------+----------------------------------------------------
02h         | Đầu ra bảng điều khiển (ghi một ký tự lên màn hình)
------------+----------------------------------------------------
09h         | In Chuỗi (hiện một chuỗi ký tự)
------------+----------------------------------------------------
15h         | Mở Tệp (dùng một tệp có sẵn)
------------+----------------------------------------------------
16h         | Đóng Tệp (ngừng sử dụng một tệp)
------------+----------------------------------------------------
20h         | Đọc Tuần tự (đọc byte từ tệp)
------------+----------------------------------------------------
21h         | Ghi Tuần tự (ghi byte vào tệp)
------------+----------------------------------------------------
22h         | Tạo Tệp (tạo một tệp mới)

Đôi khi một trong những hàm này cần thêm thông tin. Ví dụ, khi C là 09h, cặp thanh ghi DE sẽ chứa địa chỉ của các ký tự ASCII để ghi ra màn hình. Dấu đô-la ($) được dùng làm mốc đánh dấu kết thúc chuỗi.

Vậy rốt cuộc CALL 5 thực sự làm gì? Vị trí bộ nhớ tại 0005h được CP/M dọn sẵn để chứa lệnh JMP, lệnh này nhảy đến vị trí bên trong mảng BDOS của CP/M, sau đó nó kiểm tra giá trị của thanh ghi C và nhảy tới đúng chương trình con thích hợp.

CP/M từng là một hệ điều hành cực kỳ ăn khách dành cho 8080 và đến nay vẫn giữ vị thế quan trọng trong lịch sử. CP/M chính là nguồn cảm hứng chính cho hệ điều hành 16-bit mang tên QDOS (Quick and Dirty Operating System - Hệ điều hành Nhanh và Lôm côm) được viết bởi Tim Paterson thuộc Seattle Computer Products dành cho chip 16-bit 8086 và 8088 của Intel. QDOS rốt cuộc được thay tên đổi họ thành 86-DOS và được tập đoàn Microsoft mua bản quyền. Dưới cái tên MS-DOS (Microsoft Disk Operating System), hệ điều hành này được cấp phép cho IBM xài trong chiếc IBM Personal Computer đầu tiên, ra mắt năm 1981. Mặc dù một phiên bản 16-bit của CP/M (gọi là CP/M-86) cũng đã góp mặt trên IBM PC, MS-DOS nhanh chóng vươn lên thành tiêu chuẩn. MS-DOS (được gọi là PC-DOS trên các máy tính của IBM) cũng được nhượng quyền cho các nhà sản xuất khác tạo ra những chiếc máy tính tương thích với IBM PC.

Đúng như tên gọi, MS-DOS về cơ bản là một hệ điều hành đĩa, Apple DOS cũng thế, được tạo ra năm 1978 cho Apple II. Chẳng có tính năng nào đáng kể được cung cấp ngoài việc ghi tệp vào đĩa, và sau đó đọc lại những tệp này.

Về mặt lý thuyết, các chương trình ứng dụng lẽ ra chỉ được phép chọc vào phần cứng của máy tính thông qua các giao diện do hệ điều hành cung cấp. Thế nhưng nhiều tay lập trình viên thập niên 1970 và 1980 lại thường xuyên vượt mặt hệ điều hành, đặc biệt là khi phải làm việc với màn hình hiển thị video. Những chương trình ghi trực tiếp các byte vào bộ nhớ màn hình video luôn chạy nhanh hơn hẳn những chương trình làm theo đúng quy trình. Thật vậy, đối với một số ứng dụng—như các ứng dụng cần hiển thị đồ họa trên màn hình video—hệ điều hành trở nên vô dụng hoàn toàn. Điều mà các lập trình viên khoái nhất ở mấy hệ điều hành đời đầu này là chúng biết điều "tránh sang một bên" và để cho các lập trình viên tha hồ viết các chương trình có thể chạy với tốc độ nhanh nhất mà phần cứng cho phép.

Chỉ báo đầu tiên cho thấy máy tính gia đình sẽ đi theo một hướng hoàn toàn khác so với những người anh em to xác và đắt đỏ của nó có lẽ chính là ứng dụng VisiCalc. Được thiết kế và lập trình bởi Dan Bricklin (sinh năm 1951) và Bob Frankston (sinh năm 1949) và ra mắt vào năm 1979 cho Apple II, VisiCalc đã dùng màn hình để cung cấp cho người dùng một cái nhìn hai chiều về một bảng tính (spreadsheet). Trước thời của VisiCalc, bảng tính chỉ là một tờ giấy khổ rộng chằng chịt các hàng và cột thường dùng để làm một chuỗi các tính toán. VisiCalc đã hất cẳng tờ giấy đó bằng màn hình video, cho phép người dùng lượn lờ quanh bảng tính, nhập số và công thức, và tính toán lại mọi thứ sau một thay đổi.

Điểm kỳ diệu về VisiCalc là nó là một ứng dụng không thể "đạo nhái" trên các máy tính lớn hơn. Một chương trình cỡ như VisiCalc cần phải update màn hình cực kỳ nhanh. Vì lý do này, nó đã ghi trực tiếp vào bộ nhớ truy cập ngẫu nhiên được dùng cho màn hình video của Apple II. Bộ nhớ này là một phần trong không gian địa chỉ của bộ vi xử lý. Đây hoàn toàn không phải là cách mà các máy tính lớn được thiết kế hay vận hành.

Máy tính phản hồi lại bàn phím và thay đổi màn hình video càng nhanh thì tương tác tiềm năng giữa người dùng và máy tính càng trở nên gắn kết. Phần lớn các phần mềm được viết trong thập kỷ đầu tiên của máy tính cá nhân (xuyên suốt những năm 1980) đều ghi trực tiếp vào bộ nhớ màn hình video. Vì IBM đã ban hành một tiêu chuẩn phần cứng mà các nhà sản xuất máy tính khác đều nhất mực tuân theo, các hãng sản xuất phần mềm hoàn toàn có thể qua mặt hệ điều hành và sử dụng thẳng phần cứng mà chẳng sợ chương trình của mình sẽ chạy chệch nhịp (hoặc tệ hơn là tịt ngòi) trên một số máy móc. Nếu tất cả đám PC xài một giao diện phần cứng khác nhau cho màn hình video của chúng, thì hẳn sẽ quá "khoai" cho các hãng làm phần mềm để có thể theo được tất thảy những thiết kế lai căng đó.

Nhưng khi ứng dụng bắt đầu mọc lên như nấm, hàng tá rắc rối cũng trồi lên theo. Những ứng dụng hốt bạc nhiều nhất thường độc chiếm toàn bộ màn hình và triển khai một UI tinh vi xoay quanh bàn phím. Nhưng mỗi ứng dụng lại khư khư một hệ tư tưởng riêng về UI, đồng nghĩa với việc những kỹ năng bạn đã học được trong ứng dụng này chẳng thể xài ở ứng dụng khác. Đám chương trình này cũng chẳng ưa gì chuyện sống chung hòa bình. Nhảy từ chương trình này sang chương trình nọ thường đồng nghĩa với việc phải thẳng tay "kết liễu" chương trình đang chạy rồi mới khởi động được chương trình tiếp theo.

Một tầm nhìn hoàn toàn khác về máy tính cá nhân đã và đang được thai nghén trong nhiều năm tại Trung tâm Nghiên cứu Palo Alto (PARC), trung tâm này được Xerox sáng lập vào năm 1970 một phần là để làm bệ phóng phát triển các sản phẩm cho phép công ty dấn chân vào ngành công nghiệp máy tính.

Dự án "khủng" đầu tiên tại PARC là cỗ máy Alto, được phác thảo và thi công vào năm 1972 và 1973. Chiếu theo các chuẩn mực của những năm đó, đây quả là một tuyệt tác ấn tượng. Khối hệ thống dạng tủ đứng này sở hữu sức mạnh xử lý 16-bit, hai ổ đĩa 3 MB, và 128 KB bộ nhớ (có khả năng cơi nới lên 512 KB). Alto ra đời trước cả khi các bộ vi xử lý 16-bit đơn chip kịp chào đời, thành thử bộ xử lý của nó phải được dựng từ đâu đó khoảng 200 mạch tích hợp.

Màn hình hiển thị video là một trong những khía cạnh đầy dị biệt của Alto. Kích thước và hình dáng của chiếc màn hình này hệt như một tờ giấy—rộng 8 inch và cao 10 inch. Nó "chạy" ở chế độ đồ họa với 606 pixel bề ngang và 808 pixel bề dọc, cho ra tổng số 489.648 pixel. Mỗi pixel được cấp phát hẳn 1 bit bộ nhớ, tức là mỗi pixel chỉ được chọn màu đen hoặc trắng. Tổng dung lượng bộ nhớ cho màn hình hiển thị video này là 64 KB, và nó là một phần trong không gian địa chỉ của bộ xử lý.

Chỉ bằng việc ghi dữ liệu thẳng vào bộ nhớ hiển thị video này, phần mềm có thể họa nên các bức tranh trên màn hình hay phô bày văn bản với đủ loại phông chữ và kích cỡ khác nhau. Thay vì biến màn hình video thành cái máy nhại lại văn bản được gõ từ bàn phím, màn hình đã lột xác thành một mảng thông tin hai chiều với mật độ cao và là một kênh đón nhận thao tác người dùng một cách trực tiếp hơn.

Chiếc máy Alto cũng "kết nạp" một món đồ chơi nhỏ xíu tên là chuột (mouse), nó trượt tới trượt lui trên mặt bàn và có ba nút. Đây là một phát minh của kỹ sư và nhà sáng chế Douglas Engelbart (1925–2013) trong thời gian tại Trung tâm Nghiên cứu Stanford. Bằng cách di con chuột trên mặt bàn, người dùng Alto có thể di dời một con trỏ trên màn hình và thao tác với các đối tượng hiển thị trên đó.

Quãng thời gian còn lại của những năm 1970, các chương trình được nhào nặn cho Alto đã phát triển một số bản sắc vô cùng thú vị. Đa chương trình đặt vào trong cửa sổ và hiển thị cùng lúc trên cùng một màn hình. Đồ họa video của Alto chắp cánh cho phần mềm thoát khỏi cái bóng tù túng của văn bản và thực sự phản chiếu chân thực trí tưởng tượng của người dùng. Các đối tượng đồ họa (như các nút bấm, menu và những bức ảnh nhỏ nhắn gọi là biểu tượng - icon) đã chính thức trở thành một mảnh ghép của giao diện người dùng. Chuột được dùng để chọn các cửa sổ hoặc kích hoạt các đối tượng đồ họa nhằm ra lệnh cho chương trình hoạt động.

Thứ phần mềm này đã vượt khỏi ranh giới của một giao diện người dùng để tiến tới sự thân mật người dùng, một thứ phần mềm đã tạo đòn bẩy vươn tầm máy tính sang những chân trời vượt xa việc nghiền ngẫm những con số khô khan, một loại phần mềm được thiết kế—nói theo tựa đề một bài báo do Douglas Engelbart chấp bút vào năm 1963—"để Khuếch đại Trí tuệ Con người" (for the Augmentation of Man’s Intellect).

Alto chính là phát súng mở màn cho giao diện người dùng đồ họa (graphical user interface), hay GUI, thường được phát âm là "gooey" (gu-ì), và phần lớn công lao cho những ý tưởng tiên phong này thuộc về Alan Kay (sinh năm 1940). Nhưng Xerox không bán Alto (nếu có thì bèo nhất một chiếc cũng ngót nghét hơn $30.000), và phải mất ròng rã hơn một thập kỷ trước khi những ý tưởng điên rồ trong chiếc Alto được tái sinh trong một sản phẩm tiêu dùng thành công rực rỡ.

Năm 1979, Steve Jobs và một biệt đội từ Apple Computer đã viếng thăm PARC và hoàn toàn bị choáng ngợp bởi những gì họ tận mắt chứng kiến. Nhưng họ cũng phải mất hơn ba năm để trình làng một chiếc máy tính có giao diện đồ họa. Đó chính là chiếc Apple Lisa yểu mệnh vào tháng 1 năm 1983. Tuy nhiên, đúng một năm sau, Apple đã cho ra lò chiếc Macintosh mang lại thành công vang dội hơn rất nhiều.

Chiếc Macintosh bản gốc được trang bị bộ vi xử lý Motorola 68000, 64 KB ROM chứa hệ điều hành, 128 KB RAM, một ổ đĩa mềm 3.5-inch (có sức chứa 400 KB mỗi đĩa), một bàn phím, một con chuột, và một màn hình hiển thị video có khả năng phô diễn 512 pixel ngang nhân với 342 pixel dọc. (Bản thân chiếc màn hình chỉ lớn cỡ 9 inch tính theo đường chéo.) Cho ra tổng cộng 175.104 pixel. Mỗi pixel được ghim với 1 bit bộ nhớ và chỉ có hai màu đen hoặc trắng, vì vậy cần tiêu tốn chừng 22 KB cho RAM màn hình video.

Phần cứng của chiếc Macintosh sơ khai mang dáng vẻ thanh lịch nhưng khó có thể gọi là một cuộc cách mạng. Điều làm cho chiếc Mac trở nên khác biệt hoàn toàn so với những chiếc máy tính đang nhan nhản trên thị trường năm 1984 chính là hệ điều hành Macintosh, ở thời điểm đó thường được biết đến với tên gọi là phần mềm hệ thống (system software) và về sau được gọi là Mac OS, và hiện tại là macOS.

Một hệ điều hành đơn người dùng dựa trên nền tảng văn bản như CP/M hay MS-DOS hoặc Apple DOS thì dung lượng chẳng đáng là bao, và hầu hết API chỉ làm mỗi việc là hỗ trợ hệ thống tệp. Ngược lại, một hệ điều hành đồ họa tầm cỡ macOS thì cồng kềnh hơn nhiều và ôm trong mình hàng trăm hàm API. Mỗi hàm trong số đó được nhận diện bằng một cái tên phác họa đúng bản chất công việc mà hàm đó thực thi.

Trong khi một hệ điều hành dựa trên văn bản như MS-DOS chỉ cung cấp vài hàm API đơn giản cho phép các chương trình ứng dụng hiển thị văn bản lên màn hình theo phong cách của máy đánh chữ, thì một hệ điều hành đồ họa như macOS buộc phải bày ra cách thức để các chương trình có thể hiển thị đồ họa lên màn hình. Về lý thuyết, điều này có thể hoàn thành bằng cách triển khai một hàm API duy nhất cho phép một ứng dụng tô màu của một pixel tại một tọa độ ngang và dọc nhất định. Nhưng hóa ra cách này lại không hiệu quả và cho ra đồ họa chậm lắm.

Sẽ hợp lý hơn nếu hệ điều hành cung cấp trọn bộ một hệ thống lập trình đồ họa hoàn chỉnh, nghĩa là hệ điều hành gồm luôn các hàm API để vẽ đường thẳng, hình chữ nhật, đường cong và cả văn bản. Đường có thể là nét liền, nét đứt hoặc nét chấm. Hình chữ nhật và hình elip có thể được lấp đầy bằng đủ thể loại hoa văn. Văn bản có thể hiện ra với đủ các kiểu phông chữ, kích cỡ và kèm theo các hiệu ứng tô đậm hay gạch chân. Hệ thống đồ họa sẽ chịu trách nhiệm quyết định xem làm thế nào để "render" (kết xuất) các đối tượng đồ họa này thành một mớ các chấm trên màn hình.

Các chương trình chạy dưới hệ điều hành đồ họa sẽ tận dụng chính các API đó để vẽ đồ họa lên cả màn hình video của máy tính và máy in. Nhờ đó, một ứng dụng xử lý văn bản có thể hiển thị một tài liệu lên màn hình sao cho nó trông gần như là bản sao của tài liệu khi được đem đi in, một tính năng tên gọi WYSIWYG (phát âm là wiz-zy-wig). Đây là viết tắt của cụm "What you see is what you get" (Thấy gì được nấy), một câu nói để đời "đóng góp" vào từ điển máy tính bởi danh hài Flip Wilson trong vai diễn Geraldine của ông.

Một phần sức hút của giao diện người dùng đồ họa nằm ở chỗ các ứng dụng khác nhau đều mang những bộ UI na ná nhau và dựa dẫm vào thói quen trải nghiệm của người dùng. Điều này có nghĩa là hệ điều hành cũng phải hỗ trợ cho các hàm API để ứng dụng triển khai các thành phần khác nhau của giao diện người dùng, như nút bấm và menu. Mặc dù GUI nhìn chung được ca tụng là một môi trường dễ dàng cho người dùng, nhưng quan trọng không kém, nó còn là một mảnh đất màu mỡ hơn cho các lập trình viên. Các lập trình viên có thể phát triển một giao diện người dùng hiện đại mà không phải "phát minh lại bánh xe".

Thậm chí từ trước khi Macintosh ra đời, một vài tập đoàn đã âm thầm tạo một hệ điều hành đồ họa dành cho IBM PC và các dòng máy tương thích. Ở một góc độ nào đó, nhóm phát triển của Apple thuận lợi hơn vì họ được toàn quyền nhào nặn cả phần cứng lẫn phần mềm cùng lúc. Phần mềm hệ thống Macintosh chỉ phải hỗ trợ đúng một loại ổ đĩa mềm, một loại màn hình video, và hai mẫu máy in. Tuy nhiên, triển khai một hệ điều hành đồ họa cho PC lại đòi hỏi hỗ trợ cả một mớ phần cứng khác nhau.

Hơn thế nữa, dù cho chiếc IBM PC mới chỉ được ra mắt vài năm trước đó (vào năm 1981), đông đảo bà con đã kịp quen dùng ứng dụng MS-DOS ưa thích của mình và chẳng đời nào chịu bỏ chúng. Do đó, một yêu cầu mang tính sống còn đối với một hệ điều hành đồ họa cho PC là nó phải chạy được cả các ứng dụng MS-DOS lẫn những ứng dụng được dành riêng cho hệ điều hành mới. (Chiếc Macintosh từ chối chạy phần mềm của Apple II, nguyên do là vì nó xài một bộ vi xử lý khác.)

Năm 1985, Digital Research (tác giả của CP/M) đã giới thiệu GEM (Graphical Environment Manager), VisiCorp (công ty bán VisiCalc) tung ra VisiOn, và Microsoft phát hành Windows phiên bản 1.0, nó nhanh chóng được cộng đồng mạng nhắm là ứng cử viên cho ngôi vương trong cuộc "chiến tranh cửa sổ". Nhưng phải đợi đến đợt phát hành Windows 3.0 vào tháng 5 năm 1990 thì Windows mới bắt đầu quyến rũ được một lượng lớn người dùng, để rồi cuối cùng trở thành hệ điều hành thống trị cả máy tính để bàn và laptop. Bất chấp ngoại hình bề ngoài na ná nhau của Macintosh và Windows, các API dành cho hai hệ thống này lại khác nhau một trời một vực.

Dù vậy, điện thoại và máy tính bảng lại là một câu chuyện khác. Mặc dù có những nét tương đồng trong giao diện đồ họa của điện thoại, máy tính bảng và các máy tính cá nhân lớn hơn, các API này cũng lại chẳng ăn nhập gì với nhau. Hiện tại, thị trường điện thoại và máy tính bảng đang bị thống trị bởi những hệ điều hành được tạo từ Android và Apple.

Mặc dù không quá rõ ràng với hầu hết người dùng máy tính, nhưng di sản và tầm ảnh hưởng của hệ điều hành UNIX vẫn luôn duy trì một sự hiện diện cực kỳ mạnh mẽ. UNIX được phát triển vào đầu những năm 1970 tại Bell Telephone Laboratories, chủ yếu dưới bàn tay của Ken Thompson (sinh năm 1943) và Dennis Ritchie (1941–2011), hai dị nhân sở hữu những bộ râu xịn xò nhất nhì ngành công nghiệp máy tính. Cái tên ngộ nghĩnh của hệ điều hành này thực chất là một trò chơi chữ: UNIX ban đầu được viết như một phiên bản "còi xương" hơn của một hệ điều hành đàn anh tên là Multics (viết tắt của Multiplexed Information and Computing Services), mà Bell Labs đã và đang phát triển cùng với MIT và GE.

Trong giới lập trình viên cộm cán, UNIX chính là "con cưng" được tôn thờ nhất mọi thời đại. Trong khi hầu hết các hệ điều hành đều bị "đóng đinh" cho những dòng máy tính cụ thể, UNIX lại được thiết kế để có tính "di động" (portable), điều này đồng nghĩa với việc nó có thể được chế lại để chạy trên đủ mọi thể loại máy tính.

Bell Labs là một công ty con của American Telephone & Telegraph (AT&T) vào thời điểm UNIX được ấp ủ, và do đó bị trói buộc bởi các phán quyết của tòa án nhằm kìm hãm vị thế độc quyền của AT&T trong ngành điện thoại. Theo như bản án ban đầu, AT&T bị cấm tiệt việc tiếp thị UNIX; thay vào đó, công ty bị ép phải nhượng quyền cho những kẻ khác. Bắt đầu từ năm 1973, UNIX được nhượng quyền ồ ạt cho các trường đại học, tập đoàn, và cả chính phủ. Tới năm 1983, AT&T cuối cùng cũng được cho phép quay lại chốn thương trường máy tính và đã phát hành phiên bản UNIX của riêng mình.

Hậu quả là, chẳng tồn tại thứ gọi là một phiên bản UNIX "duy nhất". Thay vào đó, nó "phân thân" ra nhiều phiên bản với các tên gọi khác nhau, chạy trên đủ loại máy tính do các nhà cung cấp khác nhau rao bán. Vô số kẻ đã thọc tay vào UNIX và để lại "dấu vân tay" của mình ở lại. Tuy nhiên, vẫn có một "triết lý UNIX" thường trực dẫn dắt mọi người mỗi khi họ muốn đắp thêm vào UNIX. Một mảng của triết lý đó là dùng tệp văn bản (text files) như một mẫu số chung. Rất nhiều những chương trình dòng lệnh bé bé xinh xinh của UNIX (được gọi là tiện ích - utilities) đọc tệp văn bản, nhào nặn chúng một chút, rồi lại viết ra một tệp văn bản khác. Các tiện ích của UNIX có thể được nối nhau thành những chuỗi dài để thực thi đủ kiểu xử lý khác nhau trên mớ tệp văn bản này.

Cú chuyển mình li kỳ nhất đối với UNIX trong vài năm trở lại đây chính là sự trỗi dậy của Tổ chức Phần mềm Tự do (Free Software Foundation - FSF) và dự án GNU, cả hai đều được thai nghén bởi Richard Stallman (sinh năm 1953). GNU (phát âm không giống như tên con vật linh dương đầu bò mà thay vào đó chữ G ở đầu được phát âm rõ ràng) là viết tắt đệ quy của "GNU’s Not UNIX" (GNU không phải là UNIX), và hiển nhiên là không phải rồi. Thay vào đó, GNU định hướng trở nên tương thích với UNIX nhưng lại được phân bổ theo một phong cách ngăn ngừa phần mềm bị độc quyền hóa. Dự án GNU đã sinh ra vô số các tiện ích và công cụ tương thích với UNIX, và dĩ nhiên là cả Linux, là phần lõi (hay hạt nhân - kernel) của một hệ điều hành tương thích với UNIX.

Được viết phần lớn bởi một lập trình viên người Phần Lan tên là Linus Torvalds (sinh năm 1969), Linux đã lan toả mạnh mẽ trong những năm gần đây. Hệ điều hành Android dựa trên bộ lõi Linux, siêu máy tính thì dùng độc mỗi Linux, và Linux cũng khá phổ biến trên các máy chủ (servers) internet.

Nhưng internet là chủ đề cho chương cuối cùng của cuốn sách này.
Cảm ơn bạn đã đọc bài.
0

Thảo luận trên Bluesky

Đi

Đang tải bình luận...

Powered by Bluesky AT Protocol