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_IRUSR,

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ự