hái niệm và ví dụ
Interprocess communication (IPC) là sự truyền dữ
liệu giữa các tiến trình.
Vd1: Web browser yêu cầu 1 trang web từ Web
server. Dạng truyền này thường sử dụng các socket
trong một kết nối dạng telephone.
Vd2: Lệnh in các tên file trong 1 thư mục:
ls | lpr tiến trình giao tiếp thông qua 1 pipe (|)3
Các dạng IPC
bộ nhớ chia sẻ: các tiến trình giao tiếp bằng cách
đọc, ghi dữ liệu tại vùng nhớ xác định.
bộ nhớ ánh xạ: tương tự như bộ nhớ chia sẻ, chỉ
khác là nó được liên kết với 1 file.
pipe: giao tiếp tuần tự từ 1 tiến trình này tới 1 tiến
trình khác có liên quan.
FIFO: tương tự pipe, chỉ khác là giao tiếp giữa các
tiến trình không liên quan.
socket: hỗ trợ giao tiếp giữa các tiến trình không liên
quan thậm chí trên các máy tính khác nhau.
34 trang |
Chia sẻ: candy98 | Lượt xem: 1076 | 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 5: Giao tiếp liên 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
Chương 5. Giao tiếp liên tiến trình
Phạm Quang Dũng
2Khái niệm và ví dụ
Interprocess communication (IPC) là sự truyền dữ
liệu giữa các tiến trình.
Vd1: Web browser yêu cầu 1 trang web từ Web
server. Dạng truyền này thường sử dụng các socket
trong một kết nối dạng telephone.
Vd2: Lệnh in các tên file trong 1 thư mục:
ls | lpr
2 tiến trình giao tiếp thông qua 1 pipe (|)
3Các dạng IPC
bộ nhớ chia sẻ: các tiến trình giao tiếp bằng cách
đọc, ghi dữ liệu tại vùng nhớ xác định.
bộ nhớ ánh xạ: tương tự như bộ nhớ chia sẻ, chỉ
khác là nó được liên kết với 1 file.
pipe: giao tiếp tuần tự từ 1 tiến trình này tới 1 tiến
trình khác có liên quan.
FIFO: tương tự pipe, chỉ khác là giao tiếp giữa các
tiến trình không liên quan.
socket: hỗ trợ giao tiếp giữa các tiến trình không liên
quan thậm chí trên các máy tính khác nhau.
4Các tiêu chuẩn phân biệt loại IPC
Phạm vi giao tiếp: giữa các tiến trình có liên quan,
không liên quan trên 1 máy tính, hay trên bất kỳ máy
tính nối mạng nào.
Quyền đọc, ghi dữ liệu: tiến trình giao tiếp chỉ được
ghi dữ liệu hay đọc dữ liệu.
Số lượng tiến trình được tham gia giao tiếp
Tính đồng bộ: các tiến trình giao tiếp có được đồng
bộ hóa bởi IPC không? vd: 1 tiến trình đọc tạm dừng
đến khi có dữ liệu để đọc.
55.1. Shared Memory
Là 1 trong những phương pháp giao tiếp liên tiến trình
đơn giản nhất.
Các tiến trình truy nhập vùng nhớ chung bằng cách
gọi malloc, được trả về con trỏ tới vùng nhớ thực đó.
Khi 1 tiến trình thay đổi vùng nhớ, các tiến trình khác
nhận ra được sự thay đổi đó.
65.1.1. Fast Local Communication
Bộ nhớ chia sẻ là dạng IPC nhanh nhất
Không yêu cầu system call hoặc vào kernel
Tránh được việc copy dữ liệu không cần thiết
Phải tự cung cấp sự đồng bộ hóa,
vd1: 1 tiến trình không nên đọc dữ liệu trên bộ nhớ cho đến
khi dữ liệu đã được ghi lên đó.
vd2: 2 tiến trình không được ghi dữ liệu lên cùng vùng nhớ
tại cùng thời điểm.
Giải pháp phổ biến để tránh trạng thái tranh đua là sử dụng
cờ báo (semaphore)
75.1.2. Memory Model
Một tiến trình muốn sử dụng 1 segment (đoạn) bộ
nhớ chia sẻ phải:
Định vị đoạn (allocate)
Gắn vào đoạn (attach)
Sau khi dùng xong:
Tháo gỡ đoạn (detach)
Linux: bộ nhớ ảo (trên đĩa, cũng chứa dữ liệu thật) của mỗi
tiến trình được chia thành các trang (kích thước mặc định 4
KB). Mỗi tiến trình giữ 1 ánh xạ từ các địa chỉ bộ nhớ của nó tới
các địa chỉ bộ nhớ ảo
85.1.3. Allocation
Hàm định vị đoạn bộ nhớ: shmget(ts1,ts2,ts3)
int segment_id = shmget(shm_key,getpagesize(),
IPC_CREAT | S_IRUSR | S_IWUSR);
ts1: integer key xác định đoạn để tạo
các tiến trình không liên quan có thể truy nhập cùng
đoạn chia sẻ bằng cách xác định cùng giá trị key.
sử dụng hằng IPC_PRIVATE làm key để đảm bảo tạo
1 đoạn bộ nhớ không trùng nhau.
ts2: xác định số byte của đoạn, được làm tròn lên thành bội
số của page size.
ts3: flag value – xác định các lựa chọn cho shmget
9Allocation (tiếp)
Hàm định vị đoạn bộ nhớ: shmget(ts1,ts2,ts3)
ts3: flag value – xác định các lựa chọn cho shmget
IPC_CREAT: nên tạo 1 segment mới
IPC_EXCL: thường dùng với IPC_CREAT, khiến shmget
lỗi nếu key đã tồn tại:
Nếu có cờ này: tiến trình được sắp xếp 1 segment “loại trừ”.
Nếu ko dùng cờ này: trả về segment đã tồn tại.
mode flags: xác định quyền truy nhập đoạn của owner,
group, other.
dùng dạng 9 bit, hoặc
dùng các hằng xác định trong : S_IRUSR,
S_IWUSR, S_IROTH, S_IWOTH
10
5.1.4. Attachment and Detachment
Để làm khả dụng đoạn bộ nhớ chia sẻ, dùng shmat:
ts1: segment id trả về bởi shmget
ts2: con trỏ xác định vùng không gian địa chỉ của tiến trình
mà bạn muốn ánh xạ bộ nhớ chia sẻ, có thể truyền NULL để
Linux chọn một địa chỉ khả dụng.
ts3: cờ
SHM_RND: địa chỉ xác định bởi tham số thứ hai nên được
làm tròn xuống thành bội số của page size
SHM_RDONLY: đoạn sẽ chỉ được đọc, không được ghi
Nếu gọi thành công, shmat trả về địa chỉ của đoạn,
tiến trình con tạo bởi fork sẽ thừa kế đoạn.
11
Khi dùng xong đoạn bộ nhớ chia sẻ, nên tháo gỡ
đoạn bằng một trong các cách:
shmdt(địa chỉ trả về bởi shmat)
gọi exit và exec
12
5.1.5. Controlling and Deallocating shared memory
shmctl: trả về thông tin về đoạn bộ nhớ chia sẻ và
có thể thay đổi nó.
ts1: segment id
Để lấy thông tin về segment:
ts2: truyền IPC_STAT
ts3: con trỏ tới biến struct shmid_ds
Để loại bỏ segment:
ts2: truyền IPC_RMID; ts3: truyền NULL
Nên dùng shmctl để bỏ định vị đoạn bộ nhớ một
cách rõ ràng để tránh xung đột về giới hạn số đoạn
bộ nhớ chia sẻ trong hệ thống.
13
5.1.6. Chương trình ví dụ
Listing 5.1: shm.c
Debugging:
Lệnh ipcs –m để lấy thông tin về giao tiếp liên tiến trình sử
dụng bộ nhớ chia sẻ
Lệnh ipcs shm shm_id để loại bỏ đoạn bộ nhớ khi có lỗi
gây bởi 1 chương trình.
14
5.2. Mapped Memory
Có thể được dùng cho giao tiếp liên tiến trình hoặc là
cách dễ dàng để truy nhập nội dung của file.
Linux chia file thành các khúc có kích thước = page
size rồi copy chúng vào các trang bộ nhớ ảo; trang
được ánh xạ vào không gian địa chỉ của tiến trình.
Tiến trình có thể đọc/thay đổi nội dung file bằng cách
truy nhập/ghi bộ nhớ, cho phép truy nhập nhanh đến
file.
15
5.2.1. Mapping an ordinary file
gọi mmap(ts1,ts2,ts3,ts4,ts5,ts6):
ts1: địa chỉ bộ nhớ để ánh xạ file vào
Nếu truyền NULL: Linux tự chọn vùng khả dụng
ts2: độ dài vùng nhớ ánh xạ (byte)
ts3: xác định protection cho vùng nhớ
PROT_READ, PROT_WRITE, PROT_EXEC
ts4: flag, các lựa chọn thêm
MAP_FIXED: ấn định địa chỉ yêu cầu cho ánh xạ file
MAP_PRIVATE: việc ghi lên bộ nhớ không nên ghi lại lên
file mà ghi lên 1 bản copy riêng của file.
MAP_SHARED: việc ghi lên bộ nhớ lập tức được ghi lên
file; nên dùng chế độ này cho IPC.
16
mmap(ts1,ts2,ts3,ts4,ts5,ts6):
ts5: file descriptor
ts6: offset tính từ đầu file mà từ đó bắt đầu ánh xạ. Có thể
ánh xạ toàn bộ hoặc một phần file nhờ ts6 và ts2.
Nếu lời gọi thành công, nó trả về 1 con trỏ tới đầu
vùng nhớ. Trái lại, trả về MAP_FAILED.
Khi dùng xong ánh xạ bộ nhớ, giải phóng nó bởi
munmap(địa chỉ bắt đầu,độ dài vùng nhớ ánh xạ)
Linux tự động bỏ ánh xạ bộ nhớ khi tiến trình chấm dứt.
17
5.2.2. Các chương trình ví dụ
Listing 5.5: mmap-write.c
sinh 1 số ngẫu nhiên rồi ghi lên 1 file được ánh xạ vào bộ nhớ.
Listing 5.6: mmap-read.c
đọc 1 số nguyên từ file được ánh xạ vào bộ nhớ rồi nhân 2.
Ví dụ chạy các chương trình ví dụ trên:
% ./mmap-write /cpr/int-file
% cat /cpr/int-file
42
% ./mmap-read /cpr/int-file
value: 42
% cat /cpr/int-file
84
18
5.3. Pipes
pipe là một thiết bị nối tiếp, cho phép giao tiếp một
chiều
dữ liệu được ghi vào “write end” của pipe, sau đó
được đọc ra từ “read end”.
được sử dụng để giao tiếp giữa 2 luồng trong 1 tiến
trình hoặc giữa 2 tiến trình cha, con.
trong shell, dùng “|”, vd: % ls | sort
dung lượng dữ liệu của pipe hạn chế.
pipe tự động đồng bộ hóa 2 tiến trình.
19
5.3.1. Tạo pipe
int pipe_fds[2];
int read_fd;
int write_fd;
pipe (pipe_fds);
read_fd = pipe_fds[0];
write_fd = pipe_fds[1];
Dữ liệu được ghi lên file descriptor read_fd sau đó
có thể được đọc ra từ write_fd.
20
5.3.2. Giao tiếp giữa tiến trình cha, con
Lời gọi pipe tạo các file descriptor mà chỉ hợp lệ
trong tiến trình đó và các tiến trình con của nó.
Listing 5.7: pipe.c
fork tạo 1 tiến trình con thừa kế file descriptor
tiến trình cha ghi 1 chuỗi lên pipe, tiến trình con đọc nó ra
sử dụng fdopen chuyển các file descriptor thành FILE*
streams để sử dụng được các hàm vào-ra thư viện C chuẩn
bậc cao như printf và fgets.
21
5.3.3. Redirecting the Standard Input,
Output, Error Streams
Thông thường, bạn muốn tạo 1 tiến trình con rồi thiết
lập một đầu của pipe là input chuẩn hoặc output
chuẩn của nó.
Lời gọi dup2 có thể coi 1 file descriptor tương đương
với cái khác.
Vd: để điều hướng lại (redirect) input chuẩn của một
tiến trình tới một file descriptor fd:
dup2(fd,STDIN_FILEN0)
Các ký tự đọc từ fd không được đọc lại từ input
chuẩn
22
Chương trình ví dụ
Listing 5.8: dup2.c
sử dụng dup2 để gửi output từ pipe tới lệnh sort.
sau khi tạo pipe, chương trình phân nhánh.
chương trình chính in một số chuỗi lên pipe.
chương trình con dùng dup2 gắn read file descriptor của
pipe vào input chuẩn của nó, rồi thực hiện sort.
23
5.3.4. popen và pclose
Cách sử dụng phổ biến của pipe là để gửi/nhận dữ
liệu đến/từ chương trình đang chạy trong một tiến
trình con.
Các hàm popen và pclose giúp thực hiện điều trên
bằng cách loại đi sự cần thiết phải gọi pipe, fork,
dup2, exec, fdopen.
Listing 5.9: popen.c
24
popen(“sort”,“w”):
tham số thứ nhất được thực hiện như lệnh shell trong một
tiến trình mới chạy /bin/sh.
tham số thứ hai:
“r”: hàm trả về output stream chuẩn của tiến trình con
để tiến trình cha có thể đọc output.
“w”: hàm trả về input stream chuẩn của tiến trình con
để tiến trình cha có thể gửi dữ liệu.
pclose(stream):
đóng stream trả về bởi popen
đợi tiến trình con chấm dứt.
25
5.4. Sockets
socket là thiết bị giao tiếp 2 chiều có thể dùng để
giao tiếp với 1 tiến trình khác trên cùng máy hoặc
trên máy khác.
Các chương trình Internet như Telnet, rlogin, FTP,
talk, World Wide Web sử dụng socket.
26
5.4.1. Các System Call
socket – tạo 1 socket
closes – hủy 1 socket
connect – dùng phía client, tạo 1 kết nối giữa 2 socket
bind – gán địa chỉ cho 1 server socket
listen – dùng phía server, cấu hình socket thành trạng
thái chấp nhận
accept – dùng phía server, chấp nhận 1 kết nối
và tạo 1 socket mới cho kết nối
Các socket được biểu diễn bởi file descriptor, có thể
ghi lên đó để gửi thông tin.
27
Tạo socket
Khi tạo 1 socket, phải xác định 3 tham số:
1. communication style: xác định cách mà các gói tin được xử lý và
cách chúng được đánh địa chỉ từ sender đến receiver:
connection styles (SOCK_STREAM): đảm bảo phân phối các gói
tin theo đúng thứ tự chúng được gửi
datagram styles (SOCK_DGRAM): không đảm bảo thứ tự đúng của
các gói tin nhận được.
2. name space: xác định cách các địa chỉ socket được ghi, vd:
trong “local name space” (PF_LOCAL, PF_UNIX): là các tên file
bình thường
trong “Internet space” (PF_INET): là địa chỉ IP và số hiệu cổng
của máy
3. protocol: xác định cách dữ liệu được truyền (=0 – thường là đúng)
TCP/IP, AppleTalk network, UNIX local communication
28
Phía client: connect
connect(ts1, ts2, ts3)
ts1: địa chỉ của server socket
ts2: con trỏ tới cấu trúc địa chỉ socket
ts3: độ dài của cấu trúc địa chỉ trỏ bởi ts2 (byte).
Các định dạng địa chỉ socket khác nhau tùy theo
socket namespace.
29
Phía server: bind, listen, accept
bind(ts1, ts2, ts3)
ts1: socket file descriptor
ts2: con trỏ tới cấu trúc địa chỉ socket
ts3: độ dài của cấu trúc địa chỉ (byte)
listen(ts1, ts2)
ts1: socket file descriptor
ts2: xác định số lượng kết nối treo được xếp hàng đợi
nếu queue đầy thì ko chấp nhận thêm kết nối
ko giới hạn tổng số kết nối mà server có thể xử lý,
chỉ giới hạn số client cố gắng kết nối mà chưa được
chấp nhận
30
accept(ts1, ts2, ts3)
ts1: socket file descriptor
ts2: con trỏ tới cấu trúc địa chỉ socket, mà được điền
bởi địa chỉ của client socket
ts3: độ dài của cấu trúc địa chỉ (byte)
Lời gọi accept tạo 1 socket mới để giao tiếp với client
và trả về file descriptor tương ứng.
server socket ban đầu tiếp tục chấp nhận các kết nối
mới từ client.
31
5.4.2. Local (UNIX_domain) Sockets
Là các socket kết nối các tiến trình trên cùng máy tính sử
dụng local namespace (PF_LOCAL, PF_UNIX).
Các địa chỉ socket (tên file) chỉ được sử dụng khi tạo các kết
nối.
Tên của socket được xác định trong struct sockaddr_un
trường sun_family: phải được thiết lập là AF_LOCAL
trường sun_path: xác định tên file sử dụng, tối đa dài 108 byte
Tiến trình phải có quyền ghi đối với thư mục (để thêm file) và
quyền đọc đối với file (để kết nối tới socket).
Giao thức được phép duy nhất là 0.
32
Chương trình ví dụ
Listing 5.10 (socket-server.c) và Listing 5.11 (socket-client.c)
Chạy chương trình server trong 1 cửa sổ
% ./socket-server /tmp/socket
Chạy chương trình client trong 1 cửa sổ khác
% ./socket-client /tmp/socket “Hello world”
% ./socket-client /tmp/socket “This’s a test”
Chương trình server nhận và in các message trên. Để đóng
server, client gửi message “quit”
% ./socket-client /tmp/socket “quit”
33
5.4.3. Internet-Domain Sockets
Là các socket kết nối các tiến trình trên các máy khác
nhau sử dụng Internet namespace (PF_INET).
Địa chỉ socket (máy và số cổng) được xác định trong
struct sockaddr_in
trường sin_family: phải được thiết lập là AF_INET
trường sin_addr: xác định IP của máy (số nguyên 32-bit)
có thể dùng hàm gethostbyname
trường sin_port: xác định số hiệu cổng của máy
Listing 5.12: socket-inet.c
% ./socket-inet fita.hua.edu.vn
34
5.4.4. Socket Pairs
Hàm socketpair cho phép giao tiếp 2 chiều giữa
các tiến trình có quan hệ trong cùng 1 máy.
Tạo 2 file descriptor cho 2 socket kết nối trên 1 máy.
3 tham số đầu tiên giống như lời gọi socket, chú ý
chỉ được truyền PF_LOCAL
Tham số cuối cùng là mảng 2 số nguyên tương tự
như pipe: mảng được điền bởi các file descriptor
của 2 socket.