1. Trang chủ
  2. » Công Nghệ Thông Tin

labs operating system hutech

7 21 0

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 7
Dung lượng 263,89 KB

Nội dung

Các lệnh của Linux thực tế l à nh ững lệnh ri êng l ẻ có khả năng kết hợp v à truy ền dữ liệu cho nhau thông qua các cơ chế như : đườ ng ống pipe, chuyển hướng xuất nhập (redirect), ph[r]

(1)

Bài 3: XỬ LÝ TIẾN TRÌNH TRONG LINUX I Lý Thuyết

1 Khái quát

- Một đặc điểm bật Linux khả chạy đồng thời nhiều chương trình Hệ Điều Hành xem đơn thể mã lệnh mà điều khiển tiến trình (process) Một chương trình bao gồm nhiều

tiến trình kết hợp với

- Đối với Hệ Điều Hành, tiến trình hoạt động chia sẻ tốc độ xử lý CPU, dùng chung vùng nhớ tài nguyên hệ thống khác Các tiến trình điều phối xoay vịng Hệ Điều Hành Một chương

trình mở rộng dần ra, có lúc cần phải tách thành nhiều tiến trình để xử lý công

việc độc lập với Các lệnh Linux thực tế lệnh riêng lẻ có khả kết hợp truyền liệu cho thông qua chế : đường ống pipe, chuyển hướng xuất nhập (redirect), phát sinh tín hiệu (signal), … Chúng gọi chế giao tiếp liên tiến trình (IPC – Inter Process Comunication) Đối với

tiến trình, tìm hiểu cách tạo, hủy, tạm dừng tiến trình, đồng hóa tiến trình giao tiếp

tiến trình với

- Xây dựng ứng dụng môi trường đa tiến trình Linux cơng việc khó khăn Không môi trường đơn nhiệm, môi trường đa nhiệm tiến trình có tài ngun hạn hẹp Tiến trình hoạt động phải ln trạng thái tôn trọng sẵn sàng nhường quyền xử lý CPU cho tiến trình khác

thời điểm nào, hệ thống có yêu cầu Nếu tiến trình xây dựng khơng tốt, đổ vỡ gây lỗi, làm treo tiến trình khác hệ thống hay chí phá vỡ (crash) Hệ Điều Hành - Định nghĩa tiến trình: một thực thể điều khiển đoạn mã lệnh có riêng khơng gian địa chỉ, có ngăn xếp stack riêng rẽ, có bảng chứa thông số mô tả file mở tiến trình đặc biệt có định

danh PID (Process Identify) toàn hệ thống vào thời điểm tiến trình chạy

Như thấy, tiến trình khơng phải chương trình (tuy đơi lúc chương trình đơn giản

cấn tiến trình để hồn thành tác vụ, trường hợp xem tiến trình

chương trình một) Rất nhiều tiến trình thực thi máy với Hệ Điều Hành, người dùng nhiều người dùng đăng nhập khác Ví dụ shell bash tiến trình

thực thi lệnh ls hay cp Bản thân ls, cp lại tiến trình hoạt động tách biệt khác

- Trong Linux, tiến trình cấp không gian địa nhớ phẳng 4GB Dữ liệu tiến trình khơng thể đọc truy xuất tiến trình khác Hai tiến trình khác xâm phạm biến

Tuy nhiên, muốn chia sẻ liệu hai tiến trình, Linux cung cấp cho vùng không gian địa chung để làm điều

2 Cách hoạt động tiến trình

- Khi chương trình chạy từ dịng lệnh, nhấn phím Ctrl+z để tạm dùng chương trình

và đưa vào hoạt động phía hậu trường (background) Tiến trình Linux có trạng thái:

+ Đang chạy (running) : lúc tiến trình chiếm quyền xử lý CPU dùng tính tốn hay thực cơng việc

của

+ Chờ (waiting) : tiến trình bị Hệ Điều Hành tước quyền xử lý CPU, chờ đến lược cấp phát khác

+ Tạm dừng (suspend) : Hệ Điều Hành tạm dừng tiến trình Tiến trình đưa vào trạng thái ngủ (sleep)

Khi cần thiết có nhu cầu, Hệ Điều Hành đánh thức (wake up) hay nạp lại mã lệnh tiến trình vào

nhớ Cấp phát tài nguyên CPU để tiến trình tiếp tục hoạt động

- Trên dịng lệnh, thay dùng lệnh Ctrl+z, sử dụng lệnh bg để đưa tiến trình vào hoạt động phía hậu trường Chúng ta yêu cầu tiến trình chạy cú pháp & Ví dụ: $ls –R & Lệnh fg sẽ đem tiến trình trở hoạt động ưu tiên phía trước Thực tế đăng nhập vào hệ thống tương tác dòng lệnh, lúc tiến trình shell bash Khi gọi lệnh có

nghĩa yêu cầu bash tạo thêm tiến trình thực thi khác Về mặt lập trình,

dùng lệnh fork() để nhân tiến trình từ tiến trình cũ Hoặc dùng lệnh system() để triệu gọi

tiến trình Hệ Điều Hành Hàm exec() có khả tạo tiến trình khác

3 Cấu trúc tiến trình

- Chúng ta xem Hệ Điều Hành quản lý tiến trình nào? Nếu có hai người dùng: user1 user2 đăng nhập vào chạy chương trình grep đồng thời, thực tế, Hệ Điều Hành

quản lý nạp mã chương trình grep vào hai vùng nhớ khác

nhau gọi phân vùng tiến trình Hình sau cho thấy cách phân chia chương trình grep thành hai tiến trình cho hai người khác sử dụng

Trong hình này, user1 chạy chương trình grep tìm chuỗi abc tập tin file1

$grep abc file1

user2 chạy chương trình grep tìm chuỗi cde tập tin

user1 $grep abc file1

PID 101

Code

Data s=abc

Library

filede

file1

user2 $grep cde file2

PID 102

Code

Data s=cde

Library

filede

file2 mã lệnh grep

Thư viện C

(2)

2 file2

$grep cde file2

Chúng ta cần ta cần nhớ hai người dùng user1 user2 hai máy tính khác đăng nhập vào máy chủ Linux gọi grep chạy đồng thời Hình trạng không gian nhớ Hệ Điều Hành Linux

khi chương trình grep phục vụ người dùng

- Nếu dùng lệnh ps, hệ thống liệt kê cho thơng tin tiến trình mà Hệ Điều Hành kiểm

sốt, Ví dụ: $ps –af

Mỗi tiến trình gán cho định danh để nhận dạng gọi PID (process identify) PID thường số nguyên dương có giá trị từ 2-32768 Khi tiến trình yêu cầu khởi động, Hệ Điều Hành chọn lấy

số (chưa bị tiến trình chạy chiếm giữ) khoảng số nguyên cấp phát cho tiến trình

Khi tiến trình chấm dứt, hệ thống thu hồi số PID để cấp phát cho tiến trình khác lần sau PID bắt đầu

từ giá trị giá trị dành cho tiến trình gọi init Tiến trình init chạy

khi khởi động Hệ Điều Hành init tiến trình quản lý tạo tiến trình khác Ở ví dụ

trên, thấy lệnh ps –af sẽ hiển thị tiến trình grep chạy user1 user2 với số PID lần lượt 101 102

- Mã lệnh thực thi lệnh grep chứa tập tin chương trình nằm đĩa cứng Hệ Điều Hành nạp

vào vùng nhớ Như thấyở lược đồ trên, tiến trình Hệ Điều hành phân chia rõ ràng: vùng chứa mã lệnh (code) vùng chứa liệu (data) Mã lệnh thường giống sử dụng chung

Linux quản lý cho phép tiến trình chương trình sử dụng chung mã lệnh

Thư viện Trừ thư viện đặc thù cịn thư viện chuẩn Hệ Điều Hành cho phép chia sẻ dùng chung tiến trình hệ thống Bằng cách chia sẻ thư viện, kích thước chương trình giảm đáng kể Mã lệnh chương trình chạy hệ thống dạng tiến trình đỡ tốn nhớ

- Trừ mã lệnh thư viện chia sẻ, cịn liệu khơng thể chia sẻ tiến trình Mỗi tiến trình sở

hữu phân đoạn liệu riêng Ví dụ tiến trình grep user1 nắm giữ lưu giữ biến s có giá trị 'abc', grep user2 nắm giữ lại có biến s với giá trị 'cde'

Mỗi tiến trình hệ thống dành riêng cho bảng mô tả file (file description table) Bảng chứa

các số mô tả áp đặt cho file mở Khi tiến trình khởi động, thường Hệ Điều Hành mở sẳn

cho file : stdin (số mô tả 0), stdout (số mô tả 1), stderr (số mô tả 2) Các file tượng trưng cho thiết bị nhập, xuất, thơng báo lỗi Chúng ta mở thêm file khác Ví dụ user1 m

file file1, user2 mở file file2 Hệ Điều Hành cấp phát số mơ tả file cho tiến trình lưu riêng

chúng bảng mô tả file tiến trình

- Ngồi ra, tiến trình có riêng ngăn xếp stack để lưu biến cục giá trị trả sau lời gọi hàm Tiến

trình dành cho khoảng khơng gian riêng để lưu biến môi trường Chúng ta dùng lệnh

putenv getenv để đặt riêng biến mơi trường cho tiến trình a) Bảng thơng tin tiến trình

- Hệ Điều Hành lưu giữ cấu trúc danh sách bên hệ thống gọi bảng tiến trình (process table) Bảng

tiến trình quản lý tất PID của hệ thống với thơng tin chi tiết tiến trình chạy Ví dụng

chúng ta gọi lệnh ps, Linux thường đọc thơng tin bảng tiến trình hiển thị lệnh hay tên tiến

trình gọi: thời gian chiếm giữ CPU tiến trình, tên người sử dụng tiến trình, … b) Xem thơng tin tiến trình

- Lệnh ps của Hệ Điều Hành dùng để hiển thị thông tin chi tiết tiến trình Tùy theo tham số, ps sẽ cho biết

thơng tin tiến trình người dùng, tiến trình hệ thống tất tiến trình chạy Ví dụ ps sẽ đưa chi tiết tham số -af

- Trong thông tin ps trả về, UID tên của người dùng gọi tiến trình, PID số định danh mà hệ

thống cấp cho tiến trình, PPID số định danh tiến trình cha (parent PID) Ở gặp số

tiến trình có định danh PPID 1, định danh tiến trình init, gọi chạy hệ thống khởi động

Nếu hủy tiến trình init Hệ Điều Hành chấm dứt phiên làm việc STIME thời điểm tiến

trình đưa vào sử dụng TIME thời gian chiếm dụng CPU tiến trình CMD tồn dịng lệnh

tiến trình triệu gọi TTY hình terminal ảo nơi gọi thực thi tiến trình Như biết, người

dùng đăng nhập vào hệ thống Linux từ nhiều terminal khác để gọi tiến trình Để liệt kê tiến

trình hệ thống, sử dụng lệnh: $ps –ax 4 Tạo lập tiến trình

a) Gọi tiến trình hàm system()

- Chúng ta gọi tiến trình khác bên chương trình thực thi hàm system() Có nghĩa tạo tiến trình từ tiến trình chạy Hàm system() khai báo sau:

#include <stdlib.h>

int system( const char (cmdstr) )

(3)

Khởi tạo tiến trình

Gọi fork()

Mã lệnh tiếp tiến trình ban đầu (tiến trình cha)

Mã lệnh thực thi tiến trình (tiến

trình con)

Cơ chế phân chia tiến trình fork() Trả PID tiến trình

con Trả trị

với việc bạn gọi shell thực thi lệnh hệ thống: $sh –c cmdstr

system()sẽ trả mã lỗi 127 không khởi động shell để gọi lệnh cmdstr Mã lỗi -1 gặp

các lỗi khác Còn lại, mã trả system() mã lỗi cmdstr sau lệnh gọi trả Ví dụ sử dụng hàm system(), system.c

#include <stdlib.h> #include <stdio.h> int main()

{

printf( "Thuc thi lenh ps voi system\n" ); system( "ps –ax" );

system(“mkdir daihoc”); system(“mkdir caodang”);

printf( "Thuc hien xong \n" ); exit( );

}

Hàm system() sử dụng để gọi lệnh “ps –ax” của Hệ Điều Hành b) Thay tiến trình hành với hàm exec

- Mỗi tiến trình Hệ Điều Hành cấp cho khơng gian nhớ tách biệt để tiến trình tự hoạt động Nếu tiến

trình A triệu gọi chương trình ngồi B (bằng hàm system()chẳng hạn), Hệ Điều Hành

thường thực thao tác như: cấp phát không gian 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 chương trình B đĩa cứng không gian nhớ vừa cấp phát cho tiến trình

Đưa tiến trình vào danh sách cần điều phối Hệ Điều Hành Những công việc thường thời gian đáng kể chiếm giữ thêm tài nguyên hệ thống

Nếu tiến trình A chạy muốn tiến trình B khởi động chạy khơng gian nhớ có sẵn tiến trình A sử dụng hàm exec cung cấp bới Linux Các hàm exec thay

toàn ảnh tiến trình A (bao gồm mã lệnh, liệu, bảng mơ tả file) thành ảnh tiến trình B hồn tồn khác Chỉ có số định danh PID của tiến trình A cịn giữ lại Tập hàm exec bao gồm 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ố hàm yêu cầu đối số path hoặc file đường dẫn đến tên chương trình cần

thực thi đĩa arg đối số cần truyền cho chương trình thực thi, đối số tương tự cách

chúng ta gọi chương trình từ dịng lệnh

c) Nhân tiến trình với hàm fork()

- Thay tiến trình đơi bất lợi với Đó tiến trình chiếm giữ tồn khơng gian tiến

trình cũ khơng có khả kiểm sốt

cũng điều khiển tiếp tiến trình hành sau gọi hàm exec nữa Cách đơn giản mà

chương trình Linux thường dùng sử dụng hàm fork() để nhân hay tạo tiến trình fork() một hàm đặc biệt, thực thi, trả

về giá trị khác lần thực thi, so với hàm bình

thường trả giá trị lần thực thi Khai báo

của hàm fork() sau:

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

- Nếu thành công, fork() tách tiến trình hành tiến trình (dĩ nhiên Hệ Điều Hành phải cấp phát thêm không gian nhớ để tiến trình hoạt động) Tiến

trình ban đầu gọi tiến trình cha (parent process) tiến trình gọi tiến trình (child process) Tiến trình có số định danh PID riêng biệt

ngồi ra, tiến trình cịn mang thêm định danh

(4)

4

- Sau tách tiến trình, mã lệnh thực thi hai tiến trình chép hồn tồn giống Chỉ có

một dấu hiệu để nhận dạng tiến trình cha tiến trình con, trị trả hàm fork() Bên tiến trình con, hàm fork() trả trị Trong bên tiến trình cha, hàm fork() trả

về trị số nguyên PID tiến trình vừa tạo Trường hợp khơng tách tiến trình, fork()sẽ trả

về trị -1 Kiểu pid_t khai báo định nghĩa uinstd.h kiểu số nguyên (int) - Đoạn mã điều khiển 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 đặt đây break;

default: printf( "Day la tien trinh cha" ); // mã lệnh dành cho tiến trình cha đặt đây break;

}

d) Kiểm sốt đợi tiến trình

- Khi fork() tách tiến trình thành hai tiến trình cha con, thực tế hai tiến trình cha lẫn tiến

trình hoạt động độc lập Đơi lúc tiến trình cha cần phải đợi tiến trình thực xong tác vụ tiếp tục thực thi Ở ví dụ trên, thực thi, thấy tiến trình cha kết thúc mà tiến trình in thơng báo tiến trình cha tiến trình tranh gởi kết hình Chúng ta không muốn điều này, muốn tiến trình cha kết thúc tiến trình hồn tất thao tác

của Hơn nữa, chương trình cần thực xong tác vụ đến chương trình cha Để làm

được việc này, sử dụng hàm wait() #include <sys/types.h>

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

Hàm wait gọi yêu cầu tiến trình cha dừng lại chờ tiến trình kết thúc trước thực tiếp

các lệnh điều khiển tiến trình cha wait() làm cho liên hệ tiến trình cha tiến trình trở

nên Khi tiến trình kết thúc, hàm trả số PID tương ứng tiến trình Nếu

truyền thêm đối số stat_loc khác NULL cho hàm wait() cũng trả trạng thái mà tiến trình kết thúc biến stat_loc Chúng ta có thể sử dụng macro khai báo sẵn sys/wait.h

sau:

WIFEXITED (stat_loc) Trả trị khác tiến trình kết thúc bình thường

WEXITSTATUS (stat_loc) Nếu WIFEXITED trả trị khác 0, macro trả mã lỗi tiến

trình

WIFSIGNALED (stat_loc) Trả trị khác tiến trình kết thúc tín hiệu gửi đến WTERMSIG(stat_loc) Nếu WIFSIGNALED khác 0, macro sẽ cho biết số tín hiệu hủy tiến

trình

WIFSTOPPED(stat_loc) Trả trị khác tiến trình dừng

(5)

II Thực Hành

Bài Sử dụng hàm system(), system_demo.c tạo tiến trình sau:  Tạo thư mục ThucHanh1 ThucHanh2

 Tạo tập tin Tho.c thư mục ThucHanh1 ghi chuỗi “troi hom that dep !” vào tập

tin vừa tạo (sử dụng lệnh echo để ghi chuỗi vào tập tin: echo noi_dung_chuoi >ten_tap_tin)  Sao chép tập tin vừa tạo sang thư mục ThucHanh2 hiển thị lên hình

Bài Sử dụng hàm execlp để thay tiến trình tiến trình ps –af Hệ Điều Hành #include <unistd.h>

#include <stdio.h> int main()

{

printf( "Thuc thi lenh ps voi execlp\n" ); execlp( "ps", "ps", "–ax", );

printf( "Thuc hien xong! Nhung chung ta se khong thay duoc dong nay.\n" );

exit( ); }

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

 In câu thơng báo: “Khong the tao tien trinh !” hàm fork() trả giá trị -1  Ngược lại:

- In lần câu thông báo: “Day la tien trinh !” nếu mã trả

- In lần câu thông báo: “Day la tien trinh cha !” nếu mã trả PID tiến

trình

#include <sys/types.h> #include <unistd.h> #include <stdio.h> int main()

{

pid_t pid; char * message; int n;

pid = fork(); switch ( pid )

{

case -1:

printf( "Khong the tao tien trinh !" ); exit(1);

case 0:

message = "Day la tien trinh !";

n = 0;

for ( ; n < 5; n++ ) {

printf( "%s", message );

sleep( );

}

break;

default:

message = "Day la tien trinh cha !";

n = 0;

for ( ; n < 3; n++ ) {

printf( "%s", message );

sleep( );

}

break;

}

exit( ); }

Biên dịch thực thi chương trình này, thấy tiến trình hoạt động đồng thời in kết

quả đan xen Nếu muốn xem liên quan PID PPID của tiến trình cha lệnh

fork() phát sinh, có thể thực chương trình sau:

(6)

6

Bài Sử dụng hàm wait() để chờ tiến trình kết thúc sau gọi fork(), wait_child.c #include <unistd.h>

#include <stdio.h> #include <sys/wait.h> #include <sys/types.h> int main()

{

pid_t pid;

int child_status; int n;

// nhân tiến trình, tạo pid = fork();

switch ( pid ) {

case -1: // fork khơng tạo tiến trình mới

printf("Khong the tao tien trinh moi");

exit( );

case 0: // fork thành công, đang ở tiến trình con

n = 0;

for ( ; n < 5; n++ ) {

printf( "Tien trinh con" );

sleep( );

}

exit( ); // Mã lỗi trả tiến trình default: // fork thành công, tiến trình cha

printf("Tien trinh cha, cho tien trinh hoan thanh.\n”); // Chờ tiến trình kết thúc

wait( &child_status );

printf("Tien trinh cha – tien trinh hoan thanh.\n"); }

return ( ); }

Bài Sử dụng hàm wait() để chờ tiến trình kết thúc sau gọi fork(), wait_child2.c, kiểm

tra mã lỗi trả từ tiến trình #include <unistd.h> #include <stdio.h> #include <sys/wait.h> #include <sys/types.h> int main()

{

pid_t pid;

int child_status; int n;

// nhân bản tiến trình, tạo pid = fork();

switch ( pid ) {

case -1: // fork khơng tạo tiến trình mới

printf("Khong the tao tien trinh moi");

exit( );

case 0: // fork thành công, tiến trình con

n = 0;

for ( ; n < 5; n++ ) {

printf( "Tien trinh con" );

sleep( );

}

exit( 37 ); // Mã lỗi trả tiến trình default: // fork thành công, đang ở tiến trình cha

n = 3;

for ( ; n > 0; n ) {

printf( "Tien trinh cha" );

sleep( );

(7)

// Chờ tiến trình kết thúc wait( &child_status );

// Kiểm tra in mã lỗi trả tiến trình con

printf( "Tien trinh hoan thanh: PID = %d\n", pid ); if ( WIFEXITED( child_status ))

printf( "Tien trinh thoat voi ma %d\n",

WEXITSTATUS( child_status ) );

else

printf( "Tien trinh ket thuc binh thuong\n" );

break;

}

Ngày đăng: 04/04/2021, 03:42

TỪ KHÓA LIÊN QUAN

w