TÌM HIỂU GIẢI PHÁP ĐỒNG BỘ SEMAPHORE ỨNG DỤNG GIẢI QUYẾT BÀI TOÁN DINING- PHILOSOPHER
Trang 1TRƯỜNG ĐẠI HỌC BÁCH KHOA
KHOA CNTT
ĐỒ ÁN NGUYÊN LÝ HDH
Đề tài:
TÌM HIỂU GIẢI PHÁP ĐỒNG BỘ SEMAPHORE
ỨNG DỤNG GIẢI QUYẾT BÀI TOÁN
DINING- PHILOSOPHER
GVHD: Nguyễn Văn Nguyên
Trang 2Tôi xin cam đoan :
1 Những nội dung trong luận văn này là do tôi thực hiện dưới sự hướng dẫn trực tiếp của thầy Nguyễn Văn Nguyên
2 Mọi tham khảo dùng trong đồ án đều được trích dẫn rõ ràng tên tác giả, tên công trình, thời gian, địa điểm công bố.
3 Mọi sao chép không hợp lệ, vi phạm quy chế đào tạo, hay gian trá, tôi xin chịu hoàn toàn trách nhiệm.
Sinh viên
Trang 3CHƯƠNG 1 GIỚI THIỆU 1
1.1 K HÁI NIỆM ĐỒNG BỘ 1 1.2 C ÁC KHÁI NIỆM LIÊN QUAN 1 1.2.1 Vấn đề đoạn găng 1
1.2.2 Các điều kiện thỏa mãn đoạn găng 2
1.2.2.1 Loại bỏ tranh chấp 2
1.2.2.2 Tiến trình 2
1.2.2.3 Giới hạn đợi 2
1.3 C ÁC GIẢI PHÁP ĐỒNG BỘ 2 1.3.1 Giải pháp phần cứng 2
1.3.2 Giải pháp sử dụng biến khóa 7
1.3.3 Giải pháp kiểm tra luân phiên 8
1.3.4 Giải pháp sleep and wakeup 9
1.3.5 Giải pháp semaphore 13
1.3.6 Giải pháp monitor: 15
CHƯƠNG 2 BÀI TOÁN 19
2.1 B ÀI TOÁN DINING - PHILOSOPHER THEO GIẢI PHÁP SEMAPHORE 19 2.1.1 Yêu cầu bài toán: 19
2.1.2 Giải pháp 20
2.2 K ẾT QUẢ 21 [2] N GUYỄN P HƯƠNG L AN - H OÀNG Đ ỨC H ẢI L ẬP T RÌNH L INUX -T ẬP 1, NXB G IÁO D ỤC 2001 30 [3] HTTP :// WWW EN WIKIPEDIA ORG / WIKI /P RODUCER - CONSUMER _ PROBLEM 30 PHỤ LỤC……… 22
KẾT LUẬN VÀ HƯỚNG PHÁT TRIỂN………29
TÀI LIỆU THAM KHẢO………30
Trang 4Chương 1 GIỚI THIỆU
Một tiến trình đông bộ là một tiến trình mà nó có thể tương tác hoặc bị tác động bởi 1 tiến trình khác đang thực thi trong hệ thống Đồng tiến trình có lẽ hoặc trực tiếp chia sẻ 1 không gian địa chỉ ( có nghĩa là, cả mã nguồn và dữ liệu), hoặc được cho phép để chia sẻ dữ liệu chỉ thông qua các files Một trường hợp chính tắc đạt được khi sử dụng các tiến trình đơn giản hoặc các tuyến Cùng nhập vào chia sẻ dữ liệu có thể kết quả dẫn đến xung khắc dữ liệu Trong đồ án này, em muốn đề cập đến các kỹ thuật khác nhau để đảm bảo sự thực thi của đa tiến trình, đó là chia sẻ một không gian địa chỉ lôgic có nghĩa là làm cho dữ liệu xử lý không bị gián đoạn
1.2.1 Vấn đề đoạn găng
Xem xét một hệ thống bao gồm n tiến trình {P0, P1, …, Pn-1 } Mỗi tiến trình có một đoạn mã lệnh, được gọi là đoạn găng, trong đó tiến trình có lẽ đang thay đổi biến chung, cập nhật một bảng, viết một tệp, những gì tương tự thế đặc trưng quan trọng của hệ thống là, khi một tiến trình đang thực thi trong đoạn găng của nó, không có một tiến trình nào khác được phép thực thi trong đoạn găng của nó Vì vậy, việc thực thi của đoạn găng bởi tiến trình tranh chấp đúng lúc Vấn đề đoạn găng thiết kế một giao thức mà tiến trình có thể sử dụng để hợp tác Mỗi tiến trình phải chấp nhận yêu cầu để nhập vào đoạn găng của nó Phần mã lệnh thực hiện yêu
Trang 5cầu này được gọi là đoạn tiếp nhận (entry section) Đoạn găng có lẽ được tiếp tục bởi một thoát đoạn Đoạn mã lệnh còn lại là phần dư
1.2.2 Các điều kiện thỏa mãn đoạn găng
1.2.2.3 Giới hạn đợi
Sự tồn tại của một giới hạn trên số lần mà tiến trình được cho phép nhập vàođoạn găng của chúng sau khi tiến trình khác yêu cầu nhập vào đoạn găng và trướckhi mà yêu cầu đó được cấp
1.3.1 Giải pháp phần cứng
Như một diện mạo khác của phần mềm, phần cứng đặc trưng có thể tạo chương trình tác vụ dễ dàng hơn và chứng minh hệ thông hiệu quả Bây giờ ta biểu diễn mộtvài cấu trúc phần cứng đơn giản mà thông dụng trên nhiều hệ thống, và thể hiện làmcách nào chúng ta có thể sử dụng chúng hiệu quả trong vấn đề đoạn găng
Trang 6Boolean TestAndSet(boolean &target) {
Boolean rv = target;
Target = true;
Return rv;
}
Định nghĩa cấu trúc TestAndSet
Vấn đề doạn găng có thể được giải thích một cách đơn giản trong một môi trường đơn tiến trình nếu chúng ta có thể ngăn cấm gián đoạn xảy ra trong khi một biến dùng chung bị thay đổi Ở dạng này ta có thể chắc chắn rằng thứ tự hiện tại củacấu trúc sẽ được phép thực thi không cần đến quyền ưu tiên Không có cấu trúc nào khác có thể chạy, nên không có thay đổi bất ngờ được làm nên để biến chia sẻ.Tiếc thay, giải pháp này không khả thi trong môi trường đa tiến trình Vô hiệu hoá ngắt trên một đa tiến trình có thể mất nhiều thời gian, như 1 thông báo bị chặn đến tất cả các tiến trình Thông báo này làm dừng độ trễ đi vào mỗi đoạn găng, và
hệ thống bị giảm hiệu quả Còn về vấn đề tương tác trên đồng hồ hệ thống, nếu đồng hồ được cập nhật bởi ngắt
Nhiều máy móc vì vậy đưa ra cấu trúc phần cứng đặc biệt cho phếp chúng ta hoặc kiểm tra và thay đổi nội dung của một từ hoặc trao đổi nội dung của hai từ, tự động- có nghĩa là, như một dơn vị không ngắt Chúng ta có thể sử dụng cấu trúc dặcbiệt đó để giải quyết vấn đề đoạn găng trong mối quan hệ kiểu đơn giản thêm vào
đó thảo luận một cấu trúc dặc biệt cho một máy đặc biệt, chúng ta trừu tượng hoá khái niệm chính bên cạnh loại cấu trúc
Cấu trúc TestAndSet có thể được định nghĩa
Trang 7Do {While (TestAndSet (lock));
Critical section
Lock = false;
remainder section
} while(1);
Thực hiện loại bỏ tranh chấp với TestAndSet
Void Swap(boolean &a, boolean &b) {
Boolean temp = a;
a = b;
b = temp;
}
Định nghĩa cấu trúc Swap
Nếu máy có hỗ trợ cấu trúc TestAndSet thì chúng ta có thể thi hành loại bỏ tranhchấp bằng cách khai báo một biến lock, khởi tạo là false Cấu trúc của tiến trình Pi
được biểu diễn ở trên
Cấu trúc của Swap định nghĩa như mô tả ở trên, điều hành trên nội dung của 2 words; như cấu trúc TestAndSet, nó được thực thi tự động
Nếu máy có mục đích cấu trúc Swap, thì thì loại bỏ tranh chấp được đưa ra như tiếp sau đó Một biến toàn cục lock được khai báo và được khởi tạo là false Thêm vào đó mỗi tiến tình còn có một biến cục bộ key Cấu trúc của tiến ttrình Pi được biểu diễn ở dưới
Trang 8Thực hiện loại bỏ tranh chấp với cấu trúc Swap
Thuật toán này không thoả mãn yêu cầu bouded-waiting Chúng ta biểu diễn một thuật toán mà sử dụng cấu trúc TestAndSet Thuật toán này thoả mãn tất cả các yêu cầu của đoạn găng Cấu trúc dữ liệu thông thường là
boolean waiting[n];
boolean lock;
những cấu trúc dữ liệu trên được khởi tạo là false để giải quyết yêu cầu loại bỏ tranh chấp gặp phải, chúng ta chú ý răng tiến trình Pi có thẻ nhập vào đoạn găng chỉ nếu hoặc waiting[i]== false hoặc key == false Giá trị của key có thể trở thành false chỉ nếu TestAndSet được thực thi Tiến trình đầu tiên thực thi TestAndSet sẽ tìm key == false; tất cả các tiến trình khác phải đợi Biến waiting[i] là false chỉ nếu các tiến trình khác rời khỏi đoạn găng của nó; chỉ đuy nhất waiting[i] thiêt lập là false, đang duy trì yêu cầu tranh chấp
Trang 9Để giải thích yêu cầu tiến trình đã gặp, chúng ta chú ý rằng đối số biểu diễn cho tranh chấp còn ứng dụng tại đây, từ một tiến trình thoát ra khỏi đoạn găng hoặc thiếtlập lock là false, hoặc thiết lập waiting[j] là false Cả hai cho phép tiến trình nhập vào đoạn găng để xử lý.
Để giải thích yêu cầu bouded-waiting gặp phải, chúng ta chú ý rằng khi một tiếntrình rời khỏi đoạn găng của nó, nó quét trên mảng đang đợi trong chu kỳ lệnh (i+1,i+2,…,n-1,0,…,i-1) Nó được thiết kế tiến trình đầu tiên trong tập lệnh này nhập vào đoạn (waiting[j] == true) như tăng lên môt để nhập vào đoạn găng Bất kỳ một tiến trình đang đợi nào nhập vào đoạn găng của nó sẽ cho kết quả trong vòng n-
1 trở lại Không may thiết kế phần cứng, thi hành tự động cấu trúc TestAndSet trên
đa tiến trình là tác vụ không quan trọng Như bổ sung thi hành được xảy ra trong những cuốn sách trên cấu trúc máy tính
Trang 10Bounded-waiting loại bỏ tranh chấp với TestAndSet
1.3.2 Giải pháp sử dụng biến khóa
Khai báo một biến lock là biến toàn cục, lock có hai giá trị tương ứng với hai trạng thái Lock có giá trị = 0 khi không có tiến trình nào ở bên trong đoạn găng, và
= 1khi trong đoạn găng có tiến trình Ban đầu lock có giá trị khởi tạo = 0 Khi một tiến trình muốn đi vào đoạn găng của nó, ta kiểm tra tình trạng của lock, nếu lock khác không thì tiến trình sẽ chờ cho đến khi lock có giá trị bằng một thì nhập vào đoạn găng, sau khi hoàn thành công việc nó thiết lập lock bằng không và thoát ra khỏi đoạn găng nhường chỗ cho tiến trình khác vào
Trang 111.3.3 Giải pháp kiểm tra luân phiên
Nguyên tắc của giải pháp kiểm tra luân phiên là một tiến trình cấn xử lý đoạn găng sẽ luân phiên được gán nhãn là 0,1,0….Chương trình sử dụng một biến turn khởi tạo ban đầu băng 0 đối với tiểntình có nhãn bằng 0 thì:
Giải pháp kiểm tra luân phiên đánh nhãn =0
Đối với tiến trình có nhãn =1 thì :
While (true) {
While (turn != 1);
Trang 12Turn = 0;
Non critical_section();
}
Giải pháp kiểm tra luân phiên dánh nhãn =1
Như vậy hai tiến trình được dán nhãn 0,1 bất kỳ sẽ cùng lúc nhập vào đoạngăng gây xung đột, như thế là vi phạm vào điều kiện xử lý đoạn găng
1.3.4 Giải pháp sleep and wakeup
Cả hai giải pháp Peterson và TSL đều thoả mãn 4 điều kiện của đoạn găng, nhưng cả hai đều có khiếm khuyết vì phải tốn thời gian phải chờ Thực chất của giảipháp này thực hiện như sau:
Khi một Tiến Trình (TT) muốn đi vào đoạn găng thì nó được kiểm tra để được phép vào hay không Nếu không được thì TT đó phải chờ trong vòng lặp chờ cho đến khi vòng lặp thoát
Điều này không những làm lãng phí thời gian CPU mà nó còn đưa lại những hiệu quả không mong đợi Giả sử một máy tính cần xử lí hai TT
- TT L có độ ưu tiên thấp
- TT H có độ ưu tiên cao hơn
Nguyên tắc của bộ lập lịch là TT H sẽ được thực thi bất cứ lúc nào nó trong danh sách sẵn sàng Tại thời điểm nào đó, lúc đó TT L đang ở trong đoạn găng thì
TT H chuyển sang trạng thái sẵn sàng để thực thi (ví dụ : hoàn thành một thao tác nhập xuất) nhưng TT H lại đang trong vòng lặp chờ, Khi đó TT L không bao giờ
Trang 13lập lịch trong lúc TT H đang thực thi TT L sẽ không có cơ hội để đi vào đoạn găng Vì vậy TT H lặp vô hạn, tình huống này đôi khi gây ra vấn đề đảo ngược độ
ưu tiên
Chúng ta hãy xem một vài cách trao đổi thông tin cổ điển, cách này sẽ chặn thay
vì phải lãng phí thời gian CPU khi TT không được phép vào đoạn găng Cách đơn giản nhất là dùng cặp trạng thái "sleep" và "wakeup" Sleep là là lời gọi hệ thống xảy ra khi cần chặn một TT, nghĩa là TT đó sẽ bị chặn đến khi TT khác đánh thức
nó dậy Lời gọi wakeup nhận một tham số, xảy ra khi TT cần được đánh thức Việclựa chọn một trong hai trạng thái sleep và wakeup cần có một tham số, đó là một địachỉ bộ nhớ được sử dụng để chuyển từ trạng thái thức thành trạng thái ngủ
Vấn đề người sản xuất và người tiêu thụDương Văn Sơn
- Ta có thể xem vấn đề người sản xuất - người tiêu thụ như là vấn đề bộ đệm
có kích thước giới hạn Hai TT cùng chia sẽ một bộ đệm có kích thước cố định Người sản xuất đưa thông tin vào bộ đệm còn người tiêu thụ lấy thông tin ra khỏi
bộ đệm( tổng quát có thể có m người sản xuất và n người tiêu thụ, đơn giản chúng
ta chỉ xét trường hợp có 1 người sản xuất và một ngươi tiêu thụ)
- Điều phiền toái phát sinh khi người sản xuất muốn đưa một thông tin mới vào bộ đệm nhưng nó đã đầy, giải pháp cho ngưòi sản xuất là đưa nó vào trạng thái ngủ và được đánh thức khi người tiêu thụ lấy ra một hoặc nhiều Item trong bộ đệm Tương tự như vậy, nếu người tiêu thụ muốn lấy một Item từ một bộ đệm rỗng, thì
nó sẽ đi vào trạng thái ngủ cho đến khi người sản xuất đưa một hoặc nhiều Item vào
bộ đệm và đánh thức người tiêu thụ
- Điều này có vẻ đơn giản nhưng nó dẫn đến mâu thuẫn trong các điều kiện
mà chúng ta có thể sớm nhận thấy Để theo dõi số Item trong bộ đệm, chúng ta dùng biến count, số Item nhiều nhất trong một bộ đệm là N, người sản xuất sẽ kiểm
Trang 14tra biến count, nếu count = N thì người sản xuất sẽ đi vào trạng thái ngủ, ngược lại người sản xuất sẽ đưa thông tin mới vào bộ đệm và tăng count lên một.
- Đoạn mã của người tiêu thụ cũng tương tự như vậy, đầu tiên nó kiểm tra biến count, nếu count =0 thì người tiêu thụ đi vào trạng thái ngủ, nếu khác 0 thì nó
sẽ lấy ra một Item từ bộ đệm và giảm count đi một đơn vị, mỗi TT cũng kiểm tra xem TT khác có đang ngủ hay không, nếu có thì đánh thức nó dậy
Trang 15Giải pháp Sleep and Wakeup cho bài toán producer-consumer
Bây giờ chúng ta sẽ kiểm tra lại các mâu thuẫn điều kiện, nó có thể dẫn đến sự
cố, vì việc truy cập đến biến count không thể kiểm soát được Tình huống sau dẫn đến lỗi., bộ đệm bây giờ là rỗng và người tiêu thụ vừa kiểm tra biến count thì thấy
count=0, tại thời điểm này bộ lập lịch quyết định tạm dừng thực thi người tiêu thụ
và chuyển sang thực thi người sản xuất người sản xuất đưa một Item vào bộ đệm rồi tăng count lên 1, chú ý rằng count bây giờ là 1 Vì trước đó count là 0 và do đó người tiêu thụ phải được ngủ Lúc này người sản xuất gọi wakeup để dánh thức người tiêu thụ dậy
Thật không may, người tiêu thụ chưa thật sự ngủ, do đó tín hiệu wakeup gởi đi
bị đánh mất Khi người tiêu thụ tiếp tục thực thi, nó kiểm tra giá trị của biến count
và nhận thấy count =0 do đó nó rơi vào trạng thái ngủ, sớm hay muộn thì người tiêuthụ cũng đưa các Item vào bộ đệm và làm cho nó đầy, lúc này người tiêu thụ sẽ đi vào trạng thái ngủ Kết quả là cả hai đều ngủ vĩnh viễn
Thực chất ,vấn đề ở đây là tín hiệu wakeup gởi đi bị đánh mất, nếu nó không
bị đánh mất thị mọi thứ sẽ hoạt động bình thường, một cách giải quyết là ta thêm một bit chờ việc gọi wakeup được gởi đến một TT mà TT đó vẫn đang thức, thì bit này sẽ được bật lên Sau đó, khi TT đi vào trạng thái sleep, nếu bít chờ đánh thức
Trang 16đang bật lên thì nó sẽ tắt đi, nhưng TT vẫn ở trạng thái thức Bit đợi đánh thức là một cách xác định các tín hiệu wakeup.
1.3.5 Giải pháp semaphore
Đây là giải pháp do Dịjkstra đưa ra năm 1965, semaphore là một biến số nguyên(integer) được truy xuất chỉ thông qua 2 thao tác nguyên tử:wait và signal.Các thao tác này được đặt tên P(wait-chờ để kiểm tra) và V(signal-báo hiệu để tăng)
Nhược điểm chính của giải pháp semaphore là đòi hỏi sự chờ đợi bận.Để giải quyết yêu cầu cho việc chờ đợi bận,chúng ta có thể hiệu chỉnh định nghĩa của các thao tác wait và signal của semaphore.Khi một quá trình thực thi thao tác wait và nhận thấy rằng nếu giá trị của semaphore không dương,nó phải chờ.Tuy nhiên thay
vì chờ đợi bận,quá trình có thể nghẽn chính nó.Thao tác nghẽn đặt quá trình vào một hàng đợi gắn liền với semaphore và trạng thái quá trình được chuyển tới quá trình chờ.Sau đó điều khiển được chuyển tới bộ định thời biểu và một bộ định thời biểu chọn một quá trình khác để thực thi
Một quá trình bị nghẽn chờ trên biến semaphore nên được khởi động lại trên quátrình khác thực thi thao tác signal.Quá trình được khởi động lại bởi thao tác wakeup
và chuyển quá trình từ trạng thái chờ sang trạng thái sẵn sàng.Sau đó quá trình đượcđặt vào hang đợi sẵn sàng
Để cài đặt semaphore dưới định nghĩa này,chúng ta định nghĩa một semaphore
typedef struct{
int value;
struct process *L;
Trang 17Mỗi semaphore có một số integer value và một danh sách các quá trình L.Khi
Trang 18Thao tác block() tạm dừng quá trình gọi thao tác đó.Thao tác wakeup tiếp tục thực thi qua trình bị nghẽn P.Hai thao tác này được cung cấp bởi hệ điều hành như những lời gọi hệ thống cơ bản.
1.3.6 Giải pháp monitor:
Liên lạc giữa các TT sử dụng semaphore trông có vẻ dễ dàng, nhưng chưa hẳn
đã vậy Như đoạn chương trình trên, nếu thao tác DOWN thực hiện trước khi đưa vào hoặc lấy một Item ra khỏi bộ đệm Giả sử ta đảo ngược trật tự của hai thao tác DOWN trong đoạn mã của producer, thì mutex được tăng lên 1 trước khi empty tăng Nếu bộ đệm đã đầy thì người sản xuất sẽ bị chặn và mutex được đặt là 0, Theotrình tự, khi người tiêu thụ truy cập vào bộ đệm nó sẽ DOW N mutex xuống, và mutex bây giờ là 0, do đó nó cũng bị chặn cả hai TT sẽ bị chặn vĩnh viễn mà khôngbao giơ làm việc Tình trạng này gọi là tắc nghẽn
Vấn đề này chỉ ra rằng phải hết sức cẩn thận trong việc sử dụng các semaphore Một lỗi tìm ẩn và mọi thứ trở nên dừng hẳn Điều này giống như lập trình trong ngôn ngữ assembly
Để dễ dàng viết đúng các chương trình Hoare(1974) và Brinch Hansen(1975)
đã đề xuất một cách giao tiếp giữa các TT cao hơn, gọi là monitor Chúng được mô
tả như sau: Một monitor là tập hợp các thủ tục, các biến và cấu trúc dữ liệu tất cả được nhóm lại với nhau trong một module hoăc một gói đặc biệt Các TT có thể gọi các thủ tục trong monitor này bất cứ khi nào chúng muốn, nhưng chúng không thể truy cập trực tiếp các cấu trúc dữ liệu bên trong monitor và các thủ tục được khai báo bên ngoài monitor Sau đây là cấu trúc của một monitor được viết bằng ngôn ngữ giả Pascal:
monitor example
Integer I;