0% found this document useful (0 votes)
21 views

THHDH

meterial operating system ptit

Uploaded by

Hữu Hiếu
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
21 views

THHDH

meterial operating system ptit

Uploaded by

Hữu Hiếu
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 56

Phần 1.

Tổng quan hệ điều hành


1.1 Các khái niệm
1.1.1 Nhân linux: Linux kernel
Nhân Linux là phần cốt lõi của hệ điều hành, chịu trách nhiệm quản lý tài nguyên hệ thống
và cung cấp dịch vụ cho các ứng dụng. Nó chịu trách nhiệm về các nhiệm vụ như quản lý
quy trình, quản lý bộ nhớ, quản lý thiết bị và quản lý mạng.
1.1.2 Bản phân phối – Distributions
Bản phân phối Linux là một hệ điều hành hoàn chỉnh bao gồm nhân Linux, cùng với một
bộ ứng dụng, tiện ích và thư viện người dùng. Có nhiều bản phân phối Linux khác nhau,
mỗi bản có bộ tính năng và trình quản lý gói riêng. Một số bản phân phối Linux phổ biến
bao gồm Ubuntu, Debian, Fedora và Arch Linux, CentOS.

1.1.3 Giao diện đồ họa người dùng - Graphical user interface (GUI)
Linux cũng cung cấp giao diện đồ họa người dùng (GUI) giúp người dùng tương tác với
hệ điều hành một cách thân thiện hơn. GUI bao gồm môi trường máy tính để bàn, trình
quản lý cửa sổ và các công cụ đồ họa khác để quản lý ứng dụng, tệp và cài đặt.
1.1.4 Hệ thống tập tin – File System
Hệ thống tệp Linux được tổ chức dưới dạng cấu trúc thư mục phân cấp, với thư mục gốc ở
trên cùng. Tất cả các tệp và thư mục trong Linux được tổ chức trong thư mục gốc này, với
đường dẫn tệp bắt đầu từ thư mục gốc. Hệ thống tệp phân biệt chữ hoa chữ thường, nghĩa
là “file.txt” và “File.txt” là hai tệp khác nhau.
1.1.4.1 Các loại hệ thống tệp
Có nhiều hệ thống tệp khác nhau có thể được sử dụng với Linux, mỗi hệ thống có bộ tính
năng, đặc điểm hiệu suất và giới hạn riêng. Dưới đây là một số hệ thống tệp phổ biến được
sử dụng trong Linux:
• Ext4 - Hệ thống tệp mở rộng thứ tư là hệ thống tệp được sử dụng phổ biến nhất
trong Linux. Đây là một hệ thống tệp mạnh mẽ và đáng tin cậy, hỗ trợ các tệp và
khối lượng lớn, đồng thời có thể xử lý mức độ phân mảnh cao.
• “Btrfs” - Hệ thống tệp B-tree là một hệ thống tệp mới hơn với sự hỗ trợ tích hợp để
chụp nhanh, nén và kiểm tra tổng. Nó được thiết kế để có khả năng mở rộng cao
hơn và dễ quản lý hơn Ext4, nhưng vẫn được một số người coi là thử nghiệm.
• XFS – Hệ thống tệp XFS được thiết kế cho môi trường hiệu suất cao, hỗ trợ các tệp
lớn, tính đồng thời cao và phục hồi nhanh sau sự cố. Nó thường được sử dụng trong
môi trường doanh nghiệp và đám mây.
• NTFS - Hệ thống tệp công nghệ mới là một hệ thống tệp được sử dụng bởi hệ điều
hành Windows. Linux có thể đọc và ghi vào phân vùng NTFS, nhưng nó yêu cầu
trình điều khiển bổ sung và có thể không hỗ trợ đầy đủ tất cả các tính năng.
1.1.4.2 Cấu trúc thư mục Linux điển hình
Hệ thống tệp Linux có cấu trúc thư mục được xác định rõ ràng, với một số thư mục nhất
định được sử dụng cho các mục đích cụ thể. Dưới đây là một số thư mục phổ biến nhất mà
bạn sẽ gặp trong hệ thống tệp Linux điển hình:

• /bin: Chứa các tệp nhị phân thiết yếu cần thiết để hệ thống hoạt động bình thường.
Các tệp này bao gồm các tiện ích cốt lõi như ls, cp và rm.
• /boot: Chứa các tệp cần thiết để khởi động hệ thống, chẳng hạn như tệp cấu hình
kernel và bộ tải khởi động.
• /dev: Chứa các tệp thiết bị đại diện cho các thiết bị vật lý và ảo, chẳng hạn như ổ
cứng, ổ USB và máy in.
• /etc: Chứa các tệp cấu hình trên toàn hệ thống, bao gồm các tệp kiểm soát các dịch
vụ hệ thống và cài đặt mạng.
• /home: Chứa các thư mục home của người dùng trên hệ thống.
• /lib: Chứa các file thư viện dùng chung cần thiết để chạy các chương trình và thư
viện.
• /media: Chứa các điểm gắn kết cho phương tiện di động, chẳng hạn như ổ USB và
CD.
• /opt: Chứa các gói phần mềm tùy chọn không được cài đặt theo mặc định.
• /proc: Chứa hệ thống tệp ảo cung cấp thông tin về các tiến trình đang chạy và tài
nguyên hệ thống.
• /root: Thư mục chính của người dùng root.
• /run: Chứa dữ liệu thời gian chạy cho các dịch vụ và ứng dụng hệ thống.
• /sbin: Chứa các tệp nhị phân hệ thống được sử dụng cho các tác vụ quản trị hệ
thống, chẳng hạn như cấu hình mạng và bảo trì hệ thống.
• /srv: Chứa dữ liệu về các dịch vụ do hệ thống cung cấp, chẳng hạn như nội dung
web và tệp FTP.
• /tmp: Chứa các tệp tạm thời được sử dụng bởi các ứng dụng và hệ thống.
• /usr: Chứa các tệp người dùng, bao gồm các tệp nhị phân hệ thống, thư viện, tài liệu
và dữ liệu ứng dụng.
• /var: Chứa dữ liệu có thể thay đổi, chẳng hạn như tệp nhật ký, tệp đệm và tệp tạm
thời.

1.2 Giao diện dòng lệnh – Command Line Interface (CLI)


Linux cung cấp giao diện dòng lệnh (CLI) cho phép bạn tương tác với hệ điều hành bằng
các lệnh văn bản. CLI là một công cụ mạnh mẽ để quản lý hệ điều hành, thực hiện các tác
vụ quản trị hệ thống và chạy các ứng dụng. Nó được truy cập thông qua trình mô phỏng
thiết bị đầu cuối, cung cấp một cửa sổ để nhập lệnh và xem kết quả đầu ra của chúng.
1.2.1 Command Line Administration tasks
CLI cung cấp nhiều công cụ mạnh mẽ để quản lý và điều hành hệ điều hành Linux. Dưới
đây là một số tác vụ quản trị phổ biến có thể được thực hiện bằng dòng lệnh:

• Quản lý nhóm và người dùng: Linux hỗ trợ nhiều người dùng và nhóm, mỗi nhóm
có bộ quyền và cấp độ truy cập riêng. Bạn có thể sử dụng dòng lệnh để tạo, sửa đổi
và xóa người dùng và nhóm cũng như đặt quyền cho họ.
• Quản lý tệp và thư mục: Hệ thống tệp Linux được tổ chức dưới dạng cấu trúc thư
mục phân cấp và dòng lệnh cung cấp các công cụ mạnh mẽ để tạo, di chuyển, sao
chép và xóa các tệp và thư mục.
• Quản lý tiến trình: Dòng lệnh cho phép quản lý các quy trình đang chạy, bao gồm
khởi động, dừng và khởi động lại chúng, cũng như giám sát hiệu suất và việc sử
dụng tài nguyên của chúng.
• Quản lý gói: Linux sử dụng trình quản lý gói để cài đặt, cập nhật và xóa gói phần
mềm. Bạn có thể sử dụng dòng lệnh để quản lý các gói, bao gồm cài đặt và gỡ bỏ
gói, tìm kiếm gói và cập nhật cơ sở dữ liệu gói.
• Cấu hình mạng: Dòng lệnh cho phép bạn định cấu hình cài đặt mạng, bao gồm địa
chỉ IP, cài đặt DNS và giao diện mạng.
• Giám sát hệ thống: Dòng lệnh cung cấp một loạt công cụ để giám sát hiệu suất hệ
thống và việc sử dụng tài nguyên, bao gồm các công cụ giám sát việc sử dụng CPU,
bộ nhớ và ổ đĩa cũng như lưu lượng mạng và nhật ký hệ thống.
• Quản lý bảo mật: Dòng lệnh cung cấp các công cụ để quản lý bảo mật hệ thống,
bao gồm định cấu hình tường lửa, đặt quyền và kiểm soát truy cập cũng như quản
lý mật khẩu và xác thực người dùng.
• Bảo trì hệ thống: Dòng lệnh cung cấp các công cụ để thực hiện các tác vụ bảo trì
hệ thống, bao gồm chống phân mảnh ổ đĩa, dọn dẹp ổ đĩa và sao lưu hệ thống.
1.2.2 Một số tác vụ quản trị mẫu
Thêm người dùng: Bạn có thể sử dụng lệnh useradd để thêm người dùng mới vào hệ
thống. Ví dụ: để thêm người dùng có tên là “n21cqcn001”, bạn có thể chạy lệnh sau:

sudo useradd n21cqcn001

Cài đặt gói: Bạn có thể sử dụng lệnh apt (debian) để cài đặt gói từ kho lưu trữ. Ví dụ: để
cài đặt trình soạn thảo văn bản nano, bạn có thể chạy lệnh sau:

sudo apt install nano

Xem nhật ký hệ thống: Bạn có thể sử dụng lệnh tail để xem một vài dòng cuối cùng của
tệp nhật ký. Ví dụ: để xem 10 dòng cuối cùng của nhật ký hệ thống, bạn có thể chạy lệnh
sau:

sudo tail /var/log/syslog -n 10

Giám sát hiệu suất hệ thống: Bạn có thể sử dụng lệnh top để giám sát hiệu suất hệ thống,
bao gồm việc sử dụng CPU, mức sử dụng bộ nhớ và thông tin xử lý. Ví dụ: để theo dõi
việc sử dụng CPU, bạn có thể chạy lệnh sau:
top

htop

Dòng lệnh là một công cụ mạnh mẽ để quản lý và điều hành hệ điều hành Linux, đồng thời
cung cấp nhiều công cụ và tiện ích để thực hiện các tác vụ thông thường. Với sự hiểu biết
về dòng lệnh Linux và các tác vụ quản trị của nó, bạn có thể kiểm soát hệ thống Linux của
mình và quản lý nó hiệu quả hơn.
1.2.3 Các lệnh cơ bản
Dưới đây là một số lệnh Linux cơ bản mà bạn có thể sử dụng để điều hướng hệ thống tệp,
quản lý tệp và thư mục cũng như thực hiện các tác vụ khác:
1.2.3.1 Điều hướng / Navigation

• cd: Thay đổi thư mục


• ls: Liệt kê nội dung thư mục
• pwd: In thư mục làm việc
• mkdir: Tạo thư mục
• rmdir: Xóa thư mục
• chạm: Tạo tập tin trống
1.2.3.2 Quản lý tập tin / File Management

• cp: Sao chép tập tin


• mv: Di chuyển hoặc đổi tên file
• rm: Xóa tập tin
• cat: Nối các tập tin
1.2.3.3 Quản lý tiến trình

• ps: Liệt kê các tiến trình đang chạy


• kill: Gửi tín hiệu tới tiến trình
• top: Hiển thị mức sử dụng tài nguyên hệ thống
1.2.3.4 Quản lý gói

• apt: Công cụ gói nâng cao (được sử dụng bởi các bản phân phối dựa trên Debian)
• yum: Trình cập nhật Yellowdog đã được sửa đổi (được sử dụng bởi các bản phân
phối dựa trên Red Hat).
Bài tập:
Thay đổi hthanhsg thành mã số sinh viên của bạn
Bài 1. Tạo cây thư mục như sau
Sử dụng các lệnh

• pwd: kiểm tra thư mục hiện tại


• mkdir: để tạo thư mục
• cd: thay đổi thư mục làm việc
• cd .. : đi đến thư mục cha của thư mục hiện tại
Bài 2. Tạo tập tin
Tạo các tập tin trong thư mục /home/MSSV/HEDIEUHANH/LYTHUYET

• ghi_chu_ly_thuyet_1.txt
• ghi_chu_ly_thuyet_2.txt
Tạo các tập tin trong thư mục /home/MSSV/HEDIEUHANH/THUCHANH/BAI_TH_01

• my_code_1_1.c
• my_code_1_2.c
Tạo các tập tin trong thư mục /home/MSSV/HEDIEUHANH/THUCHANH/BAI_TH_02

• my_code_2_1.c
• my_code_2_2.c
Tạo các tập tin trong thư mục /home/MSSV/HEDIEUHANH/THUCHANH/BAI_TH_02

• my_code_3_1.c
• my_code_3_2.c

Bài 3. Sao chép tập tin và thư mục


Tạo thư mục BACKUP ở /home/MSSV/
Sao chép tập tin my_code_1_1.c từ thư mục BAI_TH_01 vào thư mục BACKUP vừa tạo
Sao chép toàn bộ thư mục LYTHUYET vào thư mục BACKUP vừa tạo.
Dùng các lệnh sau:

• touch
• cp
• cp -R

Bài 4. Di chuyển file và thư mục

• Đổi tên tập tin my_code_1.1.c trong thư mục /home/MSSV/BACKUP/ thành
my_code_1.1.c.bak
• Đổi tên các tập tin my_code_1_1.c và my_code_1_2.c trong BAI_TH_01 thành
MSSV_my_code_1_1.c và MSSV_my_code_1_2.c
• Di chuyển tập tin ghi_chu_ly_thuyet_1.txt trong thư mục “/home/MSSV/BACKUP
/LYTHUYET” vào thưc mục /home/MSSV/BACKUP
• Di chuyển toàn bộ thư mục BACKUP vào thư mục HEDIEUHANH
Dùng các lệnh

• mv
Bài 5. Nén và giải nén tập tin

• Nén tập tin ghi_chu_ly_thuyet_1.txt trong thư mục


“/home/MSSV/HEDIEUHANH/
LYTHUYET” thành backup_gclt_1.tar trong cùng thư mục.
• Nén toàn bộ thư mục HEDIEUHANH thành BK_HEDIEUHANH.tar
• Di chuyển thư mục HEDIEUHANH sang thư mục /home

Giải nén BK_HEDIEUHANH


Dùng lệnh tar --help

• tar -cf <tên_file_nén.tar> <file_cần_nén_1> … <file_cần_nén_n>


• tar -cf <tên_file_nén.tar> <thư_mục_cần_nén>
• tar -xf <file_cần_giải_nén>
Bài 6. Xóa tập tin, thư mục
Xóa tập tin my_code_3_1.c và tập tin my_code_3_2.c trong thư mục
/home/HEDIEUHANH/THUCHANH/BAI_TH_03
Xóa thư mục /home/HEDIEUHANH/THUCHANH/BAI_TH_03

Xóa thư mục /home/HEDIEUHANH/THUCHANH/BAI_TH_02

Xóa toàn bộ thư mục /home/HEDIEUHANH


Dùng lệnh:

• rm
• rm -r
• rm -rf
• rmdir
Bài 7. Thay đổi quyền
Truy cập quyền root

• Tạo người dùng với username là ptit_mssv


• Đặt mật khẩu cho người dùng ptit_mssv
• Tạo nhóm người dùng sinhvien
• Tạo nhóm người dùng giangvien
• Thêm username ptit_mssv vào nhóm sinhvien
• Tạo thư mục /home/security_folder và phân quyền cho thư mục này là 770
Truy cập bằng user ptit_mssv

• Tạo tập tin security_file.txt trong thư mục /home/security_folder

Lệnh:
• sudo -i
• passwd <username>
• groupadd <ten_group>
• usermod -a -G <ten_group> <username>
Bài 8. Quản lý tiến trình

• Truy cập thư mục /home/<MSSV> và tạo tập tin liet_ke.txt


• Dùng lệnh ls -lR / để liệt kê danh sách tập tin và thư mục trong / và kết xuất ra tập
tin liet_ke.txt
• Cho chương trình chạy ở hậu cảnh.
• Khi kết thúc chương trình hãy xem nội dung tập tin liet_ke.txt
Phần 2. Thực thi chương trình

GCC là viết tắt của Bộ sưu tập trình biên dịch GNU được sử dụng để biên dịch chủ yếu
ngôn ngữ C và C++. Nó cũng có thể được sử dụng để biên dịch Objective C và Objective
C++. Tùy chọn quan trọng nhất cần có khi biên dịch tệp mã nguồn là tên của chương trình
nguồn, phần còn lại mọi đối số đều là tùy chọn như cảnh báo, gỡ lỗi, liên kết thư viện, tệp
đối tượng, v.v. Các tùy chọn khác nhau của lệnh gcc cho phép người dùng dừng quá trình
biên dịch quá trình ở các giai đoạn khác nhau.
2.1 Header file
Trong ngôn ngữ C, các tệp tiêu đề chứa một tập hợp các hàm thư viện tiêu chuẩn được xác
định trước. .h là phần mở rộng của tệp tiêu đề trong C và chúng ta yêu cầu sử dụng tệp tiêu
đề trong chương trình của mình bằng cách đưa nó vào chỉ thị tiền xử lý C “#include”. Ngôn
ngữ C có nhiều thư viện bao gồm các hàm được xác định trước để giúp việc lập trình trở
nên dễ dàng hơn.
Ngôn ngữ C++ cũng cung cấp cho người dùng nhiều chức năng khác nhau, một trong số
đó được bao gồm trong các tệp tiêu đề. Trong C++, tất cả các tệp tiêu đề có thể kết thúc
hoặc không kết thúc bằng phần mở rộng “.h”.
Nó cung cấp các tính năng như chức năng thư viện, kiểu dữ liệu, macro, v.v. bằng cách
nhập chúng vào chương trình với sự trợ giúp của chỉ thị tiền xử lý “#include”. Các chỉ thị
tiền xử lý này được sử dụng để hướng dẫn trình biên dịch rằng các tệp này cần được xử lý
trước khi biên dịch.
Cú pháp của Header File trong C/C++
Chúng ta có thể đưa các tệp tiêu đề trong C bằng cách sử dụng một trong hai cú pháp đã
cho cho dù đó là tệp tiêu đề được xác định trước hay do người dùng xác định.

#include <filename.h> // for files in system/default directory


or
#include "filename.h" // for files in same directory as source file

Hầu hết các chương trình trên Linux khi biên dịch sử dụng các tập tin tiêu đề trong thư
mục /usr/include hoặc trong thư mục con.
2.2 Cài đặt gcc

Usage: gcc [options] file...

Options:

-pass-exit-codes Exit with highest error code from a phase.

--help Display this information.

--target-help Display target specific command line options.

--help={common|optimizers|params|target|warnings|[^]{joined|separate|undocumented}}[,...].

Display specific types of command line options.

(Use '-v --help' to display command line options of sub-processes).

--version Display compiler version information.

-dumpspecs Display all of the built in spec strings.

-dumpversion Display the version of the compiler.

-dumpmachine Display the compiler's target processor.

-print-search-dirs Display the directories in the compiler's search path.

-print-libgcc-file-name Display the name of the compiler's companion library.

-print-file-name=<lib> Display the full path to library <lib>.


-print-prog-name=<prog> Display the full path to compiler component <prog>.

-print-multiarch Display the target's normalized GNU triplet, used as

a component in the library path.

-print-multi-directory Display the root directory for versions of libgcc.

-print-multi-lib Display the mapping between command line options and

multiple library search directories.

-print-multi-os-directory Display the relative path to OS libraries.

-print-sysroot Display the target libraries directory.

-print-sysroot-headers-suffix Display the sysroot suffix used to find headers.

-Wa,<options> Pass comma-separated <options> on to the assembler.

-Wp,<options> Pass comma-separated <options> on to the preprocessor.

-Wl,<options> Pass comma-separated <options> on to the linker.

-Xassembler <arg> Pass <arg> on to the assembler.

-Xpreprocessor <arg> Pass <arg> on to the preprocessor.

-Xlinker <arg> Pass <arg> on to the linker.

-save-temps Do not delete intermediate files.

-save-temps=<arg> Do not delete intermediate files.

-no-canonical-prefixes Do not canonicalize paths when building relative

prefixes to other gcc components.

-pipe Use pipes rather than intermediate files.

-time Time the execution of each subprocess.

-specs=<file> Override built-in specs with the contents of <file>.

-std=<standard> Assume that the input sources are for <standard>.

--sysroot=<directory> Use <directory> as the root directory for headers

and libraries.

-B <directory> Add <directory> to the compiler's search paths.

-v Display the programs invoked by the compiler.

-### Like -v but options quoted and commands not executed.

-E Preprocess only; do not compile, assemble or link.

-S Compile only; do not assemble or link.

-c Compile and assemble, but do not link.

-o <file> Place the output into <file>.

-pie Create a dynamically linked position independent

executable.
-shared Create a shared library.

-x <language> Specify the language of the following input files.

Permissible languages include: c c++ assembler none

'none' means revert to the default behavior of

guessing the language based on the file's extension.

Options starting with -g, -f, -m, -O, -W, or --param are automatically

2.3 Cú pháp
gcc [-c|-S|-E] [-std=standard]
Ví dụ: Điều này sẽ biên dịch tệp source.c và cung cấp tệp đầu ra dưới dạng tệp a.out, đây
là tên mặc định của tệp đầu ra do trình biên dịch gcc cung cấp, có thể được thực thi bằng
cách sử dụng ./a.out

Các tùy chọn hữu ích nhất kèm theo ví dụ: Ở đây MSSV_my_code_1_1.c là tệp mã chương
trình C.
• -o MSSV_my_code_1_1: Điều này sẽ biên dịch tệp MSSV_my_code_1_1.c nhưng
thay vì đặt tên mặc định do đó được thực thi bằng ./opt, nó sẽ cung cấp tệp đầu ra
dưới dạng opt. -o dành cho tùy chọn tệp đầu ra.

• -Werror: Điều này sẽ biên dịch nguồn và hiển thị cảnh báo nếu có lỗi trong chương
trình, -W là để đưa ra cảnh báo.
• -Wall: Điều này sẽ không chỉ kiểm tra lỗi mà còn kiểm tra tất cả các loại cảnh báo
như lỗi biến không được sử dụng, cách tốt nhất là sử dụng cờ này trong khi biên
dịch mã.
• -ggdb3: Lệnh này cấp cho chúng tôi quyền gỡ lỗi chương trình bằng gdb, lệnh này
sẽ được mô tả sau, tùy chọn -g dùng để gỡ lỗi.
• -lm : Lệnh này liên kết thư viện math.h với tệp nguồn của chúng ta, tùy chọn -l được
sử dụng để liên kết thư viện cụ thể, đối với math.h chúng ta sử dụng -lm
• -std=c11: Lệnh này sẽ sử dụng phiên bản c11 của tiêu chuẩn để biên dịch chương
trình source.c, cho phép xác định biến trong quá trình khởi tạo vòng lặp cũng như
sử dụng phiên bản tiêu chuẩn mới hơn được ưu tiên.
• -c : Lệnh này biên dịch chương trình và cung cấp tệp đối tượng làm đầu ra, được sử
dụng để tạo thư viện.
• -v : Tùy chọn này được sử dụng cho mục đích verbose.

2.4 Bài tập


Viết chương trình C in ra màn hình các số nguyên tố từ 0 đến 100
Viết chương trình C in ra màn hình n số fibonacci đầu tiên
Phần 3. Quản lý tiến trình
3.1 Tiến trình
Một tiến trình là một chương trình đang được thực thi, sau đó tạo thành cơ sở cho mọi tính
toán. Quá trình này không giống như mã chương trình. Một tiến trình là một thực thể 'hoạt
động' trái ngược với chương trình được coi là một thực thể 'thụ động'.
Để xem các tiến trình đang thực thi trong hệ điều hành linux sử dụng lệnh
ps -aux hoặc ps -e

Để hủy tiến trình dùng lệnh


kill pid
3.2 Gọi tiến trình trong chương trình đang thực thi
Chúng ta có thể gọi một tiến trình khác bên trong một chương trình đang thực thi bằng hàm
system(). Có nghĩa là chúng ta có thể tạo ra một tiến trình mới từ một tiến trình đang chạy.
Hàm system() được khai báo như sau:

#include <stdlib.h>
int system( const char (cmdstr) )

Hàm này gọi chuỗi lệnh cmdstr thực thi và chờ lệnh chấm dứt mới quay về nơi gọi hàm.
Nó tương đương với việc bạn gọi shell thực thi lệnh của hệ thống: $sh –c cmdstr
system() sẽ trả về mã lỗi 127 nếu như không khởi động được shell để gọi lệnh cmdstr. Mã
lỗi -1 nếu gặp các lỗi khác. system()

Ví dụ:

/home/MSSV/call_system.c

gcc call_system.c -o call_system


./call_system

Thay thế tiến trình hiện tại với các hàm exec
Mỗi tiến trình được hệ điều hành cấp cho 1 không gian nhớ tách biệt để tiến trình tự do
hoạt động. Nếu tiến trình A của chúng ta triệu gọi một chương trình ngoài B (bằng hàm
system()chẳng hạn), hệ điều hành thường thực hiện các thao tác như:

• cấp phát không gian bộ nhớ cho tiến trình mới, điều chỉnh lại danh sách các tiến
trình,
• nạp mã lệnh của chương trình B trên đĩa cứng và không gian nhớ vừa cấp phát cho
tiến trình.
• Đưa tiến trình mới vào danh sách cần điều phối của hệ điều hành.
Những công việc này thường mất thời gian đáng kể và chiếm giữ thêm tài nguyên của hệ
thống.
Nếu tiến trình A đang chạy và nếu chúng ta muốn tiến trình B khởi động chạy trong không
gian bộ nhớ đã có sẵn của tiến trình A thì có thể sử dụng các hàm exec được cung cấp bới
Linux. Các hàm exec sẽ thay thế toàn bộ ảnh của tiến trình A (bao gồm mã lệnh, dữ liệu,
bảng mô tả file) thành ảnh của một tiến trình B hoàn toàn khác. Chỉ có số định danh PID
của tiến trình A là còn giữ lại. Tập hàm exec bao gồm các hàm sau:

#include <unistd.h>
extern char **environ;
int execl( const char *path, const char *arg, ... );
int execlp( const char *file, const char *arg, ... );
int execle( const char *path, const char *arg, ..., char *const envp[]);
int exect( const char *path, char *const argv[] );
int execv( const char *path, char *const argv[] );
int execvp( const char *file, char *const argv[] );

Đa số các hàm này đều yêu cầu chúng ta chỉ đối số path hoặc file là đường dẫn đến tên
chương trình cần thực thi trên đĩa. arg là các đối số cần truyền cho chương trình thực thi,
những đối số này tương tự cách chúng ta gọi chương trình từ dòng lệnh.
3.3 Nhân bản tiến trình với hàm fork
Thay thế tiến trình đôi khi bất lợi. Đó là khi tiến trình mới chiếm giữ toàn bộ không gian
của tiến trình cũ và chúng ta sẽ không có khả năng kiểm soát cũng như điều khiển tiếp
tiến trình hiện hành của mình sau khi gọi hàm exec nữa. Cách đơn giản mà các chương
trình Linux thường dùng đó là sử dụng hàm fork() để nhân bản hay tạo bản sao mới của
tiến trình.
fork() là một hàm khá đặc biệt, khi thực thi, nó sẽ trả về 2 giá trị khác nhau trong lần thực
thi, so với hàm bình thường chỉ trả về 1 giá trị trong lần thực thi. Khai báo của hàm fork()
như sau:

#include <sys/types.h>
#include <unistd.h>
pid_t fork()

Nếu thành công, fork() sẽ tách tiến trình hiện hành 2 tiến trình. Tiến trình ban đầu gọi là
tiến trình cha (parent process) trong khi tiến trình mới gọi là tiến trình con (child process).
Tiến trình con sẽ có một số định danh PID riêng biệt. ngoài ra, tiến trình con còn mang
thêm một định danh PPID (Parent Process ID) là số định danh PID của tiến trình cha.
Sau khi tách tiến trình, mã lệnh thực thi ở cả hai tiến trình được sao chép là hoàn toàn giống
nhau. Chỉ có một dấu hiệu để chúng ta có thể nhận dạng tiến trình cha và tiến trình con, đó
là trị trả về của hàm fork(). Bên trong tiến trình con, hàm fork() sẽ trả về trị 0. Trong khi
bên trong tiến trình cha, hàm fork() sẽ trả về trị số nguyên chỉ là PID của tiến trình con vừa
tạo. Trường hợp không tách được tiến trình, fork() sẽ trả về trị -1. Kiểu pid_t được khai
báo và định nghĩa trong uinstd.h là kiểu số nguyên (int).
Đoạn mã điều khiển và sử dụng hàm fork() thường có dạng chuẩn sau:

pid_t new_pid;
new_pid = fork(); // tách tiến trình
switch (new_pid){
case -1: printf( "Khong the tao tien trinh moi" ); break;
case 0: printf( "Day la tien trinh con" );
// mã lệnh dành cho tiến trình con đặt ở đây
break;
default: printf( "Day la tien trinh cha" );
// mã lệnh dành cho tiến trình cha đặt ở đây
break;
}

3.4 Kiểm soát và đợi tiến trình con


Khi fork() tách tiến trình chính thành hai tiến trình cha và con, trên thực tế cả hai tiến trình
cha lẫn tiến trình con đều hoạt động độc lập. Đôi lúc tiến trình cha cần phải đợi tiến trình
con thực hiện xong tác vụ thì mới tiếp tục thực thi. Ở ví dụ trên, khi thực thi, chúng ta sẽ
thấy rằng tiến trình cha đã kết thúc mà tiến trình con vẫn in thông báo và cả tiến trình cha
và tiến trình con đều tranh nhau gởi kết quả ra màn hình. Chúng ta không muốn điều này,
chúng ta muốn rằng khi tiến trình cha kết thúc thì tiến trình con cũng hoàn tất thao tác của
nó. Hơn nữa, chương trình con cần thực hiện xong tác vụ của nó thì mới đến chương trình
cha. Để làm được việc này, chúng ta hãy sử dụng hàm wait()

#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int &stat_loc);

Hàm wait khi được gọi sẽ yêu cầu tiến trình cha dừng lại chờ tiến trình con kết thúc trước
khi thực hiện tiếp các lệnh điều khiển trong tiến trình cha. wait() làm cho sự liên hệ giữa
tiến trình cha và tiến trình con trở nên tuần tự. Khi tiến trình con kết thúc, hàm sẽ trả về số
PID tương ứng của tiến trình con. Nếu chúng ta truyền thêm đối số stat_loc khác NULL
cho hàm thì wait() cũng sẽ trả về trạng thái mà tiến trình con kết thúc trong biến stat_loc.
Chúng ta có thể sử dụng các macro khai báo sẵn trong sys/wait.h như sau:

• WIFEXITED (stat_loc) Trả về trị khác 0 nếu tiến trình con kết thúc bình thường.
• WEXITSTATUS (stat_loc) Nếu WIFEXITED trả về trị khác 0, macro này sẽ trả về
mã lỗi của tiến trình con.
• WIFSIGNALED (stat_loc) Trả về trị khác 0 nếu tiến trình con kết thúc bởi một tín
hiệu gửi đến.
• WTERMSIG(stat_loc) Nếu WIFSIGNALED khác 0, macro này sẽ cho biết số tín
hiệu đã hủy tiến trình con.
• WIFSTOPPED(stat_loc) Trả về trị khác 0 nếu tiến trình con đã dừng.
• WSTOPSIG(stat_loc) Nếu WIFSTOPPED trả về trị khác 0, macro này trả về số
hiệu của signal.
3.5 Bài tập
3.5.1 Bài 1
Sử dụng hàm system(), system_demo.c tạo các tiến trình sau:

• Tạo thư mục THUC_HANH_3 và THUC_HANH_4 trong “/home/<MSSV>


HEDIEUHANH/THUCHANH/”
• Tạo tập tin my_system.c trong thư mục THUC_HANH_3 và ghi chuỗi “Great!
Again!” vào tập tin vừa tạo.
• Sao chép tập tin vừa tạo sang thư mục THUC_HANH_4 và hiển thị lên màn hình.
3.5.2 Bài 2
Sử dụng hàm execlp để thay thế tiến trình hiện tại bằng tiến trình ps –af của Hệ Điều Hành.

#include <unistd.h>
#include <stdio.h>
int main()
{
execlp( "ps", "ps", "–ax", 0 );
exit( 0 );
}

3.5.3 Bài 3
Tạo tập tin fork_demo.c sử dụng hàm fork() trong đó:

• In ra câu thông báo: “Can not create child process”nếu hàm fork() trả về giá trị -1.
• Ngược lại:
- In ra 2 lần câu thông báo: “This is child process” nếu mã trả về là 0.
- In ra 3 lần câu thông báo: “This is parent process” nếu mã trả về là PID của
tiến trình con.

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
pid_t pid;
char * message;
int n;
pid = fork();
……
exit( 0 );
}

3.5.4 Bài 4
Sử dụng hàm wait() để chờ tiến trình con kết thúc sau khi gọi fork(), wait_child.c
3.5.5 Bài 5
Sử dụng hàm wait() để chờ tiến trình con kết thúc sau khi gọi fork(), wait_child2.c, kiểm
tra mã lỗi trả về từ tiến trình con.
Phần 4. Lập lịch CPU

Làm thế nào để một tiến trình di chuyển vào RQ?


Khi một tiến trình được tạo, nó sẽ được đưa vào nhóm công việc. Nhóm này bao gồm
tất cả các tiến trình trong hệ thống. Bộ lập lịch công việc còn được gọi là Bộ lập lịch dài
hạn, nhận công việc hoặc tiến trình từ Nhóm công việc và đưa nó vào RQ.

Burst Time: đây là khoảng thời gian mà một tiến trình cần để hoàn thành quá trình thực
thi trên CPU. Nó biểu thị thời gian CPU thực hiện các hướng dẫn của tiến trình cụ thể
đó.
Waiting time - Thời gian chờ: Nó đề cập đến tổng lượng thời gian mà một tiến trình
dành để chờ trong hàng đợi sẵn sàng trước khi nó có cơ hội thực thi trên CPU.
Các thuật toán lập lịch
4.1 First come First serve - FCFS
4.1.1 Các khái niệm
Đến trước phục vụ trước (First Come First Served – viết tắt là FCFS) là phương pháp
điều độ đơn giản nhất, cả về nguyên tắc và cách thực hiện. Tiến trình yêu cầu CPU trước
sẽ được cấp CPU trước.
Hệ điều hành xếp tiến trình sẵn sàng vào hàng đợi FIFO. Tiến trình mới được xếp vào
cuối hàng đợi, khi CPU được giải phóng, hệ điều hành sẽ lấy tiến trình từ đầu hàng đợi
và cấp CPU cho tiến trình đó thực hiện.
Mặc dù đơn giản và đảm bảo tính công bằng, FCFS có thời gian chờ đợi trung bình của
tiến trình lớn do phải chờ đợi tiến trình có chu kỳ CPU dài trong trường hợp những tiến
trình như vậy nằm ở đầu hàng đợi.
Thuật toán FCFS thông thường là thuật toán điều độ không phân phối lại. Sau khi tiến
trình được cấp CPU, tiến trình đó sẽ sử dụng CPU cho đến khi kết thúc hoặc phải
dừng lại để chờ kết quả vào ra. Để có thể sử dụng được trong những hệ thống chia sẻ
thời gian, thuật toán đến trước phục vụ trước được cải tiến để thêm cơ chế phân phối lại.
4.1.2 Thuật toán
Cho n tiến trình với thời gian xử lý và thời gian đến của chúng, nhiệm vụ là tìm thời
gian chờ trung bình (average waiting time - awt) và thời gian quay vòng trung bình (turn
around time - tat) bằng thuật toán lập lịch FCFS.
FIFO chỉ đơn giản xếp hàng các tiến trình theo thứ tự chúng đến trong hàng đợi sẵn
sàng. Ở đây, quy trình đến trước sẽ được thực thi trước và quy trình tiếp theo sẽ chỉ bắt
đầu sau khi quy trình trước đó được thực thi đầy đủ.

• Thời gian hoàn thành (completion time): Thời gian mà tiến trình hoàn thành
quá trình thực thi của nó.
• Thời gian quay vòng: Thời gian chênh lệch giữa thời gian hoàn thành và thời
gian đến.
Thời gian quay vòng = Thời gian hoàn thành – Thời gian đến
• Thời gian chờ: Thời gian Chênh lệch giữa thời gian quay vòng và thời gian xử
lý.
Thời gian chờ đợi = Thời gian quay vòng – Thời gian xử lý.
Thuật toán:
1. Nhập các tiến trình cùng với thời gian thực thi của chúng (bt) và thời gian đến (at)
2. tìm thời gian chờ cho tất cả các tiến trình
wt[i] = bt[0] + bt[1] + … + bt[i-1] – at[i]
3. Tìm Turn Around Time
= wating_time + burst_time cho tất cả các tiến trình
4. Thời gian chờ đợi trung bình = Tổng thời gian chờ đợi / số tiến trình
5. Thời gian quay vòng trung bình = Tổng thời gian quay vòng trung bình / số tiến trình.
4.1.3 Ví dụ FCFS

Tiến trình Thời điểm vào RL Burst Time Độ ưu tiên

P1 0 10 3

P2 1 1 1

P3 2.5 2 3

P4 3 1 4

P5 4.5 5 2
Bảng 1. Ví dụ các tiến trình với thời gian đến khác nhau

Bước 1:
bt = [10, 1, 2, 1, 5]
at = [0, 1, 2.5, 3, 4.5]
Bước 2:
wt[0] = 0
wt[1] = bt[0] – at[1] = 10 - 1 = 9
wt[2] = (bt[0] + bt[1]) – at[2] = (10+1) – 2.5 = 8.5
wt[3] = (bt[0] + bt[1] + bt[2]) – at[3] = (10+1+2) – 3 = 10
wt[4] = (bt[0] + bt[1] + bt[2] + bt[3]) – at[4] = (10+1+2+1) – 4.5 = 9.5
ð wt = [0, 9, 8.5, 10, 9.5]
Bước 3: Tìm TAT
tat[0] = wt[0] + bt[0] = 0 + 10 = 10
tat[1] = wt[1] + bt[1] = 9 + 1 = 10
tat[2] = wt[2] + bt[2] = 8.5 + 2 = 10.5
tat[3] = wt[3] + bt[3] = 10 + 1 = 11
tat[4] = wt[4] + bt[4] = 9.5 + 5 = 14.5
Bước 4:
Thời gian chờ đợi trung bình = (0+9+8.5+10+9.5) / 5 = 7.4
Bước 5:
Thời gian quay vòng trung bình = (10+10+10.5+11+14.5) / 5 = 11.2

Arrival.T Burst.T Completion.T TAT Waiting.T


Process
(1) (2) (3) (4) = (3)–(1) (5)=(4)-(2)

P1 0 10 10 10 0

P2 1 1 11 10 9

P3 2.5 2 13 10.5 8.5

P4 3 1 14 11 10

P5 4.5 5 19 14.5 9.5


4.2 Round Robin
4.2.1 Các khái niệm
Điều độ quay vòng (round robin - RR) là phiên bản sửa đổi của FCFS được dùng cho
các hệ chia sẻ thời gian. Điều độ quay vòng tương tự FCFS nhưng có thể cơ chế phân
phối lại bằng cách sử dụng ngắt của đồng hồ. Hệ thống định nghĩa những khoảng thời
gian nhỏ gọi là lượng tử thời gian (time quantum) hay lát cắt thời gian (time slice) có độ
dài từ vài mili giây tới vài trăm mili giây tùy vào cấu hình cụ thể. Tiến trình sẽ lần lượt
được cấp CPU trong những khoảng thời gian như vậy trước khi bị ngắt và CPU được
cấp cho tiến trình khác.
Giống như FCFS, tiến trình sẵn sàng được xếp vào hàng đợi sao cho tiến trình đến sau
được thêm vào cuối hàng. Khi CPU được giải phóng, hệ điều hành đặt thời gian của
đồng hồ bằng độ dài lượng tử, lấy một tiến trình ở đầu hàng đợi và cấp CPU cho tiến
trình.
Sau khi được cấp CPU, tiến trình chuyển sang trạng thái chạy. Nếu tiến trình kết thúc
chu kỳ sử dụng CPU trước khi hết thời gian lượng tử, tiến trình sẽ giải phóng CPU và
trả lại quyền điều khiển cho hệ điều hành. Trong trường hợp ngược lại, khi hết độ dài
lượng tử, đồng hồ sẽ sinh ngắt. Tiến trình đang thực hiện phải dừng lại và quyền điều
khiển chuyển cho hàm xử lý ngắt của hệ điều hành. Hệ điều hành thực hiện việc chuyển
đổi ngữ cảnh và chuyển tiến trình về cuối hàng đợi sau đó chọn một tiến trình ở đầu và
lặp lại quá trình trên.
Điều độ quay vòng cho phép cải thiện thời gian đáp ứng của tiến trình so với FCFS
nhưng vẫn có thời gian chờ đợi trung bình tương đối dài. Sau đây là minh họa cho
phương pháp điều độ này với ba tiến trình P1, P2, P3 lấy từ ví dụ ở phần trước và lượng
tử thời gian có độ dài bằng 2.

• Thời gian chờ đợi của P1, P2, P3 lần lượt là 6, 6, và 4.


• Thời gian chờ đợi trung bình = (6 + 6 + 4)/3=5,33.
Một vấn đề quan trọng khi điều độ quay vòng là lựa chọn độ dài lượng tử thời gian. Nếu
lượng tử ngắn, thời gian đáp ứng sẽ giảm. Tuy nhiên, việc chuyển đổi tiến trình diễn ra
thường xuyên đòi hỏi nhiều thời gian hơn cho việc chuyển đổi ngữ cảnh. Độ dài lượng
tử nên lựa chọn lớn hơn thời gian cần thiết để tiến trình thực hiện một thao tác tương tác
tiêu biểu hoặc. Ngược lại, lượng tử càng lớn càng tốn ít thời gian chuyển đổi giữa các
tiến trình nhưng tính đáp ứng cũng kém đi. Khi lượng tử lớn tới một mức nào đó, điều
độ quay vòng sẽ trở thành FCFS.
4.2.2 Thuật toán
Bước khởi tạo: Khởi tạo Hàng đợi và đưa tiến trình đầu tiên vào
While Hàng đợi khác rỗng
Bước 1: Lấy tiến trình xảy ra đầu tiên và bắt đầu thực hiện tiến trình (với
thời gian thực thi là quantum).
Bước 2: Kiểm tra xem có yêu cầu tiến trình nào khác đã đến không. Nếu
một yêu cầu tiến trình đến trong khoảng thời gian quantum mà một tiến
trình khác đang thực thi thì hãy thêm tiến trình mới vào Ready Queue
(RQ).
Bước 3: Sau khi thời gian quantum trôi qua, hãy kiểm tra mọi tiến trình
trong RQ. Nếu RQ trống thì tiếp tục quá trình hiện tại. Nếu RQ không
trống và tiến trình hiện tại chưa hoàn tất thì hãy thêm tiến trình hiện tại
vào cuối RQ.
Kết thúc
4.2.3 Ví dụ Round Robin thời gian đến cùng nhau

Tiến trình Thời điểm vào RL Burst Time Độ ưu tiên

P1 0 10 3

P2 0 1 1

P3 0 2 3

P4 0 1 4

P5 0 5 2

Bước khởi tạo: Khai báo các giá trị và hàng đợi
bt = [10, 1, 2, 1, 5] //danh sách thời gian thực thi của tiến trình
at = [0, 0, 0, 0, 0] // danh sách thời gian tiến trình đến
rq = [p1] // hàng đợi sẵn sàng
p_current = null
quantum = 4
Vòng lặp thứ nhất với rq khác rỗng
Bước 1:
Lấy P1 từ RQ để thực thi với thời gian quantum là 4 đơn vị thời gian.
rq = []
p_current = p1
Bước 2:
Trong thời gian thực thi P1 thì có 6 tiến trình tới là P2, P3, P4, P5. Đưa
các tiến trình này vào hàng đợi RQ.
rq = [p2, p3, p4, p5]
Bước 3:
Sau khi thực hiện xong P1 với thời gian là quantum thì P1 vẫn còn 1 đơn
vị nữa chưa được thực thi và rq khác rỗng. Thêm P1 vào cuối hàng đợi.
rq = [p2, p3, p4, p5, p1]

Vòng lặp thứ hai với rq khác rỗng


Bước 1:
Lấy P2 từ RQ để thực thi với thời gian quantum là 4 đơn vị thời gian.
rq = [p3, p4, p5, p1]
p_current = p2
Bước 2:
Trong thời gian thực thi P2 thì có 0 tiến trình tới. Hàng đợi RQ như cũ.
rq = [p3, p4, p5, p1]
p_current = p2
Bước 3:
Sau khi thực hiện xong P2 với thời gian là quantum thì P2 đã thực hiện
xong.
rq = [p3, p4, p5, p1]
Vòng lặp thứ ba với rq khác rỗng
Bước 1:
Lấy P3 từ RQ để thực thi với thời gian quantum là 4 đơn vị thời gian.
rq = [p4, p5, p1]
p_current = p3
Bước 2:
Trong thời gian thực thi P3 thì không có tiến trình nào tới
rq = [p4, p5, p1]
p_current = p3
Bước 3:
Sau khi thực hiện xong P3 với thời gian là quantum thì P3 đã thực hiện
xong.
rq = [p4, p5, p1]
Vòng lặp thứ tư với rq khác rỗng
Bước 1:
Lấy P4 từ RQ để thực thi với thời gian quantum là 4 đơn vị thời gian.
rq = [p5, p1]
p_current = p4
Bước 2:
Trong thời gian thực thi P4 thì không có tiến trình nào tới
rq = [p5, p1]
p_current = p4
Bước 3:
Sau khi thực hiện xong P4 với thời gian là quantum thì P4 đã thực hiện
xong.
rq = [p5, p1]
Vòng lặp thứ năm với rq khác rỗng
Bước 1:
Lấy P5 từ RQ để thực thi với thời gian quantum là 4 đơn vị thời gian.
rq = [p1]
p_current = p5
Bước 2:
Trong thời gian thực thi P5 thì không có tiến trình nào tới
rq = [p1]
p_current = p5
Bước 3:
Sau khi thực hiện xong P5 với thời gian là quantum thì P5 thì P5 vẫn còn
tồn tại 1 đơn vị thời gian để thực hiện. Đưa P5 vào cuối hàng đợi.
rq = [p1, p5]

Vòng lặp thứ sáu với rq khác rỗng


Bước 1:
Lấy P1 từ RQ để thực thi với thời gian quantum là 4 đơn vị thời gian.
rq = [p5]
p_current = p1
Bước 2:
Trong thời gian thực thi P1 thì không có tiến trình nào tới
rq = [p5]
p_current = p1
Bước 3:
Sau khi thực hiện xong P1 với thời gian là quantum thì P1 thì P1 vẫn còn
tồn tại 2 đơn vị thời gian để thực hiện. Đưa P1 vào cuối hàng đợi.
rq = [p5, p1]
Vòng lặp thứ bảy với rq khác rỗng
Bước 1:
Lấy P5 từ RQ để thực thi với thời gian quantum là 4 đơn vị thời gian. Chi
thực hiện 1.
rq = [p1]
p_current = p1
Bước 2:
Trong thời gian thực thi P5 thì không có tiến trình nào tới
rq = [p1]
p_current = p5
Bước 3:
Sau khi thực hiện xong P5 với thời gian là quantum thì P5 đã hoàn tất.
rq = [p1]
Vòng lặp thứ tám với rq khác rỗng
Bước 1:
Lấy P1 từ RQ để thực thi với thời gian quantum là 4 đơn vị thời gian. Chi
thực hiện 1.
rq = []
p_current = p1
Bước 2:
Trong thời gian thực thi P1 thì không có tiến trình nào tới
rq = []
p_current = p1
Bước 3:
Sau khi thực hiện xong P1 với thời gian là quantum thì P1 đã hoàn tất.
rq = []
RQ rỗng, các tiến trình đã hoàn tất.
Arrival.T Burst.T Completion.T TAT Waiting.T
Process
(1) (2) (3) (4) = (3)–(1) (5)=(4)-(2)

P1 0 10 19 19 9

P2 0 1 5 5 4

P3 0 2 7 7 5

P4 0 1 8 8 7

P5 0 5 17 17 12

Thời gian chờ trung bình:


9 + 4 + 5 + 7 + 12 37
= = 7.4
5 5
Thời gian quay vòng trung bình:
19 + 5 + 7 + 8 + 17 56
= = 11.2
5 5
4.2.4 Ví dụ Round Robin thời gian đến khác nhau

Tiến trình Thời điểm vào RL Burst Time Độ ưu tiên

P1 0 5 3

P2 1 6 1

P3 2 3 3

P4 3 1 4

P5 4 5 2

P6 6 4 1

Bước khởi tạo: Khai báo các giá trị và hàng đợi
bt = [5, 6, 4, 1, 5, 4] //danh sách thời gian thực thi của tiến trình
at = [0, 1, 2, 3, 4, 6] // danh sách thời gian tiến trình đến
rq = [p1] // hàng đợi sẵn sàng
p_current = null
quantum = 4
Vòng lặp thứ nhất với rq khác rỗng
Bước 1:
Lấy P1 từ RQ để thực thi với thời gian quantum là 4 đơn vị thời gian.
rq = []
p_current = p1
Bước 2:
Trong thời gian thực thi P1 thì có 4 tiến trình tới là P2, P3, P4, P5. Đưa
các tiến trình này vào hàng đợi RQ.
rq = [p2, p3, p4, p5]
Bước 3:
Sau khi thực hiện xong P1 với thời gian là quantum thì P1 vẫn còn 1 đơn
vị nữa chưa được thực thi và rq khác rỗng. Thêm P1 vào cuối hàng đợi.
rq = [p2, p3, p4, p5, p1]
Vòng lặp thứ hai với rq khác rỗng
Bước 1:
Lấy P2 từ RQ để thực thi với thời gian quantum là 4 đơn vị thời gian.
rq = [p3, p4, p5, p1]
p_current = p2
Bước 2:
Trong thời gian thực thi P1 thì có 1 tiến trình tới là P6. Đưa các tiến trình
này vào hàng đợi RQ.
rq = [p3, p4, p5, p1, p6]
p_current = p2
Bước 3:
Sau khi thực hiện xong P2 với thời gian là quantum thì P2 vẫn còn 2 đơn
vị nữa chưa được thực thi và rq khác rỗng. Thêm P2 vào cuối hàng đợi.
rq = [p3, p4, p5, p1, p6, p2]
Vòng lặp thứ ba với rq khác rỗng
Bước 1:
Lấy P3 từ RQ để thực thi với thời gian quantum là 4 đơn vị thời gian.
rq = [p4, p5, p1, p6, p2]
p_current = p3
Bước 2:
Trong thời gian thực thi P3 thì không có tiến trình nào tới
rq = [p4, p5, p1, p6, p2]
p_current = p3
Bước 3:
Sau khi thực hiện xong P3 với thời gian là quantum thì P3 đã thực hiện
xong.
rq = [p4, p5, p1, p6, p2]
Vòng lặp thứ tư với rq khác rỗng
Bước 1:
Lấy P4 từ RQ để thực thi với thời gian quantum là 4 đơn vị thời gian.
rq = [p5, p1, p6, p2]
p_current = p4
Bước 2:
Trong thời gian thực thi P4 thì không có tiến trình nào tới
rq = [p5, p1, p6, p2]
p_current = p4
Bước 3:
Sau khi thực hiện xong P4 với thời gian là quantum thì P4 đã thực hiện
xong.
rq = [p5, p1, p6, p2]
Vòng lặp thứ năm với rq khác rỗng
Bước 1:
Lấy P5 từ RQ để thực thi với thời gian quantum là 4 đơn vị thời gian.
rq = [p1, p6, p2]
p_current = p5
Bước 2:
Trong thời gian thực thi P5 thì không có tiến trình nào tới
rq = [p1, p6, p2]
p_current = p5
Bước 3:
Sau khi thực hiện xong P5 với thời gian là quantum thì P5 thì P5 vẫn còn
tồn tại 1 đơn vị thời gian để thực hiện. Đưa P5 vào cuối hàng đợi.
rq = [p1, p6, p2, p5]
Vòng lặp thứ sáu với rq khác rỗng
Bước 1:
Lấy P1 từ RQ để thực thi với thời gian quantum là 4 đơn vị thời gian.
rq = [p6, p2, p5]
p_current = p1
Bước 2:
Trong thời gian thực thi P1 thì không có tiến trình nào tới
rq = [p6, p2, p5]
p_current = p1
Bước 3:
Sau khi thực hiện xong P1 với thời gian là quantum thì P1 đã hoàn tất.
rq = [p6, p2, p5]

Vòng lặp thứ bảy với rq khác rỗng


Bước 1:
Lấy P6 từ RQ để thực thi với thời gian quantum là 4 đơn vị thời gian.
rq = [p2, p5]
p_current = p6
Bước 2:
Trong thời gian thực thi P6 thì không có tiến trình nào tới
rq = [p2, p5]
p_current = p6
Bước 3:
Sau khi thực hiện xong P6 với thời gian là quantum thì P6 đã hoàn tất.
rq = [p2, p5]
Vòng lặp thứ bảy với rq khác rỗng
Bước 1:
Lấy P2 từ RQ để thực thi với thời gian quantum là 4 đơn vị thời gian.
rq = [p5]
p_current = p2
Bước 2:
Trong thời gian thực thi P2 thì không có tiến trình nào tới
rq = [p5]
p_current = p2
Bước 3:
Sau khi thực hiện xong P2 với thời gian là quantum thì P2 đã hoàn tất.
rq = [p5]
Vòng lặp thứ tám với rq khác rỗng
Bước 1:
Lấy P5 từ RQ để thực thi với thời gian quantum là 4 đơn vị thời gian.
rq = []
p_current = p5
Bước 2:
Trong thời gian thực thi P5 thì không có tiến trình nào tới
rq = []
p_current = p5
Bước 3:
Sau khi thực hiện xong P5 với thời gian là quantum thì P5 đã hoàn tất.
rq = []
RQ rỗng, các tiến trình đã hoàn tất.

Arrival.T Burst.T Completion.T TAT Waiting.T


Process
(1) (2) (3) (4) = (3)–(1) (5)=(4)-(2)

P1 0 5 17 17 12

P2 1 6 23 22 16

P3 2 3 11 9 6

P4 3 1 12 9 8

P5 4 5 24 20 15

P6 6 4 21 15 11

Thời gian chờ trung bình là:


12 + 16 + 6 + 8 + 15 + 11 38
= ≈ 12.66
6 3
Thời gian quay vòng trung bình là:
17 + 22 + 9 + 9 + 20 + 15 46
= ≈ 15.33
6 3
4.3 Lập lịch CPU với độ ưu tiên
4.3.1 Lập lịch CPU với độ ưu tiên độc quyền (non-preemptive)
Chỉ số Độ ưu tiên bé nhất thực hiện trước.
Ví dụ 1:

Tiến trình Thời điểm vào RL Burst Time Độ ưu tiên

P1 0 10 3

P2 1 1 1

P3 2.5 2 3

P4 3 1 4

P5 4.5 5 2

• Thực hiện Tiến trình P1 trước vì P1 có thời gian đến là 0.


• Trong thời gian thực thi P1 thì có 4 tiến trình đến là P2, P3, P4, P5.
• Sau khi thực hiện xong P1 thực hiện xong thì xét độ ưu tiên P2, P3, P4, P5. P2
có giá trị ưu tiên nhỏ nhất nên chọn P2.
• Sau khi thực hiện xong P2 thì xét độ ưu tiên P3, P4, P5. P5 có giá trị ưu tiên nhỏ
nhất nên tiến trình được ưu tiên tiếp theo là P5
• Sau khi thực hiện xong P5 thì xét độ ưu tiên P3, P4. P3 có giá trị ưu tiên nhỏ nhất
nên tiến trình được ưu tiên tiếp theo là P3
• Sau khi thực hiện xong P3 thì xét độ ưu tiên tiếp theo là P4
Arrival.T Burst.T Completion.T TAT Waiting.T
Process
(1) (2) (3) (4) = (3)–(1) (5)=(4)-(2)

P1 0 10 10 10 0

P2 1 1 11 10 9

P3 2.5 2 18 15.5 13.5

P4 3 1 19 16 15

P5 4.5 5 16 11.5 11

Thời gian chờ trung bình: (0+9+13.5+15+11)/5


Thời gian quay vòng trung bình: (10+10+15.5+16+11.5)/5
4.3.2 Lập lịch CPU với độ ưu tiên không độc quyền (preemptive)
4.3.2.1 Các khái niệm
Thuật toán lập lịch CPU ưu tiên không độc quyền sử dụng hệ thống dựa trên thứ hạng
để xác định thứ hạng cho mỗi tiến trình, trong đó các tiến trình xếp hạng thấp hơn có
mức độ ưu tiên cao hơn và các tiến trình xếp hạng cao hơn có mức độ ưu tiên thấp hơn.
Ví dụ: nếu có 10 quy trình được thực thi bằng Thuật toán ưu tiên này thì tiến trình có
hạng 1 sẽ có mức độ ưu tiên cao nhất, tiến trình có hạng 2 sẽ có mức độ ưu tiên tương
đối thấp hơn và quy trình có hạng 10 sẽ có mức độ ưu tiên ít nhất.
4.3.2.2 Thuật toán
Bước 1: Chọn tiến trình đầu tiên có thời gian đến là 0, chúng ta cần chọn tiến trình đó
vì tiến trình đó chỉ thực thi tại thời điểm t=0.
Bước 2: Kiểm tra mức độ ưu tiên của tiến trình có sẵn tiếp theo. Ở đây chúng ta cần
kiểm tra 3 điều kiện.

• nếu mức độ ưu tiên (current_process) > mức độ ưu tiên(prior_process) :- thì thực


hiện tiến trình hiện tại.
• nếu mức độ ưu tiên (current_process) < mức độ ưu tiên (prior_process) :- thì thực
hiện tiến trình trước đó.
• nếu mức độ ưu tiên (current_process) = mức độ ưu tiên (prior_process) :- thì thực
hiện tiến trình đến trước, tức là thời gian đến phải đến trước.
Bước 3: Lặp lại Bước 2 cho đến khi đạt đến tiến trình cuối cùng.
Bước 4: Khi đến tiến trình cuối cùng, hãy chọn tiến trình có mức độ ưu tiên cao nhất và
thực hiện nó. Lặp lại bước tương tự cho đến khi tất cả các tiến trình hoàn thành việc
thực thi của chúng.
4.3.2.3 Ví dụ:

Tiến trình Thời điểm vào RL Burst Time Độ ưu tiên

P1 0 10 3

P2 1 1 1

P3 2.5 2 3

P4 3 1 4

P5 4.5 5 2

Ở thời điểm t=0

• Tiến trình P1 là quá trình duy nhất có sẵn trong hàng đợi sẵn sàng vì thời gian
đến của nó là 0ms.
• Do đó, tiến trình P1 được thực thi trước tiên trong 1ms, từ 0ms đến 1ms, bất kể
mức độ ưu tiên của nó.
• Thời gian Burst còn lại (B.T) cho P1 = 10-1 = 9 ms.
Ở thời điểm t=1

• Có 2 tiến trình có sẵn trong hàng đợi sẵn sàng: P1 và P2.


• Do mức độ ưu tiên của quy trình P2 cao hơn mức ưu tiên của quy trình P1 nên
Quy trình P2 sẽ được thực thi trước.
• Do đó Quá trình P2 được thực thi trong 1ms, từ 1ms đến 2ms.
• Thời gian Burst còn lại (B.T) cho P2 = 1-1 = 0 ms.
Ở thời điểm t=2

• Tiến trình P1 là quá trình duy nhất có sẵn trong hàng đợi sẵn sàng
• Do đó, tiến trình P1 được thực thi trước tiên trong 0,5ms, từ 2ms đến 2,5ms, bất
kể mức độ ưu tiên của nó.
• Thời gian Burst còn lại (B.T) cho P1 = 9-0,5 = 8,5 ms.
Ở thời điểm t=2.5

• Có 2 tiến trình có sẵn trong hàng đợi sẵn sàng: P1 và P3.


• Độ ưu tiên của P1 và P3 là như nhau, tuy nhiên P1 vào trước nên được ưu tiên
hơn.
• Do đó tiến trình P1 được thực thi trong 0,5ms, từ 2,5ms đến 3ms.
• Thời gian Burst còn lại (B.T) cho P1 = 8,5-0,5 = 8 ms.
Ở thời điểm t=3

• Có 3 tiến trình có sẵn trong hàng đợi sẵn sàng: P1 và P3, P4.
• Độ ưu tiên của P1 và P3 lớn hơn P4; P1 và P3 là như nhau, tuy nhiên P1 vào
trước nên được ưu tiên hơn.
• Do đó tiến trình P1 được thực thi trong 1,5ms, từ 3ms đến 4,5ms.
• Thời gian Burst còn lại (B.T) cho P1 = 8-1,5 = 6,5 ms.
Ở thời điểm t=4,5

• Có 4 tiến trình có sẵn trong hàng đợi sẵn sàng: P1 và P3, P4, P5.
• Độ ưu tiên của P5 là tốt nhất.
• Do đó tiến trình P5 được thực thi trong 5ms, từ 4,5ms đến 9,5ms.
• Thời gian Burst còn lại (B.T) cho P5 = 5-5 = 0 ms.
Ở thời điểm t=9,5

• Có 3 tiến trình có sẵn trong hàng đợi sẵn sàng: P1 và P3, P4.
• Độ ưu tiên của P1 và P3 lớn hơn P4; P1 và P3 là như nhau, tuy nhiên P1 vào
trước nên được ưu tiên hơn.
• Do đó tiến trình P1 được thực thi trong 6,5ms, từ 9,5ms đến 16ms..
• Thời gian Burst còn lại (B.T) cho P1 = 6,5-5,5 = 0 ms.
Ở thời điểm t=16

• Có 2 tiến trình có sẵn trong hàng đợi sẵn sàng: P3, P4.
• Độ ưu tiên của P3 lớn hơn P4;
• Do đó tiến trình P3 được thực thi trong 2ms, từ 16ms đến 18ms..
• Thời gian Burst còn lại (B.T) cho P3 = 2-2 = 0 ms.
Ở thời điểm t=18

• Có 1 tiến trình có sẵn trong hàng đợi sẵn sàng: P4.


• Do đó tiến trình P4 được thực thi trong 1ms, từ 18ms đến 19ms..
• Thời gian Burst còn lại (B.T) cho P4 = 1-1 = 0 ms

Arrival.T Burst.T Completion.T TAT Waiting.T


Process
(1) (2) (3) (4) = (3)–(1) (5)=(4)-(2)

P1 0 10 16 6 6

P2 1 1 2 1 0
P3 2.5 2 18 15.5 13,5

P4 3 1 19 16 15

P5 4.5 5 9,5 5 0

Thời gian chờ trung bình: (6+0+13,5+15+0)/5


Thời gian TAT trung bình: (6+1+15,5+16+5)/5
4.3.3 Điều độ ưu tiên tiến trình ngắn nhất - SJF
Một phương pháp điều độ cho phép giảm thời gian chờ đợi trung bình là điều độ ưu tiên
tiến trình ngắn nhất trước (Shortest Process First - SPF), hay còn có các tên gọi khác
như công việc ngắn nhất trước (Shortest Job Fist - SJF), tiến trình ngắn nhất tiếp theo
(Shortest Process Next - SPN). Phương pháp điều độ này lựa chọn trong hàng đợi tiến
trình có chu kỳ sử dụng CPU tiếp theo ngắn nhất để phân phối CPU. Trong trường hợp
có nhiều tiến trình với chu kỳ CPU tiếp theo bằng nhau, tiến trình đứng trước sẽ
được chọn.
Ưu điểm lớn nhất của SPF so với FCFS là thời gian chờ đợi trung bình nhỏ hơn nhiều.
Xét ví dụ điều độ cho các tiến trình như ở phần trên nhưng sử dụng SPF.

Thời gian chờ đợi trung bình = (6 + 2 +0)/3 = 2,67.


Mặc dù điều độ ưu tiên tiến trình ngắn nhất có thời gian chờ đợi trung bình tối ưu,
phương pháp này rất khó sử dụng trên thực tế do đòi hỏi phải biết trước độ dài chu kỳ
sử dụng CPU tiếp theo của tiến trình.
Có hai cách để giải quyết phần nào khó khăn này.
Cách thứ nhất được áp dụng đối với hệ thống xử lý theo mẻ như tại các trung tâm tính
toán hiệu năng cao hiện nay. Quản trị hệ thống căn cứ vào thời gian đăng ký tối đa do
lập trình viên cung cấp để xếp những ứng dụng có thời gian đăng ký ngắn hơn lên
trước. Lưu ý, đây là thời gian thực hiện cả ứng dụng chứ không phài một chu kỳ sử
dụng CPU cụ thể.
Cách thứ hai là dự đoán độ dài chu kỳ sử dụng CPU tiếp theo. Cách dự đoán đơn giản
nhất là dựa trên độ dài trung bình các chu kỳ CPU trước đó để dự đoán độ dài chu kỳ
tiếp theo và ra quyết định cấp CPU.
Điều độ ưu tiên tiến trình ngắn nhất trước là điều độ không có phân phối lại. Nếu một
tiến trình được cấp CPU, tiến trình sẽ thực hiện cho tới khi không cần CPU nữa, kể cả
trong trường hợp xuất hiện tiến trình mới với chu kỳ sử dụng CPU ngắn hơn chu kỳ
CPU còn lại của tiến trình đang thực hiện. Trong phần tiếp theo ta sẽ xem xét việc thêm
cơ chế phân phối lại cho điều độ ưu tiên tiến trình ngắn nhất trước.
4.3.3.1 Đặc điểm của lập kế hoạch SJF

• Nó gắn liền với mỗi công việc như một đơn vị thời gian hoàn thành.
• Phương pháp thuật toán này hữu ích cho việc xử lý theo kiểu hàng loạt, trong đó
việc chờ đợi công việc hoàn thành là không quan trọng.
• Nó có thể cải thiện thông lượng tiến trình bằng cách đảm bảo rằng các công việc
ngắn hơn được thực hiện trước, do đó có thể có thời gian quay vòng ngắn.
• Nó cải thiện sản lượng công việc bằng cách cung cấp các công việc ngắn hơn,
cần được thực hiện trước, hầu hết có thời gian quay vòng ngắn hơn.
4.3.3.2 Thuật toán
Tính thời gian t: thời gian xử lý mà tiến trình còn yêu cầu
!
Độ ưu tiên 𝑝 = "

Ưu tiên xử lý tiến trình có 𝑝 lớn nhất. Không tính toán lại 𝑝 khi có tiến trình mới đến.

Tiến trình Thời điểm vào RL Burst Time Độ ưu tiên

P1 0 10 3

P2 1 1 1

P3 2.5 2 3

P4 3 1 4

P5 4.5 5 2

Bước 1: Ở thời điểm 0, P1 đến và bắt đầu thực thi


Bước 2: Ở thời điểm 1, P2 đến. Nhưng P1 vẫn đang thực thi cho đến hết. P1 tiếp tục
thực thi. P2 được đưa vào waiting queue wq.
wq=[p2]
Bước 3: Ở thời điểm 2.5. P3 đến. Nhưng P1 vẫn đang thực thi cho đến hết. P1 tiếp tục
thực thi. P3 được đưa vào waiting queue wq.
wq=[p2, p3]
Bước 4: Ở thời điểm 3. P4 đến. Nhưng P1 vẫn đang thực thi cho đến hết. P1 tiếp tục
thực thi. P4 được đưa vào waiting queue wq.
wq=[p2, p3, p4]
Bước 5: Ở thời điểm 4.5. P5 đến. Nhưng P1 vẫn đang thực thi cho đến hết. P1 tiếp tục
thực thi. P5 được đưa vào waiting queue wq.
wq=[p2, p3, p4, p5]
Bước 6: Ở thời điểm 10. P1 thực hiện xong. So sánh thời gian thực thi của P2, P3, P4,
P5. P2 và P4 có độ ưu tiên cao hơn P3 và P5. Tuy nhiên P2 đến trước nên được thực thi.
wq=[p3, p4, p5]
Bước 7: Ở thời điểm 11. P2 thực hiện xong. So sánh thời gian thực thi của P3, P4, P5.
P4 có độ ưu tiên cao hơn P3 và P5. P4 được lựa chọn thực thi.
wq=[p3, p5]
Bước 8: Ở thời điểm 12. P4 thực hiện xong. So sánh thời gian thực thi của P3, P5. P3
có độ ưu tiên cao hơn P5. P3 được lựa chọn thực thi.
wq=[p5]
Bước 8: Ở thời điểm 14. P3 thực hiện xong. WQ chỉ còn P5. P5 được lựa chọn thực thi.
wq=[]
Bước 9: Tất cả các tiến trình đều được thực thi. Kết thúc.
TAT Waiting.T
Arrival.T Burst.T Completion.T
Process (4) = (3)– (5)=(4)-(2)
(1) (2) (3)
(1)

P1 0 10 10 10 0

P2 1 1 11 10 9

P3 2.5 2 14 11.5 9.5

P4 3 1 12 9 8

P5 4.5 5 19 14.5 9.5

Thời gian chờ trung bình là:


0 + 9 + 9.5 + 8 + 9.5 36
= = 7.2
5 5
Thời gian quay vòng trung bình là:
10 + 10 + 11.5 + 9 + 14.5 55
= = 11
5 5

4.3.4 Điều độ ưu tiên thời gian ngắn nhất


4.3.4.1 Các khái niệm
Phiên bản ưu tiên tiến trình ngắn nhất có thêm cơ chế phân phối lại được gọi là điều độ
ưu tiên thời gian còn lại ngắn nhất trước (Shortest Remaining Time First – SRTF). Khi
một tiến trình mới xuất hiện trong hàng đợi, hệ điều hành so sánh thời gian còn lại của
tiến trình đang chạy với thời gian còn lại của tiến trình mới xuất hiện. Nếu tiến trình mới
xuất hiện có thời gian còn lại ngắn hơn, hệ điều hành sẽ thu hồi CPU của tiến trình
đang chạy và phân phối cho tiến trình mới.
4.3.4.2 Thuật toán
Tính thời gian t: thời gian xử lý mà tiến trình còn yêu cầu
!
Độ ưu tiên 𝑝 =
"

Ưu tiên xử lý tiến trình có 𝑝 lớn nhất.


Tính toán lại 𝑝 khi có tiến trình mới đến.
4.3.4.1 Ví dụ

Tiến trình Thời điểm vào RL Burst Time Độ ưu tiên

P1 0 10 3

P2 1 1 1

P3 2.5 2 3

P4 3 1 4

P5 4.5 5 2

Bước 1: Ở thời điểm 0, P1 đến và bắt đầu thực thi


Bước 2: Ở thời điểm 1, P2 đến.
Tính toán lại độ ưu tiên. P2 có độ ưu tiên hơn P1. P1 tạm dừng. Đưa P1 vào WQ.
P1 còn 9. Thực hiện P2.
wq=[p1]
Bước 3: Ở thời điểm 2. P2 thực hiện xong. P1 tiếp tục thực hiện.
wq=[]
Bước 4: Ở thời điểm 2.5. P3 đến.
Tính toán lại độ ưu tiên. P3 có độ ưu tiên hơn P1. P1 tạm dừng. Đưa P1 vào WQ.
P1 còn 8.5. Thực hiện P3.
wq=[p1]
Bước 5: Ở thời điểm 3. P4 đến. P3 còn 1.5; P4 còn 1; P1 còn 8.5
Tính toán lại độ ưu tiên. P4 có độ ưu tiên hơn P1 và P3. P3 tạm dừng. Đưa P3
vào WQ. P1 còn 8.5. Thực hiện P4.
wq=[p1, p3]
Bước 6: Ở thời điểm 4. P4 thực hiện xong.
Kiểm tra độ ưu tiên P1 (8.5) và P3 (1.5). P3 thực hiện.
wq=[p1]
Bước 7: Ở thời điểm 4.5. P5 đến.
Kiểm tra độ ưu tiên P1 (8.5), P3 (1.0), P5(5). P3 có độ ưu tiên cao nhất. Thực
hiện tiếp P3. Đưa P5 vào WQ.
wq=[p1, p5]
Bước 8: Ở thời điểm 5.5. P3 thực hiện xong.
Kiểm tra độ ưu tiên P1 (8.5), P5(5). P5 có độ ưu tiên cao nhất. Thực hiện P5.
wq=[p1, p5]
Bước 9: Ở thời điểm 10.5. P5 thực hiện xong. WQ chỉ còn P1 nên thực hiện P1.
Bước 10: Ở điểm 19. P1 thực hiện xong.
Không còn tiến trình nào. Kết thúc.
Arrival.T Burst.T Completion.T TAT Waiting.T
Process
(1) (2) (3) (4) = (3)–(1) (5)=(4)-(2)

P1 0 10 19 19 9

P2 1 1 2 1 1

P3 2.5 2 5.5 3 1

P4 3 1 4 1 0

P5 4.5 5 10.5 6 1

Thời gian chờ trung bình là:


9 + 1 + 1 + 0 + 1 12
= = 2.4
5 5
Thời gian quay vòng trung bình là:
19 + 1 + 3 + 1 + 6 30
= =6
5 5

Điều độ ưu tiên thời gian còn lại ngắn nhất


4.4 Bài tập
Bài 1. Hiện thực các thuật toán điều phối sau dùng ngôn ngữ lập trình C:

• Firt-come First-serve
• Round Robin với q = 2
• Thuật toán độ ưu tiên
• Shortest Job First (SJF)
• Shortest Remaining Time First (SRTF)
Bài 2. Hiện thực các thuật toán điều phối sau dùng ngôn ngữ lập trình Python:

• Firt-come First-serve
• Round Robin với q = 2
• Thuật toán độ ưu tiên
• Shortest Job First (SJF)
• Shortest Remaining Time First (SRTF)

Bài 3. Xét tập hợp các tiến trình sau:

Tiến trình Thời điểm vào RL Thời gian CPU Độ ưu tiên

P1 0 7 2

P2 1 1 1

P3 2.5 2 3

P4 3 1 4

P5 4.5 4 2

Hãy cho biết kết quả điều phối theo các chiến lược

• Firt-come First-serve
• Round Robin với q = 2
• Thuật toán độ ưu tiên
• Shortest Job First (SJF)
• Shortest Remaining Time First (SRTF)
Tính thời gian chờ cho từng tiến trình và thời gian chờ trung bình trong các chiến lược
trên.
Bài 4. Xét tập hợp các tiến trình sau:

Tiến trình Thời điểm vào RL Thời gian CPU Độ ưu tiên

P1 0 4 2

P2 1 1 1

P3 2 2 3

P4 3.5 1 4

P5 4 6 2
Hãy cho biết kết quả điều phối theo các chiến lược

• FCFS
• Round Robin với q = 2
• Thuật toán độ ưu tiên
• Shortest Job First
• Shortest Remaining Time First (SRTF)
Tính thời gian chờ cho từng tiến trình và thời gian chờ trung bình trong các chiến lược
trên.

You might also like