Chương 5. Giao tiếp liên tiến trình
Phạm Quang Dũng
http://fita.hua.edu.vn/pqdung
Khái niệm và ví dụ
liệu giữa các tiến trình.
Interprocess communication (IPC) là sự truyền dữ
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.
Vd1: Web browser yêu cầu 1 trang web từ Web
ls | lpr
2 tiến trình giao tiếp thông qua 1 pipe (|)
2
Vd2: Lệnh in các tên file trong 1 thư mục:
Các dạng IPC
đọc, ghi dữ liệu tại vùng nhớ xác định.
bộ nhớ chia sẻ: các tiến trình giao tiếp bằng cách
khác là nó được liên kết với 1 file.
bộ nhớ ánh xạ: tương tự như bộ nhớ chia sẻ, chỉ
trình khác có liên quan.
pipe: giao tiếp tuần tự từ 1 tiến trình này tới 1 tiến
tiến trình không liên quan.
FIFO: tương tự pipe, chỉ khác là giao tiếp giữa các
quan thậm chí trên các máy tính khác nhau.
3
socket: hỗ trợ giao tiếp giữa các tiến trình không liên
Các tiêu chuẩn phân biệt loại IPC
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.
Phạm vi giao tiếp: giữa các tiến trình có liên quan,
ghi dữ liệu hay đọc dữ liệu.
Quyền đọc, ghi dữ liệu: tiến trình giao tiếp chỉ được
Số lượng tiến trình được tham gia giao tiếp
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.
4
Tính đồng bộ: các tiến trình giao tiếp có được đồng
5.1. Shared Memory
đơn giản nhất.
Là 1 trong những phương pháp giao tiếp liên tiến trình
gọi malloc, được trả về con trỏ tới vùng nhớ thực đó.
Các tiến trình truy nhập vùng nhớ chung bằng cách
nhận ra được sự thay đổi đó.
5
Khi 1 tiến trình thay đổi vùng nhớ, các tiến trình khác
5.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
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)
6
Phải tự cung cấp sự đồng bộ hóa,
5.1.2. Memory Model
nhớ chia sẻ phải:
Định vị đoạn (allocate)
Gắn vào đoạn (attach)
Một tiến trình muốn sử dụng 1 segment (đoạn) bộ
Tháo gỡ đoạn (detach)
Sau khi dùng xong:
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…
7
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
5.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
8
Allocation (tiếp)
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_IWUSR, S_IROTH, S_IWOTH
9
Hàm định vị đoạn bộ nhớ: shmget(ts1,ts2,ts3)
5.1.4. Attachment and Detachment
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
Để làm khả dụng đoạn bộ nhớ chia sẻ, dùng shmat:
tiến trình con tạo bởi fork sẽ thừa kế đoạn.
10
Nếu gọi thành công, shmat trả về địa chỉ của đoạn,
đoạn bằng một trong các cách:
shmdt(địa chỉ trả về bởi shmat)
gọi exit và exec
11
Khi dùng xong đoạn bộ nhớ chia sẻ, nên tháo gỡ
5.1.5. Controlling and Deallocating shared memory
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
shmctl: trả về thông tin về đoạn bộ nhớ chia sẻ và
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.
12
Nên dùng shmctl để bỏ định vị đoạn bộ nhớ một
5.1.6. Chương trình ví dụ
Listing 5.1: shm.c
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.
13
Debugging:
5.2. Mapped Memory
cách dễ dàng để truy nhập nội dung của file.
Có thể được dùng cho giao tiếp liên tiến trình hoặc là
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.
Linux chia file thành các khúc có kích thước = page
truy nhập/ghi bộ nhớ, cho phép truy nhập nhanh đến
file.
14
Tiến trình có thể đọc/thay đổi nội dung file bằng cách
5.2.1. Mapping an ordinary file
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.
15
gọi 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.
mmap(ts1,ts2,ts3,ts4,ts5,ts6):
vùng nhớ. Trái lại, trả về MAP_FAILED.
Nếu lời gọi thành công, nó trả về 1 con trỏ tới đầu
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.
16
Khi dùng xong ánh xạ bộ nhớ, giải phóng nó bởi
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
17
5.3. Pipes
chiều
pipe là một thiết bị nối tiếp, cho phép giao tiếp một
được đọc ra từ “read end”.
dữ liệu được ghi vào “write end” của pipe, sau đó
trình hoặc giữa 2 tiến trình cha, con.
được sử dụng để giao tiếp giữa 2 luồng trong 1 tiến
trong shell, dùng “|”, vd: % ls | sort
dung lượng dữ liệu của pipe hạn chế.
18
pipe tự động đồng bộ hóa 2 tiến trình.
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];
có thể được đọc ra từ write_fd.
19
Dữ liệu được ghi lên file descriptor read_fd sau đó
5.3.2. Giao tiếp giữa tiến trình cha, con
trong tiến trình đó và các tiến trình con của nó.
Lời gọi pipe tạo các file descriptor mà chỉ hợp lệ
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.
20
Listing 5.7: pipe.c
5.3.3. Redirecting the Standard Input, Output, Error Streams
lập một đầu của pipe là input chuẩn hoặc output chuẩn của nó.
Thông thường, bạn muốn tạo 1 tiến trình con rồi thiết
với cái khác.
Lời gọi dup2 có thể coi 1 file descriptor tương đương
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
21
Vd: để điều hướng lại (redirect) input chuẩn của một
Chương trình ví dụ
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.
22
Listing 5.8: dup2.c
5.3.4. popen và pclose
liệu đến/từ chương trình đang chạy trong một tiến
trình con.
Cách sử dụng phổ biến của pipe là để gửi/nhận dữ
bằng cách loại đi sự cần thiết phải gọi pipe, fork,
dup2, exec, fdopen.
Các hàm popen và pclose giúp thực hiện điều trên
23
Listing 5.9: popen.c
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.
popen(“sort”,“w”):
đóng stream trả về bởi popen
đợi tiến trình con chấm dứt.
24
pclose(stream):
5.4. Sockets
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.
socket là thiết bị giao tiếp 2 chiều có thể dùng để
talk, World Wide Web sử dụng socket.
25
Các chương trình Internet như Telnet, rlogin, FTP,
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
ghi lên đó để gửi thông tin.
26
Các socket được biểu diễn bởi file descriptor, có thể
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
27
Phía client: connect
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).
connect(ts1, ts2, ts3)
socket namespace.
28
Các định dạng địa chỉ socket khác nhau tùy theo
Phía server: bind, listen, accept
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)
bind(ts1, ts2, ts3)
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
29
listen(ts1, ts2)
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)
và trả về file descriptor tương ứng.
Lời gọi accept tạo 1 socket mới để giao tiếp với client
mới từ client.
30
server socket ban đầu tiếp tục chấp nhận các kết nối
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.
31
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”
32
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
% ./socket-inet fita.hua.edu.vn
33
Listing 5.12: socket-inet.c
5.4.4. Socket Pairs
các tiến trình có quan hệ trong cùng 1 máy.
Hàm socketpair cho phép giao tiếp 2 chiều giữa
Tạo 2 file descriptor cho 2 socket kết nối trên 1 máy.
chỉ được truyền PF_LOCAL
3 tham số đầu tiên giống như lời gọi socket, chú ý
như pipe: mảng được điền bởi các file descriptor
của 2 socket.
34
Tham số cuối cùng là mảng 2 số nguyên tương tự

