Trong việc quản lý bộ nhớ phải giải quyết hai vấn đề trái ngược:
Tận dụng tối đa bộ nhớ cho phép để giảm độ phức tạp của giải thuật,
Tiết kiệm bộ nhớ để tạo môi trường cho các chương trình khác cùng hoạt động.
Mỗi chương trình đều cần bộ nhớ cho 2 loại thông tin khác nhau:
Vùng bộ nhớ để lưu trữ chương trình,
Vùng bộ nhớ lưu trữ dữ liệu cần thiết cho việc xử lý.
Nếu như để quản lý vùng bộ nhớ dành cho dữ liệu người ta chỉ cần biết điểm đầu và kích thước vùng bộ nhớ được phân phối là đủ thì quản lý và tổ chức dữ liệu cho vùng bộ nhớ dành cho chương trình phức tạp hơn nhiều. Lưu ý rằng đối với quản lý bộ nhớ mọi thông tin ghi vào đó đều là dữ liệu, chỉ có khác biệt đó là dữ liệu câu lệnh (program codes) hay dữ liệu phục vụ tính giá trị các loại biểu thức (data). Loại dữ liệu thứ 2 không thay đổi dù ta ghi nó ở nơi nào trong bộ nhớ, còn loại dữ liệu thứ nhất nói chung có nội dung phụ thuộc vào địa chỉ đầu của khối bộ nhớ chứa nó. Chính vì vậy nội dung các phần sẽ xét dưới đây chủ yếu xoay quanh việc quản lý bộ nhớ dành cho chương trình.
Ngày nay phần lớn các chương trình được viết trên các ngôn ngữ lập trình như Java, C++, Visual Basic, Pascal hay Macro Assembler, . . . Người lập trình
Nội dung của Bài IV là xét các phương pháp quản lý bộ nhớ
lô gic và bộ nhớ vật lý, cách xác lập quan hệ giữa hai loại bộ nhớ này, các kỹ thuật phân phối lại bộ nhớ và bảo vệ thông tin.
Hình 4.1. Các phép ánh xạ nhiệm vụ quản lý
khai báo các biến và nêu quy trình xử lý nội dung của các biến đó. Trên thực tế chương trình là một bảng ánh xạ từ tên sang giá trị. Việc ánh xạ xẩy ra khi thực hiện chương trình. Các hệ thống lập trình cung cấp các phương tiện để người lập trình có thể theo dõi quá trình ánh xạ này ở các mức độ chi tiết khác nhau.
Đối với máy tính điện tử chỉ có ánh xạ từ địa chỉ sang giá trị. Trước khi thực hiện chương trình các tên phải được ánh xạ sang địa chỉ.
Nhiệm vụ quản lý bộ nhớ là giải quyết các vấn đề liên quan ánh xạ từ tên sang địa chỉ và sự thay đổi ánh xạ này trong các tình huống khác nhau.
Như vậy để xem xét và giải quyết các vấn đề về quản lý bộ nhớ việc đầu tiên phải làm là khảo sát quá trình hệ thống xử lý một chương trình và các môi trường tồn tại của các đối tượng liên quan.
4.1 – Các bước xử lý chương trình
Khi có một chương trình nguồn việc đầu tiên hệ thống làm là kiểm tra cú pháp (Syntax Analys) xem chương đã viết đúng quy tắc của ngôn ngữ lập trình hay không và thông báo nếu có lỗi.
Với một chương trình đã sạch lỗi cú pháp hệ thống sẽ tiến hành phân tích ngữ nghĩa (Semantic Analys).Một trong những công việc quan trọng ở giai đoạn này là tách các tên do người sử dụng đặt, chuẩn hóa chúng thành tên trong và tạo bảng tên với các thuộc tính cho biết kiểu dữ liệu ứng với tên, bộ nhớ cần thiết và các phép tính có thể áp dụng đối với nó. Nhóm công cụ thực hiện công việc này được gọi chung là Hàm tên.
Dựa vào bảng tên hệ thống xây dựng bản đồ bộ nhớ cho các biến, tiến hành phân tích các câu lệnh, thay tên bằng địa chỉ, thay phép tính bằng mã phép tính và được một mô đun chương trình trên ngôn ngữ máy. Nhóm công cụ thực hiện các
Hình 4.2. Các bước xử lý chương trình.
công việc này có tên chung là Hàm địa chỉ. Sản phẩm của hàm địa chỉ là Mô đun đích – một file chương trình thông thường có đuôi .OBJ.
Mô đun đích không còn phụ thuộc vào ngôn ngữ dùng để viết chương trình nguồn. Nhưng nó chưa phải là một chương trình hoàn thiện vì còn thiếu nhiều thông tin liên quan tới các mô đun khác mà nó tham chiếu và sử dụng (các hằng ngoài, các chương trình con thư viện, . . .). Những thông tin còn thiếu này được gọi
là các móc nối ngoài.
Việc tạo mô đun đích bao gồm các trình sinh mã và tối ưu hóa chương trình nhận được.
Toàn bộ quá trình xử lý chương trình nguồn cho tới khi nhận được mô đun đích do chương trình dịch đảm nhiệm.
Về nguyên tắc, sau khi nhận được mô đun đích các công việc còn lại không phụ thuộc vào chương trình dịch. Tuy nhiên, để thuận tiện khai thác, các hệ thống lập trình thường đảm nhiệm luôn xử lý khâu biên tập để có một chương trình độc lập hoàn thiện. Đó là khâu xử lý các móc nối ngoài. Một mô đun, sau khi đã được biên tập có thể tham gia vào quá trình biên tập các mô đun khác. Sản phẩm của biên tập là chương trình hoàn thiện với file chương trình đuôi .COM hoặc .EXE. Tuy nhiên đây chỉ là khâu tạo chương trình. Chương trình nhận được chỉ là đầu ra của biên tập, chưa gắn với môi trường cụ thể để thực hiện. Vì vậy chương trình được xây dựng như chỉ có một mình nó trong bộ nhớ, được ghi từ đầu bộ nhớ và lưu trữ ở bộ nhớ ngoài. Để thực hiện nó, hệ thống cần phân phối bộ nhớ trong, nạp chương trình vào vùng bộ nhớ đã được phân phối, sửa lại các địa chỉ trong các câu lệnh của chương trình để tạo ra một phiên bản làm việc phù hợp với vùng bộ nhớ chứa chương trình. Đây là việc Nạp và định vị do thành phần FETCH của hệ thống đảm nhiệm.
Quá trình quản lý bộ nhớ bao trùm lên các khâu xử lý, từ biên tập đến hết khâu thực hiện chương trình.
Việc thực hiện chương trình còn liên quan tới các vấn đề về tiến trình và hoạt động của processor. Những vấn đề này sẽ được xét ở các chương sau.
Như vậy việc xử lý một chương trình liên quan tới 3 không gian: Không gian tên, Không gian bộ nhớ lô gic và không gian bộ nhớ vật lý.
Với các không gian bộ nhớ có 3 nhóm vấn đề phải giải quyết:
Cách quản lý bộ nhớ lô gic,
Cách quản lý bộ nhớ vật lý,
Cách xác lập quan hệ giữa 2 bộ nhớ: như thế nào và khi nào?
Mỗi cách giải quyết vấn đề sẽ đưa tới một cách quản lý bộ nhớ và một phạm
vi ứng dụng hiệu quả trong điều kiện môi trường nhất định.
4.2 – Cấu trúc chương trình
Bộ nhớ lô gic dùng để chứa chương trình và ở mỗi thời điểm chỉ chứa một chương trình. Chính vì vậy có thể đồng nhất cách tổ chức bộ nhớ lô gic với cách tổ chức chương trình. Mỗi cách tổ chức chương trình sẽ tương ứng với một cấu trúc. Tồn tại nhiều loại cấu trúc chương trình khác nhau và mọi cấu trúc đều đang được
sử dụng trong thực tế.
4.2.1 – Cấu trúc tuyến tính
Khi xây dựng chương trình theo cấu trúc tuyến tính chương trình biên tập sẽ tìm tất cả các mô đun cần thiết cho việc thực hiện chương trình, kết nối chúng thành một file chương trình duy nhất.
Tổ chức bộ nhớ lô gic?
Tổ chức bộ nhớ vật lý?
Xác lập quan hệ:
Như thế nào?
Khi nào?
Tổ chức bộ nhớ lô gic?
Tổ chức bộ nhớ vật lý?
Xác lập quan hệ:
Như thế nào?
Khi nào?
Hình 4.3. Các vấn đề cần giải quyết.
Đây là loại cấu trúc thường dùng nhất đối với các chương trình ứng dụng kích thước nhỏ.
Cấu trúc tuyến tính có các đặc điểm:
Đơn giản và dễ quản lý: Toàn bộ chương trình là một file, công việc lưu trữ, tìm kiếm, bảo vệ đều do hệ thống quản lý file đảm nhiệm,
Thời gian thực hiện nhanh nhất: Tất cả các thông tin cần thiết đều được lưu
trữ trong file, sau khi nạp và định vị, hệ thống không mất thời gian tìm kiếm thông tin phụ, việc nạp và định vị cũng chỉ phải thực hiện một lần trước khi thực hiện chương trình,
Có tính lưu động (mobilable) cao: Dễ dàng di chuyển cài đặt sang các hệ thống khác, dễ dàng xóa khi không còn cần dùng, việc cập nhật nâng cấp đơn thuần là sao file mới ghi đè lên file hiện có,
Tốn bộ nhớ: Với mỗi bộ dữ liệu thông thường chỉ có từ 13% đến 17% các câu lệnh trong chương trình đóng vai trò tích cực, tức là có tham gia vào việc xử lý dữ liệu,
Không cho phép khả năng dùng chung mô đun: Một mô đun nếu tham gia vào nhiều chương trình thì sẽ được lưu trữ nhiều lần cả ở bộ nhớ trong lẫn ở
bộ nhớ ngoài.
4.2.2 – Cấu trúc động (Dynamic Structure)
Sử dụng cấu trúc này người lập trình phải chủ động đưa ra các lệnh nạp và định vị mô đun khi cần thiết và xóa khỏi bộ nhớ mô đun không còn cần dùng. Việc nạp và xóa mô đun được tiến hành trong giai đoạn thực hiện chương trình. Hệ thống cung cấp một loạt các lệnh macro hỗ trợ như LOAD, ATTACH, DELETE, . . . Mỗi lệnh macro có nhiều tham số với các chế độ hoạt động khác nhau, ví dụ như lệnh LOAD có thể đơn thuần nạp và định vị mô đun vào trong bộ nhớ, nhưng cũng
có tham số cho phép nạp, định vị mô đun vào trong bộ nhớ và tự động xóa khỏi bộ nhớ mô đun này sau lần gọi mô đun thứ n.
Cấu trúc động có các ưu và nhược điểm sau:
Hình 4.4. Cấu trúc tuyến tính
Tiết kiệm bộ nhớ: Nếu tổ chức nạp và xóa mô đun một cách hợp lý có thể
cực tiểu hóa chi phí bộ nhớ cần thiết cho việc thực hiện chương trình,
Thời gian thực hiện chương trình
tăng: Công việc tìm kiếm, nạp,
định vị và xóa mô đun được tiến
hành trong thời gian thực hiện
chương trình,
Người lập trình phải tham gia vào
công tác quản lý bộ nhớ: Người
lập trình phải biết các lệnh macro
hệ thống để điều khiển quá trình
nạp – xóa mô đun, đây là một yêu
cầu rất khắt khe với người dùng,
đồng thời cấu trúc chung của
chương trình cũng trở nên phức
tạp hơn đòi hỏi người lập trình phải có tay nghề cao,
Kém lưu động: Khó có thể chuyển chương trình từ máy này sang máy khác
vì ngoài mô đun chính (mô đun gốc) còn phải mang theo và cài đặt đúng chỗ các mô đun có thể được nạp trong quá trình điều khiển động. Điều này cũng
là cho việc xóa hoặc cập nhật, nâng cấp chương trình trở nên rất khó khăn.
Cấu trúc động rất thích hợp với các chương trình hệ thống vì một trong những yêu cầu quan trọng đối với các chương trình hệ thống là tiết kiệm bộ nhớ dành cho
hệ thống. Với những người lập trình hệ thống việc tham gia quản lý bộ nhớ không phải là rào cản.
4.2.3 – Cấu trúc Overlay
Cấu trúc Overlay là cơ chế phân phối động các mô dun theo sơ đồ bộ nhớ tĩnh. Hiệu quả tiết kiệm bộ nhớ bị giảm sút một phần so với cấu trúc động thuận tiện hơn nhiều đối với người lập trình.Các mô đun được phân thành các lớp, mỗi lớp bao gồm các mô đun không cần tồn đồng thời trong quá trình thực hiện chương trình. Lớp 0 chỉ chứa mô đun gốc. Lớp i chứa các các mô đun được gọi từ lớp i-1
và không cần tồn tại đồng thời (i = 1, 2, 3, . . .). Thông tin cho biết mỗi lớp chứa những mô đun nào được gọi là Sơ đồ tổ chức Overlay. Sơ đồ này do người lập trình xây dựng và cung cấp cho chương trình biên tập. Như vậy sơ đồ tổ chức overlay là dữ liệu phục vụ biên tập và nằm ngoài chương trình nguồn. Sơ đồ này thông thường có dạng như mô tả cây bằng danh sách đỉnh kề. Dựa trên sơ đồ tổ
Hình 4.5. Cấu trúc động.
chức overlay chương trình biên tập sẽ tạo bản đồ nạp mô đun. Bộ nhớ dành cho chương trình được chia thành các phần (hoặc còn gọi là mức), đánh số từ 0 trở đi. Phần bộ nhớ thứ i dùng để nạp mô đun ở mức i và có kích thước bằng kích thước
mô đun lớn nhất của mức này. Chương trình biên tập sẽ tạo ra Sơ đồ quản lý
Overlay. Đó là bảng thông tin cho biết mô đun đã được cần phải nạp vào đâu và đã
được nạp vào bộ nhớ hay chưa. Mỗi khi có lời gọi tới mô đun chương trình
Supervisor Overlay của hệ thống sẽ kiểm tra sự tồn tại của mô đun được gọi trong
bộ nhớ và sẽ tiến hành nạp, định vị mô đun này khi cần thiết. Mô đun được nạp sẽ nằm đè lên mô đun cùng mức trước đó. Chính vì vậy trong cấu trúc overlay việc 2
mô đun cùng mức trực tiếp gọi nhau bị cấm.
Tương tự như cấu trúc động, các mô đun từ mức 1 trở đi được tập trung vào một hoặc một vài file có đuôi là .OVL.
Các phần mềm ứng dụng như PCSHELL, XTREE, các hệ quản trị Cơ sở dữ liệu FOXBASE, DATA BASE II (DB II), FOXPRO, . . . đều dựa trên chương trình
có cấu trúc overlay.
4.2.4 – Cấu trúc mô đun
Cấu trúc overlay đã đơn giản hóa phần nào công việc của người lập trình nhưng người dùng vẫn phải khai báo Sơ đồ tổ chức Overlay. Hơn thế nữa khi bộ nhớ tự do còn nhiều cấu trúc này không cho phép tận dụng lợi thế đó để nâng cao hiệu quả thực hiện chương trình. Cấu trúc mô đun đã giải quyết những vấn đề này.
Hình 4.7. Cấu trúc Overlay.
Chương trình biên tập sẽ biên tập riêng từng mô đun, tạo bảng quản lý mô đun để khi cần sử dụng có thể nạp mô đun này vào nơi bất kỳ trong bộ nhớ.
Cấu trúc này có ưu và nhược điểm sau:
Được tự động hóa hoàn toàn: Người lập trình không tham gia vào quá trình điều khiển và không cần phải cung cấp bất cứ một thông tin phụ nào,
Tốc độ thực hiện chương trình tăng khi dung lượng bộ nhớ tự do tăng: Với
dung lượng bộ nhớ tự do đủ lớn, sau một thời gian hoạt động tốc độ thực hiện chương trình sẽ tương đương với tốc độ thực hiện của chương trình có cấu trúc tuyến tính,
Dễ dàng sử dụng chung mô đun: Mỗi mô đun khác nhau chỉ cần lưu trữ một
lần ở bộ nhớ ngoài và chỉ cần nạp một lần vào bộ nhớ trong,
Hiệu quả của cấu trúc phụ thuộc vào chương trình nguồn: Nếu người lập
trình không tổ chức hệ thống mô đun hợp lý thì hiệu quả của cấu trúc có thể
bị giảm sút đáng kể.
Hình 4.8. Cấu trúc mô đun.
4.2.5 – Cấu trúc phân trang
Ở cấu trúc này chương trình được biên tập như chương trình tuyến tính, sau
đó chia chương trình thành các phần bằng nhau gọi là trang (page) và tạo bảng quản lý trang.
Khi thực hiện chương trình, cần dùng tới trang nào, nếu chưa có trong bộ nhớ trang đó sẽ được nạp và định vị vào bộ nhớ trong.
Đây là một cấu trúc hết sức tiết kiệm bộ nhớ và cũng giống như cấu trúc mô
đun, được thực hiện tự động, không có sự can thiệp của người lập trình. Ngoài ra, hiệu quả của nó không bị phụ thuộc vào cấu trúc của chương trình nguồn.
Tuy vậy nó cũng có một số nhược điểm:
Không cho phép sử dụng chung mô đun,
Việc báo lỗi khi thực hiện chương trình sẽ kém tường minh vì không thể chỉ
rõ lỗi xẩy ra ở mô đun nào,
Cần phải có một số phương tiện kỹ thuật nhất định mới có thể triển khai có
hiệu quả (điều này sẽ được nói rõ hơn ở phần quản lý bộ nhớ vật lý).
4. 3 – Quản lý bộ nhớ vật lý
Bộ nhớ vật lý là bộ nhớ trong (RAM) được lắp ở một máy tính cụ thể. Kích thước bộ nhớ trong rất ít khi thay đổi trừ khi người ta lắp thêm hoặc tháo bớt các thanh chíp bộ nhớ. Như vậy, với một cấu hình cụ thể bộ nhớ trong của máy tính có
kích thước không đổi. Một phần của bộ nhớ được dùng để lưu trữ các chương trình
và dữ liệu của hệ thống, một phần khác – phục vụ các chương trình ứng dụng đang được kích hoạt. Phần bộ nhớ còn lại sẽ thường xuyên thay đổi phụ thuộc vào các
ứng dụng được thực hiện.
Hình 4.9. Cấu trúc phân trang.
Bộ nhớ trong dùng để thực hiện chương trình, vì vậy bên cạnh bộ nhớ dành cho chương trình hệ thống còn phải cấp phát bộ nhớ phục vụ lưu trữ dữ liệu, đồng thời phải có các giải pháp bảo vệ thông tin, không để một chương trình đọc thông
tin của chương trình khác, xóa hoặc làm thay đổi nội dung của những thông tin này (nếu không được sự đồng ý của người chủ thông tin).
Như vậy các vấn đề chính trong quản lý bộ nhớ vật lý là:
Các cách tổ chức bộ nhớ,
Sơ đồ bảo vệ thông tin,
Cách xác lập quan hệ với bộ nhớ lô gic và thời điểm xác lập quan hệ,
Phải xử lý như thế nào khi thiếu bộ nhớ.
Tình trạng thiếu bộ nhớ xẩy ra khá thường xuyên mặc dù ngày nay các máy tính đều có bộ nhớ đủ lớn. Tuy vậy các chiến lược xử lý tình huống thiếu bộ nhớ là
đủ tốt và làm cho việc thiếu bộ nhớ trở nên trong suốt đối với người dùng.
Có nhiều chế độ quản lý khác nhau và mọi chế độ quản lý đều được ứng dụng trong thực tế.
4.3.1 – Chế độ phân vùng cố định
Ở chế độ này bộ nhớ được chia thành n phần, mỗi phần có kích thước cố định (không nhất thiết bằng nhau), được quản lý như một bộ nhớ độc lập và được dùng
để chạy một chương trình ứng dụng.