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 pushpop (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ớ 56.
·       Ô 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

Bài đăng phổ biến từ blog này

Deploy project Springboot MIỄN PHÍ sử dụng Render

Ứng dụng Mã hóa bất đối xứng (Asymmetric cryptography) vào Chữ ký số (Digital Signature)

API và HTTP - Một số khái niệm cơ bản cần biết về Web (Phần 2)