You are on page 1of 18

1

TRƯỜNG ĐẠI HỌC TÔN ĐỨC THẮNG


KHOA CÔNG NGHỆ THÔNG TIN

BÀI TẬP MÔN HỌC


NHẬP MÔN HỆ ĐIỀU HÀNH

Lab 5
Nhóm: 22 Tổ: 2
Thành Viên Nhóm:
1: Phạm Tiến Sang (MSSV: 52000794)
2: Đỗ Minh Nhật (MSSV: 52000697)
3: Trần Lai Phước (MSSV: 52000705)
4: Nguyễn Quốc Minh (MSSV: 52000782)
5: Trần Quang Tiến (MSSV: 51603328)
2

NỘI DUNG BÁO CÁO KẾT QUẢ


Bài 1: Lập lịch CPU.

Yêu cầu 1.1: Tính thời gian quay vòng trung bình, thời gian chờ trung bình cho
thuật toán FCFS bằng cách chỉnh sửa bổ sung hàm schedule() trong tập tin
schedule_FCFS.c

Yêu cầu 1.2: Giả sử thời gian đến của mỗi tiến trình khác nhau và khác 0. Hãy
tiếp tục chỉnh sửa hàm schedule() trong tập tin schedule_FCFS.c. Gợi ý: Trong
tập tin schedule_FCFS.c một mảng các Task đã được dùng để chứa thông tin tiến
trình theo thứ tự "First come". Hãy sắp xếp lại mảng đó với tiêu chí "Arrival
Time First", rồi tính toán và xuất ra theo thứ tự mảng.

Yêu cầu 1.3: hiện thực tập tin schedule_priority.c. Gợi ý: tương tự yêu cầu 2,
hãy sắp mảng các Task lại theo tiêu chí "Độ ưu tiên", nếu cùng độ ưu tiên thì
dùng tiêu chí phụ là FCFS.

Yêu cầu 1.4: hiện thực tập tin schedule_sjf.c. Gợi ý: tương tự yêu cầu 2, hãy sắp
mảng các Task lại theo tiêu chí "Burst", nếu cùng độ ưu tiên thì dùng tiêu chí
phụ là FCFS.

Yêu cầu 1.5: hiện thực tập tin schedule_rr.c. Gợi ý: Mảng các Task cần cập nhật
lại Burst của mỗi tác vụ sau mỗi lần đáp ứng CPU, tác vụ nào có Burst giảm còn
0 thì xóa khỏi mảng Task.

Yêu cầu 1.6: hiện thực tập tin schedule_priority_rr.c. Gợi ý: Copy lại Yêu cầu 3
và bổ sung: nếu có nhiều tác vụ cùng độ ưu tiên thì sao chép chúng và một Mảng
khác và chạy RR trên mảng đó.
3

KẾT QUẢ THỰC HIỆN

1.1 Phần source code:


/**
* cpu.h
*/
// Độ dài định mức thời gian.
#define QUANTUM 10
// Chạy task được chỉ định cho phần thời gian sau.
void run(Task *task, int start, int slice);
/**
* task.h
* Đại diện cho 1 task trong hệ thống.
*/
#ifndef TASK_H
#define TASK_H
// Struct thể hiện task.
typedef struct task {
char *name;
int tid;
int priority;
int burst;
int arrival;
} Task;
#endif
/**
* list.h
* Danh sách cấu trúc dữ liệu chứa các task trong hệ thống.
*/
#include "task.h"
struct node {
Task *task;
struct node *next;
};
// Hoạt động thêm và xóa.
void insert(struct node **head, Task *task);
void delete(struct node **head, Task *task);
void traverse(struct node *head);
4

/**
* schedulers.h
*/
#define MIN_PRIORITY 1
#define MAX_PRIORITY 10
// Thêm 1 task vào danh sách.
void add(char *name, int priority, int arrival, int burst);
// Invoke schedule.
void schedule();
/**
* CPU.c
* CPU “ảo” để theo dõi thời gian hệ thống.
*/
#include <stdio.h>
#include "task.h"
// Chạy task này vào phần thời gian được chỉ định.
void run(Task *task, int start, int slice) {
printf("Running task = [%s] [%d] [%d] [%d] from %d to %d.\n",task->name, task->priority, task-
>arrival, task->burst, start, slice+start);
}
/**
* list.c
* Danh sách các hoạt động khác nhau.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "list.h"
#include "task.h"
// Thêm 1 task mới vào danh sách các task.
void insert(struct node **head, Task *newTask) {
// Thêm task mới vào danh sách.
struct node *newNode = malloc(sizeof(struct node));
newNode->task = newTask;
newNode->next = *head;
*head = newNode;
}
// Xóa task được chọn khỏi danh sách.
5

void delete(struct node **head, Task *task) {


struct node *temp;
struct node *prev;
temp = *head;
// Trường hợp đặc biệt - đầu danh sách.
if (strcmp(task->name,temp->task->name) == 0) {
*head = (*head)->next;
}
else {
// Phần tử cuối của mảng.
prev = *head;
temp = temp->next;
while (strcmp(task->name,temp->task->name) != 0) {
prev = temp;
temp = temp->next;
}
prev->next = temp->next;
}
}
// Bỏ qua danh sách.
void traverse(struct node *head) {
struct node *temp;
temp = head;
while (temp != NULL) {
printf("[%s] [%d] [%d]\n",temp->task->name, temp->task->priority, temp->task->burst);
temp = temp->next;
}
}
/**
* Driver.c
* Lịch trong định dạng.
* [name] [priority] [CPU burst] [arrival time]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "task.h"
#include "list.h"
6

#include "schedulers.h"
// Kích thước của mảng char task.
#define SIZE 100
int main(int argc, char *argv[]) {
FILE *in;
char *temp, *name;
char task[SIZE];
int priority, arrival, burst;
// Mở file để đọc với tên là chuỗi đối số truyền vào.
in = fopen(argv[1],"r");
// Vòng lặp lấy chuỗi kí tự cho đến hết file.
while (fgets(task,SIZE,in) != NULL) {
temp = strdup(task);
name = strsep(&temp,",");
priority = atoi(strsep(&temp,","));
arrival = atoi(strsep(&temp,","));
burst = atoi(strsep(&temp,","));
// Thêm task vào scheduler dánh sách các task.
add(name,priority,arrival,burst);
// Giải phóng bộ nhớ được cấp phát cho temp.
free(temp);
}
// Đóng file.
fclose(in);
// Invoke the scheduler
schedule();
return 0;
}
/**
* schedule_fcfs.c
* Lịch trong định dạng.
* [name] [priority] [CPU burst] [arrival time]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "task.h"
#include "cpu.h"
7

#include "schedulers.h"
// Kích thước mảng task.
#define SIZE 100
static int i=0;
Task task[SIZE];
// Thêm 1 task vào danh sách.
void add(char *name, int priority, int arrival, int burst) {
task[i].name = name;
task[i].burst = burst;
task[i].arrival = arrival;
task[i].priority = priority;
i++;
}
// Invoke scheduler FCFS.
void schedule(){
int j=0;
int time=0;
// Mảng chứa thời gian chờ và thời gian quay vòng.
int wt[SIZE], tt[SIZE];
float awt = 0, att = 0;
// Sắp xếp theo tiêu chí fcfs.
for(j=0;j<i;j++) {
for(int k = j+1;k<i;k++) {
if(task[j].arrival > task[k].arrival) {
Task temp = task[j];
task[j] = task[k];
task[k] = temp;
}
}
}
// Chạy task đã được sắp xếp và tình thời gian chờ, thời gian quay vòng.
for(j=0 ; j < i ; j++) {
// Thời gian trống không có task.
if(task[j].arrival > time){
printf("Running task = IDLE from %d to %d.\n",time,task[j].arrival);
time=task[j].arrival;
}
wt[j] = time - task[j].arrival;
8

tt[j] = wt[j] + task[j].burst;


awt += wt[j];
att += tt[j];
run(&task[j],time,task[j].burst);
time += task[j].burst;
}
printf("Average waiting time: %f\n", awt / (float) i);
printf("Average turnaround time: %f\n", att / (float) i);
}
/**
* schedule_priority.c
* Lịch trong định dạng.
* [name] [priority] [CPU burst] [arrival time]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "task.h"
#include "cpu.h"
#include "schedulers.h"
// Kích thước mảng task.
#define SIZE 100
static int i=0;
Task task[SIZE];
// Thêm 1 task vào danh sách.
void add(char *name, int priority, int arrival, int burst) {
task[i].name = name;
task[i].burst = burst;
task[i].arrival = arrival;
task[i].priority = priority;
i++;
}
// invoke the scheduler
void schedule(){
int j=0, k=-1;
int time=0;
// Mảng chứa thời gian chờ và thời gian quay vòng.
int wt[SIZE], tt[SIZE];
9

float awt = 0, att = 0;


// Sắp xếp theo priority & tiêu chí fcfs.
for(j=0;j<i;j++) {
for(int k = j+1;k<i;k++) {
// Sắp xếp priority cao nhất lên trước.
if(task[j].priority < task[k].priority) {
Task temp= task[j];
task[j]=task[k];
task[k]=temp;
}
}
}
for(j=0;j<i;j++) {
for(int k = j+1;k<i;k++) {
// Sắp xếp theo fcfs khi priority bằng nhau.
if((task[j].priority==task[k].priority) && (task[j].arrival > task[k].arrival)) {
Task temp = task[j];
task[j]=task[k];
task[k]=temp;
}
}
}
// Sắp xếp task chưa chạy vào thời gian trống.
for(j=0;j<i;j++) {
if(task[j].arrival > time) {
for (k=j+1; k < i; k++) {
if (task[k].arrival <= time) {
break;
}
}
Task temp=task[j];
task[j]=task[k];
task[k]=temp;
for(int l=j+1; l<k; l++) {
Task temp = task[l];
task[l] = task[k];
task[k] = temp;
}
10

}
time += task[j].burst;
}
// Chạy task đã được sắp xếp và tình thời gian chờ, thời gian quay vòng.
time = 0;
for(j=0 ; j < i ; j++) {
// Thời gian trống không có task.
if(task[j].arrival > time){
printf("Running task = IDLE from %d to %d.\n",time,task[j].arrival);
time=task[j].arrival;
}
wt[j] = time - task[j].arrival;
tt[j] = wt[j] + task[j].burst;
awt += wt[j];
att += tt[j];
run(&task[j],time,task[j].burst);
time += task[j].burst;
}
printf("Average waiting time: %f\n", awt / (float) i);
printf("Average turnaround time: %f\n", att / (float) i);
}
/**
* schedule_sjf.c
* Lịch trong định dạng.
* [name] [priority] [CPU burst] [arrival time]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "task.h"
#include "cpu.h"
#include "schedulers.h"
// Kích thước mảng task.
#define SIZE 100
static int i=0;
Task task[SIZE];
// Thêm 1 task vào danh sách.
void add(char *name, int priority, int arrival, int burst) {
11

task[i].name = name;
task[i].burst = burst;
task[i].arrival = arrival;
task[i].priority = priority;
i++;
}
// invoke the scheduler
void schedule(){
int j=0, k=-1;
int time=0;
// Mảng chứa thời gian chờ và thời gian quay vòng.
int wt[SIZE], tt[SIZE];
float awt = 0, att = 0;
// Sắp xếp theo priority & tiêu chí fcfs.
for(j=0;j<i;j++) {
for(int k = j+1;k<i;k++) {
// Sắp xếp thời gian làm việc thấp nhất lên trước.
if(task[j].burst > task[k].burst) {
Task temp= task[j];
task[j]=task[k];
task[k]=temp;
}
}
}
for(j=0;j<i;j++) {
for(int k = j+1;k<i;k++) {
// Sắp xếp theo fcfs khi thời gian làm việc bằng nhau.
if((task[j].burst==task[k].burst) && (task[j].arrival > task[k].arrival)) {
Task temp = task[j];
task[j]=task[k];
task[k]=temp;
}
}
}
// Sắp xếp task chưa chạy vào thời gian trống.
for(j=0;j<i;j++) {
if(task[j].arrival > time) {
for (k=j+1; k < i; k++) {
12

if (task[k].arrival <= time) {


break;
}
}
Task temp=task[j];
task[j]=task[k];
task[k]=temp;
for(int l=j+1; l<k; l++) {
Task temp = task[l];
task[l] = task[k];
task[k] = temp;
}
}
time += task[j].burst;
}
// Chạy task đã được sắp xếp và tình thời gian chờ, thời gian quay vòng.
time = 0;
for(j=0 ; j < i ; j++) {
// Thời gian trống không có task.
if(task[j].arrival > time){
printf("Running task = IDLE from %d to %d.\n",time,task[j].arrival);
time=task[j].arrival;
}
wt[j] = time - task[j].arrival;
tt[j] = wt[j] + task[j].burst;
awt += wt[j];
att += tt[j];
run(&task[j],time,task[j].burst);
time += task[j].burst;
}
printf("Average waiting time: %f\n", awt / (float) i);
printf("Average turnaround time: %f\n", att / (float) i);
}
Link tham khảo:
https://classroom.google.com/u/1/c/MjY1NTQ2OTY1NzQx

1.2 Kết quả chạy chương trình:


*Yêu cầu 1.1; 1.2:
13

- Lập lịch theo tiêu chí FCFS và tính thời gian chờ trung bình và thời gian quay
vòng trung bình:

*Yêu cầu 1.3:


- Lập lịch theo Priority, tiêu chí FCFS khi Priority bằng nhau và tính thời gian
chờ trung bình và thời gian quay vòng trung bình:

*Yêu cầu 1.4:


- Lập lịch theo tiếu chí SJF, tiêu chí FCFS khi thời gian làm công việc bằng
nhau và tính thời gian chờ trung bình và thời gian quay vòng trung bình:
14

Bài 2: Chương trình ước lượng giá trị PI.


KẾT QUẢ THỰC HIỆN
2.1 Phần source code:
#include <stdio.h>
#include <pthread.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
// Số thread tối đa.
#define MAX_THREAD 40.
// Số điểm tối đa.
#define MAX_POINT 10000
int counter = 0;
int in = 0;
void* count(void* arg) {
int temp =0;
float x;
float y;
// Tiểu trình sinh ra m điểm.
for(int i=0; i<MAX_POINT;i++) {
x = ((float)rand()/(float)(RAND_MAX)) * 2 -1;
y = ((float)rand()/(float)(RAND_MAX)) * 2 -1;
// Tiểu trình cập nhật những điểm nằm trong hình tròn.
if(x*x + y*y <= 1)
temp++;
}
in+= temp;
15

counter += MAX_POINT;
}
// Chương trình chính.
int main(){
pthread_t threads[MAX_THREAD];
// Tạo ra n tiểu trình.
for (int i = 0;i < MAX_THREAD ; i++)
pthread_create(&threads[i], NULL, &count,(void*) &counter);
// Đợi n tiểu trình tham gia kết thúc.
for (int i = 0; i < MAX_THREAD ; i++)
pthread_join(threads[i],NULL);
// Tính và in ra số Pi.
printf("Pi = %f\n",(double)in / (double)counter * 4);
return 0;
}
Link tham khảo:
https://classroom.google.com/u/1/c/MjY1NTQ2OTY1NzQx

2.2 Kết quả chạy chương trình:


- Chạy chương trình xuất ra màn hình số PI đã ước lượng:

Bài 3: Chương trình sắp xếp bằng tiểu trình (Sử dụng thuật toán Merge Sort).
KẾT QUẢ THỰC HIỆN
3.1 Phần source code:
// lab3bai3.c (Merge Sort)
// Chương trình áp dụng merge sort sử dụng đa luồng.
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <stdlib.h>
// Số phần tử trong mảng.
#define MAX 20
// Số luồng.
#define THREAD_MAX 4
int a[MAX];
int part = 0;
// Hàm merge cho hợp 2 phần lại với nhau.
void merge(int low, int mid, int high) {
// n1 là kích thước của phần bên trái và n2 là kích thước của phần bên phải.
int n1 = mid - low + 1, n2 = high - mid, i, j;
16

int left[n1];
int right[n2];
// Lưu trữ dữ liệu vào phần bên trái.
for (i = 0; i < n1; i++)
left[i] = a[i + low];
// Lưu trữ dữ liệu vào phần bên phải.
for (i = 0; i < n2; i++)
right[i] = a[i + mid + 1];
int k = low;
i = j = 0;
// Hợp phần trái và phải theo thứ tự tăng dần.
while (i < n1 && j < n2) {
if (left[i] <= right[j])
a[k++] = left[i++];
else
a[k++] = right[j++];
}
// Chèn vào dữ liệu còn lại từ phần trái.
while (i < n1) {
a[k++] = left[i++];
}
// Chèn vào dữ liệu còn lại từ phần phải.
while (j < n2) {
a[k++] = right[j++];
}
}
// Hàm merge sort.
void merge_sort(int low, int high) {
// Tính điểm giữa của mảng.
int mid = low + (high - low) / 2;
if (low < high) {
// Gọi nửa phần đầu.
merge_sort(low, mid);
// Gọi nửa phần còn lại.
merge_sort(mid + 1, high);
// Gợp 2 phần lại với nhau.
merge(low, mid, high);
}
}
// Hàm thread
void* thr(void* arg) {
// Chọn trong 4 phần.
int thread_part = part++;
// Tính low và high.
int low = thread_part * (MAX / 4);
int high = (thread_part + 1) * (MAX / 4) - 1;
// Tìm điểm giữa.
int mid = low + (high - low) / 2;
17

if (low < high) {


merge_sort(low, mid);
merge_sort(mid + 1, high);
merge(low, mid, high);
}
}
// Hàm main.
int main() {
// Tạo mảng với dữ liệu ngẫu nhiên.
for (int i = 0; i < MAX; i++)
a[i] = rand() % 100;
// In ra mảng trước khi sắp xếp.
printf("Array: ");
for (int i = 0; i < MAX; i++)
printf("%d ", a[i]);
// Biến t1, t2 dùng tính thời gian chạy merge sort.
clock_t t1, t2;
t1 = clock();
pthread_t threads[THREAD_MAX];
// Tạo 4 luồng.
for (int i = 0; i < THREAD_MAX; i++)
pthread_create(&threads[i], NULL, thr, (void*)NULL);
// Đợi tất cả các luồng.
for (int i = 0; i < 4; i++)
pthread_join(threads[i], NULL);
// Gợp 4 phần còn lại.
merge(0, (MAX / 2 - 1) / 2, MAX / 2 - 1);
merge(MAX / 2, MAX/2 + (MAX-1-MAX/2)/2, MAX - 1);
merge(0, (MAX - 1)/2, MAX - 1);
t2 = clock();
// Hiện ra màng hình mảng đã được sắp xếp.
printf("\nSorted array: ");
for (int i = 0; i < MAX; i++)
printf("%d ", a[i]);
// Thời gian merge sort chạy tính bằng giây.
printf("\nTime taken: %lf\n", (t2 - t1) / (double)(CLOCKS_PER_SEC));
return 0;
}
Link tham khảo:
https://classroom.google.com/u/1/c/MjY1NTQ2OTY1NzQx

3.2 Kết quả chạy chương trình:


- Chạy chương trình với dữ liệu mảng được tạo ngẫu nhiên:
18

KẾT LUẬN

- Cách viết code lập lịch CPU và các thuật toán lập lịch.

- Áp dụng đa luồng vào chương trình như ước lượng số PI và thuật toán sắp xếp
merge sort.

You might also like