II.3.4.Hai bài toán điều phối làm ví dụ

Một phần của tài liệu Tiến trình và các loại tiến trình doc (Trang 32 - 41)

Bài toán 1: Giả sử có một ứng dụng, tạm gọi là ứn dụng Producer/Consumer, trong hệ thống đa nhiệm – đa người sử dụng. Ứng dụng này có hai tiến trình chính đó là, tiến trình người sản xuất (Producer) và tiến trình người tiêu thụ (Consumer), hai tiến trình này hoạt động đồng thời với nhau và cùng chia sẻ một bộ đệm (Buffer) có kích thước giới hạn, chỉ có 3 phần tử. Tiến trình Producer tạo ra dữ liệu và đặt vào Buffer, tiến trình Consumor nhận dữ liệu từ Buffer ra để xử lý. Rõ ràng hệ thống này cần phải có các ràng buộc sau:

1. Hai tiến trình Producer và Consumer không được đồng thời truy xuất Buffer (Buffer là tài nguyên găng).

2. Tiến trình Producer không được ghi dữ liệu vào Buffer khi Buffer đã bị đầy.

3. Tiến trình Consumerkhông được đọc dữ liệu từ Buffer khi Buffer rỗng. Hãy dùng các giải pháp Semafore, Monitor, Message để tổ chức điều độ cho các tiến trình Producer và Consumer trong bài toán trên.

II.3.4.1. Giải pháp dùng Semaphore

Với giải pháp này sơ đồ điều độ phải sử dụng 3 Semaphore:

• Full: dùng để theo dõi số chỗ đã có dữ liệu trong bộ đệm, nó được khởi gán bằng 0. Tức là, ban đầu Buffer rỗng.

• Empty: dùng để theo dõi số chỗ còn trống trên bộ đệm, nó được khởi gán bằng 3. Tức là, ban đầu Buffer không chứa một phần tử dữ liệu nào.

• Mutex: dùng để kiểm tra truy xuất đồng thời trên bộ đệm, nó được khởi gán bằng 1. Tức là, chỉ có 1 tiến trình được phép truy xuất buffre.

Sơ đồ điều độ sẽ như sau:

Program Producer/Consumer;

Var Full, Empty, Mutex: Semaphore;

{---} Procedure Producer();

Begin Repeat

< Tạo dữ liệu>;

Down(mutex); {kiểm tra và xác lập quyền truy xuất Buffer} <Đặt dữ liệu vào Buffer>;

Up(mutex); {kết thúc truy xuất buffer}

Up(Full); {đã có 1 phần tử dữ liệu trong Buffer} Until .F. End; {---} Procedure Consumer(); Begin Repeat

Down(full); {còn phần tử dữ liệu trong Buffer?}

Down(mutex); {kiểm tra và xác lập quyền truy xuất Buffer} <Nhận dữ liệu từ đệm>;

Up(mutex); {kết thúc truy xuất buffer}

Up(empty); {đã lấy 1 phần tử dữ liệu trong Buffer} Until .F.

End;

{---} BEGIN

Full = 0; Empty = 3; Mutex = 1; Produc er();

Consumer(); END.

{---}

II.3.4.2. Giải pháp dùng Monitor

Với giải pháp này người lập trình phải định nghĩa một monitor, có tên là ProducerConsumer, trong đó có hai thủ tục Enter và Remove, dùng để thao tác trên Buffer. Xử lý của các thủ tục này phụ thuộc vào các biến điều kiện full và empty. Full và Emtry được quy định định sử dụng như trong giải pháp semaphore.

Sơ đồ điều độ sẽ như sau:

Program Producer/Consumer;

Monitor ProducerConsumer;

Condition Full, Empty;

Var Count: Integer; {để đếm số phần tử đữ liệu được đưa vào Buffer} N: Interger; {số phần tử của Buffer}

Procedure Beginwrite(); Begin

Rc = Rc - 1;

If (busy) or (Rc <> 0) Then Wait(okwrite); Busy = True;

End;

Procedure FinishWrite() Begin

Busy = False;

If (Okread) Then Signal(okread) Else Signal(okwrite); End; Endmonitor. {---} BEGIN ParBegin Procedure Reader (); Begin Repeat ReaderWriter.BeginRead(); <đọc dữ liệu> ReaderWriter.FinishRead(); Until .F. End; Procedure Writer (); Begin Repeat ReaderWriter.BeginWrite(); <đọc dữ liệu> ReaderWriter.FinishWrite(); Until .F. End; Parend END. {---}

II.3.4.6. Giải pháp dùng Message

Giải pháp này cần phải có một tiến trình Sever điều khiển việc truy xuất cơ sở dữ liệu. Các tiến trình Writer và Reader gửi các thông điệp yêu cầu truy xuất đến server và nhận từ Sever các thông điệp hồi đáp tương ứng.

Sơ đồ điều độ sẽ như sau: Program Producer/Consumer; Begin ParBegin Procedure Reader(); Begin Repeat Send (Sever,Requesread); Receive(sever,value); Print(value); Until .F. End; Procedure Writer(); Begin Repeat <Tạo dữ liệu>;

Send (Sever, Requeswrite,value); Receive(sever, okwrite); Until .F. End; ParEnd End. {---} II.3. Tắc nghẽn (Deadlock) và chống tắc nghẽn II.4.1.Tắc nghẽn

Tất cả hiện tượng tắc nghẽn đều bắt nguồn từ sự xung đột về tài nguyên của hai hoặc nhiều tiến trình đang hoạt động đồng thời trên hệ thống. Tài nguyên ở đây có thể là một ổ đĩa, một record trong cơ sở dữ liệu, hay một không gian địa chỉ trên bộ nhớ chính. Sau đây là một số ví dụ để minh hoạ cho điều trên.

Ví dụ 1: Giả sử có hai tiến trình P1 vàP2 hoạt động đồng thời trong hệ thống. Tiến trình P1 đang giữ tài nguyên R1 và xin được cấp R2 để tiếp tục hoạt động, trong khi đó tiến trình P2 đang giữ tài nguyên R2 và xin được cấp R1 để tiếp tục hoạt động. Trong trường hợp này cả P1 và P2 sẽ không tiếp tục hoạt động được. Như vậy P1 và P2 rơi vào trạng thái tắc nghẽn. Ví dụ này có thể được minh hoạ bởi sơ đồ ở hình 2.

Tắc nghẽn thường xảy ra do xung đột về tài nguyên thuộc loại không phân chia được, một số ít trường hợp xảy ra với tài nguyên phân chia được. Ví dụ sau đây là trường hợp tắc nghẽn do xung đột về tài nguyên bộ nhớ, là tài nguyên thuộc loại phân chia được.

Ví dụ 2: Giả sử không gian bộ nhớ còn trống là 200Kb, và trong hệ thống có hai tiến trình P1 và P2 hoạt động đồng thời. P1 và P2 yêu cầu được sử dụng bộ nhớ như sau: P1 P2 …. …. Request1 80Kb Request1 70Kb ….. ….. Request2 30Kb Request2 40Kb ….. …..

Tắc nghẽn xảy ra khi cả hai tiến trình cùng yêu cầu thêm bộ nhớ lần thứ hai. Tại thời điểm này không gian bộ nhớ còn trống là 50Kb, lớn hơn lượng bộ nhớ mà mỗi tiến trình yêu cầu (30Kb và 40Kb), nhưng vì cả hai tiến trình đồng thời yêu cầu thêm bộ nhớ, nên hệ thống không để đáp ứng được, và tắc nghẽn xảy ra.

Ví dụ 3: Trong các ứng dụng cơ sở dữ liệu, một chương trình có thể khoá một vài record mà nó sử dụng, để dành quyền điều khiển về cho nó. Nếu tiến trình P1 khoá record R1, tiến trình P2 khoá record R2, và rồi sau đó mỗi tiến trình lại cố gắng khoá record của một tiến trình khác. Tắc nghẽn sẽ xảy ra.

Như vậy tắc nghẽn là hiện tượng: Trong hệ thống xuất hiện một tập các tiến trình, mà mỗi tiến trình trong tập này đều chờ được cấp tài nguyên, mà tài nguyên đó đang được một tiến trình trong tập này chiếm giữ. Và sự đợi này có thể kéo dài vô hạn nếu không có sự tác động từ bên ngoài.

Trong trường hợp của ví dụ 1 ở trên: hai tiến trình P1 và P2 sẽ rơi vào trạng thái tắc nghẽn, nếu không có sự can thiệp của hệ điều hành. Để phá bỏ tắc nghẽn này hệ điều hành có thể cho tạm dừng tiến trình P1 để thu hồi lại tài nguyên R1, lấy R1 cấp cho tiến trình P2 để P2 hoạt động và kết thúc, sau đó thu hồi cả R1 và R2 từ tiến trình P2 để cấp cho P1 và tái kích hoạt P1 để P1 hoạt động trở lại. Như vậy sau một khoảng thời gian cả P1 và P2 đều ra khỏi tình trạng tắc nghẽn.

Trong trường hợp của ví dụ 2 ở trên: nếu hai tiến trình này không đồng thời yêu cầu thêm bộ nhớ thì tắc nghẽn không thể xảy ra, hoặc khi cả hai tiến trình đồng thời yêu cầu thêm bộ nhớ thì hệ điều hành phải kiểm tra lượng bộ nhớ còn trống của hệ thống, nếu không đáp ứng cho cả hai tiến trình thì hệ điều hành phải có cơ chế ngăn chặn (từ chối) một tiến trình và chỉ cho một tiến trình được quyền sử dụng bộ nhớ (đáp ứng) thì tắc nghẽn cũng không thể xảy ra. Tuy nhiên để giải quyết vấn đề tắc nghẽn do thiếu bộ nhớ, các hệ điều hành thường sử dụng cơ chế bộ nhớ ảo.

tài nguyên R2 tài nguyên R1 Process P2 Process P1 Yêu cầu Yêu cầu Giữ Giữ Hình 2.6: Chờ đợi vòng tròn

Bộ nhớ ảo là một phần quan trong của hệ điều hành mà chúng ta sẽ khảo sát ở chương Quản lý bộ nhớ của tài liệu này.

Khi hệ thống xảy ra tắc nghẽn nếu hệ điều hành không kịp thời phá bỏ tắc nghẽn thì hệ thống có thể rơi vào tình trạng treo toàn bộ hệ thống. Như trong trường hợp tắc nghẽn ở ví dụ 1, nếu sau đó có tiến trình P3, đang giữ tài nguyên R3, cần R2 để tiếp tục thì P3 cũng sẽ rơi vào tập tiến trình bị tắc nghẽn, rồi sau đó nếu có tiến trình P4 cần tài nguyên R1 và R3 để tiếp tục thì P4 cũng rơi vào tập các tiến trình bị tắc nghẽn như P3, … cứ thế dần dần có thể dẫn đến một thời điểm tất cả các tiến trình trong hệ thống đều rơi vào tập tiến trình tắc nghẽn. Và như vậy hệ thống sẽ bị treo hoàn toàn.

Một phần của tài liệu Tiến trình và các loại tiến trình doc (Trang 32 - 41)

Tải bản đầy đủ (DOC)

(52 trang)
w