Tải bản đầy đủ (.doc) (30 trang)

BÁO CÁO BÀI TẬP LỚN MÔN HỆ ĐIỀU HÀNH : Hiển thị và hủy các tiến trình truyền thông IPC trên Linux

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (1.08 MB, 30 trang )

Hiển thị và hủy các tiến trình IPC trên Linux
Trường Đại Học Bách Khoa Hà Nội
Viện Điện Tử Viễn Thông

BÁO CÁO BÀI TẬP
LỚN
MÔN: HỆ ĐIỀU HÀNH
Đề tài:
Hiển thị và hủy các tiến trình truyền thông IPC trên Linux
(Bài số 4)
GIẢNG VIÊN HƯỚNG DẪN: TS. PHẠM VĂN TIẾN
SINH VIÊN : NGUYỄN TIẾN CƯỜNG
NGUYỄN VĂN GIANG(TL)
VŨ ĐÌNH QUYỀN
VŨ HỮU TIỆP
LỚP : KSTN-ĐTVT-K52
Hà Nội -10/2011
Nhóm 02 KSTN-DTVT-K52 Page 1
Hiển thị và hủy các tiến trình IPC trên Linux
Giới thiệu 3
Nhóm 02 KSTN-DTVT-K52 Page 2
Hiển thị và hủy các tiến trình IPC trên Linux
Giới thiệu
Các tiến trình trong Linux không chỉ làm việc một mình mà nó còn cần phải truyền
thông với nhau, do đó trong Linux cung cấp một số phương thức cho truyền thông liên
tiến trình, các phương pháp đó là:
• Phương pháp đường ống đơn công trong UNIX
• FIFOs
• Hàng đợi bản tin trong SYSV
• Tập hợp semaphore trong SYSV
• Chia sẻ bộ nhớ trong SYSV


• Socket mạng (theo Berkeley)
• Đường ống song công ( đường ống kiểu luồng - STREAM pipes)
Linux hỗ trợ 2 loại kí thuật IPC, xuất hiện lần đầu trong hệ thống UNIX System V
(1983). Đó là: message queue – hàng đợi bản tin, semaphore – truyền tín hiệu, shared
memory – bộ nhớ chia sẻ. Các kĩ thuật System V này đều chia sẻ các phương thức xác thực
thông thường. Các tiến trình có thể truy nhập tài nguyên của chúng chỉ bằng cách chuyển 1
nhận dạng tham chiếu duy nhất tới kernel qua các system call. Truy nhập các đối tượng
System V IPC này được kiểm tra bằng cách sử dụng các quyền truy nhập, giống như là
truy nhập tới các file đã được kiểm tra. Quyền truy nhập tới các đối tượng System file IPC
được thiết lập bởi các bộ tạo của đối tượng thông qua các system call. Nhận dạng tham
chiếu của đối tượng được sử dụng bởi mỗi kĩ thuật như 1 danh mục vào trong 1 bảng của
các tài nguyên.
Tất cả các cấu trúc dữ liệu file Linux giới thiệu các đối tượng System V IPC trong hệ
thống sẽ bao gồm cấu trúc ipc_perm mà chứa người sở hữu (owner) và bộ tạo (creator)
người dùng và nhận dạng nhóm của tiến trình. Chế độ truy nhập cho đối tượng này (người
dùng, nhóm,…) và key của đối tượng IPC. Key này được sử dụng như 1 cách xác định
nhận dạng tham chiếu của đối tượng System V IPC. 2 tập hợp của các key dược hỗ trợ:
public và private. Nếu key được public thì bất kì tiến trình nào trong hệ thống có thể tìm
thấy nhận dạng tham chiếu cho đối tượng System V IPC. Các đối tượng System V IPC có
thể không bao giờ được tham chiếu với 1 key, chỉ bởi nhận dạng tham chiếu của chúng.
Mỗi IPC có một số hiệu được sử dụng trong lõi (kernel) để xác định duy nhất một
đối tượng IPC Để nhận một số hiệu duy nhất, một khóa (key) được sử dụng. Khóa này
phải có sự đồng ý giữa bên tiến trình Client và tiến trình Server. Đây chính là bước đầu
tiên để xây dựng một framework cho một ứng dụng kiểu client/server
Nhóm 02 KSTN-DTVT-K52 Page 3
Hiển thị và hủy các tiến trình IPC trên Linux
I. Signals
Signals là một trong những phương thức giao tiếp IPC ra đời sớm nhất được sử
dụng bởi các hệ thống UNIX. Chúng được sử dụng để báo hiệu những sự kiện bất đồng
bộ tới 1 hoặc nhiều tiến trình. 1 tín hiệu được tạo ra bởi ngắt từ bàn phím hoặc điều kiện

lỗi như là yêu cầu đến 1 vị trí không tồn tại trong bộ nhớ ảo. Các tín hiệu cũng được sử
dụng bởi các shell để báo hiệu điều khiển công việc tới các tiến trình con của chúng.
Có 1 tập các tín hiệu đã được xác định mà kernel có thể tạo ra hoặc có thể được
tạo ra bởi các tiến trình khác trong hệ thống, cung cấp các quyền tương ứng. Có thể liệt
kê 1 tập các tín hiệu bằng các sử dụng lệnh kill (kill –l): 1) SIGHUP, 2) SIGINT, 3)
SIGQUIT, 4) SIGILL, 5) SIGTRAP, 6) SIGIOT, 7) SIGBUS, 8) SIGFPE, 9) SIGKILL,
10)SIGUSR1, 11)SIGSEGV, 12)SIGUSR2, 13)SIGPIPE, 14)SIGALRM, 15)SIGTERM,
17) SIGCHLD, 18) SIGCONT, 19) SIGSTOP, 20) SIGTSTP, 21) SIGTTIN, 22)
SIGTTOU, 23) SIGURG, 24) SIGXCPU, 25) SIGXFSZ, 26) SIGVTALRM,
27)SIGPROF, 28) SIGWINCH, 29) SIGIO, 30) SIGPWR.
Các tiến trình có thể chọn bỏ qua hầu hết các tín hiệu được tạo ra, trừ 2 trường
hợp: tín hiệu SIGNTOP khiến tiến trình tạm dừng hoạt động của nó hoặc tín hiệu
SIGKILL khiến tiến trình thực hiện thoát. Nói các khác, 1 tiến trình có thể lựa chọn các
ứng phó với các tín hiệu khác nhau. Các tiến trình có thể chặn các tín hiệu và nếu không
chặn, chúng có thể lựa chọn tự mình xử lý hoặc để cho kernel xử lý. Nếu kernel xử lý tín
hiệu, nó sẽ thực hiện hành động mặc định áp dụng cho tín hiệu này. Ví dụ, hành động
mặc định khi 1 tiến trình nhận được tín hiệu SIGFPE (floating point exception) là lấy ra
phần lõi (core dump)sau đó thoát. Các tín hiệu không có sự ưu tiên liên quan cố hữu. Nếu
2 tín hiệu được tạo ra cho 1 tiến trình ở cùng 1 thời điểm thì tiến trình có thể xử lý theo
bất kì thứ tự nào. Do không có kĩ thuật nào để xử lý đa tín hiệu nên 1 tiến trình không thể
cho biết nếu nó nhận được 1 hay 42 tín hiệu SIGCONT.
Linux ứng dụng các tín hiệu sử dụng thông tin lưu trữ trong task_struct cho các
tiến trình. Số lượng các tín hiệu hỗ trợ là giới hạn tương ứng với độ dài từ của bộ xử lý.
Các tiến trình với độ dài từ 32 bit có thể có 32 tín hiệu trong khi các bộ xử lý 54 bit như
Alpha AXP có thể lên tới 64 tín hiệu. Các tín hiệu treo hiện tại được giữ trong trường
signal với 1 mặt nạ của tín hiệu bị chặn được giữ trong blocked. Với các trường hợp
ngoại lệ SIGSTOP và SIGKILL, tất cả các tín hiệu có thể bị chặn. Nếu 1 tín hiệu bị chặn
được khởi tạo, nó duy trì trạng thái treo cho tới khi không còn bị chặn (unblocked). Linux
cũng giữ thông tin về các mỗi tiến trình xử lý các tín hiệu và điều này được lưu giữ trong
1 mảng các cấu trúc dữ liệu sigaction được chỏ tới bởi task_struct cho mỗi tiến trình.

Giữa các thứ khác nó chứa cả địa chỉ của routine mà sẽ xử lý tín hiệu hoặc 1 đánh dấu sễ
báo cho Linux biết rằng tín hiệu muốn bỏ qua tín hiệu này hoặc để kernel xử lý tín hiệu
này cho nó. Các tiến trình thay đổi các xử lý tín hiệu mặc định bằng cách tạo lời gọi hệ
thống (system call) và những call này thay đổi sigaction cho các tín hiệu thay đổi thích
hợp giống như là mặt nạ blocked.
Nhóm 02 KSTN-DTVT-K52 Page 4
Hiển thị và hủy các tiến trình IPC trên Linux
Không phải mọi tiến trình đều có thể gửi tín hiệu tới tất cả tiến trình khác, kernel
và super user thì có thể. Các tiến trình bình thường chỉ có thể gửi các tín hiệu tới các tiến
trình với cùng uid và gid hoặc tới các tiến trình trong cùng nhóm tiến trình (process
group). Các tín hiệu được tạo ra bằng cách thiết lập các bit thích hợp trong trường signal
của task_struct. Nếu tiến trình không chặn tín hiệu và đang chờ nhưng trong trạng thái có
thể bị ngắt (interruptible), nó có thể được wake up bằng cách thay đổi trạng thái của nó
thành Running và đảm bảo rằng nó vào trong hàng đợi chạy.
Các tín hiệu không được đưa đến tiến trình ngay khi chúng được tạo ra, chúng
phải chờ cho tới khi tiến trình chạy lại. Mỗi khi 1 tiến trình thoát khỏi 1 system call,
trường block và signal của nó được kiểm tra và nếu không có bất kì tín hiệu unblocked,
chúng có thể được chuyển đi. Các tiến trình có thể chọn việc chờ các tín hiệu nếu chúng
muốn, chúng có thể treo trong trạng thái có thể bị ngắt cho tới khi tín hiệu hiện diện.
Nếu 1 bộ xử lý (handler) tín hiệu được thiết lập tới hoạt động mặc định thì kernel
sẽ xử lý nó. Bộ xử lý tín hiệu mặc định SIGSTOP sẽ thay đổi trạng thái tín hiệu hiện tại
tới Stopped và tiếp đó chạy bộ lập biểu để lựa chọn tiến trình chạy tiếp theo. Hoạt động
mặc định cho tín hiệu SIGFPE sẽ “core dump” tiến trình và khiến nó thoát ra. Lựa chọn
khác, tiến trình có thể xác định bộ xử lý tín hiệu của riêng nó. Đây là 1 thủ tục sẽ được
gọi bất cứ khi nào tín hiệu được tạo ra và struct sigaction giữ địa chỉ của thủ tục này.
Kernel phải gọi thủ tục xử lý tín hiệu của tiến trình và cách điều này xảy ra là bộ xử lý
riêng (processor), nhưng có 1 vấn đề đó là tiến trình hiện tại đang chạy trong mode kernel
và chỉ trả về tiến trình mà đã gọi kernel hoặc thủ tục hệ thống trong mode user. Vấn đề
được giải quyết bằng cách vận dụng stack và register của tiến trình. Bộ đếm chương trình
của tiến trình được thiết lập tới địa chỉ của thủ tục xử lý tín hiệu của nó và các tham số tới

thủ tục được thêm vào “call frame” hoặc được đưa vào register. Khi tiến trình tiếp tục
hoạt động, nó xuất hiện giống như là thủ tục xử lý tín hiệu được gọi bình thường.
Linux là tương thích POSIX (Portable Operating System Interface), do đó tiến
trình có thể định rõ tín hiệu nào bị chặn khi một thủ tục xử lý tín hiệu được gọi. Điều này
có nghĩa là thay đổi mặt mạ blocked trong suốt thời gian gọi tới bộ xử lý tín hiệu các tiến
trình. Mặt nạ blocked phải được trả về giá trị gốc của nó khi thủ tục xử lý tín hiệu kết
thúc. Vì thế Linux thêm 1 “call” tới 1 thủ tục có hệ thống, thứ mà sẽ khởi tạo lại mặt nạ
blocked lên trên call stack của tiến trình đã được báo hiệu. Linux cũng tối ưu trường hợp
khi 1 vài thủ tục xử lý tín hiệu cần được gọi bởi việc sắp xếp chúng, do đó mỗi khi 1 thủ
tục xử lý thoát, cái tiếp theo sẽ được gọi cho tới khi thủ tục có hệ thống được gọi.
Nhóm 02 KSTN-DTVT-K52 Page 5
Hiển thị và hủy các tiến trình IPC trên Linux
II. Shared Memory Segments
Chia sẻ bộ nhớ cho phép một hoặc nhiều tiến trình có thể truyền thông qua một
phân vùng bộ nhớ, phân vùng này xuất hiện trong tất cả các không gian địa chỉ ảo của các
tiến trình này. Các trang của bộ nhớ ảo được tham chiếu bởi các entry trong bảng trang
của các tiến trình đang chia sẻ cho nhau. Tuy nhiên không phải các tiến trình này có cùng
địa chỉ trong bộ nhớ ảo. Với tất cả các đối tượng SYSTEM V IPC, truy cập vào một vùng
bộ nhớ được chia sẻ sẽ được điều khiển qua các khóa và kiểm tra các quyền truy nhập.
Khi bộ nhớ đang được chia sẻ, không có sự kiểm tra làm thế nào mà các tiến trình có thể
sử dụng bộ nhớ đó. Chúng phải được dựa trên các cơ chế khác, ví dụ SYSTEM V
Semaphore, để đồng bộ việc truy nhập vào bộ nhớ. Mỗi một vùng bộ nhớ được chia sẽ sẽ
được biểu diễn bằng một cấu trúc dữ liệu shmid_ds và được lưu trong vector shm_segs.
Cấu trúc shmid_ds miêu tả độ lớn của vùng bộ nhớ được chia sẻ, số tiến trình đang
sử dụng nó và thông tin về việc bộ nhớ được chia sẻ này được ánh xạ vào không gian địa
chỉ như thế nào. Cấu trúc này là thuộc tính creator của bộ nhớ được chia sẻ, điều khiển các
quyền truy nhập vào bộ nhớ đó và cũng chỉ rõ khóa của cấu trúc là chung hay là riêng. Nếu
nó có đủ quyền truy nhập nó có thể khóa bộ nhớ được chia sẻ vào bộ nhớ vật lý.
Mỗi tiến trình mong muốn chia sẻ bộ nhớ sẽ phải đính vào bộ nhớ ảo đó qua một lời
gọi hệ thống. Lời gọi này sẽ tạo một cấu trúc dữ liệu vm_area_struct, cấu trúc này mô tả

vùng nhớ được chia sẻ cho tiến trình này. Tiến trình này có thể chọn vị trí trong không
gian địa chỉ ảo cho bộ nhớ được chia sẻ hoặ nó để cho Linux cứ chọn một không gian nhớ
nào đủ lớn. Cấu trúc vm_area_struct mới sẽ được đặt vào một dánh sách của
vm_area_struct được trỏ tới bởi cấu trúc shmid_ds. Các con trỏ vm_next_shared và
vm_prev_shared được sử dụng để nối chúng lại với nhau. Bộ nhớ ảo thực tế không được
tạo trong quá trình đính tiến trình vào, nó xảy ra khi tiến trình đầu tiên có ý định truy cập
vào bộ nhớ đó.Thời điểm đầu tiên mà một tiến trình truy nhập và một trong số các trang
của bộ nhớ ảo, một lỗi trang sẽ xuất hiện. Khi Linux sửa lỗi trang này, nó có thể tìm được
cấu trúc vm_area_struct được dùng để miêu tả nó. Các mã được dùng đẻ sửa lỗi trang của
bộ nhớ được chia sẻ sẽ tìm trong danh sách các entry của bảng trang cho cấu trúc shmid_ds
này để nhìn xem nếu có entry tồn trại cho trang này trong bộ nhớ được chia sẻ. Nếu không
tồn tại, nó sẽ chỉ định trang vật lý và tạo một entry bảng trang cho nó. Để đi vào được các
bảng trang của tiến trình hiện tại, entry này phải được lưu vào cấu trúc shmid_ds. Có nghĩa
là khi tiến trình tiếp theo muốn truy nhập vào bộ nhớ này và dính lỗi trang, mã để sửa lỗi
trang trong bộ nhớ được chia sẻ cũng sẽ sử dụng trang vật lý được tạo mới gần đây cho tiến
trình này. Do đó, tiến trình đầu tiên truy nhập vào một trang của bộ nhớ được chia sẻ, trang
náy sẽ được tạo bởi bộ nhớ này và sau đó truy nhập bởi các tiến trình khác, các tiến trình
này tạo ra các trang và các trang này được gắn vào không gian địa chỉ ảo.
Khi một tiến trình không còn muốn chia sẻ bộ nhớ, nó sẽ gỡ ra khỏi bộ nhớ. Việc gỡ
này chỉ ảnh hưởng đến tiến trình hiện tại. Cấu trúc vm_area_struct sẽ được gỡ khỏi cấu
trúc shmid_ds. Các bảng trang của tiến trình hiện tại sẽ được cập nhật để không xác nhận
cho bộ nhớ ảo đang được sử dụng để chia sẻ. Khi tiến trình cuối bị gõ khỏi phân vùng bộ
nhớ, các trang của bộ nhớ được chia sẻ trong bộ nhớ vật lý sẽ được giải phóng.
Nhóm 02 KSTN-DTVT-K52 Page 6
Hiển thị và hủy các tiến trình IPC trên Linux
III. Message Queues
Các hàng đợi bản tin cho phép một hoặc nhiều tiến trình có thể ghi các bản tin vào, các
bản tin này có thể được đọc bởi một hoặc nhiều tiến trình khác. Linux duy trì một danh sách các
hàng đợi bản tin, còn gọi là vector msgque, mỗi phần tử trong danh sách này sẽ trỏ vào một cấu
trúc dữ liệu msqid_ds, cấu trúc này được sử dụng để mô tả các thuộc tính của hàng đợi bản tin.

Khi một hàng đợi bản tin được tạo một cấu trúc dữ liệu msqid_ds sẽ được định ra từ bộ nhớ của
hệ thống và được cài vào vector.
Mỗi cấu trúc dữ liệu msqid_ds bao gồm một cấu trúc ipc_perm và các con trỏ trỏ vào các
bản tin trong hàng đợi. Thêm vào đó, Linux lưu các thời điểm có sự thay đổi trong hàng đợi như
thời điểm gần nhất có bản tin được ghi vào hàng đợi. Cấu trúc msqid_ds cũng bao gồm hai hàng
đợi ở trạng thái chờ, một cho bên ghi và một cho bên đọc các bản tin trong hàng đợi bản tin.
Mỗi thời điểm mà một tiến trình định ghi một bản tin vào hàng đợi, số hiệu về người sử
dụng và nhóm sẽ được so sánh với chế độ trong cấu trúc dữ liệu ipc_perm của hàng đợi này. Nếu
tiến trình có thể ghi vào hàng đợi thì bản tin có thể được sao chép từ không gian địa chỉ của tiến
trình vào cấu trúc dữ liệu msg và đặt tại cuối của hàng đợi bản tin. Mỗi bản tin được gắn với một
dạng cụ thể, dạng này được thỏa thuận giữa các tiến trình truyền thông với nhau. Tuy nhiêu có
thể không có đủ chỗ cho các bản tin do Linux giới hạn số lượng và kích thước của các bản tin có
thể ghi vào hàng đợi. Trong trường hợp này tiến trình có thể được thêm vào hàng đợi trạng thái
chờ để ghi của hàng đợi bản tin. và bộ định thời được gọi để chọn một tiến trình mới để chạy.
Tiến trình này sẽ được đánh thức khi một hoặc nhiều bản tin được đọc ra từ hàng đợi bản tin này.
Đọc từ hàng đợi là một quá trình tương tự. Một lần nữa, quyền truy cập vào hàng đợi
trạng thái ghi của tiến trình được kiểm tra. Một tiến trình đang đọc có thể chọn hoặc lấy bản tin
đầu tiên trong hàng đợi có dạng khác nó hoặc chọn các bản tin với các dạng cụ thể. Nếu không
có bản tin nào thỏa mãn các tiêu chuẩn này thì tiến trình đang đọc sẽ được thêm vào hàng đợi
trạng thái chờ đọc của hàng đợi bản tin và bộ định thời sẽ chạy. Khi một bản tin mới được ghi
vào hàng đợi thì tiến trình này sẽ được đánh thức và chạy lại một lần nữa
Nhóm 02 KSTN-DTVT-K52 Page 7
Hiển thị và hủy các tiến trình IPC trên Linux
IV. Semaphores
Với dạng đơn giản nhất, Semaphore là một khu vực trong memory và giá trị của nó
có thể được kiểm tra hoặc khởi tạo bởi nhiều tiến trình. Toán tử kiểm tra wait (hoặc P) và
toán tử signal ( hoặc V) là nguyên tố hay toán tử uninterruptable để đảm bảo khi nó hoạt
động thì không thể dừng nó lại được. Kết quả của toán tử kiểm tra P và toán tử V là phép
cộng của giá trị hiện tại của semaphore với giá trị khởi tạo ban đầu, giá trị khởi tạo này có thể
âm hoặc dương. Tùy theo kết quả của toán tử P và V mà một tiến trình nào đó phải sleep cho

đến khi giá trị semaphore được thay đổi bởi một tiến trình khác. Semaphore có hai loại là
 Counting Semaphore: có giá trị nguyên
 Binary Semaphore ( mutex): có giá trị 0 hoặc 1
Semaphore có thể được sử dụng để thực thi tại khu vực tranh chấp ( critical sections).
Giả sử ta có nhiều tiến trình đọc và ghi dữ liệu từ cùng một file. Và ta muốn các file
này phải được tổ chức một cách chặt chẽ. Ta có thể sử dụng một semaphore với giá trị khởi
tạo ban đầu là 1.Sử dụng hai toán tử P và V , toán tử P (toán tử wait) chờ khi Semaphore S
âm và giảm S đi 1 nếu S>0; toán tử V ( toán tử signal) tăng S lên 1.
Mỗi một đối tượng Semaphore System V IPC mô tả một semaphore array và Linux
sử dụng cấu trúc semid_ds để biểu diễn chúng. Tất cả các cấu trúc semid_ds trong hệ thống
được trỏ bởi một vector smeary. Mỗi một semaphore array có các sem_nsems, mỗi
sem_nsems được mô tả bởi cấu trúc sem .Tất cả các tiến trình được cho phép tính toán
semaphore array của một đối tượng Semaphore System V IPC có thể tạo ra các system call
biểu diễn các toán tử trong chúng. System call có thể chỉ ra nhiều toán tử và mỗi toán tử bao
gồm ba đầu vào: semaphore index, giá trị toán tử và một tập các cờ. Semaphore index là một
số hiệu trong semaphore array. Giá trị của toán tử là giá trị sẽ được thêm vào giá trị hiện tại
của semaphore. Đầu tiên Linux kiểm tra xem liệu rằng tất cả các toán tử có thành công hay
không? Một toán tử sẽ thành công nếu giá trị của nó khi thêm vào giá trị semaphore hiện tại
phải lớn hơn 0 hoặc cả giá trị của toán tử và giá trị hiện tại của semaphore đều bằng 0.Nếu có
bất kì toán tử Semaphore nào không thành công thì hệ điều hành sẽ dừng tiến trình tất nhiên
là chỉ với những trường hợp các cờ của toán tử không yêu cầu hàm của hệ thống là non-
blocking. Nếu tiến trình ban đầu bị dừng bởi hệ điều hành , hệ điều hành phải lưu lại giá trị
của toán tử Semaphore và đưa tiến trình hiện tại vào hàng đợi wait. Nó thực hiện điều này
thông qua việc xây dựng một cấu trúc sem_queue trong stack và điền vào đó. Một cấu trúc
sem_queue sẽ được đặt ở cuối của hàng đợi của đối tượng Semaphore ( sử dụng các con trỏ
sem_peddning và sem_pening_last). Tiến trình hiện tại được đặt trong hàng đợi trong cấu
trúc sem_queue và scheduler được gọi để lựa chọn tiến trình khác thực hiện.
Nếu như tất cả các toán tử Semaphore đều thành công và tiến trình hiện tại không cần
thiết bị dừng, Linux sẽ tiếp tục và áp dụng các toán tử tới các đối tương thích hợp trong
Nhóm 02 KSTN-DTVT-K52 Page 8

Hiển thị và hủy các tiến trình IPC trên Linux
semaphore array. Bây giờ Linux sẽ phải kiểm tra xem tiến trình nào đang waiting ,tiến trình
nào đã bị dừng, những tiến trình đó sẽ được áp dụng các toán tử semaphore. Hệ điều hành sẽ
đánh thức các tiến trình đang sleep và làm cho nó available cho việc khởi động lại ở lần tiếp
theo khi scheduler chạy.Hệ điều hành sẽ xem lướt qua danh sách pending từ lúc bắt đầu cho
đến khi không còn toán tử nào trong danh sách wait nữa và do đó không có tiến trình nào cần
được wake up.
Một vấn đề nảy sinh với Semaphore là Deadlock. Deadlock xảy ra khi một tiến trình
thay đổi giá trị Semaphore khi nó vào vùng Critical Section nhưng thất bại trong việc rời
khỏi vùng đó vì xung đột hoặc bị kill. Linux chống lại việc này bằng cách duy trì một danh
sách lân cận các semaphore array. Ý tưởng này là khi những lân cận này được áp dụng
Semaphore sẽ được đưa ngược trở về trạng thái của nó trước đó trước khi cá toán tử được
thực hiện. Những điều chỉnh này được lưu dữ trong cấu trúc sem_undo được đặt trong cả cấu
trúc semid_ds và task_struct.
Mỗi toán tử Semaphore có thể yêu cầu một adjustment để được duy trì. Linux sẽ duy
trì nhiều nhất là một sem_undo cho mỗi một tiến trình tương ứng với mỗi semaphore array.
Nếu như tiến trình đang yêu cầu không có adjustment thì một adjustment sẽ được tạo ra khi
cần thiết.Một cấu trúc sem_udo mới được đặt trong cấu trúc tast_struct của tiến trình đó và
cả trong cấu trúc semid_ds của semaphore array. Khi một toán tử được apply tới các
semaphore trong semaphore array thì số đối của giá trị đó sẽ được thêm vào đầu vào của
semaphore trong mảng adjustment của cấu trúc sem_udo của tiến trình đó.

Nhóm 02 KSTN-DTVT-K52 Page 9
Hiển thị và hủy các tiến trình IPC trên Linux
V. Pipelines
Tất cả các hệ vỏ (shell) của Linux đều cho phép chuyển hướng (redirectio). Ví dụ $
ls | pr | lp dẫn đầu ra của lệnh ls liệt kê các file hướng dẫn (pipe) tới đầu vào chuẩn của
lệnh pr để đánh số trang chúng (paginate). Cuối cùng đầu ra chuẩn từ lệnh pr được dẫn
(pipe) vào đầu vào chuẩn của lệnh lpr để in kết quả ra máy in mặc định. Tiếp đó các pipe là
các luồng byte đơn hướng sẽ kết nối đầu ra chuẩn từ 1 tiến trình tới đầu vào chuẩn của một

tiến trình khác. Hệ vỏ sẽ thiết lập các pipe tạm thời này giữa các tiến trình.
Trong Linux, 1 pipe được thực hiện bằng cách sử dụng 2 cấu trúc dữ liệu file mà cả 2
điểm ở tại cùng VFS inode thứ mà bản thân nó trỏ tới 1 trang vật lý bên trong bộ nhớ. Hình
2.1 chỉ ra rằng mỗi cấu trúc dữ liệu file chứa các con trỏ tới các vector thủ tục hoạt động
fiel khác, một con trỏ cho việc ghi và các con trỏ khác cho việc đọc.
Việc này che đi những khác biệt cơ bản với các system call thực hiện đọc và ghi tới
các file gốc. Giống như việc ghi tiến trình vào pipe được thực hiện, các byte được sao chép
vào trong trang dữ liệu chia sẻ và khi việc đọc tiến trình thực hiện, các byte được sao chép
ra từ trang dữ liệu chia sẻ. Linux cần phải đồng bộ truy nhập pipe. Nó phải đảm bảo rằng
việc đọc và ghi của pipe phải theo từng bước và để thực hiện nó cần sử dụng các khóa,
hàng đợi và tín hiệu.
Khi việc ghi muốn ghi vào pipe, nó sử dụng các hàm thư viện ghi chuẩn. Tất cả các
hàm này chuyển các file descriptor vào trong tập các cấu trúc dữ liệu file của tiến trình.
Các system call của Linux sử dụng thủ tục ghi được trỏ tới bởi cấu trúc dữ liệu file mô tả
pipe này. Các thủ tục ghi đó sử dụng thông tin lưu trong VFS inode mô tả pipe để quản lý
yêu cầu ghi.
Nếu có đủ room để ghi tất cả các byte vào trog pipe và chỉ cần pipe khôg bị khóa các
bộ đọc của nó, Linux khóa nó để ghi và sao chép các byte đã được ghi từ không gian địa
chỉ tiến trình vào trong trang dữ liệu chia sẻ. Nếu pipe bị khóa bởi bộ đọc hoặc nếu không
có đủ room cho dữ liệu thì tiến trình hiện tại được đưa vào trạng thái chờ trong hàng đợi
của pipe inode và bộ định biểu được gọi, tiến trình khác có thể chạy. Tiến trình ở trạng thái
có thể ngắt, do đó nó có thể nhận tín hiệu và sẽ được đánh thức bởi bộ đọc khi có đủ room
cho dữ liệu ghi hoặc khi pipe được mở khóa (unlock). Khi dữ liệu được ghi, VFS inode của
pipe được mở khóa và bất kì bộ đọc chờ nào đang ngủ (sleep) trong hàng đợi của inode tự
nó sẽ được đánh thức.
Việc đọc dữ liệu từ pipe tương tự như việc ghi vào pipe. Các tiến trình được cho
phép thực hiện việc đọc không chặn (non-blocking) (nó phụ thuộc vào chế độ chúng mở
file hoặc pipe) và trong trường hợp này, nếu không có dữ liệu để đọc hoặc nếu pipe bị
khóa, 1 lỗi sẽ được trả về. Điều này có nghĩa là tiến trình có thể tiếp tục chạy. Khả năng
khác là chờ trên hàng đợi của pipe inode cho tới khi tiến trình ghi kết thúc. Khi cả 2 tiến

trình kết thúc với pipe, pipe inode sẽ được loại bỏ với trang dữ liệu chia sẽ
Nhóm 02 KSTN-DTVT-K52 Page 10
Hiển thị và hủy các tiến trình IPC trên Linux
Linux cũng hỗ trợ các named pipe, còn được gọi là các FIFO do các pipe hoạt động
theo nguyên tắc First In First Out. Dữ liệu đầu tiên được ghi vào pipe sẽ là dữ liệu đầu tiến
được đọc ra từ pipe. Không giống như các pipe thông thường, các FIFO không phải là các
đối tượng tạm thời, chúng là các thực thể trong hệ thống file và có thể được tạo ra bằng
lệnh mkfifo. Các tiến trình có thể tự do sử dụng FIFO chỉ cần chúng có quyền truy nhập
thích hợp. Cách các FIFO đó được mở có chút khác với các pipe. 1 pipe (2 cấu trúc dữ liệu
file, VFS inode vả trang dữ liệu chia sẻ) được tạo ra “in one go” trong khi 1 FIFO tồn tại
sẵn sàng và được đóng mở bởi người dùng của nó. Linux phải xử lý các bộ đọc mở FIFO
trước khi các bộ ghi mở nó cũng như các bộ đọc thực hiện đọc trước khi bất kì bộ ghi nào
thực hiện ghi. Còn lại, về cách xử lý các FIFO hầu như giống hệt pipe và chúng cũng sử
dụng các hoạt động và cấu trúc dữ liệu tương tự.
Nhóm 02 KSTN-DTVT-K52 Page 11
Hiển thị và hủy các tiến trình IPC trên Linux
VI. Thiết kế chương trình
Các chương trình thực thi bao gồm hai khối chính :
Khối I: Hai chương trình khởi tạo IPC bằng Message Queue , Shared Memory,
Semaphore phục vụ cho việc thử nghiệm và kiểm tra chương trình hiển thị, các chương
trình này sẽ tạo ra ngữ cảnh truyền thông liên tiến trình theo cơ chế hàng đợi bản tin và
chia sẻ bộ nhớ với môt hình Client/Server, trong đó nhiều tiến trình đóng vai trò là Client
sẽ trao đổi thông tin với một tiến trình đóng vai trò là Server.
 Khối II: Chương trình hiển thị các thông tin về IPC và hủy các tiến trình đang truyền
thông IPC với nhau theo cơ chế hàng đợi bản tin và chia sẻ bộ nhớ.
Mô tả chi tiết hơn về hai khối sẽ được trình bày dưới đây.
1. Chương trình khởi tạo IPC
Ba chương trình khởi tạo một ngữ cảnh truyền thông IPC giữa các tiến trình với
nhau theo cơ chế hàng đợi bản tin - Message Queue và chia sẻ bộ nhớ - Shared
Memory,và Semaphore các tiến trình Client sẽ liên tục “truyền” liên tục các bản tin cho

tiến trình Server. Tiến trình Server nhận các bản tin này và hiển thị nội dung. Để thực
hiện được việc này thì các Client và Server sẽ phải cùng nhau chia sẻ tài nguyên hệ thống
đó là một phân vùng bộ nhớ hoặc một hàng đợi bản tin. Việc quản lý các tiến trình truy
nhập để sử dụng tài nguyên này được thực hiện nhờ cơ chế khác, ví dụ như Semaphore,
do đó đôi khi ta thấy số hiệu IPC của Semaphore có thể trùng với số hiệu IPC của
Message Queue hoặc Shared Memory.
Nhóm 02 KSTN-DTVT-K52 Page 12
Hiển thị và hủy các tiến trình IPC trên Linux
1.1. Shared Memory
Thực hiện khởi tạo Shared Memory client và server, client và server sẽ trao đổi
bản tin với nhau.
Hình 6.1: Kết quả chương trình tạo Shared Memory
Nhóm 02 KSTN-DTVT-K52 Page 13
Hiển thị và hủy các tiến trình IPC trên Linux
1.2. Message Queue
Thực hiện khởi tạo Message Queue client và server, client và server sẽ trao đổi
bản tin với nhau.
Hình 6.2: Kết quả chương trình tạo Message Queue
Nhóm 02 KSTN-DTVT-K52 Page 14
Hiển thị và hủy các tiến trình IPC trên Linux
1.3. Semaphores
Hình 6.3: Kết quả chương trình tạo Semaphore
Nhóm 02 KSTN-DTVT-K52 Page 15
Hiển thị và hủy các tiến trình IPC trên Linux
2. Chương trình hiển thị thông số IPC và hủy tiến trình
Chương trình được thiết kế dạng một lệnh Shell trong Linux/Unix, ngoài yêu cầu
của đề bài là hiển thị các tiến trình đang truyền thông IPC với nhau và khi hủy một tiến
trình trong phiên IPC đó thì các tiến trình khác sẽ tự hủy; chương trình còn có các tùy
chọn để hiển thị các thông số về IPC SYSTEM V trên hệ điều hành.
2.1. Chương trình ipc

Chương trình ipc có các lựa chọn sau:
 ipc a: hiển thị tất cả các thông tin IPC Message Queue, Semaphore, Shared Memory.
Là kết hợp đầu ra của ipc s, ipc m, và ipc q.
 ipc s: hiển thị thông tin IPC Semaphore. Các thông số hiển thị:
o semid: số hiệu của một mảng semaphore
o sem_nth: giá trị thứ n trong mảng semaphore
o sempid: PID của tiến trình tạo ra mảng semaphore
o ncnt: số tiến trình đang chờ để semaphore đếm đến giá trị cận trên dương của
semaphore.
o zcnt: số tiến trình đang chờ để semaphore đếm về 0
 ` ipc m: hiển thị thông tin IPC Shared Memory. Các thông số được hiển thị:
o shmid: số hiệu của phân vùng nhớ được chia sẻ
o owner: tên login của chủ của phân vùng nhớ được chia sẻ này
o cpid: tiến trình khởi tạo ra vùng nhớ chia sẻ
o lpid: tiến trình gần nhất hoạt động trên phân vùng nhớ được chia sẻ này (attach
hoặc deattach ra khỏi phân vùng nhớ).
o nattch: số lượng tiến trình đang được gắn vào phân vùng nhớ
 ipc r <SHMID> : hiển thị các tiến trình đang truyền thông theo cơ chế chia sẻ bộ nhớ
trên phân vùng nhớ có số hiện SHMID, số hiệu này có thể lấy được từ ipc m. Các
thông số được hiển thị:
o PID: PID của tiến trình đang thực hiện truyền thông IPC qua cơ chế Shared
Memory
o CMDLINE: tên của tiến trình hay command line để chạy tiến trình
 ipc q: hiển thị thông tin IPC Message Queue và các tiến trình đang truyền thông theo
cơ chế hàng đợi bản tin – Message Queue với nhau. Các thông số được hiển thị:
o msqid: số hiệu của hàng đợi bản tin đang tồn tại trong hệ điều hành
o lspid: PID của tiến trình thực hiện việc ghi bản tin vào hàng đợi gần đây nhất,
tính từ thời điểm lệnh được thực thi
o lrpid: PID của tiến trình thực hiện việc đọc bản tin từ hàng đợi gần đây nhất,
tính từ thời điểm lệnh được thực thi.

Nhóm 02 KSTN-DTVT-K52 Page 16
Hiển thị và hủy các tiến trình IPC trên Linux
 ipc k <PID>: hủy các tiến trình có pid xác định và các tiến trình thực hiện ipc theo cơ
chế hàng đợi bản tin – Message Queue với nó với nó.
 ipc x <PID> : hủy các tiến trình có pid xác định và các tiến trình thực hiện ipc theo cơ
chế chia sẻ bộ nhớ - Shared Memory với nó
2.2. Kết quả hiển thị thông số IPC

 ipc s:
Hình 6.4: Kết quả thực hiện lệnh “ipc s”
 ipc m:
Nhóm 02 KSTN-DTVT-K52 Page 17
Hiển thị và hủy các tiến trình IPC trên Linux
Hình 6.5: Kết quả thực hiện lệnh “ipc m”
Nhóm 02 KSTN-DTVT-K52 Page 18
Hiển thị và hủy các tiến trình IPC trên Linux
 ipc q
Hình 6.6: Kết quả thực hiện lệnh “ipc q”
Nhóm 02 KSTN-DTVT-K52 Page 19
Hiển thị và hủy các tiến trình IPC trên Linux
 ipc a:
Hình 6.7: Kết quả thực hiện lệnh “ipc a”
Nhóm 02 KSTN-DTVT-K52 Page 20
Hiển thị và hủy các tiến trình IPC trên Linux
VII. Thí nghiệm và kết quả
Thí nghiệm hiển thị các tiến trình đang truyền thông IPC theo cơ chế Shared Memory ,
Message Queue, ngữ cảnh truyền thông theo mô hình Client/Server, trong đó các tiến trình
Client sẽ liên tục gửi các bản tin cho Server, Server nhận các bản tin và hiển thị nội dung các bản
tin đó. Ngoài ra trong thí nghiệm này cũng sẽ thực hiện hủy một tiến trình bất kì trong nhóm các
tiến trình đang truyền thông IPC với nhau, sau khi tiến trình này bị hủy thì các tiến trình còn lại

trong nhóm cũng bị hủy.
1. Thí nghiệm 1
Hiển thị các tiến trình đang truyền thông theo cơ chế Shared Memory và tiến hành hủy tiến trình
 Các bước tiến hành:
o Chạy chương trình shm tạo ra ba Client và một Server, ba Client và Server
này sẽ được attach vào một phân vùng nhớ, chương trình cũng hiển thị PID
của ba Client và Server. Client sẽ gửi các dữ liệu liên tục vào vùng nhớ này và
Server liên tục đọc dữ liệu từ chính vùng nhớ đó. Quá trình truyền dữ liệu
giữa Client và Server là vòng lặp vô cùng.
Kết quả
Hình 7.1: Quá trình truyền nhận giữa các tiến trình Client và tiến trình Server
Nhóm 02 KSTN-DTVT-K52 Page 21
Hiển thị và hủy các tiến trình IPC trên Linux
o Chạy chương trình ipc m để hiển thị các thông số về chia sẻ bộ nhớ trong hệ
điều hành , ta có thể thấy được giá trị của số hiệu vùng nhớ được chia sẻ.
Kết quả : Số hiệu vùng nhớ thu được là SHMID=983051
Hình 7.2: Chương trình hiển thị các thông số về chia sẻ bộ nhớ giữa các tiến trình
Nhóm 02 KSTN-DTVT-K52 Page 22
Hiển thị và hủy các tiến trình IPC trên Linux
o Chạy chương trình ipc r SHMID để hiển thị các tiến trình đang truyền thông
với nhau qua cơ chế chia sẻ bộ nhớ trong phân vùng nhớ được chia sẻ có số
hiệu là SHMID.
Kết quả: PID của các tiến trình là 2975,2976,2977 và 2978. Kết quả này chính xác
với PID hiển thị từ chương trình shm
Hình 7.3: Chương trình hiển thị các tiến trình có PID là 2975,2976,2977 và 2978
dang truyền thông IPC với nhau thông qua cơ chế Shared Memory. Nhờ cột hiển thị
Command Line mà ta có thể thấy được các tiến trình trên đã được hiển thị đúng.
Nhóm 02 KSTN-DTVT-K52 Page 23
Hiển thị và hủy các tiến trình IPC trên Linux
o Chọn một tiến trình bất kì trong các tiến trình vừa thu được từ bước trước, ví

dụ chọn tiến trình có PID là 2975 . Chạy chương trình ipc x PID để hủy toàn
bộ các tiến trình đang cùng chia sẻ bộ nhớ với tiến trình có PID
Nhóm 02 KSTN-DTVT-K52 Page 24
Hiển thị và hủy các tiến trình IPC trên Linux
2. Thí nghiệm 2
Hiển thị các tiến trình đang truyền thông theo cơ chế Message Queue và tiến hành hủy tiến trình
 Các bước tiến hành:
o Chạy chương trình mq tạo ra ba Client và một Server, ba Client và Server
này ghi và đọc các bản tin trong một hàng đợi bản tin ,chương trình cũng hiển
thị PID của ba Client của Server .Các Client sẽ ghi các dữ liệu liên tục vào
hàng đợi bản tin này và Server sẽ liên tục lấy dữ liệu từ chính hàng đợi đó ra.
Quá trình truyền dữ liệu giữa Client và Server là vòng lặp vô cùng.
Kết quả
Hình 7.5: Quá trình truyền nhận giữa các tiến trình Client và tiến trình Server
Nhóm 02 KSTN-DTVT-K52 Page 25

×