3.1. Looking at Processes
Tiến trình (Process): là chương trình đang
được chạy.
Vd:
có 2 terminal window -> 2 tiến trình
mỗi terminal window chạy 1 shell -> mỗi shell là
một tiến trình
gõ lệnh trong shell -> chương trình tương ứng
được thực hiện trong 1 tiến trình mới.
Lập trình viên chuyên nghiệp thường sử dụng
nhiều luồng hợp tác trong cùng một ứng
dụng:
ứng dụng thực hiện được nhiều việc hơn
tăng tính mạnh mẽ của ứng dụng
tăng tính hữu dụng của các chương trình đã tồn
tạ
22 trang |
Chia sẻ: candy98 | Lượt xem: 585 | Lượt tải: 0
Bạn đang xem trước 20 trang tài liệu Bài giảng Nguyên lý Hệ điều hành - Chương 3: Tiến trình - Phạm Quang Dũng, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
Tiến trình
23.1. Looking at Processes
Tiến trình (Process): là chương trình đang
được chạy.
Vd:
có 2 terminal window -> 2 tiến trình
mỗi terminal window chạy 1 shell -> mỗi shell là
một tiến trình
gõ lệnh trong shell -> chương trình tương ứng
được thực hiện trong 1 tiến trình mới.
3 Lập trình viên chuyên nghiệp thường sử dụng
nhiều luồng hợp tác trong cùng một ứng
dụng:
ứng dụng thực hiện được nhiều việc hơn
tăng tính mạnh mẽ của ứng dụng
tăng tính hữu dụng của các chương trình đã tồn
tại
4Process IDs
Mỗi tiến trình trong HĐH Linux có Process ID
duy nhất (pid)
pid là số 16-bit được Linux gán tuần tự khi
một tiến trình mới được tạo.
Mỗi tiến trình có một parent process, ngoại
trừ tiến trình init.
C, C++:
sử dụng định nghĩa kiểu pid_t
Các system call: getpid(), getppid()
5
6Viewing active processes
Lệnh shell: ps
Hiển thị các tiến trình đang chạy trên hệ thống
Hiển thị tất cả các tiến trình (-e)
73.2. Creating Processes
Dùng system
Tuy nhiên, vì hàm system sử dụng shell để thực
hiện lệnh nên kết quả phụ thuộc loại shell và
quyền của user.
8Dùng fork và exec
Để tạo một tiến trình mới:
đầu tiên sử dụng fork để tạo bản sao (tiến trình
con) của tiến trình hiện tại
sau đó dùng exec để chuyển một trong hai tiến
trình thành một cá thể của chương trình muốn tạo
9Gọi fork
Tiến trình cha tiếp tục thực hiện chương trình
tại điểm mà fork được gọi
Tiến trình con cũng thực hiện chương trình
tương tự từ điểm đó.
Giá trị trả về của tiến trình cha là PID của tiến
trình con
Giá trị trả về của tiến trình con là 0.
Vd: Listing 3.3: fork.c
10
Sử dụng exec family
Khi một chương trình gọi exec, tiến trình đó lập tức dừng việc
thực hiện và bắt đầu thực hiện một chương trình mới từ đầu.
Hàm trong tên có chữ p (execvp, execlp): chấp nhận tên 1
chương trình và tìm CT trong đường dẫn hiện tại
Hàm trong tên có chữ v (execv, execvp, execve): chấp nhận danh
sách tham số cho chương trình mới như một NULL-terminated
array của các con trỏ tới các chuỗi ký tự. Hàm trong tên có chữ l
(execl, execlp, execle) chấp nhận danh sách tham số sử dụng cơ
chế tham biến của C.
Hàm trong tên có chữ e (execve, execle): chấp nhận một tham số
thêm, một mảng của các biến môi trường
11
Ví dụ sử dụng fork và exec
Listing 3.4: fork-exec.c
12
3.3. Signals
Signals: cơ chế để giao tiếp và thao tác với các tiến
trình trong Linux
Chủ đề signals rất rộng, ở đây ta chỉ xét một số
signals quan trọng nhất và các kỹ thuật được sử
dụng để điều khiển tiến trình.
Một signal là một message đặc biệt được gửi tới một
tiến trình.
Signals là không đồng bộ: khi 1 tiến trình nhận 1
signal, nó lập tức xử lý signal mà không cần đợi kết
thúc hàm hiện tại hoặc thậm chí chưa kết thúc dòng
lệnh hiện tại.
13
Các cách gửi signal đến tiến trình
HĐH Linux có thể gửi các signals tới một tiến trình
đang cố gắng thực hiện một hành động không hợp lệ
Vd: SIGBUS (bus error), SIGSEGV (segmentation violation),
SIGFPE (floating point exception)
Xử lý mặc định là kết thúc tiến trình, tạo 1 core file.
Tiến trình này cũng có thể gửi signal tới tiến trình
khác:
Kết thúc tiến trình khác: SIGTERM, SIGKILL
Gửi 1 lệnh tới 1 chương trình đang chạy: SIGUSR1, SIGUSR2
14
Hàm sigaction
được dùng để thiết lập cách xử lý một signal.
tham số thứ nhất: signal number
tham số thứ hai: cách xử lý mong muốn
tham số thứ ba: nhận cách xử lý trước đó
Trường quan trọng nhất trong cấu trúc sigaction thứ
nhất hoặc thứ hai là sa_handler, có thể nhận 1
trong 3 giá trị:
SIG_DFL: xác định cách xử lý mặc định cho signal
SIG_IGN: xác định là signal nên bị bỏ qua
Con trỏ tới một hàm signal-handler, hàm nên có 1 tham số
là signal number và kiểu trả về là void.
15
.
Vì các signal là không đồng bộ, chương trình
chính ở trạng thái “mong manh” khi signal
được xử lý.
Vì vậy nên tránh thực hiện vào/ra hoặc gọi
các hàm thư viện, hàm hệ thống trong các
signal handler.
Signal handler nên thực hiện công việc cần
thiết tối thiểu rồi trả điều khiển về cho
chương trình chính.
16
Việc gán giá trị cho một biến toàn cục có thể nguy
hiểm vì thực tế phép gán có thể được thực hiện trong
2 hay nhiều lệnh máy. Nếu một signal xuất hiện xen
giữa thì biến bị rơi vào trạng thái bị phá vỡ.
Nên dùng kiểu đặc biệt sig_atomic_t (kiểu int) khi
sử dụng biến toàn cục để lập cờ cho signal trong một
hàm signal-handler. Linux đảm bảo phép gán giá trị
cho các biến kiểu này được thực hiện chỉ trong 1
lệnh.
17
Ví dụ
Sử dụng 1 hàm signal handler để đếm số lần
chương trình nhận được SIGUSR1.
Listing 3.5: sigusr1.c
18
3.4. Process Termination
Bình thường thì tiến trình có thể chấm dứt khi:
chương trình đang thực hiện gọi hàm exit
hàm main của chương trình trả về giá trị
Mỗi tiến trình có một exit code – số mà tiến trình trả
về cho cha nó.
Tiến trình có thể bị dừng bất thường khi nhận được 1
signal như SIGBUS, SIGSEGV, SIGFPE, SIGINT, SIGTERM
Tiến trình tự gửi signal SIGABRT cho chính nó qua hàm
abort để chấm dứt tiến trình
signal mạnh nhất SIGKILL: lập tức dừng tiến trình
19
Lệnh shell: % kill –KILL pid
Lệnh C:
kill(child_pid,SIGTERM);
(dùng các header sys/types.h và signal.h)
20
3.4.1. Đợi chấm dứt tiến trình
Tiến trình cha và tiến trình con được lập lịch độc lập
với nhau.
Linux là HĐH đa nhiệm, các tiến trình có thể được
thực hiện cùng nhau, ta ko thể đoán trước được tiến
trình con sẽ được chạy trước hay sau tiến trình cha.
Trong một số trường hợp, có thể dùng các system
call wait family để cho phép tiến trình cha đợi tiến
trình con kết thúc và nhận thông tin kết thúc đó.
21
3.4.2. Các system call wait
wait:
khóa tiến trình, gọi nó đến khi một trong các tiến
trình con của nó thoát (hoặc khi 1 lỗi xuất hiện).
mã trạng thái thoát trả về là 1 số nguyên. Dùng
macro WIFEXITED để xác định trạng thái này:
=True: thoát bình thường
=False: thoát không bình thường (chết vì tín hiệu
không được xử lý.
Vd: code trang 81
22
Các system call wait(tiếp)
waitpid:
Đợi kết thúc của 1 tiến trình con cụ thể.
wait3:
Trả về thống kê sử dụng CPU của tiến trình con
đang tồn tại.
wait4:
Cho phép xác định các lựa chọn thêm về cần đợi
các tiến trình nào.