1. Trang chủ
  2. » Giáo Dục - Đào Tạo

Môn hệ Điều hành bài tập thực hành 5

39 0 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Môn hệ điều hành bài tập thực hành 5
Tác giả Bùi Anh Khôi
Người hướng dẫn GVHD: Nguyễn Xuân Duy
Trường học Đại Học Quốc Gia Thành Phố Hồ Chí Minh - Trường Đại Học Công Nghệ Thông Tin
Chuyên ngành Hệ Điều Hành
Thể loại Bài tập thực hành
Năm xuất bản 2025
Thành phố Thành phố Hồ Chí Minh
Định dạng
Số trang 39
Dung lượng 589,12 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

NỘI DUNG BÀI LÀM Phân biệt các khái niệm chương trình program, tiến trình process và tiểu trình thread?. - Chương trình là tập hợp các câu lệnhd được viết bằng ngôn ngữ lập tình, chưa đ

Trang 1

TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN

KHOA KỸ THUẬT MÁY TÍNH

MÔN HỆ ĐIỀU HÀNH BÀI TẬP THỰC HÀNH 5

GVHD: Nguyễn Xuân Duy Bách Sinh viên thực hiện: Bùi Anh Khôi - 23520759

 Tp Hồ Chí Minh, 05/2025 

Trang 2

NHẬN XÉT CỦA GIÁO VIÊN HƯỚNG DẪN

……., ngày…… tháng……năm 2025

Người nhận xét

(Ký tên và ghi rõ họ tên)

Trang 4

NỘI DUNG BÀI LÀM

Phân biệt các khái niệm chương trình (program), tiến trình (process) và tiểu trình (thread)?

- Chương trình là tập hợp các câu lệnhd được viết bằng ngôn ngữ lập tình, chưa được thực thi và nó tồn tại ở dạng tĩnh

- Tiến trình làm một thực thể động, là chương trình đang được thực thi Một chương trình có thể tạo ra nhiều tiến trình và mỗi tiến trình có không gian bộ nhớ và tài nguyên riêng

- Tiểu trình là đơn vị nhỏ hơn trong tiến trình, dùng để chia sẻ tài nguyên và thực thi song song trong cùng một tiến trình Tất cả các thread của một tiến trình

dùng chung không gian địa chỉ và tài nguyên

Sự tranh chấp xảy ra khi nào? Cho ví dụ

- Sự tranh chấp xảy ra khi nhiều tiến trình hoặc thread cùng truy cập và thay đổi một thời nguyên dùng chung mà không có cơ chế đồng bộ hợp lý

- Ví dụ:

o Có 2 thread A và B cùng tăng giá trị biến x = 0, khi đó cả hai cùng đọc x

= 0, rồi cùng cộng 1 và ghi x = 1, kết quả mong muốn cả người dùng là x

= 2, nhưng thực tế x = 1 từ đó ta thấy được sự tranh chấp của cả 2 biến A

o Tốn CPU: Ở giải pháp này tốn CPU rất nhiều vì kiểm tra liên tục

o Độ phức tạp: Giải pháp này dễ dàng lập trình nhưng không hiệu quả

o Phạm vi hoạt động: Dùng ở một số hệ điều hành cũ, hoặc phần cứng đơn giản

- Sleep & wake up

Trang 5

o Cách hoạt động: tiến trình ngủ khi không thể tiếp tục và chỉ thức dậy khi

o Phạm vi hoạt động: Dùng ở hầu hết hệ điều hành hiện đại

- Ví dụ về một số hệ điều hành sử dụng 2 nhóm giải pháp trên:

o Busy waiting: một số hệ điều hành thời gian thực đơn giản, hoặc các hệ thóng nhúng không dùng interupt

o Sleep and wake up:

#define MSSV_4SOCUOI 759 // 4 số cuối của MSSV: 0759

#define MIN_ROUNDS 10 // Bắt đầu kiểm tra sau 10 vòng

int sells = 0; // Số sản phẩm đã bán

int products = 0; // Số sản phẩm đã tạo

int rounds = 0; // Số vòng đã chạy

sem_t sem, sem1; // Semaphore để đồng bộ luồng

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // Khóa mutex để bảo vệ dữ liệu dùng chung

Trang 6

// Hàm kiểm tra điều kiện an toàn sau MIN_ROUNDS vòng

void check_condition() {

pthread_mutex_lock(&mutex); // Khóa mutex khi truy cập biến toàn cục

rounds++; // Tăng số vòng

if (rounds >= MIN_ROUNDS) {

if (products < sells || products > sells + MSSV_4SOCUOI) {

printf("VI PHẠM: sells = %d, products = %d → DỪNG CHƯƠNG TRÌNH!\n", sells, products); exit(0); // Vi phạm điều kiện: kết thúc chương trình

sem_wait(&sem); // Đợi đến lượt

int rand_sells = (rand() % 5) + 1; // Ngẫu nhiên từ 1–5

sells += rand_sells;

printf("BÁN: +%d → sells = %d (max: %d)\n", rand_sells, sells, sells + MSSV_4SOCUOI);

check_condition(); // Kiểm tra điều kiện sau khi bán

sem_post(&sem1); // Cho phép luồng sản xuất chạy

}

return NULL;

}

// Tiến trình B: mô phỏng tạo sản phẩm

void* processB(void* arg) {

while (1) {

sem_wait(&sem1); // Đợi đến lượt

int rand_products = (rand() % 5) + 1; // Ngẫu nhiên từ 1–5

products += rand_products;

Trang 7

printf("TẠO: +%d → products = %d\n", rand_products, products);

check_condition(); // Kiểm tra điều kiện sau khi tạo

sem_post(&sem); // Cho phép luồng bán tiếp tục

}

return NULL;

}

int main() {

srand(time(NULL)); // Khởi tạo seed cho random

// Khởi tạo semaphore

sem_init(&sem, 0, 1); // Cho phép A chạy đầu tiên

sem_init(&sem1, 0, 0); // B chờ

// Tạo 2 luồng

pthread_t tA, tB;

pthread_create(&tA, NULL, processA, NULL);

pthread_create(&tB, NULL, processB, NULL);

// Chờ 2 luồng (sẽ kết thúc nếu điều kiện vi phạm)

Trang 8

o Khai báo và khởi tạo

▪ Nội dung code

#define MSSV_4SOCUOI 759

#define MIN_ROUNDS 10

int sells = 0, products = 0, rounds = 0;

sem_t sem, sem1;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

▪ MSSV_4SOCUOI: là giới hạn trên để kiểm tra điều kiện

▪ MIN_ROUNDS: Số vòng tối thiểu trước khi bắt đầu kiểm tra điều kiện

▪ Khai báo các biến toàn cục:

• sells: Tổng số sản phẩm đã bán

Trang 9

• products: Tổng số sản phẩm sản xuất

• rounds: Số vòng giao tiếp giữa A và B diễn ra

▪ Semaphore: sem, sem1: đồng bộ luồng A và B

▪ Mutex: mutex: bảo vệ khi truy cập biến toàn cục trong môi trường đa luồng

▪ Tiến trình bán hàng chờ đến lượt chạy bằng sem_wait(&sem)

▪ Thực hiện random bán ngẫu nhiên 1 – 5 sản phẩm

▪ Gọi hàm check_condition() để kiểm tra điều kiện

▪ Gửi tín hiệu cho tiến trình tạo sản phẩm bằng sem_post(&sem1)

Trang 10

▪ Tiến trình sản xuất chờ đến lượt chạy bằng sem_wait(&sem1)

▪ Thực hiệnm random sản xuất ngẫu nhiên 1 – 5 sản phẩm

▪ Gọi hàm check_condition() để kiểm tra điều kiện

▪ Gửi tiến hiệu cho tiến trình bán bằng sem_post(&sem)

o Hàm main()_Khởi tạo và chờ luồng

▪ Nội dung code int main() {

srand(time(NULL));

sem_init(&sem, 0, 1); // A chạy trước

sem_init(&sem1, 0, 0); // B chờ

pthread_t tA, tB;

pthread_create(&tA, NULL, processA, NULL);

pthread_create(&tB, NULL, processB, NULL);

▪ Dùng srand() để tạo số ngẫu nhiên khác nhau mỗi lần chạy chương trình

▪ Khởi tạo semaphort: A được phép chạy đầu tiên, B phải đợi

▪ Tạo 2 luồng A và B hoạt động song song vơi snhau

▪ pthread_join giúp chương trình chínhd đợi đến khi có lỗi thì kết thúc

▪ Dọn dẹp tài ngyên khi semaphort kết thúc

Trang 11

int count = 0; // số phần tử hiện tại trong mảng

void* producer(void* arg) {

while (1) {

if (count < MAX) {

int num = rand() % 100;

a[count] = num; // thêm số vào cuối mảng

Trang 12

}

int main() {

pthread_t prod, cons;

pthread_create(&prod, NULL, producer, NULL);

pthread_create(&cons, NULL, consumer, NULL);

Producer: Added 83 → count = 1

Producer: Added 86 → count = 2

Consumer: Removed 86 → count = 1

Producer: Added 77 → count = 2

Consumer: Removed 77 → count = 1

Producer: Added 15 → count = 2

Producer: Added 93 → count = 3

Consumer: Removed 93 → count = 2

Producer: Added 35 → count = 3

Consumer: Removed 35 → count = 2

Producer: Added 86 → count = 3

Producer: Added 92 → count = 4

Consumer: Removed 92 → count = 3

Producer: Added 49 → count = 4

Consumer: Removed 49 → count = 3

Producer: Added 21 → count = 4

Producer: Added 62 → count = 5

Consumer: Removed 62 → count = 4

Producer: Added 27 → count = 5

Consumer: Removed 27 → count = 4

Producer: Added 90 → count = 5

Producer: Added 59 → count = 6

Consumer: Removed 59 → count = 5

Trang 13

Producer: Added 63 → count = 6

Consumer: Removed 63 → count = 5

Producer: Added 26 → count = 6

Producer: Added 40 → count = 7

Consumer: Removed 40 → count = 6

Producer: Added 26 → count = 7

Consumer: Removed 26 → count = 6

Producer: Added 72 → count = 7

Producer: Added 36 → count = 8

Consumer: Removed 36 → count = 7

Producer: Added 11 → count = 8

Consumer: Removed 11 → count = 7

Producer: Added 68 → count = 8

Producer: Added 67 → count = 9

Consumer: Removed 67 → count = 8

Producer: Added 29 → count = 9

Consumer: Removed 29 → count = 8

Producer: Added 82 → count = 9

Producer: Added 30 → count = 10

Consumer: Removed 30 → count = 9

Producer: Added 62 → count = 10

Consumer: Removed 62 → count = 9

Producer: Added 23 → count = 10

Consumer: Removed 23 → count = 9

Producer: Added 67 → count = 10

Consumer: Removed 67 → count = 9

Producer: Added 35 → count = 10

Consumer: Removed 35 → count = 9

Producer: Added 29 → count = 10

Consumer: Removed 29 → count = 9

Producer: Added 2 → count = 10

Consumer: Removed 2 → count = 9

Producer: Added 22 → count = 10

Consumer: Removed 22 → count = 9

Producer: Added 58 → count = 10

Consumer: Removed 58 → count = 9

Producer: Added 69 → count = 10

Consumer: Removed 69 → count = 9

Producer: Added 67 → count = 10

Trang 14

Consumer: Removed 67 → count = 9

Producer: Added 93 → count = 10

Consumer: Removed 93 → count = 9

Producer: Added 56 → count = 10

Consumer: Removed 56 → count = 9

Producer: Added 11 → count = 10

^C

bui@bui-VirtualBox:~/Downloads/LAB5$

- Ta tìm thấy các lỗi như sau:

o Chương trình in ra “Nothing in array a” trong khi producer đã thêm phần tử vì consumer đọc count trước khi producer cập nhật count do thiếu đồng bộ đọc-ghi biến chung

o Count tăng giảm không theo thứ tự chính xác

o Producer và Consumer cùng truy cập mảng không đồng bộ, cùng đọc và ghi mảng mà không khóa truy cập dẫn đến lỗi dữ liệu

- Chương trình đã thực hiện đồng bộ bằng semaphore

int count = 0; // số phần tử hiện tại trong buffer

int in = 0; // chỉ số chèn phần tử tiếp theo

int out = 0; // chỉ số lấy phần tử tiếp theo

sem_t emptySlots; // semaphore đếm số ô trống trong buffer

sem_t fullSlots; // semaphore đếm số ô đầy trong buffer

Trang 15

pthread_mutex_t mutex; // mutex để bảo vệ truy cập buffer và biến count

void *producer(void *arg) {

int item;

while (1) {

item = rand() % 100;

sem_wait(&emptySlots); // chờ nếu buffer đầy

pthread_mutex_lock(&mutex); // khóa truy cập buffer

// Thêm phần tử vào buffer

sem_post(&fullSlots); // báo có thêm phần tử

sleep(rand() % 2); // giả lập thời gian sản xuất

sem_wait(&fullSlots); // chờ nếu buffer rỗng

pthread_mutex_lock(&mutex); // khóa truy cập buffer

Trang 16

// Lấy phần tử ra khỏi buffer

sem_post(&emptySlots); // báo có thêm ô trống

sleep(rand() % 2); // giả lập thời gian tiêu thụ

}

return NULL;

}

int main() {

pthread_t prodThread, consThread;

// Khởi tạo semaphore và mutex

sem_init(&emptySlots, 0, BUFFER_SIZE); // ban đầu buffer có BUFFER_SIZE ô trống

sem_init(&fullSlots, 0, 0); // ban đầu buffer chưa có phần tử nào

pthread_mutex_init(&mutex, NULL);

// Tạo thread Producer và Consumer

pthread_create(&prodThread, NULL, producer, NULL);

pthread_create(&consThread, NULL, consumer, NULL);

// Chờ 2 thread chạy (thường không return)

pthread_join(prodThread, NULL);

Trang 17

Producer: Added 83 → count = 1

Consumer: Removed 83 → count = 0

Producer: Added 15 → count = 1

Consumer: Removed 15 → count = 0

Producer: Added 86 → count = 1

Producer: Added 49 → count = 2

Consumer: Removed 86 → count = 1

Consumer: Removed 49 → count = 0

Producer: Added 90 → count = 1

Consumer: Removed 90 → count = 0

Producer: Added 63 → count = 1

Consumer: Removed 63 → count = 0

Producer: Added 72 → count = 1

Producer: Added 11 → count = 2

Consumer: Removed 72 → count = 1

Producer: Added 29 → count = 2

Producer: Added 30 → count = 3

Producer: Added 23 → count = 4

Consumer: Removed 11 → count = 3

Producer: Added 29 → count = 4

Producer: Added 22 → count = 5

Producer: Added 69 → count = 6

Consumer: Removed 29 → count = 5

Producer: Added 93 → count = 6

Consumer: Removed 30 → count = 5

Trang 18

Consumer: Removed 23 → count = 4

Consumer: Removed 29 → count = 3

Producer: Added 73 → count = 4

Consumer: Removed 22 → count = 3

Consumer: Removed 69 → count = 2

Producer: Added 98 → count = 3

Producer: Added 15 → count = 4

Producer: Added 13 → count = 5

Producer: Added 91 → count = 6

Producer: Added 56 → count = 7

Producer: Added 62 → count = 8

Producer: Added 96 → count = 9

Consumer: Removed 93 → count = 8

Producer: Added 25 → count = 9

Producer: Added 27 → count = 10

Consumer: Removed 73 → count = 9

Producer: Added 46 → count = 10

Consumer: Removed 98 → count = 9

Producer: Added 57 → count = 10

Consumer: Removed 15 → count = 9

Producer: Added 95 → count = 10

Consumer: Removed 13 → count = 9

Consumer: Removed 91 → count = 8

^C

bui@bui-VirtualBox:~/Downloads/LAB5$

- So sánh giữa 2 kết quả chương trinh

Kiểm soát số phần tử buffer Có thể vượt giới hạn Được giới hạn bởi empty/ full

Độ chính xác biến count Có thể sai do race conditiion Luôn đúng vì có mutex bảo vệ Trật tự hoạt động Producer có thể thêm liên tục Luân phiên ổn định

Câu 3

- Code

#include <stdio.h>

#include <pthread.h>

Trang 19

int x = 0;

void* processA(void* arg) {

for (int i = 0; i < 30; i++) {

void* processB(void* arg) {

for (int i = 0; i < 30; i++) {

pthread_create(&t1, NULL, processA, NULL);

pthread_create(&t2, NULL, processB, NULL);

Trang 24

o Process A chạy trước và hoàn thành toàn bộ 30 vòng lặp

o Sau đó, process B mới bắt đầu chạy:

o Kết quả:

▪ A bắt đầu từ x = 0 và sau 30 bước, x = 10

▪ Nhưng B bắt đầu từ x = 13 rồi quay lại x = 11 => điều này chứng tỏ có xảy ra lỗi race condition

 Chương trình hiện tại đang có lỗi racecondition và cần khắc phục bằng phương pháp đồng bộ sử dụng mutex

Trang 25

for (int i = 0; i < 30; i++) {

void* processB(void* arg) {

for (int i = 0; i < 30; i++) {

pthread_create(&t1, NULL, processA, NULL);

pthread_create(&t2, NULL, processB, NULL);

Trang 31

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

pthread_cond_t cv_v_ready = PTHREAD_COND_INITIALIZER;

pthread_cond_t cv_w_ready = PTHREAD_COND_INITIALIZER;

pthread_cond_t cv_y_ready = PTHREAD_COND_INITIALIZER;

pthread_cond_t cv_z_ready = PTHREAD_COND_INITIALIZER;

pthread_cond_t cv_final_ready = PTHREAD_COND_INITIALIZER;

int v_ready = 0, w_ready = 0, y_ready = 0, z_ready = 0;

int y_final_ready = 0, z_final_ready = 0;

Trang 34

while (!w_ready || !z_ready)

Trang 35

pthread_create(&t[0], NULL, calc_w, NULL); // (a)

pthread_create(&t[1], NULL, calc_v, NULL); // (b)

pthread_create(&t[2], NULL, calc_y, NULL); // (c)

pthread_create(&t[3], NULL, calc_z, NULL); // (d)

pthread_create(&t[4], NULL, calc_y_final, NULL); // (e)

pthread_create(&t[5], NULL, calc_z_final, NULL); // (f)

pthread_create(&t[6], NULL, calc_ans, NULL); // (g)

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

Trang 36

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

pthread_cond_t cond_v_done = PTHREAD_COND_INITIALIZER;

pthread_cond_t cond_w_y_done = PTHREAD_COND_INITIALIZER;

pthread_cond_t cond_yz_done = PTHREAD_COND_INITIALIZER;

// Các biến trạng thái báo hiệu các bước đã hoàn thành

int v_done = 0;

int w_y_done = 0;

int yz_done = 0;

▪ Biến x1 -> x6 là các dữ liệu đầu vào

▪ w, v, y, z, ans: các biến kết quả

▪ pthread_mutex_t mutex: Khóa để bảo bệ vùng truy cập

▪ ptrhead_cond_t cond_*: Điều kiện để báo hiệu giữa các thread

▪ v_done, w_y_done, yz_done: Các cờ trạng thái các bước tính toán đã hoàn thành

o Thread thực hiện w = x1 * x2 và báo hiệu

void *thread_w(void *arg) {

▪ Cập nhật w_y_done = 1 để báo các thread biết w đã xong

▪ Gọi pthread_cond_broadcast để đánh thứcc các thread đang chờ w

▪ Mở khóa mutex

o Thread thực hiện v = x3 * x4 và báo hiệu

void *thread_v(void *arg) {

Ngày đăng: 25/06/2025, 08:09

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w