Liên Lạc và Đồng bộ hóa tiến trình
BÀI 3LIÊN LẠC & ĐỒNG BỘ TIẾN TRÌNH I. LIÊN LẠC GIỮA CÁC TIẾN TRÌNH 1. Nhu cầu liên lạc giữa các tiến trình- Chia sẻ thông tin- Hợp tác hoàn thành tác vụ 2. Các Cơ Chế Liên lạc 2.1. Tín hiệu (Signal) Một tín hiệu được sử dụng để thông báo cho tiến trình về một sự kiện nào đó xảy ra. Ví dụ : Một số tín hiệu của UNIXTín hiệu Mô tảSIGINT Người dùng nhấn phím Ctl-C để ngắt xử lý tiến trìnhSIGILL Tiến trình xử lý một chỉ thị bất hợp lệSIGKILL Yêu cầu kết thúc một tiến trìnhSIGFPT Lỗi chia cho 0SIGSEGV Tiến trình truy xuất đến một địa chỉ bất hợp lệSIGCLD Tiến trình con kết thúcVới mỗi tín hiệu sẽ có một hàm để xử lý tín hiệu do phần cứng hoặc hđh cung cấp (signal handler) Các tín hiệu được gởi đi bởi :- Phần cứng (ví dụ lỗi do các phép tính số học)- Hạt nhân hệ điều hành gởi đến một tiến trình (Tiến trình truy xuất đến một địa chỉ bất hợp lệ). - Một tiến trình gởi đến một tiến trình khác ( ví dụ tiến trình cha yêu cầu một tiến trình con kết thúc)- Người dùng ( ví dụ nhấn phím Ctl-C để ngắt xử lý của tiến trình)Khi một tiến trình nhận một tín hiệu, nó có thể xử sự theo một trong các cách sau :- Bỏ qua tín hiệu - Xử lý tín hiệu bằng cách gọi hàm xử lý tín hiệu- Xử lý theo cách riêng của tiến trình.Hình: Liên lạc bằng tín hiệu24 Nhận xét - tiến trình nhận tín hiệu không thể xác định trước thời điểm nhận tính hiệu.- các tiến trình chỉ có thể thông báo cho nhau về một sự kiện, không thể trao đổi dữ liệu 2.2. Đường ống (Pipe)Là một kênh liên lạc trực tiếp giữa hai tiến trình, dữ liệu xuất của tiến trình này được chuyển đến làm dữ liệu nhập cho tiến trình kia dưới dạng một dòng các byte. Thứ tự dữ liệu truyền qua pipe được bảo toàn theo nguyên tắc FIFO. Một tiến trình chỉ có thể sử dụng một pipe do nó tạo ra hay kế thừa từ tiến trình cha.Hình: Liên lạc qua pipeHệ điều hành cung cấp các hàm (lời gọi hệ thống) read/write cho các tiến trình thực hiện thao tác đọc/ghi dữ liệu trong pipe. Hệ điều hành cũng chịu trách nhiệm đồng bộ hóa việc truy xuất pipe trong các tình huống:- Tiến trình đọc pipe sẽ bị khóa nếu pipe trống, nó sẽ phải đợi đến khi pipe có dữ liệu để truy xuất.- Tiến trình ghi pipe sẽ bị khóa nếu pipe đầy, nó sẽ phải đợi đến khi pipe có chỗ trống để chứa dữ liệu.Nhận xét:- Một tiến trình kết nối với một pipe chỉ có thể thực hiện một trong hai thao tác đọc hoặc ghi- Cho phép truyền dữ liệu không cấu trúc.- Chỉ để liên lạc giữa hai tiến trình có quan hệ cha-con, và trên cùng một máy tính.2.3. Vùng nhớ chia sẻ (shared memory)Nhiều tiến trình cùng có thể truy xuất đến một vùng nhớ dùng chung. Dữ liệu mà các tiến trình muốn gởi cho nhau, chỉ cần đặt vào vùng nhớ này.Vùng nhớ chia sẻ độc lập với các tiến trình, khi một tiến trình muốn truy xuất đến vùng nhớ này, tiến trình phải kết gắn vùng nhớ chung đó vào không gian địa chỉ riêng của từng tiến trình, và thao tác trên đó như một vùng nhớ riêng của mình. 25 Hình Liên lạc qua vùng nhớ chia sẻNhận xét:- Là phương pháp nhanh nhất để trao đổi dữ liệu giữa các tiến trình.- Vùng nhớ chia sẻ cần được bảo vệ bằng những cơ chế đồng bộ hóa - Không thể áp dụng hiệu quả trong các hệ phân tán 2.4 Trao đổi thông điệp (Message)Hai tiến trình P và Q muốn liên lạc với nhau, cần thiết lập một mối liên kết giữa hai tiến trình, sau đó P, Q sử dụng các hàm send, receive do hđh cung cấp để trao đổi thông điệp, khi sự liên lạc chấm dứt mối liên kết giữa hai tiến trình sẽ bị hủy. Liên kết không tường minh - Send(message) : gởi một thông điệp- Receive(message) : nhận một thông điệpLiên kết tường minh:- Send(destination, message) : gởi một thông điệp đến destination- Receive(source,message) : nhận một thông điệp từ sourceNhận xét: các tiến trình có thể trao đổi dữ liệu ở dạng có cấu trúc. 2.5. SocketsSocket là kênh liên lạc hai chiều. Hai tiến trình muốn liên lạc với nhau, mỗi tiến trình cần tạo một socket riêng. Các thao tác đọc/ghi lên socket chính là sự trao đổi dữ liệu giữa hai tiến trình.Có hai cách liên lạc qua socket:a) Liên lạc thư tín (socket đóng vai trò bưu cục): hai tiến trình không cần kết nối, “tiến trình gởi” ghi dữ liệu vào socket của mình, dữ liệu sẽ được chuyển cho socket của “tiến trình nhận”, “tiến trình nhận” sẽ nhận dữ liệu bằng cách đọc dữ liệu từ socket của “tiến trình nhận”. Dữ liệu gởi ở dạng gói có chứa thông tin IP của máy nhận và port của tiến trình nhận (Port là một số hiệu dùng để phân biệt các tiến trình trên cùng một máy, các tiến trình này có nhu cầu liên lạc với tiến trình khác)Khi liên lạc thư tín: - “tiến trình gởi” không chắc chắn thông điệp được gởi đến “tiến trình nhận” - Hai thông điệp được gởi theo một thứ tự nào đó có thể đến “tiến trình nhận” theo một thứ tự khác. - Một tiến trình sau khi đã tạo một socket có thể sử dụng nó để liên lạc với nhiều tiến trình khác nhau.b) Liên lạc điện thoại (socket đóng vai trò tổng đài): hai tiến trình cần kết nối trước khi truyền/nhận dữ liệu và kết nối được duy trì suốt quá trình truyền nhận dữ liệu. Khi liên lạc điện thoại dữ liệu truyền nhận bảo đảm chính xác và đúng thứ tự gởi, nếu sai sẽ được gởi lại.Nhận xét: Cơ chế socket có thể sử dụng để chuẩn hoá mối liên lạc giữa các tiến trình vốn không liên hệ với nhau, và có thể hoạt động trong những hệ thống khác nhau và trong môi trường phân tán. 26 II. ĐỒNG BỘ HÓA (SYNCHRONIZATION)1. Nhu cầu đồng bộ Hệ điều hành cũng cần cung cấp những cơ chế đồng bộ để bảo đảm hoạt động của các tiến trình đồng hành không tác động sai lệch đến nhau vì các lý do sau đây:1.1. Yêu cầu độc quyền truy xuất (Mutual exclusion) Tại một thời điểm, chỉ có một tiến trình được quyền truy xuất một tài nguyên không thể chia sẻ.1.2. Yêu cầu phối hợp (Synchronization)Có trường hợp các tiến trình cần hợp tác với nhau, ví dụ một tiến trình chỉ có thể xử lý nếu một tiến trình khác đã kết thúc một công việc nào đó …2. Bài toán đồng bộ hoá 2.1. Vấn đề tranh đoạt điều khiển (race condition)Khi có nhiều tiến trình đọc và ghi dữ liệu trên cùng một vùng nhớ chung, thì dữ liệu dung chung có thể không xác định vì phụ thuộc vào sự điều phối tiến trình của hệ thống. Tình huống này được gọi là tình huống tranh đoạt điều khiển.Ví dụ: Giả sử có hai tiến trình P1 và P2 sử dụng vùng nhớ chung lưu trữ biến taikhoan .Mỗi tiến trình muốn rút một khoản tiền tienrut từ tài khoản bằng đoạn mã sau:if (taikhoan - tienrut >=0) taikhoan = taikhoan - tienrut;else error(« khong the rut tien ! »);Giả sử tài khoản hiện còn 800, P1 muốn rút 500 và P2 muốn rút 400. Có thể xảy ra tình huống sau : Sau khi đã kiểm tra điều kiện (taikhoan - tienrut >=0) là đúng, P1 hết thời gian xử lý mà hệ thống cho phép, hệ điều hành cấp phát CPU cho P2. P2 kiểm tra điều kiện (800-400>=0) là đúng, taikhoan được cập nhật lại là 400. Khi P1 được tiếp tục xử lý, nó sẽ không kiểm tra lại điều kiện (taikhoan - tienrut >=0) mà thực hiện rút tiền. Giá trị của taikhoan sẽ lại được cập nhật thành -100. Tình huống lỗi xảy ra ! 2.2. Miền găng (critical section)Đoạn chương trình có khả năng xảy ra lỗi khi truy xuất tài nguyên dùng chung được gọi là miền găng Trong ví dụ trên, đoạn mã : if (taikhoan - tienrut >=0)taikhoan = taikhoan - tienrut;của mỗi tiến trình tạo thành một miền găng.27 Có thể giải quyết lỗi nếu bảo đảm tại một thời điểm chỉ có một tiến trình được xử lý lệnh trong miền găng, nghĩa là tại một thời điểm chỉ có một tiến trình truy xuất tài nguyên dùng chung.Khi giải quyết bài toán miền găng cần chú ý 4 điều kiện sau :- ĐK1: Không có hai tiến trình cùng ở trong miền găng cùng lúc. - ĐK2: Không có giả thiết về tốc độ của các tiến trình, cũng như về số lượng bộ xử lý - ĐK3: Một tiến trình bên ngoài miền găng không được ngăn cản các tiến trình khác vào miền găng.- ĐK4: Không có tiến trình nào phải chờ vô hạn để được vào miền găng.III. CÁC GIẢI PHÁP ĐỒNG BỘ 1. Giải pháp busy waiting 1.1. Các giải pháp phần mềm (đồng bộ bằng chương trình)a) Sử dụng các biến cờ hiệu: Các tiến trình dùng chung biến lock (khoá cửa) , với ý nghĩa sau: lock=0 là không có tiến trình trong miền găng, lock=1 là có một tiến trình trong miền găng.Biến lock được khởi động là 0. Một tiến trình muốn vào miền găng trước tiên kiểm tra giá trị của biến lock. Nếu lock = 0, tiến trình đặt lại giá trị cho lock = 1 và đi vào miền găng. Nếu lock đang nhận giá trị 1, tiến trình phải chờ bên ngoài miền găng cho đến khi lock có giá trị 0. Cấu trúc chương trình sử dụng biến khóa để đồng bộ có dạng sau:while (TRUE) //tien trinh có thể truy xuất miền găng nhiều lần{while (lock == 1); // waitlock = 1; critical-section ();lock = 0;Noncritical-section ();}Nhận xét:- Giải pháp này có thể vi phạm điều kiện thứ nhất là hai tiến trình có thể cùng ở trong miền găng tại một thời điểm. Giả sử một tiến trình nhận thấy lock = 0 và chuẩn bị vào miền găng, nhưng trước khi nó có thể đặt lại giá trị cho lock là 1, nó bị tạm dừng để một tiến trình khác hoạt động. Tiến trình thứ hai này thấy lock vẫn là 0 thì vào miền găng và đặt lại lock = 1. Sau đó tiến trình thứ nhất được tái kích hoạt, nó gán lock = 1 lần nữa rồi vaò miền găng. Như vậy tại thời điểm đó cả hai tiến trình đều ở trong miền găng.b) Sử dụng biến luân phiên : (dùng cho hai tiến trình)Hai tiến trình A, B sử dụng chung biến turn với ý nghĩa sau: turn = 0, tiến trình A được vào miền găng, turn=1 thì B được vào miền găng.28 Turn được khởi động với giá trị 0. Nếu turn = 0, tiến trình A được vào miền găng. Nếu turn = 1, tiến trình A đi vào một vòng lặp chờ đến khi turn nhận giá trị 0 thì A được vào miền găng. Khi tiến trình A rời khỏi miền găng, nó đặt giá trị turn về 1 để cho phép tiến trình B đi vào miền găng. Cấu trúc tiến trình Awhile (TRUE) {while (turn != 0); // waitcritical-section ();turn = 1;Noncritical-section ();}Cấu trúc tiến trình Bwhile (TRUE) {while (turn != 1); // waitcritical-section ();turn = 0;Noncritical-section ();}Nhận xét:- Hai tiến trình không thể vào miền găng cùng lúc.- Có thể vi phạm điều kiện thứ ba: một tiến trình có thể bị ngăn chặn vào miền găng bởi một tiến trình khác không ở trong miền găng. Giả sử tiến trình A đang ở trong phần Noncritical-section (), thì B không thể vào miền găng hai lần liên tiếp. Như vậy, giải pháp này phụ thuộc vào tốc độ thực hiện của hai tiến trình, nó vi phạm cả điều kiện thứ hai.c) Giải pháp của Peterson: kết hợp hai giải pháp trên. Các tiến trình chia sẻ hai biến chung :int turn; // đến phiên aiint inter [2]; // khởi động là FALSE Khởi đầu, inter [0]=inter [1]=FALSE và giá trị của turn được khởi động là 0 hay 1. Nếu inter [i] = TRUE có nghĩa là tiến trình Pi (i=0,1) muốn vào miền găng. Turn=i là đến lượt PiĐể có thể vào được miền găng, trước tiên tiến trình Pi đặt giá trị inter [i]=TRUE ( xác định rằng tiến trình Pi muốn vào miền găng), sau đó đặt turn=j (đề nghị thử tiến trình Pj vào miền găng). Nếu tiến trình Pj không quan tâm đến việc vào miền găng (inter [j]=FALSE), thì Pi có thể vào miền găng, nếu không, Pi phải chờ đến khi inter [j]=FALSE. Khi tiến trình Pi rời khỏi miền găng, nó đặt lại giá trị cho inter [i]= FALSE. 29 Cấu trúc tiến trình Pi trong giải pháp Petersonwhile (TRUE) {int j = 1- i; // j là tiến trình còn lạiinter [i]= TRUE;turn = j;//iwhile (turn == j && inter [j]==TRUE);critical-section ();inter [i] = FALSE;Noncritical-section ();}Nhận xét:Nếu cả hai tiến trình đều muốn vào miền găng thì inter [i] = inter [j] =TRUE nhưng giá trị của turn chỉ có thể hoặc là 0 hoặc là 1, do vậy chỉ có một tiến trình được vào miền găng. 1.2. Các giải pháp phần cứnga) Cấm ngắt: Tiến trình cấm tất cả các ngắt trước khi vào miền găng, và phục hồi ngắt khi ra khỏi miền găng.Khi đó, ngắt đồng hồ cũng không xảy ra, do vậy hệ thống không thể tạm dừng hoạt động của tiến trình đang xử lý để cấp phát CPU cho tiến trình khác, nhờ đó tiến trình hiện hành yên tâm thao tác trên miền găng mà không sợ bị tiến trình nào khác tranh chấp.Nhận xét:- Cấm tất cả các ngắt là nguy hiểm- Nếu hệ thống có nhiều bộ xử lý, lệnh cấm ngắt chỉ có tác dụng trên bộ xử lý đang xử lý tiến trình, còn các tiến trình hoạt động trên các bộ xử lý khác vẫn có thể truy xuất đến miền găng.b) Chỉ thị TSL (Test-and-Set): Giải pháp cần sự trợ giúp của phần cứng. Nhiều máy tính cung cấp một chỉ thị đặc biệt cho phép kiểm tra và cập nhật nội dung một vùng nhớ trong một thao tác không thể phân chia, gọi là chỉ thị Test-and-Set Lock (TSL) và được định nghĩa như sau:Test-and-Setlock(boolean target){Test-and-Setlock = target;target = TRUE;}Nếu có hai chỉ thị TSL xử lý đồng thời (trên hai bộ xử lý khác nhau), chúng sẽ được xử lý tuần tự . Có thể cài đặt giải pháp truy xuất độc quyền với TSL bằng cách sử dụng thêm một biến lock, được khởi gán là FALSE. Tiến trình phải kiểm tra giá trị của biến lock trước khi vào miền găng, nếu lock = FALSE, tiến trình có thể vào miền găng. 30 Cấu trúc một chương trình trong giải pháp TSL while (TRUE) {while (Test-and-Setlock(lock));critical-section ();lock = FALSE;Noncritical-section (); } Các giải pháp trên đây đều phải thực hiện một vòng lặp để kiểm tra xem có được vào miền găng hay không nên tiến trình đang chờ vẫn chiếm dụng CPU. Do đó cần tránh các giải pháp « busy waiting » nếu có thể. 2. Giải pháp « SLEEP and WAKEUP »Khi một tiến trình chưa đủ điều kiện vào miền găng, nó gọi SLEEP để tự khóa (không sử dụng CPU) đến khi có một tiến trình khác gọi WAKEUP để giải phóng cho nó. Một tiến trình gọi WAKEUP khi ra khỏi miền găng để đánh thức một tiến trình đang chờ, tạo cơ hội cho tiến trình này vào miền găng :Cấu trúc chương trình trong giải pháp SLEEP and WAKEUPint busy; // 1 nếu miền găng đang bị chiếm, nếu không là 0 int blocked; // đếm số lượng tiến trình đang bị khóawhile (TRUE){if (busy){ blocked = blocked + 1; sleep();}else busy = 1;critical-section ();busy = 0;if(blocked){ wakeup(process); blocked = blocked - 1;}Noncritical-section ();}Nhận xét:- Có thể vi phạm điều kiện thứ nhất: Có thể có hai tiến trình cùng trong miền găng cùng lúc.Giả sử tt A kiểm tra biến busy, thấy busy=0, nhưng chưa kịp gán busy=1 thì đến lượt tt B. B thấy busy=0, B gán busy=1 và vào miền găng. Trong khi B chưa ra khỏi miền găng thì đến lượt A, A gán busy=1 và vào miền găng!31 - Có thể vi phạm điều kiện thứ ba: một tiến trình có thể bị ngăn chặn vào miền găng bởi một tiến trình khác không ở trong miền găngGiả sử tiến trình A vào miền găng, và trước khi nó rời khỏi miền găng thì tiến trình B được kích hoạt. Tiến trình B thử vào miền găng nhưng nó nhận thấy A đang ở trong đó, do vậy B tăng giá trị biến blocked và chuẩn bị gọi SLEEP để tự khoá. Tuy nhiên trước khi B có thể thực hiện SLEEP, tiến trình A lại được tái kích hoạt và ra khỏi miền găng. Khi ra khỏi miền găng A nhận thấy có một tiến trình đang chờ (blocked=1) nên gọi WAKEUP và giảm giá trị của blocked. Khi đó tín hiệu WAKEUP sẽ lạc mất do tiến trình B chưa thật sự « ngủ » để nhận tín hiệu đánh thức !Khi tiến trình B được tiếp tục xử lý, nó mới goi SLEEP và tự ngủ vĩnh viễn ! Lỗi này xảy ra do việc kiểm tra biến busy và việc gọi SLEEP là những hành động tách biệt, có thể bị ngắt nửa chừng trong quá trình xử lý.Để tránh những tình huống tương tự, hệ điều hành cung cấp những cơ chế đồng bộ hóa dựa trên ý tưởng của chiến lược « SLEEP and WAKEUP » nhưng được xây dựng bao hàm cả phương tiện kiểm tra điều kiện vào miền găng giúp sử dụng an toàn.3. SemaphoreĐược Dijkstra đề xuất vào 1965, một semaphore s là một biến có các thuộc tính sau:- Một giá trị nguyên dương e(s)- Một hàng đợi f(s) lưu danh sách các tiến trình đang chờ trên semaphore s - Có hai thao tác được định nghĩa trên semaphore s:Down(s): e(s)=e(s)-1. Nếu e(s) < 0 thì tiến trình phải chờ trong f(s), ngược lại tiến trình tiếp tục. Up(s): e(s)=e(s)+1. Nếu e(s)<=0 thì chọn một tiến trình trong f(s) cho tiếp tục (đánh thức) .Hình: Semaphore sCài đặt down, up: Gọi P là tiến trình thực hiện thao tác Down(s) hay Up(s). Down(s): e(s) = e(s) - 1;if (e(s) < 0) {status(P)= blocked; //chuyển P sang trạng thái bị khoá (chờ)enter(P,f(s)); //cho P vào danh sách chờ f(s)}32 Up(s): e(s) = e(s) + 1;if (e(s)<= 0 ){exit(Q,f(s)); //lấy một tt Q ra khỏi f(s)status (Q) = ready; //chuyển Q sang trạng thái sẵn sàngenter(Q,ready-list); //cho Q vào danh sách sẵn sàng} Nhận xét:- Hệ điều hành cần cài đặt các thao tác Down, Up là độc quyền.- |e(s)| = số tiến trình đang chờ trong f(s).- Có thể dùng semaphore để giải quyết bài toán miền găng hay đồng bộ giữa các tiến trình.* Giải quyết bài toán miền găng bằng Semaphores:Dùng một semaphore s, e(s) được khởi gán là 1. Tất cả các tiến trình áp dụng cùng cấu trúc chương trình sau:while (TRUE) {Down(s);critical-section ();Up(s);Noncritical-section ();}* Giải quyết bài toán đồng bộ bằng Semaphores: Ví dụ: Giả sử P1 làm job1, P2 làm job2 và muốn job1 làm trước rồi mới làm job2, ta có thể cho hai tiến trình dùng chung một semaphore s, khởi gán e(s) là 0 và hai tiến trình có cấu trúc như sau:P1:while (TRUE) { job1();Up(s); //đánh thức P2}P2:while (TRUE) {Down(s); // chờ P1 đánh thứcjob2();} 33 [...]... hai lệnh Wait và Signal: Wait(c): chuyển trạng thái tiến trình gọi sang chờ (blocked) , và đặt tiến trình này vào hàng đợi trên biến điều kiện c Signal(c): nếu có một tiến trình đang chờ trong hàng đợi của c, tái kích hoạt tiến trình đó, và tiến trình gọi sẽ rời khỏi monitor Hình : Cấu trúc một Monitor Wait(c) : status(P)= blocked; //chuyển P sang trạng thái chờ enter(P,f(c)); //đặt P vào hàng đợi f(c)... truy xuất từ tiến trình kiểm soát tài nguyên.Khi sử dụng xong tài nguyên , tiến trình gởi một thông điệp khác đến tiến trình kiểm soát để báo kết thúc truy xuất Tiến trình kiểm soát , khi nhận được thông điệp yêu cầu tài nguyên, nó sẽ chờ đến khi tài nguyên sẵn sàng để cấp phát thì gởi một thông điệp đến tiến trình đang bị khóa trên tài nguyên đó để đánh thức tiến trình này Cấu trúc tiến trình yêu cầu... semaphore và monitor có thể giải quyết được vấn đề truy xuất độc quyền trên các máy tính có một hoặc nhiều bộ xử lý chia sẻ một vùng nhớ chung Nhưng không thuận lợi trong các hệ thống phân tán, khi mà mỗi bộ xử lý sỡ hữu một bộ nhớ riêng biệt và liên lạc thông qua mạng Trong những hệ thống phân tán, cơ chế trao đổi thông điệp sẽ đơn giản hơn và được dùng để giải quyết bài toán đồng bộ hóa Bài tập Bài 1... vượt quá 20 Cần sửa chữa đoạn chương trình trên như thế nào để bảo đảm X không vượt quá 20 ? Bài 6.Xét hai tiến trình xử lý đoạn chương trình sau : process P1 { A1 ; A2 } process P2 { B1 ; B2 } Đồng bộ hoá hoạt động của hai tiến trình này sao cho cả A1 và B1 đều hoàn tất trước khi A2 hay B2 bắt đầu 38 Bài 7.Tổng quát hoá bai 6: cho các tiến trình xử lý đoạn chương trình sau : process P1 { for ( i =... thinking; } } Cấu trúc tiến trình Pi thực hiện viec ăn của triết gia thứ i while (TRUE) { Noncritical-section (); dp.pickup(i); eat(); dp.putdown(i); Noncritical-section (); } 5 Trao đổi thông điệp Có một tiến trình kiểm soát việc sử dụng tài nguyên và nhiều tiến trình khác yêu cầu tài nguyên này 36 Tiến trình có yêu cầu tài nguyên sẽ gởi một thông điệp đến tiến trình kiểm soát và sau đó chuyển sang... 100; j ++) Bj } Đồng bộ hoá hoạt động của hai tiến trình này sao cho cả với k bất kỳ ( 2 . BÀI 3LIÊN LẠC & ĐỒNG BỘ TIẾN TRÌNH I. LIÊN LẠC GIỮA CÁC TIẾN TRÌNH 1. Nhu cầu liên lạc giữa các tiến trình- Chia sẻ thông tin-. một tiến trình (Tiến trình truy xuất đến một địa chỉ bất hợp lệ). - Một tiến trình gởi đến một tiến trình khác ( ví dụ tiến trình cha yêu cầu một tiến trình