Chuyện gì xảy ra khi bạn chạy một chương trình
Chuyện gì xảy ra khi bạn chạy một chương trình
(Bài
viết này chỉ dành cho các bạn học lập trình và mong muốn hiểu rõ hơn về cách chương
trình của mình vận hành. Nếu bạn là người ngoại đạo và vẫn muốn tiếp tục xem,
thì xin mời )
Về tổng quan, khi bạn chạy chương trình
(program), chương trình sẽ được nạp vào trong bộ nhớ chính và chờ thực thi. Lúc
này, chương trình được gọi là tiến trình (process). Process chờ một khoảng thời
gian cho đến khi nó được lựa chọn vào trong processor để thực thi (quá trình lựa
chọn gọi là short-term scheduler). Đây là quá trình sơ bộ, nhưng ở đây mình sẽ phân
tích kỹ hơn một chút.
Khi bạn thực thi một chương trình, nó sẽ nạp theo một
cấu trúc nhất định. Với mỗi hệ điều hành khác nhau thì cấu trúc sẽ khác nhau,
nhưng về mặt trừu tượng, nó sẽ có dạng như sau.
Stack: Vùng lưu trữ các
biến cục bộ, các giá trị trả về, địa chỉ trả về,… Sử dụng cấu trúc LIFO. Các
thao tác trên stack thường thông qua push và pop (nhưng vẫn có thể
truy cập ngẫu nhiên – truy cập tại vị trí bất kỳ)
Heap: Vùng lưu trữ các object
(Java), có thể truy cập ngẫu nhiên
Data: Vùng lưu trữ các
giá trị static, các biến cục bộ,…
Text: Đây là nơi chứa đoạn
code chương trình, nơi processor truy cập để thực thi chương trình
*Phần
khoảng trắng gọi là hole, là nơi mà stack và heap phát triển (mở rộng) (stack
phát triển đi xuống, heap phát triển đi lên).
Đây chỉ là bộ nhớ về mặt ý tưởng, tức là, dữ liệu thực
tế được lưu trữ có thể không giống cấu trúc trên. Để hiểu hơn về virtual
memory, tìm kiếm từ khóa đấy trên Wiki.
Ta sẽ lấy ví dụ để hiểu rõ cách bộ nhớ lưu trữ.
Đầu tiên, khi chạy chương trình, process sẽ được đưa vào
trong RAM, còn phần code sẽ được nạp vào trong vùng TEXT. Process này sẽ đợi 1
thời gian trước khi được thực thi. Khi đến lượt, process sẽ thực thi một khoảng
thời gian nhất định rồi sẽ trở lại hàng chờ (nếu process vẫn chưa thực thi hết,
hoặc chờ I/O), hoặc kết thúc (nếu process đã hoàn thành hết nhiệm vụ). Trong quá
trình thực thi, cấu trúc của process sẽ thay đổi như sau
1. Đầu
tiên, a có giá trị 5 và b có giá trị 8 sẽ được nạp vào trong vùng
stack.
2. Tiếp
đó, các tham biến a, b (Ở đây a, b dưới là các biến thuộc hàm
mul() ) và được tạo ra. Biến c được tạo ra, và ngoài ra còn tạo ra 2 ô
nhớ 5 và 6.
· Ô
5: Lưu trữ giá trị trả về của hàm mul()
· Ô
6: Lưu trữ địa chỉ trả về (return address) thể hiện vị trí để hàm mul() đưa
giá trị trả về.
3. Giá
trị trong 2 biến a, b được nạp vào processor. Processor thực hiện
tính toán, sau đó trả về giá trị đã tính về return value.
4. Kết
quả thông qua return address tại ô 6, trả giá trị về ô c. Sau đó,
dữ liệu thuộc hàm mul() bị pop ra khỏi vùng nhớ, trả lại vùng nhớ cho máy tính.
Và đó chính là quá trình một process thực thi, hay nói
cách khác là quá trình hoạt động của một chương trình. Còn rất nhiều thứ liên
quan đến process như quá trình process lựa chọn để được cấp phát processor, hay
cách các process lưu trữ trên bộ nhớ chính, là một lượng kiến thức khổng lồ, không
thể viết gọn trong một bài được. Hãy cùng mình từ từ khám phá nhé!
Nội dung bài viết thuộc về Lê Công Diễn.
Người viết: Lê Công Diễn
Mang đi nhớ ghi nguồn
Nhận xét
Đăng nhận xét