45
TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Viện Công nghệ Thông tin và Truyền thông BÀI TẬP LỚN HỆ ĐIỀU HÀNH Sinh viên thực hiện: 1. Chu Đức Lộc SHSV: 20091678 2. Phạm Quang Toản SHSV: 20092793 Mã lớp: 21538 Giáo viên hướng dẫn: TS. Phạm Đăng Hải 1

He Dieu Hanh

Embed Size (px)

Citation preview

Page 1: He Dieu Hanh

TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI

Viện Công nghệ Thông tin và Truyền thông

BÀI TẬP LỚN HỆ ĐIỀU HÀNH

Sinh viên thực hiện:

1. Chu Đức Lộc SHSV: 20091678

2. Phạm Quang Toản SHSV: 20092793

Mã lớp: 21538

Giáo viên hướng dẫn: TS. Phạm Đăng Hải

1

Page 2: He Dieu Hanh

HÀ NỘI – 2011

M c l cụ ụA Các phương pháp truyền thông Client-Server...............................................3

1 Khái niệm...........................................................................................................3

2 Các phương pháp truyền thông (Khái quát):......................................................3

B Chương trình mô phỏng chat đơn giản thông qua socket.............................4

C Chương trình mô phỏng hàng đợi đa mức có phản hồi.................................6

D Bài toán người đọc và biên tập viên...............................................................11

E Bài toán người thợ cắt tóc ngủ gật.................................................................15

F Bathroom problem..........................................................................................19

G Producer Consumer........................................................................................24

H Dining philosophers........................................................................................27

I Bài toán tạo phân tử H2O...............................................................................30

J Đọc Master Boot Record, đưa ra các phân vùng chính của ổ cứng, nếu phân vùng ổ C sử dụng hệ thống file FAT32 thì đưa ra thông tin về ổ............33

K Tài liệu tham khảo:.........................................................................................35

2

Page 3: He Dieu Hanh

A Các phương pháp truyền thông Client-Server

1 Khái ni mệMô hình client-server là một mô hình nổi tiếng trong mạng máy tính, được áp dụng rất rộng rãi và là mô hình của mọi trang web hiện có. Ý tưởng của mô hình này là máy con (đóng vài trò là máy khách) gửi một yêu cầu (request) để máy chủ (đóng vai trò người cung ứng dịch vụ), máy chủ sẽ xử lý và trả kết quả về cho máy khách.

Thuật ngữ server được dùng cho những chương trình thi hành như một dịch vụ trên toàn mạng. Các chương trình server này chấp nhận tất cả các yêu cầu hợp lệ đến từ mọi nơi trên mạng, sau đó nó thi hành dịch vụ và trả kết quả về máy yêu cầu.

Một chương trình được coi là client khi nó gửi các yêu cầu tới máy có chương trình server và chờ đợi câu trả lời từ server.

Chương trình server và client nói chuyện với nhau bằng các thông điệp (messages) thông qua một cổng truyền thông liên tác IPC (Interprocess Communication). Để một chương trình server và một chương trình client có thể giao tiếp được với nhau thì giữa chúng phải có một chuẩn để nói chuyện, chuẩn này được gọi là giao thức. Nếu một chương trình client nào đó muốn yêu cầu lấy thông tin từ server thì nó phải tuân theo giao thức mà server đó đưa ra.

2 Các ph ng pháp truy n thông (Khái quát):ươ ề 2.1 Socket

Một socket là một thiết bị truyền thông 2 chiều tương tự như một tập tin. Chúng ta có thể đọc hay ghi lên nó. Tuy nhiên mỗi socket là một thành phần trong một mối nối nào đó giữa các máy trên mạng máy tính và các thao tác đọc/ghi chính là sự trao đổi dữ liệu giữa các ứng dụng trên nhiều máy khác nhau.

3

Page 4: He Dieu Hanh

Ở đây ta hiểu Socket trong Winsock như là một “phương tiện” để ứng dụng mạng có thể trao đổi dữ liệu. Nghĩa là 1 Server thì sẽ cần một Socket để lắng nghe, chờ đợi các kết nối từ client và Client thì phải cần có một Socket để kết nối tới Sever.

2.2 RMI

RMI (Remote Method Invocation) là một cơ chế cho phép một đối tượng đang chạy trên một máy ảo Java này ( Java Virtual Machine) gọi các phương thức của một đối tượng đang tồn tại trên một máy ảo Java khác (JVM).

Thực chất RMI là một cơ chế gọi phương thức từ xa đã được thực hiện và tích hợp trong ngôn ngữ Java. Vì Java là một ngôn ngữ lập trình hướng đối tượng, nên phương pháp lập trình trong RMI là phương pháp hướng đối tượng do đó các thao tác hay các lời gọi phương thức đều liên quan đến đối tượng. Ngoài ra, RMI còn cho phép một Client có thể gửi tới một đối tượng đến cho Server xử lý, và đối tượng này cũng có thể được xem là tham số cho lời gọi hàm từ xa, đối tượng này cũng có những dữ liệu bên trong và các hành vi như một đối tượng thực sự.

2.3 RPC

RPC (Remote Procedure Calls) – Thủ tục gọi hàm từ xa là một kỹ thuật tiến bộ cho quá trình kết nối từ Client đến Server để sử dụng các ứng dụng và dịch vụ. RPC cho phép client có thể kết nối tới 1 dịch vụ sử dụng dynamic port nằm ở một máy tính khác. Trong hệ thống mạng máy tính hiện nay có rất nhiều dịch vụ và ứng dụng sử dụng cơ chế kết nối RPC.

RPC được thiết kế để cung cấp cho việc truyền tải thông tin giữa client và server dễ dànghơn,  bảo mật hơn, và thuận tiện hơn cho việc đồng bộ hóa các luồn dữ liệu.

Các thông điệp gửi cho một dịch vụ RPC được biểu diễn bởi ngôn ngữ XDR (External Data Representation): dạng thức biểu diễn dữ liệu ngoài. Chỉ có các kiểu dữ liệu có thể được định nghĩa bởi XDR mới có thể truyền đi.

B Chương trình mô phỏng chat đơn giản thông qua socket

+Server:

import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;

4

Page 5: He Dieu Hanh

import java.net.InetAddress;import java.net.ServerSocket;import java.net.Socket;public class Server {public static void main(String[] args) {// Xử lí các trường hợp ngoại lệ có thể xảy ra của các lệnh đặt trong khối try...catchtry { // Khởi tạo sever tại cổng 6132 ServerSocket server = new ServerSocket(1234); // Tạo vòng lặp vô hạn while (true) { System.out.println("Listening..."); // Chờ cho đến khi có Client kết nối tới thì sẽ trả Client về Socket sock Socket sock = server.accept(); // Lấy thông tin về Client vừa conect tới InetAddress addr = sock.getInetAddress(); System.out.println("Connection made to " + addr.getHostName()+ " (" + addr.getHostAddress() + ") \n"); ObjectInputStream ois = new ObjectInputStream(sock.getInputStream()); ObjectOutputStream oos = new ObjectOutputStream(sock.getOutputStream()); Object infor = ois.readObject(); System.out.println(infor.toString()); oos.writeObject("Hi, I'm Server \n"); // Đóng kết nối sock.close(); }} catch (ClassNotFoundException x) {System.out.println(x);} catch (IOException x) {System.out.println("Exception detected: " + x);}}}

+ Client

import java.io.*;import java.net.Socket;public class Client{public static void main(String[] args) {Socket sock;int port = 1234;String hostname = "127.0.0.1"; // Địa chỉ để chat trên cùng một máy

5

Page 6: He Dieu Hanh

// Xử lí các trường hợp ngoại lệ có thể xảy ra của các lệnh đặt trong khối try...catchtry { sock = new Socket(hostname, port); System.out.println("Connect successfully \n"); ObjectOutputStream oos = new ObjectOutputStream(sock.getOutputStream()); ObjectInputStream ois = new ObjectInputStream(sock.getInputStream()); oos.writeObject("Hello, I'm Client \n"); Object infor = ois.readObject(); System.out.println(infor.toString());} catch (ClassNotFoundException x) {System.out.println(x);} catch (IOException x) {System.out.println(x);} catch (Exception x) {System.out.println(x);}}}}}

C Chương trình mô phỏng hàng đợi đa mức có phản hồi

+ Bài toán:

Sử dụng 3 hàng đợi với 3 mức độ ưu tiên lần lượt là 1, 2, 3. Các tiến trình trên cùng 1 hàng đợi có cùng mức độ ưu tiên.

* Queue 1 sử dụng chiến lược điều phối RR với lượng tử thời gian là 8.

* Queue 2 sử dụng chiến lược điều phối RR với lượng tử thời gian là 16.

* Queue 3 sử dụng chiến lược điều phối FCFS.

+ Thuật toán:

* Khi 1 tiến trình P1 yêu cầu CPU mà không được đáp ứng ngay thì xếp nó vào Queue 1.

* Nếu hết lượng tử thời gian dùng CPU ở Queue 1 mà P1 vẫn chưa thực hiện xong thì đẩy nó xuống Queue 2.

* Nếu hết lượng tử thời gian dùng CPU ở Queue 2 mà P1 vẫn chưa thực hiện xong thì đẩy nó xuống Queue 3.

6

Page 7: He Dieu Hanh

* Thực hiện các tiến trình theo mức độ ưu tiên và thứ tự trong hàng đợi.

+ Sử dụng chương trình:

* Nhập số lượng tiến trình tham gia điều phối.

* Với mỗi tiến trình thì nhập thời điểm bắt đầu vào hệ thống và thời gian chạy cần thiết để tiến trình hoàn tất.

* Chương trình sẽ in ra thời điểm chạy của các tiến trình.

+ Chương trình:

#include<iostream.h>

#include<stdlib.h>

#define max 100

float t[max], b[max];

int q1[max], q2[max], q3[max], vt[max], kt[max], n, f1, r1, f2, r2, f3, r3;

void sort()

{ int i,j,t3; float t1,t2;

for (i=1; i<n; ++i)

{ t3=vt[i]; j=i;

while ((j>0)&&(b[vt[j-1]]>b[t3])) {

vt[j]=vt[j-1];

--j;

}

vt[j]=t3;

}

}

7

Page 8: He Dieu Hanh

void push(int q[], int i, int &f, int &r)

{ if ((max-f+r)%max==max-1) {cout<<"hang doi day"; return;}

q[r]=i;

r=(r+1)%max;

}

int isempty(int q[], int f, int r)

{ return (f==r);

}

int pop(int q[], int &f, int &r)

{ int gt=q[f];

f=(f+1)%max;

return gt;

}

int ketthuc()

{ int i;

for (i=0; i<n; ++i)

if (!kt[i]) return 0;

return 1;

}

int main()

{ float td;

int tt,i,ok;

8

Page 9: He Dieu Hanh

system("cls");

cout<<"So luong tien trinh tham gia: "; cin>>n;

for (i=0; i<n; ++i) {

cout<<"Thoi diem tien trinh "<<i<<" xuat hien: "; cin>>b[i];

cout<<"Thoi gian de tien trinh hoan thanh: "; cin>>t[i];

}

for (i=0; i<n; ++i) {vt[i]=i; kt[i]=0;}

sort();

i=1; td=b[vt[0]];

f1=f2=f3=r1=r2=r3=0;

push(q1,vt[0],f1,r1);

while (!ketthuc()) {

if (!isempty(q1,f1,r1)) {

tt=pop(q1,f1,r1);

if (t[tt]>8) {

cout<<td<<" -> "<<td+8<<" Tien trinh "<<tt<<" dang chay"<<endl;

td+=8; t[tt]-=8; push(q2,tt,f2,r2);

}

else {

cout<<td<<" -> "<<td+t[tt]<<" Tien trinh "<<tt<<" chay va ket thuc"<<endl;

td+=t[tt]; kt[tt]=1;

}

}

else if(!isempty(q2,f2,r2)) {

tt=pop(q2,f2,r2);

9

Page 10: He Dieu Hanh

if (t[tt]>16) {

cout<<td<<" -> "<<td+16<<" Tien trinh "<<tt<<" dang chay"<<endl;

td+=16; t[tt]-=16; push(q3,tt,f3,r3);

}

else {

cout<<td<<" -> "<<td+t[tt]<<" Tien trinh "<<tt<<" chay va ket thuc"<<endl;

td+=t[tt]; kt[tt]=1;

}

}

else if (!isempty(q3,f3,r3)) {

tt=pop(q3,f3,r3);

cout<<td<<" -> "<<td+t[tt]<<" Tien trinh "<<tt<<" chay va ket thuc"<<endl;

td+=t[tt]; kt[tt]=1;

}

ok=0;

while ((i<n)&&(b[vt[i]]<=td)) {

ok=1;

push(q1,vt[i],f1,r1);

++i;

}

if ((i<n)&&(!ok)) {td=b[vt[i]]; push(q1,vt[i],f1,r1); ++i;}

}

system("pause");

}

10

Page 11: He Dieu Hanh

+ Ví dụ:

Tiến trìnhThời điểm vào hệ

thốngThời gian thực thi

0 2 9

1 1 4

2 0 40

Kết quả:

0 ->8 Tiến trình 2 đang chạy...

8 ->12 Tiến trình 1 chạy và kết thúc

12 ->20 Tiến trình 0 đang chạy...

20 ->36 Tiến trình 2 đang chạy...

36 ->37 Tiến trình 0 chạy và kết thúc

37 ->53 Tiến trình 2 chạy và kết thúc

D Bài toán người đọc và biên tập viên

+ Yêu cầu:

Nhiều tiến trình (Readers) cùng truy cập cơ sở dữ liệu (CSDL).

Một số tiến trình (Writers) cập nhật CSDL.

Cho phép một số lượng tùy ý các tiến trình (Readers) cùng truy cập CSDl. Đang tồn tại một tiến trình Reader truy cập CSDL, mọi tiến trình Readers khác mới xuất hiện đều được truy cập CSDL (Tiến trình Writers phải xếp hàng chờ đợi.

Chỉ cho phép một tiến trình Writers cập nhật CSDL tại một thời điểm

11

Page 12: He Dieu Hanh

Vấn đề không trưng dụng. Các tiến trình ở trong đoạn găng mà không bị ngắt.

+ Cài đặt

Khởi tạo semaphore

Mutex=1; // Kiểm tra truy xuất reader

db=1; // Kiểm tra truy xuất cơ sở dữ liệu

turnstile=1; // Dùng để điều độ tránh tình trạng đói CPU của các tiến trình Writers;

int rc=0; // Số tiến trình Readers truy cập CSDL

Readers()

{ While (1) {

Wait(turnstile);

Signal(turnstile);

// Dành quyền đọc CSDL

Wait(mutex);

//Thêm 1 tiến trình reader

rc=rc+1;

// Giành quyền truy xuất CSDL nếu là tiến trình đọc đầu tiên

if (rc==1) wait(db);

// Giải phóng quyền đọc cho các tiến trình readers khác

signal(mutex);

// Đọc cơ sở dữ liệu

read_database();

wait(mutex);

rc=rc-1;

// Nếu là readers cuối cùng thì giải phóng db để cho Writers có thể truy cập

if (rc==0) signal(db);

signal(mutex);

{Xử lí dữ liệu đọc}

12

Page 13: He Dieu Hanh

}

}

Writers()

{ While (1) {

wait(turnstile);

{Chuẩn bị dữ liệu để ghi}

// Giành quyền truy xuất cơ sở dữ liệu

wait(db);

// Cập nhật dữ liệu;

write_database();

signal(turnstile);

// Giải phóng quyền truy xuất cơ sở dữ liệu

signal(db);

}

}

+ Chương trình

#include <windows.h>#include <stdio.h>

int rc=0;HANDLE mutex, db, turnstile, mutex1;FILE *f1,*f2;

void writer(int i){while(1){

WaitForSingleObject(turnstile,INFINITE);WaitForSingleObject(db,INFINITE);f1=fopen("text","wt");fprintf(f1,"Day la lan cap nhat cua writer %d",i);fclose(f1);ReleaseSemaphore(turnstile,1,NULL);ReleaseSemaphore(db,1,NULL);

13

Page 14: He Dieu Hanh

}}

void reader(){ char s[100]; while(1){

WaitForSingleObject(turnstile,INFINITE);ReleaseSemaphore(turnstile,1,NULL);WaitForSingleObject(mutex,INFINITE);++rc; if (rc==1) WaitForSingleObject(db,INFINITE);ReleaseSemaphore(mutex,1,NULL); f1=fopen("text","rt");fgets(s,80,f1);fclose(f1);WaitForSingleObject(mutex,INFINITE);--rc;if (rc==0) ReleaseSemaphore(db,1,NULL); ReleaseSemaphore(mutex,1,NULL); WaitForSingleObject(mutex1,INFINITE);f2=fopen("ketqua","at");fprintf(f2,"%s ",s); fclose(f2);ReleaseSemaphore(mutex1,1,NULL);

}}

int main(){HANDLE h1[3], h2[10];DWORD Id;int i;f1=fopen("text","wt");fclose(f1);mutex = CreateSemaphore(NULL,1, 1, NULL);db = CreateSemaphore(NULL,1, 1, NULL);turnstile = CreateSemaphore(NULL,1, 1, NULL);mutex1 = CreateSemaphore(NULL,1, 1, NULL);for (i=0; i<3; ++i) h1[i]=CreateThread(NULL,0,

(LPTHREAD_START_ROUTINE)writer,i,0,&Id);

14

Page 15: He Dieu Hanh

for (i=0; i<10; ++i) h2[i]=CreateThread(NULL,0,

(LPTHREAD_START_ROUTINE)reader,NULL,0,&Id); WaitForMultipleObjects(3, h1, TRUE, INFINITE);WaitForMultipleObjects(10, h2, TRUE, INFINITE);getch();return 0;

}

+ 1 đoạn kết quả ví dụ khi chạy chương trình:

Day la lan cap nhat cua writer 0 Day la lan cap nhat cua writer 1 Day la lan cap nhat cua writer 0 Day la lan cap nhat cua writer 0 Day la lan cap nhat cua writer 2 Day la lan cap nhat cua writer 1 Day la lan cap nhat cua writer 0 Day la lan cap nhat cua writer 0 Day la lan cap nhat cua writer 0 Day la lan cap nhat cua writer 0

* Như vậy ta thấy các tiến trình đã được điều một cách hợp lí. Các câu in ra đầy đủ (chứng tỏ không có sự truy cập file của reader khi writer đang cập nhật), một câu có thể in ra nhiều lần liên tiếp( chứng tỏ nhiều tiến trình reader có thể truy cập file cùng lúc).

E Bài toán người thợ cắt tóc ngủ gật

+ Yêu cầu:

Có N ghế đợi dành cho khách hàng

Một người thợ chỉ có thể cắt tóc cho một khách hàng tại 1 thời điểm, nếu không có khách hàng đợi thì người thợ cắt tóc ngủ

Khi một khách hàng tới

+ Nếu thợ cắt tóc đang ngủ thì đánh thức anh ta dậy.

+ Nếu thợ cắt tóc đang làm việc:

Nếu không còn ghế đợi trống thì bỏ đi.

Nếu còn ghế bỏ trống thì ngồi đợi.

+ Cài đặt

Khởi tạo semaphore

mutex=1;

15

Page 16: He Dieu Hanh

customers=0; // Nếu customers>0 thì có nghĩa là có khách hàng đợi, nếu customers=0 thì sẽ cho thợ cắt tóc ngủ

haircut=1 // Nếu không có người đang cắt tóc thì haircut=1, nếu có người đang cắt tóc thì haircut=0;

int waiting_customers=0; //Số lượng khách hàng đang đợi

int customer()

{ wait(mutex);

if (waiting_customers>=N) {

signal(mutex); return 0;

}

waiting_customers+=1;

signal(mutex);

signal(customers);

wait(haircut);

return 1;

}

void barber()

{ while (1) {

wait (customers);

wait (mutex);

waiting_customers-=1;

signal(mutex);

cattoc();

signal(haircut);

}

}

16

Page 17: He Dieu Hanh

+ Chương trình

#include<windows.h>

#include<stdio.h>

#include<conio.h>

HANDLE mutex,haircut,customers;

int waiting_customers=0,N=10;

void customer()

{ int t;

while(1) {

t=rand()%1000;

sleep(t);

WaitForSingleObject(mutex,INFINITE);

printf(" khach vao ");

if (waiting_customers>=N) {

ReleaseSemaphore(mutex,1,NULL); return ;

}

waiting_customers+=1;

ReleaseSemaphore(mutex,1,NULL);

ReleaseSemaphore(customers,1,NULL);

WaitForSingleObject(haircut,INFINITE);

}

}

void barber()

17

Page 18: He Dieu Hanh

{ int t,ok;

while (1) {

WaitForSingleObject(mutex,INFINITE);

if (waiting_customers==0) { ok=1;printf("Tho ngu");} else ok=0;

ReleaseSemaphore(mutex,1,NULL);

WaitForSingleObject(customers,INFINITE);

WaitForSingleObject(mutex,INFINITE);

if (ok) printf(" Tho day ");

ReleaseSemaphore(mutex,1,NULL);

WaitForSingleObject(mutex,INFINITE);

waiting_customers-=1;

printf(" cat toc ");

ReleaseSemaphore(mutex,1,NULL);

t=rand()%5000;

sleep(t);

printf(" cat xong ");

ReleaseSemaphore(haircut,1,NULL);

}

}

int main()

{

HANDLE cus,bar;

DWORD Id;

int i;

srand(time(0));

mutex=CreateSemaphore(NULL,1,1,NULL);

haircut=CreateSemaphore(NULL,1,1,NULL);

18

Page 19: He Dieu Hanh

customers=CreateSemaphore(NULL,0,10,NULL);

bar = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)barber, NULL, 0, &Id);

cus=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)customer, NULL, 0, &Id);

WaitForSingleObject(cus,INFINITE);

WaitForSingleObject(bar,INFINITE);

getch();

return 0;

}

+ Kết quả :

Tho ngu khach vao Tho day cat toc cat xong Tho ngu khach vao Tho day cat toc khach vao cat xong cat toc khach vao cat xong cat toc cat xong Tho ngu ...

* Như vậy các tiến trình đã được điều độ đúng.

F Bathroom problem

+ Bài toán:

Một phòng tắm phục vụ cho cả nam và nữ nhưng chỉ phục vụ cho nam (hoặc nữ ) trong một thời điểm nhất định.

Nếu phòng tắm chưa có người thì ai cũng có thể vào.

Nếu phòng tắm đang được sử dụng thì chỉ có người cùng giới tính với người trong phòng tắm mới có thể vào.

Số lượng người sử dụng phòng tắm trong một đơn vị thời gian là có giới hạn ( trong trường hợp này ta giả sử là 5 người).

+ Yêu cầu:

Có 2 kiểu tiến trình male() và female().

Mỗi tiến trình ở trong bathroom một khoảng thời gian ngẫu nhiên.

+ Cài đặt

19

Page 20: He Dieu Hanh

int m=0; // Số nam trong phòng tắm.

fm=0; // Số nữ trong phòng tắm.

Khởi tạo semaphore

room=1; // Nếu phòng tắm trống thì room=0;

maleMultiplex=5; // Khi có 1 người là nam vào phòng tắm thì giảm maleMultiplex đi 1 và nếu có 1 người là nam ra khỏi phòng tắm thì tăng maleMultiplex lên 1.

femaleMultiplex=5; // Tương tự như maleMultiplex nhưng với điều kiện người ra ( vào) phòng tắm là nữ.

turnstile=1; // Giảm đi 1 khi có tiến trình xin vào phòng tắm. Dùng để điều độ tránh tình trạng đói CPU của tiến trình male hoặc female.

mutex1=1; // Điều độ biến đếm m;

mutex2=1; // Điều độ biến đếm fm;

mutex=1; // Điều độ quyền truy cập file văn bản in kết quả.

+ Chương trình

#include <windows.h>

#include <stdio.h>

int m=0, fm=0;

HANDLE room, maleMultiplex, femaleMultiplex, turnstile, mutex1, mutex2, mutex;

FILE *f;

void male(){

int t;

while(1){

WaitForSingleObject(turnstile,INFINITE);

WaitForSingleObject(mutex1,INFINITE);

++m;

20

Page 21: He Dieu Hanh

if (m==1) WaitForSingleObject(room,INFINITE);

ReleaseSemaphore(mutex1,1,NULL);

ReleaseSemaphore(turnstile,1,NULL);

WaitForSingleObject(maleMultiplex,INFINITE);

WaitForSingleObject(mutex,INFINITE);

f=fopen("text","at");

fprintf(f,"Nam vao ");

fclose(f);

ReleaseSemaphore(mutex,1,NULL);

// Tạo thời gian ngẫu nhiên sử dụng phòng tắm

t=rand()%5000;

sleep(t);

WaitForSingleObject(mutex,INFINITE);

f=fopen("text","at");

fprintf(f,"Nam ra ");

fclose(f);

ReleaseSemaphore(mutex,1,NULL);

ReleaseSemaphore(maleMultiplex,1,NULL);

WaitForSingleObject(mutex1,INFINITE);

--m;

if (m==0) ReleaseSemaphore(room,1,NULL);

ReleaseSemaphore(mutex1,1,NULL);

}

}

void female(){

int t;

while(1){

WaitForSingleObject(turnstile,INFINITE);

21

Page 22: He Dieu Hanh

WaitForSingleObject(mutex2,INFINITE);

++fm;

if (fm==1) WaitForSingleObject(room,INFINITE);

ReleaseSemaphore(mutex2,1,NULL);

ReleaseSemaphore(turnstile,1,NULL);

WaitForSingleObject(femaleMultiplex,INFINITE);

WaitForSingleObject(mutex,INFINITE);

f=fopen("text","at");

fprintf(f,"Nu vao ");

fclose(f);

ReleaseSemaphore(mutex,1,NULL);

// Tạo thời gian ngẫu nhiên sử dụng phòng tắm

t=rand()%5000;

sleep(t);

WaitForSingleObject(mutex,INFINITE);

f=fopen("text","at");

fprintf(f,"Nu ra ");

fclose(f);

ReleaseSemaphore(mutex,1,NULL);

ReleaseSemaphore(femaleMultiplex,1,NULL);

WaitForSingleObject(mutex2,INFINITE);

--fm;

if (fm==0) ReleaseSemaphore(room,1,NULL);

ReleaseSemaphore(mutex2,1,NULL);

}

}

int main(){

HANDLE h1[10], h2[10];

22

Page 23: He Dieu Hanh

DWORD Id;

int i;

srand(time(0));

mutex = CreateSemaphore(NULL,1, 1, NULL);

room = CreateSemaphore(NULL,1, 1, NULL);

turnstile = CreateSemaphore(NULL,1, 1, NULL);

mutex1 = CreateSemaphore(NULL,1, 1, NULL);

mutex2 = CreateSemaphore(NULL,1, 1, NULL);

femaleMultiplex = CreateSemaphore(NULL,5, 5, NULL);

maleMultiplex = CreateSemaphore(NULL,5, 5, NULL);

for (i=0; i<10; ++i)

h1[i] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)male, NULL, 0, &Id);

for (i=0; i<10; ++i)

h2[i] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)female, NULL, 0, &Id);

WaitForMultipleObjects(10, h1, TRUE, INFINITE);

WaitForMultipleObjects(10, h2, TRUE, INFINITE);

getch();

return 0;

}

+ Một kết quả chạy khi chạy chương trình:

Nam vao Nam vao Nam vao Nam vao Nam vao Nam ra Nam vao Nam ra Nam vao Nam ra Nam vao Nam ra Nam ra Nam vao Nam vao Nam ra Nam ra Nam ra Nam ra Nam ra Nu vao Nu vao Nu vao Nu vao Nu vao Nu ra Nu ra Nu vao Nu ra Nu ra Nu vao Nu ra Nu vao Nu vao Nu vao Nu ra Nu ra Nu ra Nu ra Nu ra Nam vao Nam vao Nam vao Nam vao Nam vao

* Như vậy ta thấy cách điều phối này đảm bảo sự công bằng nhưng không khai thác được tối đa khả năng phục vụ của phòng tắm. Ví dụ: Khi có ít hơn 5 người

23

Page 24: He Dieu Hanh

đàn ông trong phòng tắm, 1 người phụ nữ đến chờ thì những người đàn ông đến sau người phụ nữ này cũng sẽ phải chờ trong khi vẫn còn chỗ trống trong phòng tắm.

G Producer Consumer

+ Bài toán

Đồng bộ hóa nhiều Producer , nhiều consumer dùng đèn hiệu

+ Yêu cầu:

Producer sản xuất ra cần nào consumer sã tiêu thụ cần đấy

Điều hòa count để chi có duy nhất 1 tiến trình truy cập nó tại 1 thời điểm

Đồng bộ hóa trong mỗi Producer và consumer

+ Khởi tạo :

Đèn empty xem buffer rỗng hay không. Khởi tạo là max = kích thước buffer,

và giá trị cực đại cũng là max

Đèn full kiểm tra bufer đầy hay không. Khởi tạo là 0 và cực đại là max kích thước buffer

Đèn mutex điều phối các tiến trình trong 1 producer , consumer. Khi có nhiều producer và consumer. Khởi tạo là 1 và cực đại là 1.

Đèn s điều phối count, sao cho tại một thời điểm chỉ có 1 tiến trình được dùng count. Khởi tạo là 1 và cực đại là 1.

+Chương trình

#include<windows.h>

#include<iostream.h>

#include<stdio.h>

#include<conio.h>

#define max 10

#define maxProducer 100

#define maxConsumer 100

HANDLE s,empty,full,mutex;

24

Page 25: He Dieu Hanh

int buffer[max],in=0,out=0,count=0,tam;

void producer() {

while (1) {

while (count==max);

WaitForSingleObject(empty,INFINITE);

WaitForSingleObject(mutex,INFINITE);

{

buffer[in]=in;

in=(in+1)%max;

}

ReleaseSemaphore(mutex,1,NULL);

ReleaseSemaphore(full,1,NULL);

WaitForSingleObject(s,INFINITE);

++count;

ReleaseSemaphore(s,1,NULL);

}

}

/*consumer se in ra theo thu tu producer nhap vao tu 0 toi 9 lien tuc */

void consumer() {

while (1) {

while (count==0);

WaitForSingleObject(full,INFINITE);

WaitForSingleObject(mutex,INFINITE);

{

tam=buffer[out];

buffer[out]=0;

printf("%d ",tam);

out=(out+1)%max;

25

Page 26: He Dieu Hanh

}

ReleaseSemaphore(mutex,1,NULL);

ReleaseSemaphore(empty,1,NULL);

WaitForSingleObject(s,INFINITE);

--count;

ReleaseSemaphore(s,1,NULL);

}

}

int main()

{

HANDLE Producer[maxProducer];

HANDLE Consumer[maxConsumer];

DWORD Id;

int m,n,i;

cout<<"Nhap so luong cua Producer :"; cin>>n;

cout<<"nhap so luong cua Consumer :"; cin>>m;

s=CreateSemaphore(0,1,1,0);

mutex=CreateSemaphore(0,1,1,0);

empty=CreateSemaphore(0,max,max,0);

full=CreateSemaphore(0,0,max,0);

for(i=0; i<n; i++)

Producer[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)producer,NULL,0,&Id);

26

Page 27: He Dieu Hanh

for(i=0; i<m; i++)

Consumer[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)consumer,NULL,0,&Id);

WaitForMultipleObjects(n, Producer,TRUE, INFINITE);

WaitForMultipleObjects(m, Consumer,TRUE, INFINITE);

getch();

return 0;

}

+Kết quả :

0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9

0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9

0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9

H Dining philosophers

+ Bài toán:

5 triết gia ăn tối quanh một bàn tròn

Trước mỗi triết gia có một đĩa mì

Giữa hai đĩa kề nhau có một cái dĩa

Các triết gia thực hiện luân phiên, liên tục hai việc: Ăn và Nghĩ

Mỗi triết gia cần 2 cái dĩa để ăn

Chỉ lấy một dĩa tại một thời điểm

Cái bên trái trước rồi cái bên phải

27

Page 28: He Dieu Hanh

Ăn xong để dĩa vào vị trí cũ

Viết chương trình đồng bộ bữa tối 5 triết gia

+ Khởi tạo semaphore

Các fork bằng 1 và giá trị tối đa là 1

+ Chương trình :

#include<windows.h>

#include<iostream.h>

#include<stdio.h>

#include<conio.h>

HANDLE fork[5],mutex;

void Dining(int i)

{

int j,p,q;

while(1)

{

j = i%2;

p=(i + j)%5;

q=(i+1 - j)% 5;

WaitForSingleObject(fork[p],INFINITE);

WaitForSingleObject(fork[q],INFINITE);

WaitForSingleObject(mutex,INFINITE);

cout<<" triet gia "<<i<<"lay dia"<<p<<"va"<<q<<" ";

ReleaseSemaphore(mutex,1,NULL);

ReleaseSemaphore(fork[q],1,NULL);

ReleaseSemaphore(fork[p],1,NULL);

WaitForSingleObject(mutex,INFINITE);

28

Page 29: He Dieu Hanh

cout<<" triet gia "<<i<<" nghi"<<" ";

ReleaseSemaphore(mutex,1,NULL);

}

}

int main()

{

int i;

HANDLE philosopher[5];

DWORD Id;

for(i=0; i<5; i++)

fork[i]=CreateSemaphore(0,1,1,0);

mutex=CreateSemaphore(0,1,1,0);

for(i=0; i<5; i++)

philosopher[i] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Dining,(void *)i,0,&Id);

getch();

return 0;

}

Kết quả :

Triet gia 0 nghi triet gia 1 lay dia 2 va 1 triet gia 1 nghi triet gia 2 lay dia 2 va 3 triet gia 2 nghi triet gia 3 lay dia 4 va 3

triet gia 3 nghi triet gia 4 lay dia 4 va 0 triet gia 2 nghi

29

Page 30: He Dieu Hanh

triet gia 1 lay dia 2 va 1 triet gia 3 lay dia 4 va 3 triet gia 4 nghi triet gia 0 lay dia 0 va 1

I Bài toán tạo phân tử H2O

+ Yêu cầu:

Có 2 kiểu tiến trình (luồng): oxygen và hydrogen

Để kết hợp các tiến trình thành phân tử nước, cần 1 ba-ri-e để các tiến trình phải đợi cho tới khi một phân tử nước sẵn sàng được tạo ra.

Khi mỗi tiến trình vượt qua ba-ri-e, nó phải kích hoạt liên kết.

Tất cả các tiến trình trong cùng một phân tử nước phải tạo liên kết, trước khi một tiến trình của phân tử nước khác gọi tới thủ tục tạo liên kết.

+ Khởi tạo:

int oxygen=0; // Số lượng nguyên tử oxy sản xuất được.

hydrogen=0; // Số lượng nguyên tử hydro sản xuất được.

Semaphore:

mutex=1; // Đèn báo bảo vệ 2 biến đếm oxygen và hydrogen.

oxyqueue =0; // Hàng đợi của các nguyên tử oxy.

hydroqueue=0; // Hàng đợi của các nguyên tử hydro.

+ Chương trình:

#include <windows.h>

#include<stdio.h>

int oxygen=0, hydrogen=0;

HANDLE mutex, oxyqueue, hydroqueue;

void Oxygen()

{while (1) {

WaitForSingleObject(mutex,INFINITE);

30

Page 31: He Dieu Hanh

// Tạo 1 nguyên tử oxy

oxygen+=1; printf("Tao oxy ");

if (hydrogen>=2) {

// Loại 2 nguyên tử hydro ra khỏi hàng đợi hydroqueue

ReleaseSemaphore(hydroqueue,2,NULL);

hydrogen-=2;

// Loại 1 nguyên tử oxy ra khỏi hàng đợi oxyqueue

ReleaseSemaphore(oxyqueue,1,NULL);

oxygen-=1;

}

// Khi chưa tạo được liên kết thì nguyên tử phải chờ

else { printf("Oxy cho "); ReleaseSemaphore(mutex,1,NULL);}

// Nạp 1 nguyên tử oxy vào hàng đợi oxyqueue

WaitForSingleObject(oxyqueue,INFINITE);

printf("Oxy sinh lien ket ");

ReleaseSemaphore(mutex,1,NULL);

}

}

void Hydrogen()

{ while (1) {

WaitForSingleObject(mutex,INFINITE);

// Tạo 1 nguyên tử hydro

hydrogen+=1; printf("Tao hydro ");

if ((hydrogen>=2)&&(oxygen>=1)) {

ReleaseSemaphore(hydroqueue,2,NULL);

hydrogen-=2;

ReleaseSemaphore(oxyqueue,1,NULL);

31

Page 32: He Dieu Hanh

oxygen-=1;

}

// Khi chưa tạo được liên kết thì nguyên tử phải chờ

else {printf("Hydro cho "); ReleaseSemaphore(mutex,1,NULL);}

// Nạp 1 nguyên tử hydro vào hàng đợi hydroqueue

WaitForSingleObject(hydroqueue,INFINITE);

printf("Hydro sinh lien ket ");

}

}

int main()

{ HANDLE h1[10], h2[20];

DWORD Id;

int i=0,j=0,k;

srand(time(0));

mutex = CreateSemaphore(NULL,1, 1, NULL);

oxyqueue = CreateSemaphore(NULL,0, 10, NULL);

hydroqueue = CreateSemaphore(NULL,0, 10, NULL);

do {

k=rand()%50;

if ((k%2==0)&&(i<10)) {h1[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Oxygen, NULL, 0, &Id); ++i;}

else if (j<20) { h2[j] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Hydrogen, NULL, 0, &Id); ++j;}

} while ((j<20)&&(i<10));

WaitForMultipleObjects(10, h1, TRUE, INFINITE);

WaitForMultipleObjects(20, h2, TRUE, INFINITE);

getch();

return 0;

32

Page 33: He Dieu Hanh

}

+ Một kết quả khi chạy chương trình:

Tao oxy Oxy cho Tao hydro Hydro cho Tao hydro Hydro sinh lien ket Oxy sinh lien ket Hydro sinh lien ket Tao hydro Hydro cho Tao oxy Oxy cho Tao oxy Oxy cho Tao oxy Oxy cho Tao hydro Hydro sinh lien ket Hydro sinh lien ket Oxy sinh lien ket Tao oxy Oxy cho Tao oxy Oxy cho Tao oxy Oxy cho Tao hydro Hydro cho Tao hydro Hydro sinh lien ket Hydro sinh lien ket Oxy sinh lien ket Tao hydro Hydro cho Tao oxy Oxy cho Tao hydro Hydro sinh lien ket Oxy sinh lien ket Hydro sinh lien ket Tao hydro Hydro cho Tao hydro Hydro sinh lien ket Hydro sinh lien ket Oxy sinh lien ket Tao oxy Oxy cho Tao oxy Oxy cho ...

* Kết quả cho thấy các tiến trình đã được điều độ đúng đắn ( ngay khi có đủ 1 nguyên tử oxy và 2 nguyên tử hydro thì lập tức tạo liên kết sinh ra phân tử H2O)

J Đọc Master Boot Record, đưa ra các phân vùng chính của ổ cứng, nếu phân vùng ổ C sử dụng hệ thống file FAT32 thì đưa ra thông tin về ổ.

+ Chương trình

#include <windows.h>

#include <stdio.h>

int main(int argc, char *argv[]){

HANDLE hDisk, hpartition;

BYTE Buf[512];

int byteread, i, t1;

long t;

hDisk = CreateFile("\\\\.\\PhysicalDrive0", GENERIC_READ,

FILE_SHARE_READ | FILE_SHARE_WRITE,

NULL,OPEN_EXISTING,0,NULL);

if (hDisk == INVALID_HANDLE_VALUE) printf("Loi thiet bi");

else {

33

Page 34: He Dieu Hanh

ReadFile(hDisk,Buf,512,byteread,NULL);

for(i=0; i<512;i++) printf(" %02X ",Buf[i]);

}

i=446;

printf("\n");

printf("____________________________________________________________________________\n");

printf(" | | Starting | Ending | Sector | Number |\n");

printf(" Type | Boot |____________________|____________________| before | of |\n");

printf(" | | HdR | Cyl | Sect | HdR | Cyl | Sect | | sector |\n");

printf("________|______|_____|_______|______|_____|_______|______|________|_________|\n");

do {

if (Buf[i+4]==0x0B) printf(" Fat32 |");

else if((Buf[i+4]>=0x05)&&(Buf[i+4]<=0x0F)) printf("Extended|");

else printf(" Unused |");

if (Buf[i]==0x80) printf(" Yes |"); else printf(" No |");

printf(" %3d |",Buf[i+1]);

t1=Buf[i+2]+Buf[i+3]*256;

printf(" %3d |",t1>>6);

printf(" %2d |",t1&0x3f);

printf(" %3d |",Buf[i+5]);

t1=Buf[i+6]+Buf[i+7]*256;

printf(" %3d |",t1>>6);

printf(" %2d |",t1&0x3f);

t=Buf[i+8]+Buf[i+9]*256+Buf[i+10]*256*256+Buf[i+11]*256*256*256;

printf("%8d|",t);

34

Page 35: He Dieu Hanh

t=Buf[i+12]+Buf[i+13]*256+Buf[i+14]*256*256+Buf[i+15]*256*256*256;

printf("%9d|",t);

i+=16;

printf("\n");

} while (i<495);

CloseHandle(hDisk);

hpartition = CreateFile("\\\\.\\C:", GENERIC_READ,

FILE_SHARE_READ | FILE_SHARE_WRITE,

NULL,OPEN_EXISTING,0,NULL);

if (hpartition == INVALID_HANDLE_VALUE) printf("Loi thiet bi");

else {

ReadFile(hpartition,Buf,512,byteread,NULL);

for(i=0; i<512;i++) printf(" %02X ",Buf[i]);

}

printf("Kich thuoc 1 sector: %d byte",Buf[11]+Buf[12]*256);

CloseHandle(hpartition);

return 0;

}

K Tài liệu tham khảo:

+ Giáo trình Hệ điều hành của TS. Phạm Đăng Hải - Đại học Bách Khoa Hà Nội

+ The Little Book of Semaphore – Allen B.Downey

35