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

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.

pdf34 trang | Chia sẻ: candy98 | Lượt xem: 809 | Lượt tải: 0download
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.