Cụ thể, khi một ứng dụng yêu cầu sử dụng một thiết bị,hệ điều hành sẽ gọi đến trình điều khiển của thiết bị tương ứng để thực hiện các thao tác trên thiết bị.Trình điều khiển thiết bị đư
Thiết bị vào ra
Trong hệ điều hành Windows, có nhiều loại thiết bị vào ra (input/output devices) khác nhau được hỗ trợ để cho phép người dùng tương tác với máy tính Sau đây là một số thiết bị vào ra phổ biến trên hệ điều hành Windows Thiết bịzI / Ozcó thể được chia thành hai loại là Block devicesz(thiết bị khối) đây là loại thiết bị mà trình điều khiển giao tiếp bằng cách gửi toàn bộ khối dữ liệu Ví dụ: Ổ đĩa cứng, thiết bị USB Flash, máy ảnh USB và loại thứ 2 là Character devicesz(thiết bị ký tự): Loại thiết bị mà trình điều khiển giao tiếp bằng cách gửi và nhận các ký tự đơn (byte hoặc mã 8 - octa) Ví dụ: các loại card màn hình, card âm thanh hoặc các cổng serial port, parallel TrừzCPUzthì các thiết bị ngoại vi khác thường sẽ có một trình điều khiển đi kèm (CPUzcó kiểu xử lý riêng và thường đi cùng với phần cứng, có bộ nhớ độc lập)
Hình 1: các loại thiết bị vào ra trong Windows.
Thiết bị điều khiển
Mỗi thiết bị điều khiển(TBĐK) có thể điều khiển được 1,2,4, thiết bị ngoại vi(TBNV) Tùy theo số giác cắm có trên TBĐK Nếu giao diện điều khiển chuẩn(ANSI, IEEE, ISO, ) có thể nối tới nhiều thiết bị khác Mỗi TBĐK có các thanh ghi riêng để làm việc với CPU Dùng các không gian địa chỉ đặc biệt cho các thanh ghi: cổng vào ra giao diện TBĐK và TBNV: Giao diện mức rất thấp • Sector = 512bytes = 4096bits
• Bộ điều khiển đĩa phải đọc/ghi các bit và nhóm lại thành các sector• HĐH chỉ làm việc với các TBĐK• Thông qua các thanh ghi điều khiển của thiết bị Các câu lệnh và tham số sẽ được đưa vào các thanh ghi điều khiển Khi 1 lệnh được bộ điều khiển chấp nhận, CPU sẽ để cho bộ điều khiển hoạt động một mình và nó quay sang làm công việc khác Khi lệnh thực hiện xong, bộ điều khiển sẽ báo cho CPU bằng tín hiệu ngắt CPU sẽ lấy KQ và trạng thái thiết bị thông qua các thanh ghi điều khiển
Trình điều khiển thiết bị
Là đoạn mã trong nhân của hệ thống cho phép tương tác trực tiếp với phần cứng thiết bị Trình điều khiển thiết bị (hay còn gọi là Driver) là một phần mềm đặc biệt được viết để cho phép hệ điều hành tương tác với các thiết bị phần cứng như bàn phím, chuột, ổ đĩa cứng, card mạng, card âm thanh, và nhiều loại thiết bị khác.
Các trình điều khiển này được thiết kế để cung cấp một giao diện trung gian giữa phần cứng và hệ điều hành, cho phép hệ điều hành giao tiếp với thiết bị và điều khiển nó một cách hiệu quả Cụ thể, khi một ứng dụng yêu cầu sử dụng một thiết bị, hệ điều hành sẽ gọi đến trình điều khiển của thiết bị tương ứng để thực hiện các thao tác trên thiết bị.
Trình điều khiển thiết bị được viết bằng ngôn ngữ lập trình C hoặc C++, và được tích hợp vào hệ điều hành Windows dưới dạng file thực thi có đuôi sys Các trình điều khiển này thường được cài đặt kèm với hệ điều hành, tuy nhiên, khi cập nhật hệ điều hành hoặc thêm một thiết bị mới, người dùng có thể cần phải cài đặt thêm trình điều khiển cho thiết bị đó.
Trình điều khiển thiết bị cung cấp cho hệ điều hành các hàm API (Application Programming Interface) để truy xuất đến các chức năng của thiết bị, như đọc/ghi dữ liệu, truyền/nhận tín hiệu, cài đặt cấu hình, kiểm tra trạng thái, và các thao tác khác Hơn nữa, các trình điều khiển này còn cung cấp các thông số và tùy chọn cấu hình để người dùng có thể điều chỉnh cách thiết bị hoạt động phù hợp với nhu cầu sử dụng của mình Tóm lại, trình điều khiển thiết bị là một phần quan trọng của hệ thống quản lý vào ra trong hệ điều hành Windows, đóng vai trò quan trọng trong việc đảm bảo tương tác hiệu quả giữa phần cứng và hệ điều hành, từ đó đáp ứng nhu cầu sử dụng của người dùng một cách tốt nhất Cung cấp 1giao diện chuẩn cho các Tbnv khác nhau Các device driver thường được chia làm 2 mức, Mức cao được truy nhập qua các lời gọi hệ thống ,cài đặt tập lời gọi chuẩn như open(), close(), read(), write() Là giao diện của nhân HĐH với trình điều khiển Luồng mức cao khởi động thiết bị thực hiện vào/ra và sau đó đặt luồng điều khiển tạm nghỉ Mức thấp: Được thực hiện như 1 thủ tục ngắt Đọc dữ liệu đầu vào, hoặc đưa khối dữ liệu tiếp theo ra ngoài Đánh thức luồng tạm nghỉ mức trên khi vào/ra kết thúc Để tích hợp với trình quản lý I/O và các thành phần hệ thống I/O khác, trình điều khiển thiết bị phải tuân thủ các nguyên tắc triển khai dành riêng cho loại thiết bị mà nó quản lý và vai trò của nó trong việc quản lý thiết bị Trong phần này, chúng ta sẽ xem xét các loại trình điều khiển thiết bị mà Windows hỗ trợ cũng như cấu trúc bên trong của trình điều khiển thiết bị.
1.3.1 Các loại trình điều khiển thiết bị.
Windows hỗ trợ nhiều loại trình điều khiển thiết bị và môi trường lập trình.zNgay cả trong một loại trình điều khiển thiết bị, môi trường lập trình có thể khác nhau, tùy thuộc vào loại thiết bị cụ thể mà trình điều khiển dành cho.zPhân loại rộng nhất của trình điều khiển là liệu đó là trình điều khiển chế độ người dùng hay chế độ nhân.zWindows hỗ trợ một số loại trình điều khiển chế độ người dùng:
Trình điều khiển máy inzcủa hệ thống con Windowszdịch các yêu cầu đồ họa độc lập với thiết bị thành các lệnh dành riêng cho máy in.zSau đó, các lệnh này thường được chuyển tiếp tới trình điều khiển cổng chế độ nhân chẳng hạn như trình điều khiển cổng máy in bus nối tiếp vạn năng (USB) (Usbprint.sys).
Trình điều khiển Khung Trình điều khiển Chế độ Người dùng (UMDF) là trình điều khiển thiết bị phần cứng chạy ở chế độ người dùng.zChúng giao tiếp với thư viện hỗ trợ UMDF chế độ nhân thông qua ALPC.zXem phần Khung Trình điều khiển Chế độ Người dùng (UMDF) ở phần sau của chương này để biết thêm thông tin.
Trong chương này, trọng tâm là trình điều khiển thiết bị kernel- mode.zCó nhiều loại kernel-mode driver, có thể chia thành các loại cơ bản sau:
Trình điều khiển hệ thống tệpzchấp nhận các yêu cầu I/O đối với các tệp và đáp ứng các yêu cầu bằng cách đưa ra các yêu cầu của riêng chúng, rõ ràng hơn, cho các trình điều khiển thiết bị mạng hoặc bộ nhớ chung.
Trình điều khiển Plug and Playzhoạt động với phần cứng và tích hợp với trình quản lý nguồn và trình quản lý PnP của Windows.zChúng bao gồm trình điều khiển cho thiết bị lưu trữ dung lượng lớn, bộ điều hợp video, thiết bị đầu vào và bộ điều hợp mạng.
Trình điều khiển Non-Plug and Playz, cũng bao gồmzcác phần mở rộng kernelz, là các trình điều khiển hoặc mô-đun mở rộng chức năng của hệ thống.zChúng thường không tích hợp với PnP hoặc trình quản lý năng lượng vì chúng thường không quản lý một phần cứng thực tế.zCác ví dụ bao gồm API mạng và trình điều khiển giao thức.zTrình điều khiển của Process Monitor.
Trong danh mục trình điều khiển chế độ nhân có các phân loại khác dựa trên mô hình trình điều khiển mà trình điều khiển tuân thủ và vai trò của trình điều khiển trong việc phục vụ các yêu cầu thiết bị.
1.3.2 Cấu trúc của một trình điều khiển.
Hệ thống I/O thúc đẩy việc thực thi các trình điều khiển thiết bị.zTrình điều khiển thiết bị bao gồm một tập hợp các thường trình được gọi để xử lý các giai đoạn khác nhau của yêu cầu I/O.zHình 2zminh họa các thói quen chức năng trình điều khiển chính.
Hình 2: Quy trình trình điều khiển thiết bị chính
Quy trình khởi tạo là quá trình mà khi một thiết bị được cắm vào máy tính, hệ thống sẽ xác định loại thiết bị và tải trình điều khiển phù hợp Quá trình này được gọi là Plug and Play (PnP) và nó bao gồm các giai đoạn như tìm kiếm trình điều khiển, tải và cài đặt trình điều khiển
Quy trình bổ sung thiết bị là quá trình mà khi một thiết bị mới được cắm vào máy tính, hệ thống sẽ tạo ra các tài nguyên cho thiết bị đó, bao gồm các địa chỉ bộ nhớ, địa chỉ I/O và IRQ Một tập hợp các quy trình điều phối được sử dụng để quản lý các yêu cầu I/O từ các ứng dụng và chuyển chúng đến các trình điều khiển thiết bị tương ứng Quy trình bắt đầu I/O là quá trình mà khi một ứng dụng yêu cầu thực hiện một hoạt động I/O, hệ thống sẽ khởi tạo một yêu cầu I/O và gửi nó đến trình điều khiển thiết bị tương ứng Một quy trình dịch vụ ngắt (ISR) được sử dụng để xử lý các tín hiệu ngắt từ thiết bị Khi thiết bị cần truyền tải thông tin đến hệ thống, nó sẽ gửi một tín hiệu ngắt đến ISR và ISR sẽ xử lý tín hiệu ngắt này Quy trình DPC phục vụ được sử dụng để xử lý các yêu cầu I/O trong nền, mà không ảnh hưởng đến hiệu suất của hệ thống Một hoặc nhiều quy trình hoàn thành I/O là các quy trình được sử dụng để xử lý các yêu cầu I/O đã được hoàn thành Một quy trình hủy I/O được sử dụng để hủy các yêu cầu I/O đang chờ hoặc đang được thực hiện Các thường trình điều phối nhanh được sử dụng để xử lý các yêu cầu I/O đơn giản và nhanh hóng Các trình điều khiển sử dụng trình quản lý bộ đệm trong Windows để quản lý các bộ đệm I/O Một thói quen dỡ tải được sử dụng để giải phóng bộ nhớ và tài nguyên khi một thiết bị bị gỡ bỏ khỏi hệ thống.
1.3.3 Đối tượng Trình điều khiển và Đối tượng Thiết bị.
Khi một luồng mở một điều khiển cho một đối tượng tệp (được mô tả trong phầnzXử lý I/Ozở phần sau của chương này), trình quản lý I/O phải xác định từ tên của đối tượng tệp trình điều khiển (hoặc các trình điều khiển) nào nó sẽ gọi để xử lý yêu cầu zHơn nữa, trình quản lý I/O phải có khả năng định vị thông tin này vào lần tới khi một luồng sử dụng cùng một tệp xử lý.zCác đối tượng hệ thống sau đáp ứng nhu cầu này:
Chu kỳ một yêu cầu vào ra
Trong hệ điều hành Windows, chu kỳ của một yêu cầu vào/ra (I/O request) bao gồm các bước sau:
Tạo yêu cầu vào/ra (I/O request): Ứng dụng gửi yêu cầu vào/ra tới hệ thống thông qua các API của hệ thống (ví dụ: CreateFile, ReadFile, WriteFile, ).
Xử lý yêu cầu vào/ra bởi trình quản lý I/O (I/O Manager): Khi yêu cầu vào/ra được gửi tới hệ thống, trình quản lý I/O xác định trình điều khiển và thiết bị tương ứng với yêu cầu và chuyển yêu cầu đến trình điều khiển của thiết bị.
Xử lý yêu cầu vào/ra bởi trình điều khiển thiết bị (Device Driver): Trình điều khiển thiết bị xử lý yêu cầu vào/ra bằng cách gửi các yêu cầu tới thiết bị phần cứng hoặc xử lý các yêu cầu bằng phần mềm (ví dụ: đọc dữ liệu từ bộ đệm, ghi dữ liệu vào bộ đệm, ).
Hoàn thành yêu cầu vào/ra (I/O Completion): Sau khi yêu cầu vào/ra được xử lý bởi trình điều khiển thiết bị, nó sẽ thông báo cho trình quản lý I/O (I/O Manager) về kết quả của yêu cầu Sau đó, trình quản lý I/O sẽ thông báo cho ứng dụng về kết quả của yêu cầu vào/ra thông qua các API tương ứng (ví dụ:
Chu kỳ của một yêu cầu vào/ra có thể là đồng bộ hoặc bất đồng bộ Trong yêu cầu đồng bộ, ứng dụng sẽ bị chặn và đợi kết quả của yêu cầu trước khi tiếp tục thực hiện các tác vụ tiếp theo Trong yêu cầu bất đồng bộ, ứng dụng có thể tiếp tục thực hiện các tác vụ khác trong khi đợi kết quả của yêu cầu vào/ra.
H ình 3: chu kỳ một yêu cầu vào ra.
Giao tiếp thiết bị ngoại vi với hệ điều hành
Sau khi hệ điều hành(HDH) gửi yêu cầu ra thiết bị ngoại vi(TBNV), HĐH cần phải biết TBNV hoàn thành yêu cầu vào ra TBNV gặp lỗi Có thể thực hiện theo 2 p/pháp Ngắt và thăm dò.
Ngắt (interrupt): Đây là phương pháp được ưu tiên sử dụng để giao tiếp với các thiết bị ngoại vi Khi một thiết bị ngoại vi cần truyền dữ liệu tới hệ điều hành, nó sẽ tạo ra một ngắt để thông báo cho hệ điều hành biết Hệ điều hành sẽ ngắt tạm thời việc đang thực hiện để xử lý ngắt này Sau khi xử lý xong ngắt, hệ điều hành sẽ trả lại quyền điều khiển cho tiến trình hoặc luồng đang chạy trước đó.
Thăm dò (polling): Phương pháp này sử dụng việc kiểm tra trạng thái của thiết bị ngoại vi liên tục để xem nó có sẵn dữ liệu hay không Khi thiết bị ngoại vi đã sẵn sàng truyền dữ liệu, hệ điều hành sẽ đọc dữ liệu từ thiết bị này Tuy nhiên, phương pháp này không hiệu quả và tốn nhiều tài nguyên hơn so với phương pháp sử dụng ngắt, vì nó yêu cầu hệ điều hành phải kiểm tra trạng thái của thiết bị liên tục mà không biết khi nào thiết bị này sẽ sẵn sàng.
Tuy nhiên, phương pháp sử dụng ngắt không phải lúc nào cũng hiệu quả hơn so với phương pháp thăm dò Nếu thiết bị ngoại vi có tốc độ truyền dữ liệu chậm hoặc ít sử dụng, phương pháp thăm dò có thể hiệu quả hơn do không tốn nhiều tài nguyên của hệ thống Ngoài ra, một số thiết bị ngoại vi không hỗ trợ phương pháp sử dụng ngắt, và do đó phương pháp thăm dò là cách duy nhất để giao tiếp với chúng.
Các thanh ghi thiết bị xuất hiện với CPU dưới dạng các vị trí bộ nhớ tại một địa chỉ vật lý cụ thể.zKhi CPU ghi vào các vị trí này, bộ điều khiển PCI tích hợp nhận ra rằng các truy cập này phải được định tuyến đến thiết bị thích hợp Điều này có nghĩa là một phần bộ nhớ vật lý trên hệ thống được dành riêng cho các tương tác với thiết bị.zChúng tôi gọi đây làzI/O ánh xạ bộ nhớz.zPhần bộ nhớ dành riêng cho các tương tác này được kiểm soát bởizThanh ghi Địa chỉ Cơ sởz(BAR).zCác thanh ghi này được cấu hình trong quá trình khởi động theo giao thức PCI.
Ngoài ra, CPU có thể truy cập các thiết bị thông qua các hướng dẫn đặc biệt.znền tảng x86 chỉ định một số hướng dẫn vào/ra nhất định được sử dụng để truy cập thiết bị.zMỗi lệnh cần chỉ định thiết bị đích - cổng I/O - cũng như một số giá trị sẽ được chuyển đến thiết bị.zMô hình này được gọi làzMô hình Cổng I/Oz Đường dẫn từ thiết bị đến tổ hợp CPU có thể có hai tuyến đường.zCác thiết bị có thể tạo ra các ngắt cho CPU.zCPU có thể thăm dò thiết bị bằng cách đọc các thanh ghi trạng thái của chúng để xác định xem chúng có một số phản hồi/dữ liệu cho CPU hay không Với các ngắt, nhược điểm là các trình xử lý ngắt.zCó các bước thực tế liên quan đến trình xử lý ngắt tiêu tốn chu kỳ CPU.zCó thể có cài đặt/đặt lại mặt nạ ngắt cũng như các tác động gián tiếp khác do ô nhiễm bộ đệm Điều đó đang được nói, các ngắt có thể được kích hoạt bởi thiết bị ngay khi thiết bị có thông tin cho CPU Để thăm dò ý kiến, HĐH có cơ hội chọn thời điểm sẽ thăm dò ý kiến Hệ điều hành có thể chọn thăm dò ý kiến vào những thời điểm ô nhiễm bộ đệm sẽ ở mức thấp nhất Tuy nhiên, chiến lược này có thể gây ra sự chậm trễ trong cách quan sát hoặc xử lý sự kiện, vì việc xử lý diễn ra tại một thời điểm nào đó sau khi sự kiện được thiết bị tạo ra Ngoài ra, quá nhiều cuộc bỏ phiếu có thể giới thiệu chi phí CPU có thể không hợp lý.
2 Ngắt và xử lý ngắt.
Khái niệm ngắt
Trong hệ điều hành Windows, ngắt (interrupt) được sử dụng để quản lý các hoạt động vào/ra (I/O operations) Khi một thiết bị ngoại vi được kết nối với hệ thống, nó có thể yêu cầu các dịch vụ I/O bằng cách gửi các tín hiệu ngắt đến bộ điều khiển thiết bị tương ứng Bộ điều khiển này sẽ sử dụng các tín hiệu ngắt để giao tiếp với hệ thống và yêu cầu các dịch vụ I/O Khi một tín hiệu ngắt được nhận, hệ thống sẽ tạm dừng việc thực hiện các tác vụ hiện tại và chuyển tới xử lý các yêu cầu I/O được yêu cầu bởi thiết bị ngoại vi Hệ thống sử dụng một hệ thống ngắt ưu tiên để xác định độ ưu tiên của các yêu cầu I/O được yêu cầu bởi các thiết bị ngoại vi khác nhau Các yêu cầu I/O của các thiết bị ngoại vi ưu tiên cao hơn sẽ được xử lý trước các yêu cầu I/O của các thiết bị ngoại vi ưu tiên thấp hơn Trong quá trình xử lý yêu cầu I/O, hệ thống sẽ tương tác với bộ điều khiển thiết bị và truy cập dữ liệu trên thiết bị ngoại vi Sau khi các yêu cầu I/O được xử lý hoàn tất, hệ thống sẽ trả lại việc thực hiện các tác vụ hiện tại và tiếp tục thực hiện các tác vụ khác.
Tuy nhiên, cũng có một số hạn chế khi sử dụng ngắt trong việc quản lý I/O, chẳng hạn như tốc độ xử lý chậm hơn so với thực hiện thăm dò (polling) hoặc độ trễ thêm khi xử lý các yêu cầu I/O Ngoài ra, sử dụng ngắt cũng yêu cầu phải có cơ chế đồng bộ hóa để đảm bảo tính nhất quán của dữ liệu truyền tải giữa thiết bị ngoại vi và hệ thống.
Ngắt là hiện tượng dừng đột xuất chương trình để chuyển sang thực hiện chương trình khác ứng với một sự kiện nào đó xảy ra • Ngắt >< chương trình con !?
Xử lý ngắt
Quá trình xử lý ngắt trong hệ điều hành Windows bao gồm các bước sau: Ghi nhận đặc trưng sự kiện gây ngắt vào ô nhớ cố định: Khi một thiết bị ngoại vi gây ra sự kiện cần được xử lý, nó sẽ gửi một tín hiệu ngắt đến bộ điều khiển ngắt của hệ thống Bộ điều khiển ngắt sẽ lưu trữ thông tin về sự kiện gây ngắt vào một ô nhớ cố định Ghi nhận trạng thái của tiến trình bị ngắt: Tiến trình đang thực thi sẽ bị ngắt bởi sự kiện này Trước khi bắt đầu xử lý ngắt, trạng thái của tiến trình đó cần phải được ghi nhận để sau này có thể khôi phục lại trạng thái đó Chuyển địa chỉ của chương trình xử lý ngắt vào thanh ghi con trỏ lệnh: Chương trình xử lý ngắt được gọi để xử lý sự kiện ngắt Để thực hiện điều này, địa chỉ của chương trình xử lý ngắt cần được chuyển vào thanh ghi con trỏ lệnh Sử dụng bảng vector ngắt: Hệ điều hành Windows sử dụng bảng vector ngắt để liên kết các sự kiện ngắt với chương trình xử lý ngắt tương ứng Bảng vector ngắt lưu trữ địa chỉ của các chương trình xử lý ngắt Thực hiện chương trình xử lý ngắt: Chương trình xử lý ngắt được gọi để xử lý sự kiện ngắt Sau khi xử lý sự kiện ngắt, nó sẽ trả lại quyền điều khiển cho tiến trình bị ngắt Khôi phục lại tiến trình bị ngắt: Trạng thái của tiến trình bị ngắt cần được khôi phục lại để nó có thể tiếp tục thực hiện công việc mà nó đang làm trước khi bị ngắt Đó là quy trình xử lý ngắt trong hệ điều hành Windows Nó giúp hệ thống quản lý các sự kiện ngắt và xử lý chúng một cách hiệu quả để đảm bảo tính ổn định và đáng tin cậy của hệ thống.Trình xử lý ngắt xác định nguyên nhân của ngắt, thực hiện xử lý cần thiết, thực hiện khôi phục trạng thái và thực hiện quay lại lệnhzngắtzđể trả lại quyền điều khiển cho CPU.z(Trình xử lý ngắtzsẽ xóazngắt bằng cách bảo dưỡng thiết bị.)
(Lưu ý rằng trạng thái được khôi phục không cần phải giống trạng thái đã được lưu khi ngắt.)
Hình 4 - Chu kỳ I/O điều khiển ngắt.
Mô tả ở trên là đủ cho I/O điều khiển ngắt đơn giản, nhưng có ba nhu cầu trong điện toán hiện đại làm phức tạp bức tranh: Sự cần thiết phải hoãn xử lý ngắt trong quá trình xử lý quan trọng Nhu cầu xác định trình xử lý ngắtznàozsẽ gọi mà không cần phải thăm dò tất cả các thiết bị để xem thiết bị nào cần chú ý và Cần có các ngắt đa cấp để hệ thống có thể phân biệt giữa các ngắt có mức độ ưu tiên cao và thấp để có phản ứng phù hợp Những vấn đề này được xử lý trong kiến trúc máy tính hiện đại với phần cứng bộzđiều khiển ngắtz.
Hầu hết các CPU hiện nay đều có hai dòng yêu cầu ngắt: Một dòng khôngzche đượczđối với các tình trạng lỗi nghiêm trọng và một dòng cózthể che đượczmà CPU có thể tạm thời bỏ qua trong quá trình xử lý quan trọng Cơ chế ngắt chấp nhận mộtzđịa chỉ zthường , là một trong một tập hợp nhỏ các số để bù vào một bảng được gọi làzvectơ ngắt Bảng này (thường nằm ở địa chỉ vật lý 0?) chứa địa chỉ của các thường trình được chuẩn bị để xử lý các ngắt cụ thể Số lượng trình xử lý ngắt có thể có vẫn vượt quá phạm vi số lượng ngắt đã xác định, do đó, nhiều trình xử lýzngắt có thể được xâu chuỗiz.zThực tế, các địa chỉ được giữ trong các vectơ ngắt là các con trỏ đầu cho danh sách liên kết của các trình xử lý ngắt.
Hình 5 cho thấy vector ngắt Intel Pentium.zCác ngắt từ 0 đến 31 là không che được và dành riêng cho các lỗi nghiêm trọng về phần cứng và các lỗi khác.zCác ngắt có thể che dấu, bao gồm các ngắt I/O của thiết bị bình thường bắt đầu ở ngắt 32 Phần cứng ngắt hiện đại cũng hỗ trợz các mức ưu tiên ngắtz, cho phép hệ thống chỉ che dấu các ngắt có mức ưu tiên thấp hơn trong khi phục vụ ngắt có mức ưu tiên cao hoặc ngược lại để cho phép tín hiệu có mức ưu tiên cao làm gián đoạn quá trình xử lý của mức ưu tiên thấp.
Hình 5 - Bảng vector sự kiện bộ xử lý Intel Pentium.
Tại thời điểm khởi động, hệ thống sẽ xác định thiết bị nào có mặt và tải các địa chỉ trình xử lý thích hợp vào bảng ngắt Trong quá trình hoạt động, các thiết bị báo lỗi hoặc hoàn thành các lệnh thông qua các ngắt Các ngoại lệ, chẳng hạn như chia cho 0, truy cập bộ nhớ không hợp lệ hoặc cố gắng truy cập các hướng dẫn chế độ kernel có thể được báo hiệu thông qua các ngắt Việc cắt thời gian và chuyển đổi ngữ cảnh cũng có thể được thực hiện bằng cơ chế ngắt Bộ lập lịch đặt bộ hẹn giờ phần cứng trước khi chuyển quyền kiểm soát sang quy trình người dùng Khi bộ hẹn giờ tăng dòng yêu cầu ngắt, CPU sẽ thực hiện lưu trạng thái và chuyển quyền điều khiển sang bộ xử lý ngắt thích hợp, bộ xử lý này sẽ chạy bộ lập lịch Bộ lập lịch thực hiện khôi phục trạng thái của một quy trìnhz khác ztrước khi đặt lại bộ hẹn giờ và đưa ra lệnh quay lại từ bị gián đoạn Một ví dụ tương tự liên quan đến hệ thống phân trang cho bộ nhớ ảo - Lỗi trang gây ra gián đoạn, do đó đưa ra yêu cầu I/O và chuyển đổi ngữ cảnh như mô tả ở trên, di chuyển quy trình bị gián đoạn vào hàng đợi và chọn một quy trình khác để chạy zKhi yêu cầu I/O đã hoàn thành (tức là khi trang được yêu cầu đã được tải vào bộ nhớ vật lý), thì thiết bị sẽ ngắt và trình xử lý ngắt sẽ chuyển quy trình từ hàng đợi sang hàng đợi sẵn sàng, (hoặc tùy thuộc vào thuật toán lập lịch trình và chính sách, có thể tiếp tục và ngữ cảnh chuyển nó trở lại CPU )
Các cuộc gọi hệ thống được thực hiện thông quazcác ngắt phần mềm , zcòn gọi là bẫy Khi một chương trình ( thư viện ) cần công việc được thực hiện ở chế độ nhân, nó sẽ đặt thông tin lệnh và có thể là địa chỉ dữ liệu trong một số thanh ghi nhất định, sau đó phát sinh một ngắt phần mềm.z(Ví dụ: 21 hex trong DOS.) Hệ thống thực hiện lưu trạng thái và sau đó gọi trình xử lý ngắt thích hợp để xử lý yêu cầu ở chế độ kernel.zCác ngắt phần mềm thường có mức độ ưu tiên thấp, vì chúng không khẩn cấp bằng các thiết bị có không gian đệm hạn chế Các ngắt cũng được sử dụng để kiểm soát các hoạt động của kernel và lên lịch các hoạt động để có hiệu suất tối ưu.zVí dụ: việc hoàn thành thao tác đọc đĩa bao gồmzhaizlần ngắt: Ngắt ưu tiên cao xác nhận hoàn thành thiết bị và đưa ra yêu cầu đĩa tiếp theo để phần cứng không ở trạng thái chờ Ngắt có mức ưu tiên thấp hơn chuyển dữ liệu từ không gian bộ nhớ nhân sang không gian người dùng, sau đó chuyển quy trình từ hàng đợi sang hàng đợi sẵn sàng Hệ điều hành Solaris sử dụng nhân đa luồng và các luồng ưu tiên để gán các luồng khác nhau cho các trình xử lý ngắt khác nhau.zĐiều này cho phép xử lý "đồng thời" nhiều ngắt và đảm bảo rằng các ngắt có mức độ ưu tiên cao sẽ được ưu tiên hơn các ngắt có mức độ ưu tiên thấp và các quy trình của người dùng.
III dịch vụ vào ra của hệ thống
Khái niệm
Vùng đệm (buffer) là một khu vực lưu trữ dữ liệu tạm thời trong bộ nhớ của hệ thống Trong hệ điều hành Windows, vùng đệm thường được sử dụng để lưu trữ các dữ liệu liên quan đến các hoạt động vào/ra, như đọc và ghi tập tin, gửi và nhận dữ liệu qua mạng, và các hoạt động tương tự.
Khi một chương trình muốn thực hiện một hoạt động vào/ra, nó thường sẽ truyền dữ liệu đến vùng đệm và chờ đợi cho hoạt động được thực hiện bởi hệ thống Sau khi hoạt động vào/ra kết thúc, chương trình có thể truy cập các dữ liệu đã được xử lý trong vùng đệm.
Vùng đệm thường được sử dụng để giảm thiểu số lần truy cập trực tiếp vào ổ đĩa hoặc mạng, giảm tải cho hệ thống và tăng tốc độ hoạt động của chương trình Tuy nhiên, việc sử dụng vùng đệm cũng có thể dẫn đến một số vấn đề, chẳng hạn như mất dữ liệu do lỗi xảy ra trong quá trình ghi vào vùng đệm Do đó, việc quản lý vùng đệm được thực hiện cẩn thận là rất quan trọng trong các ứng dụng vào/ra của hệ điều hành Windows.
Bộ đệm của I/O được thực hiện vì (ít nhất) 3 lý do chính:
Sự khác biệt về tốc độ giữa hai thiết bị.z(Xem Hình 6 bên dưới.) Một thiết bị chậm có thể ghi dữ liệu vào bộ đệm và khi bộ đệm đầy, toàn bộ bộ đệm sẽ được gửi đến thiết bị nhanh cùng một lúc.zĐể thiết bị chậm vẫn có chỗ để ghi trong khi quá trình này đang diễn ra, bộ đệm thứ hai được sử dụng và hai bộ đệm thay phiên nhau khi mỗi bộ đệm trở nên đầy.zĐiều này được gọi làz đệm đôi. ( Bộ đệm đôi thường được sử dụng trong đồ họa ( hoạt hình), để một hình ảnh màn hình có thể được tạo trong bộ đệm trong khi bộ đệm
( đã hoàn thành ) khác được hiển thị trên màn hình Điều này ngăn người dùng nhìn thấy bất kỳ hình ảnh màn hình nào chưa hoàn thiện )
Sự khác biệt về kích thước truyền dữ liệu.zBộ đệm được sử dụng đặc biệt trong các hệ thống mạng để chia các thông điệp thành các gói nhỏ hơn để truyền và sau đó để lắp ráp lại ở phía nhận. Để hỗ trợzngữ nghĩa sao chép Ví dụ: khi một ứng dụng đưa ra yêu cầu ghi đĩa, dữ liệu sẽ được sao chép từ vùng bộ nhớ của người dùng vào bộ đệm nhân.zGiờ đây, ứng dụng có thể thay đổi bản sao dữ liệu của chúng, nhưng dữ liệu cuối cùng được ghi ra đĩa là phiên bản của dữ liệu tại thời điểm yêu cầu ghi được thực hiện.
Hình 6 - Tốc độ truyền thiết bị của Sun Enterprise 6000 ( logarit ).
Phân loại
Vùng đệm trong hệ điều hành Windows có thể được phân loại vào các loại sau: Loại 1 gồm Vùng đệm vào là nơi chứa các dữ liệu
FCFS (First-Come, First-Served) là một trong những thuật toán điều phối truy cập đĩa được sử dụng trong hệ điều hành Windows Theo đó, các yêu cầu truy cập đến đĩa được xử lý theo thứ tự đến trước, được gửi đến đĩa trước và được xử lý trước.
Khi một yêu cầu truy cập đến đĩa được gửi đến, hệ điều hành sẽ đưa yêu cầu này vào hàng đợi và xử lý các yêu cầu theo thứ tự của hàng đợi đó Khi một yêu cầu được xử lý xong, yêu cầu tiếp theo trong hàng đợi sẽ được xử lý tiếp theo.
Tuy nhiên, thuật toán FCFS có một số nhược điểm Khi một yêu cầu có thời gian xử lý lâu được đưa vào hàng đợi, các yêu cầu tiếp theo cũng phải chờ đợi đến khi yêu cầu đó được hoàn thành, dẫn đến thời gian chờ đợi dài và làm giảm hiệu quả xử lý yêu cầu trên đĩa Ngoài ra, thuật toán FCFS cũng không sử dụng các kỹ thuật tối ưu hóa khác như prefetching, buffering và caching để tăng tốc độ truy cập đĩa.
Do nhược điểm này, các thuật toán điều phối truy cập đĩa khác như SSTF, SCAN, C-SCAN, LOOK, C-LOOK được phát triển để giải quyết các vấn đề của thuật toán FCFS và cải thiện hiệu suất xử lý truy cập đĩa.
Phương pháp lập lịchzđơn giản nhất là FCFS(first-come,first- served) Thuật toán này rất dể lập trình nhưng không cung cấpzđược một dịch vụ tốt Ví dụ : cần phảizđọc các khối theo thứ tự như sau :
Giả sử hiện tạizđầu đọc đang ở vị trí 53 Như vậyzđầu đọc lần lượtzđi qua các khối 53, 98, 183, 37, 122, 14, 124, 65, và 67 như hình sau :
Số lượng xi lanh do đầu di chuyển:
#include int calculateTotalSeekTime(int *requests, int numRequests, int initialPosition) { int totalSeekTime = 0; int currentPosition = initialPosition; for (int i = 0; i < numRequests; i++) { totalSeekTime += abs(requests[i] - currentPosition); currentPosition = requests[i];
} int main() { int numRequests; int initialPosition; printf("Nhap so luong yeu cau truy cap dia: "); scanf("%d", &numRequests); printf("Nhap vi tri ban dau cua dau doc/ghi: "); scanf("%d", &initialPosition); int *requests = (int *) malloc(numRequests * sizeof(int)); printf("Nhap cac yeu cau truy cap dia:\n"); for (int i = 0; i < numRequests; i++) { printf("Yeu cau thu %d: ", i + 1); scanf("%d", &requests[i]);
} int totalSeekTime = calculateTotalSeekTime(requests, numRequests, initialPosition); printf("Tong do dai chuyen dau doc/ghi: %d\n", totalSeekTime); free(requests); return 0;
2.3 Thuật toán SSTF Định nghĩa SSTF(Shortest Seek Time First)
Dạng đầy đủ của SSTF là Shortest Seek Time First SSTF là một thuật toán lập lịch lưu trữ thứ cấp xác định chuyển động của đầu và cánh tay của đĩa trong việc phục vụ các yêu cầu đọc và ghi SSTF hoạt động như một thuật toán lập lịch đĩa và nó là một cải tiến dựa trên thuật toánzFCFS.
Nó làm giảm tổng thời gian tìm kiếm so với FCFS.
Thuật toán lập lịch trên disk SSTF (Shortest Seek Time First) hoạt động dựa trên việc lựa chọn truy cập đến các vị trí trên đĩa cứng sao cho thời gian di chuyển đầu đọc/ghi từ vị trí hiện tại đến vị trí cần truy cập là ngắn nhất.
Cách hoạt động của thuật toán SSTF như sau:
Bước 1: Đầu tiên, thiết lập vị trí hiện tại là vị trí ban đầu của đầu đọc/ghi.
Bước 2: Tìm và chọn vị trí trên đĩa gần nhất với vị trí hiện tại Điều này được thực hiện bằng cách so sánh khoảng cách giữa các vị trí trên đĩa và vị trí hiện tại, và chọn vị trí có khoảng cách ngắn nhất.
Bước 3: Di chuyển đầu đọc/ghi đến vị trí đã chọn ở bước trước.
Bước 4: Lặp lại từ bước 2 đến khi tất cả các vị trí trên đĩa được truy cập.
Trong quá trình thực hiện, thuật toán SSTF tối ưu hóa việc di chuyển đầu đọc/ghi trên đĩa bằng cách chọn các vị trí gần nhất trước, giúp giảm thiểu thời gian di chuyển và tăng hiệu suất truy xuất dữ liệu.
Tuy nhiên, cũng cần lưu ý rằng thuật toán SSTF có thể gặp phải vấn đề “cạnh tranh” (starvation) khi các yêu cầu truy cập tới các vị trí cách xa vị trí hiện tại Trong trường hợp này, các yêu cầu gần vị trí hiện tại sẽ được ưu tiên, gây ra việc các yêu cầu cách xa có thể bị lờ đi hoặc chờ đợi lâu hơn Điều này có thể gây ra sự bất công trong việc phục vụ các yêu cầu và làm tăng thời gian truy cập.
Tóm lại, thuật toán lập lịch trên disk SSTF là một phương pháp quản lý việc truy cập dữ liệu trên đĩa cứng dựa trên nguyên tắc chọn vị trí gần nhất trước Mặc dù mang lại hiệu suất tốt trong việc giảm thiểu thời gian di chuyển, thuật toán cũng có nhược điểm về vấn đề cạnh tranh khi các yêu cầu cách xa vị trí hiện tại. Đặc điểm của SSTF là thuật toán chọn các yêu cầu có thời gian tìm kiếm tối thiểu – từ vị trí người đứng đầu hiện tại Vì thời gian tìm kiếm tăng lên với tổng số cylinders mà phần đầu đi qua, thuật toán SSTF chọn yêu cầu đang chờ xử lý gần nhất với vị trí phần đầu hiện tại Thuật toán có vẻ hợp lý Nó phục vụ tất cả các yêu cầu gần với vị trí head hiện tại trước khi nó di chuyển head ra xa để phục vụ các yêu cầu khác Giả định này là cơ sở cho thuật toán SSTF (Shortest Seek Time First) So với FCFS, tổng thời gian tìm kiếm thấp hơn Mục đích của SSTF là cung cấp throughput tăng lên Thuật toán SSTF phục vụ những yêu cầu đòi hỏi số lượng chuyển động đầu ít nhất từ vị trí hiện tại – bất kể hướng Thời gian chờ đợi ít hơn trong SSTF Thời gian phản hồi trung bình thấp do thuật toán SSTF có thể không hoạt động như một thuật toán công bằng đối với chuỗi các yêu cầu của dự án.
Thuật toán này sẽ di chuyển đầu đọc đến các khối cần thiết theo vị trí lần lượt gần với vị trí hiện hành của đầu đọc nhất Ví dụ : cần đọc các khối như sau :
Giả sử hiện tại đầu đọc đang ở vị trí 53 Như vậy đầu đọc lần lượt đi qua các khối
Số lượng xi lanh do đầu di chuyển:
// Hàm tính tong seek time int calculateSeekTime(int *requests, int headPosition, int numRequests) { int seekTime = 0; int currentPosition = headPosition; int i; int *processed = (int *) malloc(numRequests * sizeof(int)); for (i = 0; i < numRequests; i++) { processed[i] = 0;
} for (i = 0; i < numRequests; i++) { int shortestDistance = INT_MAX; int shortestIndex = -1; for (int j = 0; j < numRequests; j++) { if (!processed[j]) { int distance = abs(currentPosition - requests[j]); if (distance < shortestDistance) { shortestDistance = distance; shortestIndex = j;
} processed[shortestIndex] = 1; seekTime += shortestDistance; currentPosition = requests[shortestIndex];
} int main() { int numRequests; int headPosition; printf("Nhap soluong yeu cau truy nhap dia: "); scanf("%d", &numRequests); int *requests = (int *) malloc(numRequests * sizeof(int)); printf("Nhap vi tri ban dau cua dia doc/ghi: "); scanf("%d", &headPosition); printf("Nhap cac yeu cau truy cap dia:\n"); for (int i = 0; i < numRequests; i++) { printf("Nhap yeu cau %d:",i+1); scanf("%d", &requests[i]);
} int seekTime = calculateSeekTime(requests, headPosition, numRequests); printf("Tong thoi gian tim kiem la: %d\n", seekTime); free(requests); return 0;
Trong hệ điều hành Windows, thuật toán SCAN được gọi là
"Elevator Algorithm" Thuật toán này hoạt động tương tự như mô tả ở trên, di chuyển đầu đọc/ghi đĩa từ đầu đến cuối và ngược lại để xử lý các yêu cầu truy cập đến đĩa theo thứ tự đặt hàng.
Thuật toán SSTF
Định nghĩa SSTF(Shortest Seek Time First)
Dạng đầy đủ của SSTF là Shortest Seek Time First SSTF là một thuật toán lập lịch lưu trữ thứ cấp xác định chuyển động của đầu và cánh tay của đĩa trong việc phục vụ các yêu cầu đọc và ghi SSTF hoạt động như một thuật toán lập lịch đĩa và nó là một cải tiến dựa trên thuật toánzFCFS.
Nó làm giảm tổng thời gian tìm kiếm so với FCFS.
Thuật toán lập lịch trên disk SSTF (Shortest Seek Time First) hoạt động dựa trên việc lựa chọn truy cập đến các vị trí trên đĩa cứng sao cho thời gian di chuyển đầu đọc/ghi từ vị trí hiện tại đến vị trí cần truy cập là ngắn nhất.
Cách hoạt động của thuật toán SSTF như sau:
Bước 1: Đầu tiên, thiết lập vị trí hiện tại là vị trí ban đầu của đầu đọc/ghi.
Bước 2: Tìm và chọn vị trí trên đĩa gần nhất với vị trí hiện tại Điều này được thực hiện bằng cách so sánh khoảng cách giữa các vị trí trên đĩa và vị trí hiện tại, và chọn vị trí có khoảng cách ngắn nhất.
Bước 3: Di chuyển đầu đọc/ghi đến vị trí đã chọn ở bước trước.
Bước 4: Lặp lại từ bước 2 đến khi tất cả các vị trí trên đĩa được truy cập.
Trong quá trình thực hiện, thuật toán SSTF tối ưu hóa việc di chuyển đầu đọc/ghi trên đĩa bằng cách chọn các vị trí gần nhất trước, giúp giảm thiểu thời gian di chuyển và tăng hiệu suất truy xuất dữ liệu.
Tuy nhiên, cũng cần lưu ý rằng thuật toán SSTF có thể gặp phải vấn đề “cạnh tranh” (starvation) khi các yêu cầu truy cập tới các vị trí cách xa vị trí hiện tại Trong trường hợp này, các yêu cầu gần vị trí hiện tại sẽ được ưu tiên, gây ra việc các yêu cầu cách xa có thể bị lờ đi hoặc chờ đợi lâu hơn Điều này có thể gây ra sự bất công trong việc phục vụ các yêu cầu và làm tăng thời gian truy cập.
Tóm lại, thuật toán lập lịch trên disk SSTF là một phương pháp quản lý việc truy cập dữ liệu trên đĩa cứng dựa trên nguyên tắc chọn vị trí gần nhất trước Mặc dù mang lại hiệu suất tốt trong việc giảm thiểu thời gian di chuyển, thuật toán cũng có nhược điểm về vấn đề cạnh tranh khi các yêu cầu cách xa vị trí hiện tại. Đặc điểm của SSTF là thuật toán chọn các yêu cầu có thời gian tìm kiếm tối thiểu – từ vị trí người đứng đầu hiện tại Vì thời gian tìm kiếm tăng lên với tổng số cylinders mà phần đầu đi qua, thuật toán SSTF chọn yêu cầu đang chờ xử lý gần nhất với vị trí phần đầu hiện tại Thuật toán có vẻ hợp lý Nó phục vụ tất cả các yêu cầu gần với vị trí head hiện tại trước khi nó di chuyển head ra xa để phục vụ các yêu cầu khác Giả định này là cơ sở cho thuật toán SSTF (Shortest Seek Time First) So với FCFS, tổng thời gian tìm kiếm thấp hơn Mục đích của SSTF là cung cấp throughput tăng lên Thuật toán SSTF phục vụ những yêu cầu đòi hỏi số lượng chuyển động đầu ít nhất từ vị trí hiện tại – bất kể hướng Thời gian chờ đợi ít hơn trong SSTF Thời gian phản hồi trung bình thấp do thuật toán SSTF có thể không hoạt động như một thuật toán công bằng đối với chuỗi các yêu cầu của dự án.
Thuật toán này sẽ di chuyển đầu đọc đến các khối cần thiết theo vị trí lần lượt gần với vị trí hiện hành của đầu đọc nhất Ví dụ : cần đọc các khối như sau :
Giả sử hiện tại đầu đọc đang ở vị trí 53 Như vậy đầu đọc lần lượt đi qua các khối
Số lượng xi lanh do đầu di chuyển:
// Hàm tính tong seek time int calculateSeekTime(int *requests, int headPosition, int numRequests) { int seekTime = 0; int currentPosition = headPosition; int i; int *processed = (int *) malloc(numRequests * sizeof(int)); for (i = 0; i < numRequests; i++) { processed[i] = 0;
} for (i = 0; i < numRequests; i++) { int shortestDistance = INT_MAX; int shortestIndex = -1; for (int j = 0; j < numRequests; j++) { if (!processed[j]) { int distance = abs(currentPosition - requests[j]); if (distance < shortestDistance) { shortestDistance = distance; shortestIndex = j;
} processed[shortestIndex] = 1; seekTime += shortestDistance; currentPosition = requests[shortestIndex];
} int main() { int numRequests; int headPosition; printf("Nhap soluong yeu cau truy nhap dia: "); scanf("%d", &numRequests); int *requests = (int *) malloc(numRequests * sizeof(int)); printf("Nhap vi tri ban dau cua dia doc/ghi: "); scanf("%d", &headPosition); printf("Nhap cac yeu cau truy cap dia:\n"); for (int i = 0; i < numRequests; i++) { printf("Nhap yeu cau %d:",i+1); scanf("%d", &requests[i]);
} int seekTime = calculateSeekTime(requests, headPosition, numRequests); printf("Tong thoi gian tim kiem la: %d\n", seekTime); free(requests); return 0;
Thuật toán SCAN
Trong hệ điều hành Windows, thuật toán SCAN được gọi là
"Elevator Algorithm" Thuật toán này hoạt động tương tự như mô tả ở trên, di chuyển đầu đọc/ghi đĩa từ đầu đến cuối và ngược lại để xử lý các yêu cầu truy cập đến đĩa theo thứ tự đặt hàng.
Tuy nhiên, có một số thay đổi và tùy chỉnh trong thuật toán SCAN của Windows để đáp ứng các yêu cầu cụ thể của hệ thống Ví dụ, Windows cho phép người dùng cấu hình các thông số như chiều dài hàng đợi, độ ưu tiên của các yêu cầu và các thông số khác để tối ưu hóa hiệu suất truy cập đĩa.
Ngoài ra, Windows cũng sử dụng các thuật toán điều phối truy cập đĩa khác như C-SCAN, C-LOOK và nhiều thuật toán khác để đáp ứng các yêu cầu truy cập đĩa khác nhau Mỗi thuật toán có ưu nhược điểm riêng và sẽ được sử dụng phù hợp với tình huống cụ thể trong hệ thống.
Thuật toán SCAN có một số ưu điểm, bao gồm việc tránh được hiện tượng độ trễ bên trái (left skew) hoặc độ trễ bên phải (right skew) và đảm bảo rằng tất cả các yêu cầu truy cập đều được xử lý trong quá trình quét Tuy nhiên, nó cũng có một số hạn chế, chẳng hạn như việc thiết kế phần cứng đọc/ghi phải hỗ trợ chuyển đổi hướng di chuyển và đòi hỏi thời gian di chuyển dài nếu có nhiều yêu cầu truy cập trên các đường chéo khác nhau.
Theo thuật toán này, đầu đọc sẽ di chuyển về một phía của đĩa và từ đó di chuyển qua phía kia Ví dụ : cần đọc các khối như sau :
Giả sử hiện tại đầu đọc đang ở vị trí 53 Như vậy đầu đọc lần lượt đi qua các khối
Số lượng xi lanh do đầu di chuyển
#include void sort(int arr[], int n) { int i, j, temp; for (i = 0; i < n-1; i++) { for (j = 0; j < n-i-1; j++) { if (arr[j] > arr[j+1]) { temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp;
} int findPosition(int arr[], int n, int head) { int i; for (i = 0; i < n; i++) { if (arr[i] > head) { return i;
} void scan(int arr[], int n, int head, int direction) { int distance = 0; int currentPosition = findPosition(arr, n, head); if (direction == 0) { printf("Direction: Left to Right\n"); for (int i = currentPosition; i < n; i++) { printf("Move to %d\n", arr[i]); distance += abs(head - arr[i]); head = arr[i];
} distance += abs(head - (n-1)); head = n-1; printf("Move to %d\n", head); for (int i = currentPosition - 1; i >= 0; i ) { printf("Move to %d\n", arr[i]); distance += abs(head - arr[i]); head = arr[i];
} else { printf("Direction: Right to Left\n"); for (int i = currentPosition - 1; i >= 0; i ) { printf("Move to %d\n", arr[i]); distance += abs(head - arr[i]); head = arr[i];
} distance += abs(head - 0); head = 0; printf("Move to %d\n", head); for (int i = currentPosition; i < n; i++) { printf("Move to %d\n", arr[i]); distance += abs(head - arr[i]); head = arr[i];
} int main() { int requests[] = {98, 183, 37, 122, 14, 124, 65, 67}; int size = sizeof(requests) / sizeof(requests[0]); int head; int direction; printf("Enter the initial position of head: "); scanf("%d", &head); printf("Enter the direction (0 for Left to Right, 1 for Right to Left): "); scanf("%d", &direction); sort(requests, size); scan(requests, size, head, direction); return 0;
Thuật toán C-SCAN
Thuật toán C-SCAN (Circular-SCAN) là một trong các thuật toán điều phối truy cập đĩa được sử dụng trong hệ điều hành Windows
Nó là một biến thể của thuật toán SCAN và giải quyết một số vấn đề của thuật toán SCAN.
Giống như thuật toán SCAN, C-SCAN xử lý các yêu cầu truy cập đến đĩa theo hướng đầu đến cuối hoặc ngược lại trên đường đĩa Tuy nhiên, thay vì quay lại đầu đường đĩa sau khi xử lý hết yêu cầu trên đường đó, C-SCAN sẽ quay trở lại đầu đường đĩa và xử lý các yêu cầu mới từ đầu đường đĩa Điều này giúp giảm thời gian chờ đợi của các yêu cầu trên đường đĩa và tăng tốc độ xử lý truy cập đĩa.
Thuật toán C-SCAN hoạt động như sau:
Chọn một hướng đi ban đầu (thường là hướng từ đầu đến cuối hoặc ngược lại).
Xử lý tất cả các yêu cầu trên đường đĩa theo hướng đã chọn.
Khi đã xử lý hết các yêu cầu trên đường đĩa, đầu đọc sẽ quay trở lại đầu đường đĩa và xử lý các yêu cầu mới từ đầu đường đĩa theo cùng hướng đi ban đầu.
Tiếp tục quá trình xử lý các yêu cầu trên đường đĩa và quay trở lại đầu đường đĩa để xử lý các yêu cầu mới.
Vì thuật toán C-SCAN chỉ xử lý các yêu cầu trên đường đĩa theo một hướng đi duy nhất, nên nó có thể gây ra tình trạng starvation (yêu cầu không được xử lý vì bị đẩy ra ngoài hàng đợi) Để giải quyết vấn đề này, thuật toán C-LOOK (Circular-LOOK) đã được phát triển.
Thuật toán này tương tự như thuật toán SCAN, chỉ khác là khi nó di chuyển đến một đầu nào đó của đĩa, nó sẽ lập tức trở về đầu bắt đầu của đĩa Lấy lại ví dụ trên, khi đó thứ tự truy xuất các khối sẽ là : 53, 65, 67, 98, 122, 124, 183, 199, 0, 14, 37 như hình sau :
Tổng quãng đường đầu đọ di chuyển :
#include void sort(int arr[], int n) { int i, j, temp; for (i = 0; i < n-1; i++) { for (j = 0; j < n-i-1; j++) { if (arr[j] > arr[j+1]) { temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp;
} int findPosition(int arr[], int n, int head) { int i; for (i = 0; i < n; i++) { if (arr[i] > head) { return i;
} int findPosition1(int arr[], int n, int head) { int i; for (i = n-1; i >=0; i ) { if (arr[i] < head) { return i;
} void scan(int arr[], int n, int head, int direction) { int distance = 0; int k=head; int currentPosition = findPosition(arr, n, head); int currentPosition1 = findPosition1(arr, n, head); int count=0; if (direction == 0) { printf("Huong: Tu trai sang phai\n"); for (int i = currentPosition; i < n; i++) { printf("Move to %d\n", arr[i]); count ++; distance += abs(head - arr[i]); head = arr[i];
} if(k>arr[0]){ distance += abs(199-head); head9; printf("Move to %d\n", head); head = 0; distance += 199; printf("Move to %d\n", head); for (int i = 0; i < n-count; i++) { printf("Move to %d\n", arr[i]); distance += abs(head - arr[i]); head = arr[i];
} printf("tong quang duong dau doc/ ghi di la: %d", distance);
} else { printf("tong quang duong dau doc/ ghi di la: %d", distance); }
} else { printf("Huong: Tu phai sang trai\n"); for (int i = currentPosition1; i >= 0; i ) { printf("Move to %d\n", arr[i]); count ++; distance += abs(head - arr[i]); head = arr[i];
} if(k=count; i ) { printf("Move to %d\n", arr[i]); distance += abs(head - arr[i]); head = arr[i];
} printf("tong quang duong dau doc/ghi di la: %d", distance);
} else { printf("tong quang duong dau doc/ghi di la: %d", distance); }
} int main() { int requests[] = {98, 183, 37, 122, 14, 124, 65, 67}; int size = sizeof(requests) / sizeof(requests[0]); int head; int direction; printf("nhap vi tri ban dau cua dau doc/ghi: "); scanf("%d",&head); printf("nhap huong: "); scanf("%d",&direction); sort(requests , size); scan( requests , size, head, direction) ;
Thuật toán LOOK/C-LOOK
Thuật toán LOOK và C-LOOK là các thuật toán lập lịch truy cập đĩa được sử dụng trong hệ điều hành Windows Cả hai thuật toán này đều là các biến thể của thuật toán SCAN.
Thuật toán LOOK: Thuật toán LOOK (còn gọi là Elevator algorithm) là một thuật toán lập lịch truy cập đĩa đơn giản và hiệu quả Các yêu cầu truy cập đến đĩa sẽ được xếp vào một hàng đợi và được thực thi theo thứ tự gần nhất đến vị trí hiện tại của đầu đọc/ghi Tuy nhiên, khi đầu đọc/ghi đến đầu hoặc đuôi của đĩa thì thuật toán sẽ đổi hướng và quay trở lại thực hiện các yêu cầu truy cập nằm trên hướng đi ngược lại Việc đổi hướng này sẽ giúp giảm thiểu thời gian chờ đợi của các yêu cầu truy cập nằm trên đường đi.
Thuật toán C-LOOK: Thuật toán C-LOOK là một biến thể của thuật toán LOOK Tương tự như thuật toán LOOK, các yêu cầu truy cập đến đĩa cũng được xếp vào một hàng đợi và được thực thi theo thứ tự gần nhất đến vị trí hiện tại của đầu đọc/ghi Tuy nhiên, khi đầu đọc/ghi đến đầu hoặc đuôi của đĩa thì thuật toán không đổi hướng và quay trở lại thực hiện các yêu cầu truy cập nằm trên hướng đi ban đầu Điều này có nghĩa là các yêu cầu truy cập nằm trên hướng đi ngược lại sẽ không được thực thi cho đến khi tất cả các yêu cầu trên hướng đi ban đầu được thực thi xong Việc này có thể dẫn đến một số yêu cầu truy cập phải chờ đợi lâu hơn, tuy nhiên nó cũng giúp giảm thiểu thời gian chờ đợi trung bình của các yêu cầu truy cập.
Tóm lại, cả hai thuật toán LOOK và C-LOOK đều sử dụng phương pháp quét đĩa để sắp xếp các yêu cầu truy cập và giúp tối ưu hoá thời gian truy cập đĩa trong hệ điều hành Windows.
Nhận xét rằng cả hai thuật toán lập lịch SCAN và C-SCAN luôn luôn chuyển đầu đọc của đĩa từ đầu này sang đầu kia Nhưng thông thường thì đầu đọc chỉ chuyển đến khối xa nhất ở mỗi hướng chứ không đến cuối Do đó SCAN và C-SCAN được chỉnh theo thực tế và gọi là lập lịch LOOK Như hình sau :
Tỏng quãng đường đầu đọc/ghi di chuyển:
#include void sort(int arr[], int n) { int i, j, temp; for (i = 0; i < n-1; i++) { for (j = 0; j < n-i-1; j++) { if (arr[j] > arr[j+1]) { temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp;
} int findPosition(int arr[], int n, int head) { int i; for (i = 0; i < n; i++) { if (arr[i] > head) { return i;
} int findPosition1(int arr[], int n, int head) { int i; for (i = n-1; i >=0; i ) { if (arr[i] < head) { return i;
} void scan(int arr[], int n, int head, int direction) { int distance = 0; int k=head; int currentPosition = findPosition(arr, n, head); int currentPosition1 = findPosition1(arr, n, head); int count=0; if (direction == 0) { printf("Huong: Tu trai sang phai\n"); for (int i = currentPosition; i < n; i++) { printf("Move to %d\n", arr[i]); count ++; distance += abs(head - arr[i]); head = arr[i];
} if(k>arr[0]){ distance += abs(arr[n-1]-arr[0]); head=arr[0]; for (int i = 0; i < n-count; i++) { printf("Move to %d\n", arr[i]); distance += abs(head - arr[i]); head = arr[i];
} printf("tong quang duong dau doc/ ghi di la: %d", distance);
} else { printf("tong quang duong dau doc/ ghi di la: %d", distance); }
} else { printf("Huong: Tu phai sang trai\n"); for (int i = currentPosition1; i >= 0; i ) { printf("Move to %d\n", arr[i]); count ++; distance += abs(head - arr[i]); head = arr[i];
} if(k=count; i ) { printf("Move to %d\n", arr[i]); distance += abs(head - arr[i]); head = arr[i];
} printf("tong quang duong dau doc/ghi di la: %d", distance);
} else { printf("tong quang duong dau doc/ghi di la: %d", distance); }
} int main() { int requests[] = {98, 183, 37, 122, 14, 124, 65, 67}; int size = sizeof(requests) / sizeof(requests[0]); int head; int direction; printf("nhap vi tri ban dau cua dau doc/ghi: "); scanf("%d",&head); printf("nhap huong: "); scanf("%d",&direction); sort(requests , size); scan( requests , size, head, direction) ;
Vấn đề lựa chọn thuật toán
Việc lựa chọn thuật toán phù hợp là rất quan trọng để đảm bảo tối ưu hiệu năng của hệ thống truy cập đĩa Tuy nhiên, không có một thuật toán nào là tốt nhất cho tất cả các trường hợp Có nhiều yếu tố phải xem xét để lựa chọn thuật toán phù hợp như: loại ổ đĩa, tốc độ truy cập, loại tập tin, hệ điều hành, v.v.
Khi lựa chọn thuật toán điều phối truy cập đĩa, cần xem xét các yêu cầu và tính chất của hệ thống để chọn ra thuật toán phù hợp nhất Một số yêu cầu và tính chất cần xem xét bao gồm:
Thời gian trung bình của một yêu cầu truy cập đĩa: Mục tiêu là giảm thiểu thời gian trung bình để tăng hiệu suất hệ thống Thời gian chờ đợi của các yêu cầu: Mục tiêu là giảm thiểu thời gian chờ đợi để đảm bảo hệ thống hoạt động một cách trơn tru Thời gian đáp ứng: Mục tiêu là đảm bảo các yêu cầu được xử lý một cách nhanh chóng để đáp ứng nhu cầu của người dùng Thông lượng: Mục tiêu là tối đa hóa số lượng yêu cầu xử lý được trong một đơn vị thời gian Tính công bằng: Mục tiêu là đảm bảo rằng các yêu cầu được xử lý theo thứ tự được gửi đến Số lượng yêu cầu truy cập đĩa đang chờ xử lý: Mục tiêu là giảm thiểu số lượng yêu cầu đang chờ xử lý để đảm bảo hệ thống hoạt động một cách hiệu quả Tùy thuộc vào tính chất và yêu cầu của hệ thống, người quản trị có thể lựa chọn thuật toán điều phối truy cập đĩa phù hợp nhất để tối ưu hóa hiệu suất hệ thống.
Các thuật toán định vị và truy cập đĩa như FCFS, SSTF, SCAN, C- SCAN, LOOK và C-LOOK đều có những ưu điểm và hạn chế riêng Dưới đây là một số đánh giá về từng thuật toán để người quản trị hệ thống có thể lựa chọn thuật toán phù hợp nhất: FCFS (First Come First Serve): Thuật toán này đơn giản và dễ hiểu nhất Nó đảm bảo độ ưu tiên cho các yêu cầu được gửi đến trước Tuy nhiên, nó không cân nhắc đến khoảng cách giữa các yêu cầu, dẫn đến thời gian trung bình của truy cập đĩa có thể lớn SSTF (Shortest Seek Time First): Thuật toán này tìm kiếm yêu cầu có khoảng cách ngắn nhất đến vị trí hiện tại của đầu đọc Điều này giúp giảm thiểu thời gian trung bình của truy cập đĩa, đặc biệt là trong những tình huống có nhiều yêu cầu truy cập đến đĩa Tuy nhiên, nó có thể dẫn đến hiện tượng đói đầu (starvation), khi có một số yêu cầu luôn ở phía xa đầu đọc và không bao giờ được thực hiện SCAN và C-SCAN (Elevator Algorithm): Cả SCAN và C-SCAN đều điều hướng đầu đọc từ đầu đến cuối đĩa hoặc ngược lại và giải quyết vấn đề đói đầu của SSTF SCAN sẽ dừng lại ở cả hai đầu đĩa khi đi đến cuối đĩa và chuyển hướng quay lại Trong khi đó, C-SCAN chỉ dừng lại ở đầu đọc và quay lại đầu đọc để bắt đầu lại truy cập Tuy nhiên, hai thuật toán này có thể dẫn đến hiện tượng trễ lớn (long waiting time) cho các yêu cầu ở giữa đường truy cập đĩa LOOK và C-LOOK: Đây là những thuật toán cải tiến của SCAN và C-SCAN Giống như SCAN và C-SCAN, chúng điều hướng đầu đọc từ đầu đến cuối đĩa hoặc ngược lại Tuy nhiên, khi đầu đọc đến cận cảnh với các yêu cầu, chúng không dừng lại mà tiếp tục di chuyển.
Trong hệ điều hành Windows, thuật toán LOOK và C-LOOK thường được ưu tiên sử dụng vì chúng có thể giảm thiểu thời gian trung bình của việc truy cập đĩa Tuy nhiên, nếu hệ thống đang xử lý nhiều yêu cầu cùng lúc, thì thuật toán SSTF có thể cho kết quả tốt hơn Do đó, tùy thuộc vào từng trường hợp cụ thể, người quản trị hệ thống cần lựa chọn thuật toán phù hợp nhất để đạt được hiệu suất tối ưu của hệ thống.