Hệ điều hành (3) - Quản lý tiến trình

Bài trước: Hệ điều hành (2) - Hệ thống quản lý tập tin
-----

4         Quản lý tiến trình


4.1       Thành phần cơ bản của một hệ thống máy tính


Trong đó,

– Bộ xử lý (Processor) – một bộ -> CPU (central processing unit)

– Bộ nhớ chính (Main Memory): không có khả năng duy trì thông tin khi shutdown (volatile). Cũng được gọi real memory hoặc primary memory

– Thành phần nhập xuất (I/O module): các loại bộ nhớ phụ, thiết bị giao tiếp, thiết bị đầu cuối (terminal)


– Bus hệ thống (System bus): giúp quá trình giao tiếp giữa processor, memory, và I/O modules

4.2       Chu trình đọc và thực thi lệnh




– Vi xử lý đọc (fetch) lệnh từ bộ nhớ

+ Bộ đếm chương trình (Program counter (PC)) chứa địa chỉ của lệnh kế tiếp sẽ được đọc

+ Lệnh đã được đọc, được lưu trong thanh ghi lệnh (instruction register (IR))

+ Bộ đếm chương trình sẽ tăng lên 1 sau khi đọc 1 lệnh từ bộ nhớ

– Sau đó Vi xử lý sẽ thực thi lệnh trong thanh ghi IR

Ví dụ:

Thanh ghi IR có độ dài 16 bit. Cấu trúc của một lệnh được chia thành hai phần: bốn bit đầu là mã lệnh (opcode) --> có thể thể hiện được 16 lệnh khác nhau, mười hai bit tiếp theo là địa chỉ truy cập bộ nhớ --> có thể truy cập tới 4096 (4K) từ nhớ khác nhau. Được biểu diễn bằng ba số hexadecimal.


Một đoạn thực thi chương trình:


Một số mã lệnh:

Quá trình thực thi lệnh (trang 13):

– Nạp dữ liệu từ địa chỉ 940 của bộ nhớ vào thanh ghi AC.

– Cộng thanh ghi AC với giá trị tại địa chỉ 941 của bộ nhớ. Kết quả để trên thanh ghi AC.

– Ghi dữ liệu trên thanh ghi AC vào bộ nhớ tại địa chỉ 941.


4.3       Khái niệm về tiến trình


Tiến trình là một chương trình đang xử lý, mỗi tiến trình có một không gian địa chỉ, một con trỏ lệnh, một tập các thanh ghi và stack riêng. Tiến trình có thể cần đến một số tài nguyên như CPU, bộ nhớ chính, các tập tin và thiết bị nhập/xuất. Hệ điều hành sử dụng bộ điều phối (scheduler) để quyết định thời điểm cần dừng hoạt động của tiến trình đang xử lý và lựa chọn tiến trình tiếp theo cần thực hiện. Trong hệ thống có những tiến trình của hệ điều hành và tiến trình của người dùng.

– Xem processes trong Task Manager.

Đọc thêm trang 46,

4.4       Khái niệm tiểu trình (thread)


Một tiến trình có thể tạo nhiều tiểu trình, mỗi tiểu trình thực hiện một chức năng nào đó và thực thi đồng thời cũng bằng cách chia sẻ CPU. Các tiểu trình trong cùng một tiến trình dùng chung không gian địa chỉ tiến trình nhưng có con trỏ lệnh, tập các thanh ghi và stack riêng. Một tiểu trình cũng có thể tạo lập các tiểu trình con, và nhận các trạng thái khác nhau như một tiến trình.

Đọc thêm trang 47, 48, 49, 50:


4.5       Các trạng thái của tiến trình


Đọc trang 51,

4.6       Các giải thuật/thuật toán điều phối tiến trình


Trang 58,


– Giải thuật FCFS

– Giải thuật SJF

– Giải thuật P

– Giải thuật RR

– Giải thuật MQ

– Giải thuật MFQ

Tính thời gian chờ trung bình.

Xem thêm:

https://www.youtube.com/watch?v=qa8labtyDXk


4.7       Thực hành

4.7.1 Cài đặt tiểu trình

[Program.cs]

using System;

using System.Threading;

class Program

{

    private int iterations;

    private string message;

    private int delay;

 

    public Program(int iterations, string message, int delay)

    {

        this.iterations = iterations;

        this.message = message;

        this.delay = delay;

    }

 

    public void MyThread() // tạo tiểu trình

    {

        Thread thread = new Thread(DisplayMessage); // tạo tiểu trình trỏ tới một hàm cụ thể

        Console.WriteLine("{0}:Starting new thread.",DateTime.Now.ToString("HH:mm:ss.ffff"));

        thread.Start(); // chạy tiểu trình

    }

 

    public void DisplayMessage() // hàm sẽ được chạy dưới hình thức một tiểu trình

    {

        for(int count = 0; count < iterations; count++)

        {

            Console.WriteLine("{0}:{1}", DateTime.Now.ToString("HH:mm:ss.ffff"), message);

            Thread.Sleep(delay);

        }

    }

    static void Main(string[] args)

    {

        Program example = new Program(500, "A thread example.", 500);

        example.MyThread(); // gọi và thực thi tiểu trình từ chương trình chính (main)

        for(int count = 0; count < 1000; count++)

        {

            Console.WriteLine("{0} : Continue processing...",

                DateTime.Now.ToString("HH:mm:ss.ffff"));

            Thread.Sleep(500);

        }

        Console.WriteLine("Main method complete. Press Enter.");

    }

}

 

Giải thích để hiểu đoạn mã ở trên

Trước khi giải thích các đoạn mã ở trên, cần tìm hiểu ngắn gọn một số khái niệm liên quan.

Phần mềm máy tính là tập hợp các lệnhdữ liệu, được dùng để hướng dẫn máy tính thực hiện các chức năng cụ thể.

Tập hợp các lệnh được gọi là chương trình.

Một chương trình có thể ở trạng thái tĩnh là các lệnh đang được lưu trong các tập tin trên đĩa cứng.

Một chương trình có thể ở trạng thái động là các lệnh đang được thực thi trong RAM và CPU.

Tiến trình là một chương trình ở trạng thái động, mỗi tiến trình có một không gian địa chỉ (trong RAM), một con trỏ lệnh, một tập các thanh ghi (trong CPU) và stack riêng. Tiến trình có thể cần đến một số tài nguyên như CPU, bộ nhớ chính, các tập tin và thiết bị nhập/xuất.

Quá trình chạy của một tiến trình:


Tiến trình trên RAM:





Chạy chương trình Program.cs và xem tiến trình trong Task Manager (thiết lập vòng lặp trong hàm Main khoảng 1000 lần để dễ quan sát):



Tiểu trình là gì?

Một tiến trình có thể tạo nhiều tiểu trình, mỗi tiểu trình thực hiện một chức năng cụ thể.

Các tiểu trình trong cùng một tiến trình dùng chung không gian địa chỉ của tiến trình nhưng có con trỏ lệnh, tập các thanh ghi và stack riêng.

Tiểu trình cũng là đơn vị xử lý cơ bản trong hệ thống, nó cũng xử lý tuần tự đoạn mã của nó, các tiểu trình cũng chia sẻ thời gian xử lý của CPU như các tiến trình.

Các tiểu trình trong một tiến trình chia sẻ một không gian địa chỉ chung, điều này có nghĩa các tiểu trình có thể chia sẻ các biến toàn cục của tiến trình, có thể truy xuất đến stack của tiểu trình khác trong cùng tiến trình. Như vậy với mô hình tiểu trình, trong hệ thống có thể tồn tại nhiều dòng xử lý cùng chia sẻ một không gian địa chỉ bộ nhớ, các dòng xử lý này hoạt động song song với nhau.



Giải thích đoạn mã trong Program.cs:

Chương trình Program.cs gồm hai tiểu trình: tiểu trình chính (Main) và tiểu trình example.

Để tạo thread trong C#:

Bước 1: Tạo một hàm cần thực thi riêng biệt, song song với tiểu trình chính (hàm Main). Ví dụ:

public void DisplayMessage() // hàm sẽ được chạy dưới hình thức một tiểu trình

    {

        for(int count = 0; count < iterations; count++)

        {

            Console.WriteLine("{0}:{1}", DateTime.Now.ToString("HH:mm:ss.ffff"), message);

            Thread.Sleep(delay);

        }

    }

Bước 2: Tạo tiểu trình bằng cách tạo ra một đối tượng thuộc lớp Thread, truyền vào phương thức khởi tạo tên hàm đã được tạo ở bước 1; gọi phương thức Start() để chạy tiểu trình. Ví dụ:  

public void MyThread() // tạo tiểu trình

    {

        Thread thread = new Thread(DisplayMessage); // tạo tiểu trình trỏ tới một hàm cụ thể

        Console.WriteLine("{0}:Starting new thread.",DateTime.Now.ToString("HH:mm:ss.ffff"));

        thread.Start(); // chạy tiểu trình

    }

Bước 3: Chạy tiểu trình chính (hàm Main), trong tiểu trình chính sẽ gọi tiểu trình được tạo ra ở Bước 2. Ví dụ:

    static void Main(string[] args)

    {

        Program example = new Program(500, "A thread example.", 500);

        example.MyThread(); // gọi và thực thi tiểu trình từ chương trình chính (main)

        for(int count = 0; count < 1000; count++)

        {

            Console.WriteLine("{0} : Continue processing...",

                DateTime.Now.ToString("HH:mm:ss.ffff"));

            Thread.Sleep(500);

        }

        Console.WriteLine("Main method complete. Press Enter.");

    }

Quan sát kết quả sẽ thấy các câu thông báo của hàm Main() và hàm DisplayMessage() được hiển thị đan xen nhau (do chạy song song). Trong các tiểu trình có dùng lệnh Sleep() để dừng chương trình một thời gian, giúp quan sát kết quả dễ hơn.

4.7.2 Tiểu trình dùng chung vùng nhớ

Như đã đề cập trong phần khái niệm tiểu trình: các tiểu trình trong cùng một tiến trình sẽ dùng chung không gian địa chỉ của tiến trình (trong RAM) nhưng có con trỏ lệnh, tập các thanh ghi và stack riêng.

Phần này sẽ viết một chương trình gồm tiểu trình chính (hàm Main) và hai tiểu trình con. Hai tiểu trình con sẽ tham chiếu tới cùng một biến (một vùng nhớ trên RAM). Biến dùng chung giữa hai tiểu trình con có tên là count; hai tiểu trình con có tên là TieuTrinhCong và TieuTrinhTru.

Ý tưởng của chương trình:

– Gán cho biến count giá trị ban đầu (ví dụ: count = 10)

– Tiểu trình chính (hàm Main) sẽ gọi hai tiểu trình con

– TieuTrinhCong(): sẽ tăng liên tục biến count lên 2500 lần

– TieuTrinhTru(): sẽ giảm liên tục biến count lên 2500 lần

– Sau khi chạy xong hai tiểu trình con, sẽ xuất giá trị của biến count trong tiểu trình chính để quan sát kết quả của biến count.

[Thread_Cong_Tru.cs]

using System;

using System.Threading;

class Thread_Cong_Tru

{

    private int count = 10;

 

    public void HamCong()

    {

        for(int i = 0; i < 2500; i++)

        {

            count = count + 1;

            Console.WriteLine("Gia tri count trong ham cong: " + count);

            Thread.Sleep(300);

        }

    }

    public void HamTru()

    {

        for (int i = 0; i < 2500; i++)

        {

            count = count - 1;

            Console.WriteLine("Gia tri count trong ham tru: " + count);

            Thread.Sleep(300);

        }

    }

static void Main(string[] args)

    {

        Thread_Cong_Tru test = new Thread_Cong_Tru();

        Console.WriteLine("Gia tri khoi tao cua bien count (trong tieu trinh Main): " + test.count);

        // tạo và chạy tiểu trình cộng

        Thread TieuTrinhCong = new Thread(test.HamCong);

        TieuTrinhCong.Start();

        // tạo và chạy tiểu trình trừ

        Thread TieuTrinhTru = new Thread(test.HamTru);

        TieuTrinhTru.Start();

        Console.WriteLine("Gia tri ket thuc cua bien count (trong tieu trinh Main): " + test.count);

    }

}

// Giá trị của biến count có thể là 9, 10, 11, 12, 13: do biến dùng chung này bị thao tác cùng lúc từ hai tiểu trình nên không thể kiếm soát được giá trị. Đây là lý do cần phải đồng bộ hóa giữa các tiến/tiểu trình.

---------------------------------------


Lab 8. Viết chương trình cho phép nhập một số nguyên dương, tìm các số nguyên tố và số chính phương từ 0 tới số vừa nhập. Sử dụng phương pháp lập trình tuần tự, nghĩa là cho người dùng nhập vào một số, chương trình sẽ chạy chức năng tìm và xuất số nguyên dương ra màn hình trước, sau đó sẽ chạy chức năng tìm và xuất số chính phương ra màn hình. (sử dụng ngôn ngữ lập trình tùy chọn)


Lab 9. Viết chương trình cho phép nhập một số nguyên dương, tìm các số nguyên tố và số chính phương từ 0 tới số vừa nhập. Sử dụng phương pháp lập trình đa tiểu trình. Xem ví dụ tham khảo: Cài đặt đa tiểu trình (multipthreading) bằng ngôn ngữ C#. https://www.youtube.com/watch?v=HCrZyk_r6i0


Lab 10. Cài đặt đa tiểu trình cho bài toán đếm xuôi và đếm ngược cùng lúc. Xem giao diện:


– Người dùng nhập một số, bấm vào nút Đếm xuôi và Đếm ngược, máy tính sẽ thực hiện đếm và xuất ra màn hình.

4.8       Câu hỏi ôn tập


1.      Trong CPU, thanh ghi PC là viết tắt của:

A. Personal Computer

B. Professional Computer

C. Program Control

D. Program Counter

2.      Trong CPU, thanh ghi IR là viết tắt của:

A. Increment Register

B. Instruction Register

C. Index Register

D. Identifier Register

3.      Diễn giải quá trình thực thi của chương trình tại mục “Chu trình đọc và thực thi lệnh - Một đoạn thực thi chương trình”.

4.      Phân biệt tiến trình và tiểu trình?

5.      Hiểu và tính thời gian chờ trung bình của các giải thuật lập lịch CPU (điều phối tiến trình) sau: FCFS, P, SJF. Tham khảo: https://www.youtube.com/watch?v=EnXUx082wYg
--------
Cập nhật: [1/6/2021]
-------
Bài tiếp theo: Hệ điều hành (4) - Liên lạc và đồng bộ hóa giữa các tiến trình
Danh sách các bài học
-----
Bạn muốn tự học HTML bài bản? Xem thêm