Professional Documents
Culture Documents
IT007.N25 Lab3 HoMinhTri 21522701
IT007.N25 Lab3 HoMinhTri 21522701
*
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:
+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.
+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.
-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_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:
.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ả:
-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.
- 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.
-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
-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ả:
- 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.
- 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.
- 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.
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ả: