Android 12 hỗ trợ truyền qua FUSE, giúp giảm thiểu chi phí FUSE để đạt được hiệu suất tương đương với quyền truy cập trực tiếp vào hệ thống tệp cấp thấp. Tính năng truyền qua FUSE được hỗ trợ trong các nhân android12-5.4
, android12-5.10
và android-mainline
(chỉ để kiểm thử). Điều này có nghĩa là khả năng hỗ trợ tính năng này phụ thuộc vào nhân mà thiết bị sử dụng và phiên bản Android mà thiết bị đang chạy:
Các thiết bị nâng cấp từ Android 11 lên Android 12 không thể hỗ trợ tính năng truyền qua FUSE vì nhân của các thiết bị này bị đóng băng và không thể chuyển sang một nhân đã được nâng cấp chính thức bằng các thay đổi truyền qua FUSE.
Các thiết bị chạy Android 12 có thể hỗ trợ FUSE passthrough khi sử dụng một nhân chính thức. Đối với những thiết bị như vậy, mã khung Android triển khai tính năng truyền qua FUSE được nhúng trong mô-đun đường chính MediaProvider. Mô-đun này sẽ tự động nâng cấp. Những thiết bị không triển khai MediaProvider dưới dạng một mô-đun chính (ví dụ: thiết bị Android Go) cũng có thể truy cập vào các thay đổi của MediaProvider vì những thay đổi này được chia sẻ công khai.
FUSE so với SDCardFS
Hệ thống tệp trong không gian người dùng (FUSE) là một cơ chế cho phép hạt nhân (trình điều khiển FUSE) thuê ngoài các thao tác được thực hiện trên hệ thống tệp FUSE cho một chương trình không gian người dùng (trình nền FUSE) triển khai các thao tác. Android 11 không dùng SDCardFS nữa và đặt FUSE làm giải pháp mặc định cho hoạt động mô phỏng bộ nhớ. Trong quá trình thay đổi này, Android đã triển khai trình nền FUSE riêng để chặn các hoạt động truy cập tệp, thực thi các tính năng bảo mật và quyền riêng tư bổ sung, đồng thời thao tác với các tệp trong thời gian chạy.
Mặc dù FUSE hoạt động hiệu quả khi xử lý thông tin có thể lưu vào bộ nhớ đệm, chẳng hạn như các trang hoặc thuộc tính, nhưng FUSE lại làm giảm hiệu suất khi truy cập vào bộ nhớ ngoài, đặc biệt là trên các thiết bị tầm trung và cấp thấp. Những hồi quy này là do một chuỗi các thành phần hợp tác trong quá trình triển khai hệ thống tệp FUSE, cũng như nhiều công tắc từ không gian kernel sang không gian người dùng trong quá trình giao tiếp giữa trình điều khiển FUSE và trình nền FUSE (so với quyền truy cập trực tiếp vào hệ thống tệp thấp hơn, gọn gàng hơn và được triển khai hoàn toàn trong kernel).
Để giảm thiểu những trường hợp hồi quy này, các ứng dụng có thể sử dụng tính năng nối để giảm việc sao chép dữ liệu và sử dụng ContentProvider API để truy cập trực tiếp vào các tệp hệ thống tệp cấp thấp. Ngay cả khi có những các hoạt động tối ưu hoá khác này, các hoạt động đọc và ghi có thể bị giảm băng thông khi sử dụng FUSE so với quyền truy cập trực tiếp vào hệ thống tệp thấp hơn – đặc biệt là với các hoạt động đọc ngẫu nhiên, trong đó không có hoạt động lưu vào bộ nhớ đệm hoặc đọc trước nào có thể giúp ích. Ngoài ra, những ứng dụng truy cập trực tiếp vào bộ nhớ thông qua đường dẫn /sdcard/
cũ sẽ tiếp tục gặp phải tình trạng giảm hiệu suất đáng kể, đặc biệt là khi thực hiện các thao tác chuyên sâu về IO.
Yêu cầu không gian người dùng SDcardFS
Việc sử dụng SDcardFS có thể tăng tốc quá trình mô phỏng bộ nhớ và kiểm tra quyền của FUSE bằng cách xoá lệnh gọi không gian người dùng khỏi nhân. Các yêu cầu của không gian người dùng tuân theo đường dẫn: Không gian người dùng → VFS → sdcardfs → VFS → ext4 → Bộ nhớ đệm trang/Bộ nhớ.
Hình 1. Yêu cầu không gian người dùng SDcardFS
Yêu cầu không gian người dùng FUSE
Ban đầu, FUSE được dùng để bật tính năng mô phỏng bộ nhớ và cho phép các ứng dụng sử dụng bộ nhớ trong hoặc thẻ SD ngoài một cách minh bạch. Việc sử dụng FUSE sẽ gây ra một số chi phí phát sinh vì mỗi yêu cầu của không gian người dùng đều tuân theo đường dẫn: Không gian người dùng → VFS → Trình điều khiển FUSE → Trình nền FUSE → VFS → ext4 → Bộ nhớ đệm trang/Bộ nhớ.
Hình 2. Yêu cầu không gian người dùng FUSE
Yêu cầu truyền qua FUSE
Hầu hết các quyền truy cập tệp đều được kiểm tra tại thời điểm mở tệp, với các lần kiểm tra quyền bổ sung xảy ra khi đọc và ghi vào tệp đó. Trong một số trường hợp, có thể biết tại thời điểm mở tệp rằng ứng dụng yêu cầu có toàn quyền truy cập vào tệp được yêu cầu, do đó, hệ thống không cần tiếp tục chuyển tiếp yêu cầu đọc và ghi từ trình điều khiển FUSE đến trình nền FUSE (vì việc đó sẽ chỉ di chuyển dữ liệu từ nơi này sang nơi khác).
Với tính năng truyền qua FUSE, trình nền FUSE xử lý một yêu cầu mở có thể thông báo cho trình điều khiển FUSE rằng thao tác này được phép và tất cả các yêu cầu đọc và ghi tiếp theo có thể được chuyển tiếp trực tiếp đến hệ thống tệp cấp thấp hơn. Điều này giúp tránh được chi phí phát sinh khi chờ trình nền FUSE của không gian người dùng trả lời các yêu cầu của trình điều khiển FUSE.
Sau đây là nội dung so sánh các yêu cầu FUSE và FUSE passthrough.
Hình 3. Yêu cầu FUSE so với yêu cầu truyền qua FUSE
Khi một ứng dụng thực hiện quyền truy cập vào hệ thống tệp FUSE, các thao tác sau sẽ xảy ra:
Trình điều khiển FUSE xử lý và đưa yêu cầu vào hàng đợi, sau đó trình bày yêu cầu đó cho trình nền FUSE xử lý hệ thống tệp FUSE đó thông qua một phiên bản kết nối cụ thể trên tệp
/dev/fuse
mà trình nền FUSE không thể đọc.Khi nhận được yêu cầu mở một tệp, trình nền FUSE sẽ quyết định xem có nên cung cấp tính năng truyền qua FUSE cho tệp cụ thể đó hay không. Nếu có sẵn, trình nền sẽ:
Thông báo cho trình điều khiển FUSE về yêu cầu này.
Cho phép truyền qua FUSE cho tệp bằng cách dùng ioctl
FUSE_DEV_IOC_PASSTHROUGH_OPEN
. Thao tác này phải được thực hiện trên chỉ số mô tả tệp của/dev/fuse
đã mở.
ioctl nhận (dưới dạng tham số) một cấu trúc dữ liệu chứa những nội dung sau:
Bộ mô tả tệp của tệp hệ thống tệp cấp thấp là mục tiêu của tính năng truyền qua.
Giá trị nhận dạng duy nhất của yêu cầu FUSE hiện đang được xử lý (phải mở hoặc tạo và mở).
Các trường bổ sung có thể để trống và dành cho các lần triển khai trong tương lai.
Nếu ioctl thành công, trình nền FUSE sẽ hoàn tất yêu cầu mở, trình điều khiển FUSE sẽ xử lý phản hồi của trình nền FUSE và một tham chiếu đến tệp hệ thống tệp thấp hơn sẽ được thêm vào tệp FUSE trong nhân. Khi một ứng dụng yêu cầu thao tác đọc/ghi trên một tệp FUSE, trình điều khiển FUSE sẽ kiểm tra xem có sẵn tham chiếu đến một tệp hệ thống tệp cấp thấp hay không.
Nếu có một tệp tham chiếu, trình điều khiển sẽ tạo một yêu cầu Hệ thống tệp ảo (VFS) mới có cùng các tham số nhắm đến tệp hệ thống tệp thấp hơn.
Nếu không có thông tin tham chiếu, trình điều khiển sẽ chuyển tiếp yêu cầu đến trình nền FUSE.
Các thao tác trên xảy ra đối với thao tác đọc/ghi và đọc-lặp/ghi-lặp trên các tệp chung cũng như thao tác đọc/ghi trên các tệp được ánh xạ vào bộ nhớ. Tính năng truyền qua FUSE cho một tệp nhất định sẽ tồn tại cho đến khi tệp đó bị đóng.
Triển khai tính năng truyền qua FUSE
Để bật tính năng truyền qua FUSE trên các thiết bị chạy Android 12, hãy thêm các dòng sau vào tệp $ANDROID_BUILD_TOP/device/…/device.mk
của thiết bị mục tiêu.
# Use FUSE passthrough
PRODUCT_PRODUCT_PROPERTIES += \
persist.sys.fuse.passthrough.enable=true
Để tắt tính năng truyền qua FUSE, hãy bỏ qua thay đổi cấu hình ở trên hoặc đặt persist.sys.fuse.passthrough.enable
thành false
. Nếu trước đây bạn đã bật tính năng truyền qua FUSE, thì việc tắt tính năng này sẽ ngăn thiết bị sử dụng tính năng truyền qua FUSE nhưng thiết bị vẫn hoạt động.
Để bật/tắt tính năng truyền qua FUSE mà không cần nháy thiết bị, hãy thay đổi thuộc tính hệ thống bằng các lệnh ADB. Sau đây là ví dụ minh hoạ.
adb root
adb shell setprop persist.sys.fuse.passthrough.enable {true,false}
adb reboot
Để được trợ giúp thêm, hãy tham khảo triển khai tham chiếu.
Xác thực tính năng truyền qua FUSE
Để xác thực rằng MediaProvider đang sử dụng tính năng truyền qua FUSE, hãy kiểm tra logcat
để biết thông báo gỡ lỗi. Ví dụ:
adb logcat FuseDaemon:V \*:S
--------- beginning of main
03-02 12:09:57.833 3499 3773 I FuseDaemon: Using FUSE passthrough
03-02 12:09:57.833 3499 3773 I FuseDaemon: Starting fuse...
Mục FuseDaemon: Using FUSE passthrough
trong nhật ký đảm bảo rằng tính năng truyền qua FUSE đang được sử dụng.
CTS Android 12 bao gồm CtsStorageTest
, trong đó có các kiểm thử kích hoạt tính năng chuyển tiếp FUSE. Để chạy kiểm thử theo cách thủ công, hãy dùng atest như minh hoạ bên dưới:
atest CtsStorageTest