You are on page 1of 28

Câu 1: Mối quan hệ cha-con giữa các tiến trình

a. Vẽ cây quan hệ parent-child


1
└── 86 WindowServer
├── 281 iTunes
├── 282 Terminal
│ └── 287 login
│ └── 293 -bash
│ ├── 461 firefox-bin
│ └── 751 Aquamacs
├── 531 Safari
└── 726 Mail
b. Cách sử dụng lệnh ps để tìm tiến trình cha của một một tiến trình dựa vào PID của nó.
.Trước tiên ta dùng lệnh ps -ef để hiển thị tất cả các tiến trình đang chạy với dữ liệu đầy
đủ nhất cho mỗi tiến trình.
.Sau đó ta thực hiện lệnh sau: ps -o ppid= -p <PID>
(PID là id của tiến trình mà ta muốn tìm tiến trình cha)
.Ví dụ:

*
Trong
lệnh ps
-o
ppid=
-p
<PID>:
- Tùy chọn -o để chỉ định các trường thông tin bạn muốn hiển thị.
- Trường ppid là ID của tiến trình cha.
c. Cách sử dụng lệnh pstree để tìm tiến trình cha của một tiến trình dựa vào PID của nó.
* Các options của lệnh pstree:
pstree [-a, --arguments] [-c, --compact-not] [-C, --color attr]
[-g, --show-pgids] [-h, --highlight-all, -H pid, --highlight-pid pid]
[-l, --long] [-n, --numeric-sort] [-N, --ns-sort ns] [-p, --show-pids]
[-s, --show-parents] [-S, --ns-changes] [-t, --thread-names]
[-T, --hide-threads] [-u, --uid-changes] [-Z, --security-context]
[-A, --ascii, -G, --vt100, -U, --unicode] [pid, user]
pstree -V, --version
.Ở đây ta sẽ sử dụng 2 options là:
-s để hiển thị tiến trình cha (PPID) của tiến trình con (PID)
-p và để hiển thị số PID của tiến trình
.Ví dụ: pstree -p -s 2823
Câu 2:

.Đoạn chương trình trên sử dụng hàm fork() để tạo một tiến trình con.
1. Trong phần của tiến trình cha:
 Biến pid được khai báo để lưu giá trị ID của tiến trình con khi sử dụng hàm
fork().Biến num_coconuts được khởi tạo với giá trị 17.
 Hàm fork() được gọi để tạo một tiến trình con. Khi gọi fork(), tiến trình cha sẽ tạo
một bản sao của chính nó và trả về ID của tiến trình con cho tiến trình cha và trả
về 0 cho tiến trình con.
 Trong tiến trình cha, kiểm tra giá trị pid. Nếu pid là 0, nghĩa là đang thực thi trong
tiến trình con, không phải tiến trình cha. Do đó, biến num_coconuts được gán giá
trị 42 và tiến trình con kết thúc với lệnh exit(0).
 Trong tiến trình cha, chờ cho tiến trình con kết thúc bằng cách sử dụng hàm
wait(NULL). Hàm này đảm bảo rằng tiến trình cha không kết thúc trước khi tiến
trình con hoàn thành.
 Cuối cùng, in ra giá trị của biến num_coconuts (17) bằng câu lệnh printf.
2. Trong phần của tiến trình con:
 Nếu giá trị pid trả về từ hàm fork() là 0, đó là tiến trình con. Trong trường hợp
này, biến num_coconuts được gán giá trị 42.
 Tiến trình con kết thúc với lệnh exit(0).
.Kết quả chạy chương trình sẽ in ra dòng "I see 17 coconuts!". Lý do là vì khi gọi hàm
fork(), child process sẽ sao chép toàn bộ bộ nhớ của parent process, bao gồm cả các biến
và giá trị của chúng. Tuy nhiên, khi child process thay đổi giá trị của biến num_coconuts,
nó chỉ thay đổi trong không gian bộ nhớ của nó, không ảnh hưởng đến parent process. Do
đó, parent process vẫn giữ nguyên giá trị ban đầu của biến num_coconuts là 17.
Câu 3:
*Các hàm được sử dụng để làm thay đổi thuộc tính của pthread:

 pthread_attr_init (pthread_attr_t *attr): để khởi tạo đối tượng thuộc tính luồng


với các giá trị mặc định.

 pthread_attr_destroy (pthread_attr_t *attr): để xóa bộ nhớ cấp phát cho đối


tượng thuộc tính luồng và làm cho nó không hợp lệ.

 pthread_attr_setdetachstate (pthread_attr_t *attr, int detachstate): để đặt trạng


thái detach của luồng (joinable hoặc detached) cho đối tượng thuộc tính luồng.

 pthread_attr_getdetachstate (const pthread_attr_t *attr, int *detachstate): để lấy


trạng thái detach của luồng từ đối tượng thuộc tính luồng.

 pthread_attr_setscope (pthread_attr_t *attr, int scope): để đặt phạm vi tranh chấp


của luồng (process hoặc system) cho đối tượng thuộc tính luồng.

 pthread_attr_getscope (const pthread_attr_t *attr, int *scope): để lấy phạm vi


tranh chấp của luồng từ đối tượng thuộc tính luồng.

 pthread_attr_setstackaddr (pthread_attr_t *attr, void *stackaddr): để đặt địa chỉ


ngăn xếp của luồng cho đối tượng thuộc tính luồng.

 pthread_attr_getstackaddr (const pthread_attr_t *attr, void **stackaddr): để lấy


địa chỉ ngăn xếp của luồng từ đối tượng thuộc tính luồng.

 pthread_attr_setstacksize (pthread_attr_t *attr, size_t stacksize): để đặt kích


thước ngăn xếp của luồng cho đối tượng thuộc tính luồng.

 pthread_attr_getstacksize (const pthread_attr_t *attr, size_t *stacksize): để lấy


kích thước ngăn xếp của luồng từ đối tượng thuộc tính luồng.

 pthread_attr_setschedpolicy (pthread_attr_t *attr, int policy): để đặt chính sách


lập lịch của luồng cho đối tượng thuộc tính luồng.

 pthread_attr_getschedpolicy (const pthread_attr_t *restrict attr, int *restrict


policy): để lấy chính sách lập lịch của luồng từ đối tượng thuộc tính luồng.

 pthread_attr_setguardsize (pthread_attr_t *attr, size_t guardsize): để đặt kích


thước bảo vệ ngăn xếp của luồng cho đối tượng thuộc tính luồng.
 pthread_attr_getguardsize (const pthread_attr_t *attr, size_t *guardsize): để lấy
kích thước bảo vệ ngăn xếp của luồng từ đối tượng thuộc tính luồng.
*Các chương trình minh họa:
-pthread_attr_init :

+Khái quát:
.Hàm pthread_attr_init có prototype như sau:

#include <pthread.h>
int pthread_attr_init(pthread_attr_t *attr);

.Trong đó, attr là con trỏ trỏ đến đối tượng thuộc tính luồng cần khởi tạo. Hàm
này trả về 0 nếu thành công, hoặc một số dương là mã lỗi nếu có lỗi.

+Code và kết quả:

+Công dụng trong chương trình:


Tác dụng của hàm pthread_attr_init trong ví dụ trên là để khởi tạo một đối tượng
thuộc tính luồng với các giá trị mặc định cho các thuộc tính như trạng thái detach,
kích thước ngăn xếp, chính sách lập lịch, v.v. Điều này có nghĩa là khi tạo luồng
mới với đối tượng thuộc tính luồng này, luồng sẽ có các thuộc tính theo giá trị mặc
định của hệ thống. Đây là một cách để thiết lập các thuộc tính cho các luồng mới
một cách nhanh chóng và tiện lợi.
- pthread_attr_destroy:

+Khái quát:
.Hàm pthread_attr_destroy có prototype như sau:

#include <pthread.h>
int pthread_attr_destroy(pthread_attr_t *attr);

.Trong đó, attr là con trỏ trỏ đến đối tượng thuộc tính luồng cần xóa. Hàm này trả
về 0 nếu thành công, hoặc một số dương là mã lỗi nếu có lỗi.

+Code và kết quả:

+Công dụng trong chương trình:

Tác dụng của hàm pthread_attr_destroy trong chương trình trên là để xóa


bộ nhớ cấp phát cho đối tượng thuộc tính luồng và làm cho nó không hợp lệ. Điều
này có nghĩa là đối tượng thuộc tính luồng này không thể được sử dụng để tạo các
luồng mới. Đây là một cách để tránh rò rỉ bộ nhớ và giảm thiểu lãng phí tài
nguyên của tiến trình.

-pthread_attr_setdetachstate:
+Khái quát:
Hàm pthread_attr_setdetachstate có prototype như sau:

#include <pthread.h>
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);

Trong đó, attr là con trỏ trỏ đến đối tượng thuộc tính luồng cần đặt trạng thái
detach, detachstate là giá trị chỉ định trạng thái detach của luồng. Có hai giá trị có
thể được sử dụng cho detachstate:

 PTHREAD_CREATE_JOINABLE: Luồng được tạo ra với đối tượng thuộc tính


luồng này sẽ ở trạng thái joinable, tức là có thể được chờ kết thúc bằng
hàm pthread_join và lấy kết quả trả về của luồng.
 PTHREAD_CREATE_DETACHED: Luồng được tạo ra với đối tượng thuộc
tính luồng này sẽ ở trạng thái detached, tức là không thể được chờ kết thúc bằng
hàm pthread_join và sẽ tự động giải phóng tài nguyên khi kết thúc.
Hàm này trả về 0 nếu thành công, hoặc một số dương là mã lỗi nếu có lỗi.

+Code và kết quả:

+Công dụng trong chương trình:


Tác dụng của hàm pthread_attr_setdetachstate trong chương trình trên là để
đặt trạng thái detach của luồng là detached cho đối tượng thuộc tính luồng. Điều
này có nghĩa là luồng được tạo ra với đối tượng thuộc tính luồng này sẽ không thể
được chờ kết thúc bằng hàm pthread_join và sẽ tự động giải phóng tài nguyên khi
kết thúc. Đây là một cách để tránh tạo ra các zombie thread gây lãng phí tài
nguyên của tiến trình.

-pthread_attr_getdetachstate:

+Khái quát:
.Hàm pthread_attr_getdetachstate có prototype như sau:

#include <pthread.h>
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);

.Trong đó, attr là con trỏ trỏ đến đối tượng thuộc tính luồng cần lấy trạng thái
detach, detachstate là con trỏ trỏ đến biến lưu giá trị chỉ định trạng thái detach của
luồng. Có hai giá trị có thể được lưu vào detachstate:

 PTHREAD_CREATE_JOINABLE: Luồng được tạo ra với đối tượng thuộc tính


luồng này sẽ ở trạng thái joinable, tức là có thể được chờ kết thúc bằng
hàm pthread_join và lấy kết quả trả về của luồng.
 PTHREAD_CREATE_DETACHED: Luồng được tạo ra với đối tượng thuộc
tính luồng này sẽ ở trạng thái detached, tức là không thể được chờ kết thúc bằng
hàm pthread_join và sẽ tự động giải phóng tài nguyên khi kết thúc.

.Hàm này trả về 0 nếu thành công, hoặc một số dương là mã lỗi nếu có lỗi.
+Code và kết quả:

+Công dụng trong chương trình:


Tác dụng của hàm pthread_attr_getdetachstate trong ví dụ trên là để lấy
trạng thái detach của luồng từ đối tượng thuộc tính luồng. Điều này có nghĩa là ta
có thể biết được luồng được tạo ra với đối tượng thuộc tính luồng này sẽ có trạng
thái joinable hay detached. Đây là một cách để kiểm tra và điều chỉnh các thuộc
tính cho các luồng mới một cách linh hoạt và chính xác.
-pthread_attr_setscope:
+Khái quát:
Hàm pthread_attr_setscope dùng để thiết lập thuộc tính phạm vi cạnh
tranh (contention scope) của đối tượng thuộc tính luồng. Thuộc tính phạm vi cạnh
tranh xác định tập hợp các luồng mà một luồng cạnh tranh với nhau để có được tài
nguyên như CPU. Hàm pthread_attr_setscope có prototype như sau:
int pthread_attr_setscope(pthread_attr_t *attr, int scope);
 attr: một con trỏ đến một đối tượng thuộc tính luồng
 scope: một giá trị nguyên chỉ định phạm vi cạnh tranh
Nó trả về một giá trị nguyên cho biết thành công hay thất bại của hoạt động.
POSIX.1 quy định hai giá trị có thể cho scope:
PTHREAD_SCOPE_SYSTEM: Luồng cạnh tranh với tất cả các luồng
khác trong tất cả các tiến trình trên hệ thống đang ở trong cùng một miền phân bổ
lịch biểu (một nhóm một hoặc nhiều bộ xử lý). Các luồng
PTHREAD_SCOPE_SYSTEM được lập lịch biểu liên quan đến nhau theo chính
sách và độ ưu tiên của chúng12.
PTHREAD_SCOPE_PROCESS: Luồng cạnh tranh với tất cả các luồng
khác trong cùng một tiến trình được tạo ra với phạm vi cạnh tranh
PTHREAD_SCOPE_PROCESS. Các luồng PTHREAD_SCOPE_PROCESS
được lập lịch biểu liên quan đến các luồng khác trong tiến trình theo chính sách và
độ ưu tiên của chúng12.
POSIX.1 yêu cầu một triển khai hỗ trợ ít nhất một trong những phạm vi cạnh
tranh này. Linux hỗ trợ PTHREAD_SCOPE_SYSTEM, nhưng không hỗ trợ
PTHREAD_SCOPE_PROCESS.

+Code và kết quả:


+Công dụng trong chương trình:
Đoạn code này sẽ tạo ra bốn luồng với thuộc tính phạm vi cạnh tranh
là PTHREAD_SCOPE_SYSTEM, nghĩa là chúng sẽ cạnh tranh với các luồng khác trên
hệ thống để có được CPU. Đoạn code này cũng sẽ in ra giá trị của thuộc tính phạm vi
cạnh tranh sau khi thiết lập và chờ cho tất cả các luồng hoàn thành công việc của chúng.
Tác dụng của hàm pthread_attr_setscope trong ví dụ này là cho phép điều khiển
phạm vi cạnh tranh của các luồng được tạo ra, từ đó có thể ảnh hưởng đến hiệu suất và
khả năng đáp ứng của chương trình.

-pthread_attr_getscope:
+Khái quát:
Hàm pthread_attr_getscope có prototype như sau:
int pthread_attr_getscope(const pthread_attr_t *restrict attr, int *restrict scope);
 attr: một con trỏ hằng đến một đối tượng thuộc tính luồng
 scope: một con trỏ đến một biến nguyên lưu trữ giá trị thuộc tính phạm vi cạnh
tranh
 Nó trả về một giá trị nguyên cho biết thành công hay thất bại của hoạt động.

+Code và kết quả:

+Công dụng trong chương trình:


Đoạn code này sẽ lấy giá trị phạm vi cạnh tranh của đối tượng thuộc tính luồng và
in ra màn hình. Nếu giá trị là PTHREAD_SCOPE_SYSTEM, nghĩa là các luồng sẽ
cạnh tranh với các luồng khác trên hệ thống để có được CPU. Nếu giá trị
là PTHREAD_SCOPE_PROCESS, nghĩa là các luồng sẽ cạnh tranh với các luồng khác
trong cùng tiến trình để có được CPU. Nếu giá trị không xác định, nghĩa là hệ thống
không hỗ trợ phạm vi cạnh tranh này.
Tác dụng của hàm pthread_attr_getscope trong ví dụ này là cho phép kiểm tra
phạm vi cạnh tranh của các luồng được tạo ra, từ đó có thể điều chỉnh chính sách và độ
ưu tiên lập lịch biểu cho chúng.

- pthread_attr_setstackaddr :
+Khái quát:
.Hàm pthread_attr_setstackaddr  có prototype như sau:
int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr);
 *pthread_attr_t attr là tham số đầu tiên của hàm, là một con trỏ kiểu
pthread_attr_t đến một đối tượng thuộc tính luồng (attr) đã được khởi tạo bởi hàm
pthread_attr_init().
 *void stackaddr là tham số thứ hai của hàm, là một con trỏ kiểu void đến vị trí bộ
nhớ được chỉ định để sử dụng làm ngăn xếp ban đầu cho luồng mới. Nó phải có ít
nhất PTHREAD_STACK_MIN byte bộ nhớ được cấp phát.

+Code và kết quả:


Do hàm pthread_attr_setstackaddr có thể gây ra các vấn đề về khả năng di động
(portability) và an toàn (safety) của chương trình dẫn đến việc chương trình bị lỗi nên ở
đây ta sẽ xử dụng hàm có chức năng tương tự để thay thế là pthread_attr_setstack
+Công dụng trong chương trình:
Tác dụng của hàm pthread_attr_setstack trong đoạn chương trình trên là để thiết
lập địa chỉ và kích thước của ngăn xếp cho luồng mới. Hàm này nhận vào ba tham số:
một con trỏ đến đối tượng thuộc tính luồng, một con trỏ đến vị trí bộ nhớ sẽ dùng làm
ngăn xếp ban đầu cho luồng mới, và một biến kiểu size_t để chỉ kích thước của ngăn xếp.
Hàm này sẽ gán hai thuộc tính stackaddr và stacksize của đối tượng thuộc tính luồng
bằng hai giá trị được truyền vào. Khi luồng mới được tạo ra bằng hàm pthread_create,
nó sẽ sử dụng ngăn xếp đã được thiết lập này để thực hiện chức năng của mình.

-pthread_attr_getstackaddr:
+Khái quát:
.Hàm pthread_attr_getstackaddr  có prototype như sau:
int pthread_attr_getstack(const pthread_attr_t *restrict attr, void **restrict stackaddr,
size_t *restrict stacksize);
 attr là một con trỏ đến một đối tượng thuộc tính luồng (thread attributes object)
đã được khởi tạo bởi hàm pthread_attr_init().
 stackaddr là một con trỏ đến một vùng nhớ do người dùng xác định, nơi hàm này
sẽ đặt địa chỉ cơ sở (lowest addressable byte) của ngăn xếp (stack) được sử dụng
bởi luồng (thread) được tạo ra bởi đối tượng thuộc tính luồng attr.
 stacksize là một con trỏ đến một vùng nhớ do người dùng xác định, nơi hàm này
sẽ đặt kích thước của ngăn xếp được sử dụng bởi luồng được tạo ra bởi đối tượng
thuộc tính luồng attr.
.Hàm này trả về 0 nếu thành công, hoặc một mã lỗi nếu thất bại

+Code và kết quả:


Do hàm pthread_attr_getstackaddr có thể gây ra các vấn đề về khả năng di động
(portability) và an toàn (safety) của chương trình dẫn đến việc chương trình bị lỗi nên ở
đây ta sẽ xử dụng hàm có chức năng tương tự để thay thế là pthread_attr_getstack.
+Công dụng trong chương trình:
Tác dụng của hàm pthread_attr_getstack trong chương trình trên là để lấy lại địa
chỉ và kích thước của ngăn xếp (stack) của luồng (thread) được tạo ra bởi đối tượng
thuộc tính luồng (thread attributes object) được tham chiếu bởi attr.
Hàm này trả về địa chỉ và kích thước của ngăn xếp trong các bộ nhớ đệm được trỏ đến
bởi mystack và mystacksize.
Hàm này được sử dụng để kiểm tra xem có thiết lập được địa chỉ và kích thước ngăn xếp
cho đối tượng thuộc tính luồng không, và in ra kết quả để so sánh với các giá trị ban đầu.
Hàm này cung cấp chức năng tương thích với tiêu chuẩn SUSv3 và yêu cầu địa chỉ
ngăn xếp là địa chỉ thấp nhất của vùng bộ nhớ đã cấp phát cho ngăn xếp.

-pthread_attr_setstacksize:
+Khái quát:
.Hàm pthread_attr_setstacksize  có prototype như sau:
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
 attr là một con trỏ đến một đối tượng thuộc tính luồng (thread attributes
object) đã được khởi tạo bởi hàm pthread_attr_init().
 stacksize là kích thước (tính bằng byte) của ngăn xếp (stack) được sử dụng bởi
luồng (thread) được tạo ra bởi đối tượng thuộc tính luồng attr. Kích thước này phải
ít nhất bằng PTHREAD_STACK_MIN.
.Hàm này thiết lập kích thước ngăn xếp cho đối tượng thuộc tính luồng. Kích
thước ngăn xếp của một luồng được cố định khi tạo luồng. Chỉ có luồng chính mới có
thể phát triển động ngăn xếp của nó. Hàm này trả về 0 nếu thành công, hoặc một mã
lỗi nếu thất bại.
+Code và kết quả:

+Công dụng trong chương trình:


Hàm pthread_attr_setstacksize dùng để thiết lập kích thước ngăn xếp (stack) cho
một luồng (thread). Cụ thể trong chương trình bằng cách sử dụng hàm
pthread_attr_setstacksize, ta đã thiết lập kích thước ngăn xếp cho luồng thành 1MB, và
16MB ( 8MB là mặc định ).

- pthread_attr_getstacksize:
+Khái quát:
.Hàm pthread_attr_getstacksize  có prototype như sau:
int pthread_attr_getstacksize (const pthread_attr_t *restrict attr , size_t *restrict stacksize
);
 attr: con trỏ hằng đến đối tượng thuộc tính luồng, chỉ được tham chiếu bởi con trỏ
này trong hàm.
 stacksize: con trỏ đến biến lưu kích thước ngăn xếp, chỉ được tham chiếu bởi con
trỏ này trong hàm.
 Giá trị trả về: số nguyên biểu diễn kết quả của hàm, 0 là thành công, khác 0 là lỗi.

+Code và kết quả (sử dụng lại chương trình của hàm
pthread_attr_setstacksize):
+Công dụng trong chương trình:
Hàm pthread_attr_getstacksize dùng để lấy kích thước ngăn xếp (stack) của một
luồng (thread) sau khi được thiết lập bởi hàm pthread_attr_setstacksize . Cụ thể trong
chương trình bằng cách sử dụng hàm pthread_attr_getstacksize, ta đã lấy được kích
thước ngăn xếp của luồng là 1MB, và 16MB ( 8MB là mặc định ).

- pthread_attr_getschedpolicy:
+Khái quát:
.Hàm pthread_attr_getschedpolicy  có prototype như sau:
int pthread_attr_getschedpolicy(const pthread_attr_t *restrict attr, int *restrict policy);
 *const pthread_attr_t restrict attr: tham số đầu tiên của hàm, là một con trỏ hằng
đến một đối tượng thuộc tính luồng. Từ khóa restrict chỉ ra rằng đối tượng thuộc
tính luồng chỉ được truy cập thông qua con trỏ này.
 *int restrict policy: tham số thứ hai của hàm, là một con trỏ đến một số
nguyên. Từ khóa restrict chỉ ra rằng số nguyên này chỉ được truy cập thông qua
con trỏ này. Các giá trị có thể của thuộc tính này là SCHED_FIFO, SCHED_RR
và SCHED_OTHER.

+Code và kết quả:

+Công dụng trong chương trình:


Tác dụng của hàm pthread_attr_getschedpolicy trong ví dụ này là để hiển thị chính
sách lập lịch mặc định của một đối tượng thuộc tính luồng. Chính sách này sẽ được áp
dụng cho các luồng được tạo ra bằng đối tượng thuộc tính luồng này, nếu không có sự
thay đổi nào khác. 
- pthread_attr_setschedpolicy:
+Khái Quát:
.Hàm pthread_attr_setschedpolicy  có prototype như sau:
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
.Hàm này nhận vào một con trỏ đến pthread_attr_t (attr) để chỉ định thuộc tính
của luồng và một giá trị nguyên policy để đặt chính sách lập lịch.
.Hàm trả về giá trị 0 nếu thành công và một giá trị khác 0 nếu có lỗi xảy ra.
. Chính sách lập lịch chỉ có hiệu lực nếu bạn đã thiết lập thuộc tính kế thừa lập lịch
của luồng là PTHREAD_EXPLICIT_SCHED bằng cách gọi hàm
pthread_attr_setinheritsched().
Các loại chính sách lập lịch được sử dụng trong hàm pthread_attr_setschedpolicy() là:
 SCHED_FIFO: là chính sách lập lịch theo thứ tự vào trước ra trước (first in first
out). Theo chính sách này, một luồng thời gian thực sẽ được chạy liên tục cho đến
khi nó tự nguyện nhường CPU hoặc bị một luồng thời gian thực khác có độ ưu
tiên cao hơn giành quyền sử dụng CPU. Các luồng thời gian thực có cùng độ ưu
tiên sẽ được xếp vào một hàng đợi FIFO và được chạy theo thứ tự vào trước ra
trước.
 SCHED_RR: là chính sách lập lịch vòng tròn (round robin). Theo chính sách
này, một luồng thời gian thực sẽ được chạy trong một khoảng thời gian cố định
(time slice) và sau đó nhường CPU cho luồng thời gian thực khác có cùng độ ưu
tiên. Các luồng thời gian thực có cùng độ ưu tiên sẽ được xếp vào một hàng đợi
vòng tròn và được chạy theo lượt.
 SCHED_OTHER: là chính sách lập lịch mặc định cho các luồng thông thường.
Theo chính sách này, một luồng thông thường sẽ được chạy dựa trên độ ưu tiên
tương đối của nó so với các luồng khác. Độ ưu tiên tương đối của một luồng thông
thường có thể được điều chỉnh bằng cách sử dụng giá trị nice, từ -20 (cao nhất)
đến +19 (thấp nhất). Chính sách này sử dụng thuật toán Completely Fair
Scheduler (CFS) để phân bổ CPU cho các luồng thông thường một cách công
bằng.
 SCHED_BATCH: là chính sách lập lịch dành cho các luồng batch, tức là các
luồng không cần tương tác với người dùng và yêu cầu nhiều tài nguyên CPU.
Chính sách này tương tự như SCHED_OTHER, nhưng làm cho các luồng batch
ít bị đánh thức để xem xét lập lịch hơn các luồng thông thường. Mục đích của
chính sách này là giảm thiểu số lần chuyển đổi ngữ cảnh (context switch) và tăng
hiệu suất của các luồng batch.
 SCHED_IDLE: là chính sách lập lịch dành cho các luồng rảnh rỗi, tức là các
luồng có độ ưu tiên rất thấp và chỉ được chạy khi không có luồng nào khác muốn
sử dụng CPU. Chính sách này có thể được sử dụng cho các luồng nền hoặc các
công việc không quan trọng.

+Code và kết quả:

+Công dụng trong chương trình:


Trong đoạn code, hàm này được gọi hai lần:
 Lần đầu tiên, hàm này được gọi để đặt chính sách lập lịch cho luồng là
SCHED_RR (Round Robin), tức là luồng sẽ được chạy trong một khoảng thời
gian cố định và sau đó nhường CPU cho luồng khác có cùng độ ưu tiên. Mục đích
của việc này có thể là để tăng khả năng phản hồi của luồng hoặc để thử nghiệm
chức năng của hàm.
 Lần thứ hai, hàm này được gọi để khôi phục chính sách lập lịch ban đầu cho
luồng, tức là SCHED_OTHER (mặc định), tức là luồng sẽ được chạy dựa trên độ
ưu tiên tương đối của nó so với các luồng khác. Mục đích của việc này có thể là để
tránh ảnh hưởng đến các luồng khác trong hệ thống hoặc để kết thúc chức năng
của hàm.

- pthread_attr_getguardsize:
+Khái quát:
. Hàm pthread_attr_getguardsize  có prototype như sau:
int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize);
 attr: Con trỏ đến đối tượng thuộc tính luồng để lấy kích thước vùng bảo vệ.
 guardsize: Con trỏ đến biến lưu trữ kích thước vùng bảo vệ.
.Hàm trả về giá trị 0 nếu thành công, cho biết kích thước vùng bảo vệ đã được lấy
thành công, hoặc một mã lỗi nếu có lỗi xảy ra.

+Code và kết quả:


+Công dụng trong chương trình:
Trong chương trình trên, chúng ta sử dụng hàm pthread_attr_getguardsize để lấy
kích thước vùng bảo vệ cho luồng. Vùng bảo vệ là một phần của bộ nhớ được cung cấp
cho mỗi luồng để đảm bảo tính an toàn và tránh xâm nhập vào các vùng nhớ khác.

- pthread_attr_setguardsize:
+Khái quát:
. Hàm pthread_attr_setguardsize  có prototype như sau:
int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);
- attr: con trỏ đến đối tượng thuộc tính luồng
- guardsize: kích thước mới của vùng bảo vệ cho ngăn xếp luồng
- Trả về: 0 nếu thành công, hoặc một số lỗi khác nếu thất bại.
. Hàm pthread_attr_setguardsize  quan trọng trong việc quản lý chương trình vì
nó giúp bảo vệ chương trình khỏi các lỗi do tràn ngăn xếp của luồng. Tràn ngăn
xếp có thể gây ra các hậu quả nghiêm trọng như vi phạm bộ nhớ, ghi đè dữ liệu
quan trọng, hoặc thực thi mã độc. Bằng cách đặt kích thước của vùng bảo vệ cho
ngăn xếp luồng, chương trình có thể phát hiện và xử lý các lỗi tràn ngăn xếp một
cách an toàn và hiệu quả. Hàm trên cũng cho phép chương trình tùy biến kích
thước của vùng bảo vệ theo nhu cầu của từng luồng, tối ưu hóa việc sử dụng bộ
nhớ và tài nguyên hệ thống.

+Code và kết quả:

+Công dụng trong chương trình:


Công dụng của hàm pthread_attr_setguardsize trong chương trình này là:
 Đặt kích thước của vùng bảo vệ cho ngăn xếp của luồng mới được tạo ra bằng
cách sử dụng đối tượng thuộc tính luồng attr. Kích thước mới được đặt là 1024
bytes, nhỏ hơn kích thước mặc định là 4096 bytes (tùy thuộc vào hệ thống).
 Giảm kích thước của vùng bảo vệ có thể giúp tiết kiệm bộ nhớ và tài nguyên hệ
thống, nhưng cũng có thể làm tăng nguy cơ tràn ngăn xếp nếu luồng sử dụng quá
nhiều không gian ngăn xếp. Do đó, việc đặt kích thước của vùng bảo vệ cần phải
cân nhắc kỹ lưỡng theo nhu cầu của từng luồng và chương trình.

Câu 4:
*Code:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
#include<signal.h>
void signalHandle(int signal){
printf("\nYou are pressed CTRL+C! Goodbye!\n");
exit(0);
}
int main(){
printf("Welcome to IT007, I am 21522735!\n");
signal(SIGINT , signalHandle);
pid_t pid = fork();
if (pid == -1) {
// Xử lý lỗi khi không tạo được quy trình con
printf("Error creating child process.\n");
exit(1);
} else if (pid == 0) {
// Quy trình con: Chạy Vim để mở tệp abcd.txt
system("gedit abcd.txt");
exit(1);
} else {
// Quy trình cha: Tiếp tục chờ tín hiệu hoặc thực hiện các công việc khác
while (1) {
// Vòng lặp vô hạn để chương trình không kết thúc
}
}
}
*Kết quả:

You might also like