/storage/emulated/0/
thực sự được /data/media/0/
phơi bày thông qua một hệ thống tập tin giả lập / ảo chứ không phải hệ thống thực tế.
Điều này có liên quan đến câu trả lời trước đây của tôi ở đây , nhưng với nhiều chi tiết liên quan hơn.
BẢO QUẢN ANDROID:
Trên Android 5 :
/sdcard >S> /storage/emulated/legacy >S> /mnt/shell/emulated/0
/mnt/shell/emulated >E> /data/media
Trên Android 6+ :
# for (Java) Android apps (running inside zygote virtual machine)
# "/storage to VIEW" bind mount is inside a separate mount namespace for every app
/sdcard >S> /storage/self/primary
/storage/self >B> /mnt/user/USER-ID
/mnt/user/USER-ID/primary >S> /storage/emulated/USER-ID
/storage/emulated >B> /mnt/runtime/VIEW/emulated
/mnt/runtime/VIEW/emulated >E> /data/media
# for services/daemons/processes in root/global namespace (VIEW = default)
/sdcard >S> /storage/self/primary
/storage >B> /mnt/runtime/default
/mnt/runtime/default/self/primary >S> /mnt/user/USER-ID/primary
/mnt/user/USER-ID/primary >S> /storage/emulated/USER-ID
/storage/emulated >B> /mnt/runtime/default/emulated
/mnt/runtime/default/emulated >E> /data/media
* >S>
cho symlink, >E>
cho mô phỏng và >B>
gắn kết
* USER-ID
của người dùng hiện tại trong trường hợp Multiple Users
hoặc Work Profile
, thông thường 0
là của chủ sở hữu thiết bị
* VIEW
là một trong read
(đối với các ứng dụng có sự cho phép.READ_EXTERNAL_STORAGE) hoặc write
(allow.WRITE_EXTERNAL_STORAGE) hoặc default
(cho các tiến trình đang chạy trong root / không gian tên gắn kết toàn cầu tức là bên ngoài hợp tử)
* Có một số khác biệt nhỏ trên các phiên bản Android trước đây nhưng khái niệm mô phỏng vẫn giống nhau kể từ khi được triển khai.
* Để biết thêm một chút chi tiết về triển khai không gian tên gắn kết của Android, hãy xem câu trả lời này .
Nói tóm lại, /sdcard
và /storage/emulated/0
- đại diện cho hệ thống tập tin FAT / vFAT / FAT32 - hướng tới /data/media/0
(hoặc /mnt/expand/[UUID]/media/0
trong trường hợp Lưu trữ thông qua) thông qua FUSE
hoặc sdcardfs
mô phỏng.
Không phải là Android cụ thể nhưng nhìn chung liên quan đến Linux, symlink và mount mount (xem "Tạo mount mount") nằm ngoài phạm vi của câu hỏi này, vì câu hỏi chủ yếu là về phần mô phỏng.
Mô phỏng:
Tại sao thi đua ở đây? Hệ thống tệp được mô phỏng là một lớp trừu tượng trên hệ thống tệp thực tế ( ext4
hoặc f2fs
) phục vụ cơ bản hai mục đích:
- Giữ lại kết nối USB của thiết bị Android với PC (được triển khai thông qua MTP bây giờ một ngày)
- Hạn chế truy cập trái phép các ứng dụng / quy trình vào phương tiện cá nhân của người dùng và dữ liệu của các ứng dụng khác trên thẻ SD.
Đọc Hành trình lưu trữ của Android để biết chi tiết, tóm tắt là:
Các thiết bị Android ban đầu thiếu bộ nhớ trong và dựa vào thẻ SD bên ngoài (về mặt vật lý) thường sử dụng hệ thống tập tin FAT để đảm bảo khả năng tương thích với hầu hết các PC (tham khảo sự thống trị của Microsoft trên thế giới PC).
Khi bộ nhớ trong tăng kích thước, cùng một hệ thống tập tin đã được chuyển sang thẻ SD bên trong (vẫn được gọi là "bên ngoài").
Nhưng việc triển khai FAT / vFAT có hai vấn đề chính được Google giải quyết dần dần:
- Các thiết bị Android được kết nối trực tiếp với PC ( USB Mass Storage ) giống như chúng ta kết nối ổ USB hiện nay. UMS hiển thị thiết bị ở cấp độ khối và ngắt kết nối thẻ SD khỏi khung Android (không gắn kết), do đó làm cho toàn bộ dữ liệu không có sẵn cho các ứng dụng và có thể phá vỡ nhiều chức năng.
- FAT (được yêu thích của Windows trong những ngày phát triển) không bao giờ được thiết kế để thực thi các quyền UNIX (chế độ, uid, gid và các liên kết tương tự , và
ioctls
tương tự FS_IOC_FIEMAP
). Vì vậy, tất cả dữ liệu trên thẻ SD có sẵn cho tất cả các ứng dụng (vì mọi ứng dụng Android là người dùng UNIX / Linux và không có giới hạn), do đó không gây ra sự lo ngại nghiêm trọng về quyền riêng tư và bảo mật.
Cả hai vấn đề này đều được giải quyết thông qua thi đua:
- Lưu trữ thẻ SD thực tế đã được chuyển sang
/data
phân vùng (hoặc phân vùng độc lập / sdcard trên một số thiết bị trước đây) chứa ext4
hệ thống tệp (dần dần được thay thế bởi f2fs
), thực hiện đầy đủ các quyền UNIX.
- Thiết kế này được thực hiện bằng cách sử dụng UMS vì không thể hiển thị toàn bộ
/data
phân vùng cho PC vì 2 lý do nữa: (1)
nó chứa rất nhiều cài đặt và dữ liệu của ứng dụng sẽ được bảo vệ khỏi các ứng dụng khác cũng như người dùng. (2)
Hệ thống tập tin Linux không được Windows hỗ trợ.
Vì vậy, UMS đã được thay thế bằng Giao thức truyền phương tiện, đây là phần mở rộng loại máy khách-máy chủ thành PTP - một giao thức đã được thiết lập. MTP không để lộ thiết bị khối nhưng hoạt động thông qua ngăn xếp phần mềm. Máy chủ MTP chạy trên Android dưới dạng một ứng dụng ( android.process.media
) được đóng hộp hoàn toàn trong khung Android, không có khả năng thực hiện bất kỳ tác vụ leo thang nào.
Bây giờ các ứng dụng (và MTP, cũng là một ứng dụng) tương tác với bộ lưu trữ giả lập /data/media
, đạt được cả hai mục đích cùng một lúc, tức là thực thi kiểm tra quyền bên dưới và trông giống như hệ thống tệp FAT ở bề mặt trên.
Google hiện đang triển khai mô phỏng thông qua sdcardfs để khắc phục những thiếu sót của FUSE ; một chính là chi phí đầu vào / đầu ra tức là để cải thiện tốc độ đọc / ghi.
GIẤY PHÉP LƯU TRỮ NGOẠI THẤT:
Khái niệm về các tệp Công khai và Riêng tư trên bộ nhớ ngoài có thể được trình bày bằng một ví dụ:
Cài đặt ứng dụng Termux.
Tạo thư mục /sdcard/Android/data/com.termux/test_dir
và /sdcard/test_dir
.
Tạo tập tin /sdcard/Android/data/com.termux/test_file
và /sdcard/Android/data/com.termux/test_file
.
Thực hiện các lệnh sau:
* Bạn nên cài đặt WhatsApp hoặc chọn một số thư mục riêng của ứng dụng khác.
Bây giờ Buộc dừng ứng dụng Termux và cấp quyền Lưu trữ . Thực hiện lại các lệnh:
Xem sự khác biệt về quyền của cùng một tệp và thư mục. Điều này dường như không thể đơn giản nếu không có sự mô phỏng trên hệ thống tệp Linux gốc khi có hàng trăm ứng dụng (người dùng) được xử lý đồng thời. Đây là mô phỏng hệ thống tệp cho phép cùng một tệp được hiển thị với ba bộ quyền khác nhau cùng một lúc độc lập với quyền ban đầu của nó trên hệ thống tệp thực tế:
# touch /data/media/0/test_file
# stat -c '%a %u %g %n' /data/media/0/test_file
644 1023 1023 /data/media/0/test_file
# stat -c '%a %u %g %n' /mnt/runtime/*/emulated/0/test_file
660 0 1015 /mnt/runtime/default/emulated/0/test_file
640 0 9997 /mnt/runtime/read/emulated/0/test_file
660 0 9997 /mnt/runtime/write/emulated/0/test_file
Ngoài ra, hãy xem UID của bạn là gì?
Liên quan: