电子产业一站式赋能平台

PCB联盟网

搜索
查看: 37|回复: 0
收起左侧

嵌入式Linux:存储映射I/O

[复制链接]

983

主题

983

帖子

8449

积分

高级会员

Rank: 5Rank: 5

积分
8449
发表于 昨天 08:00 | 显示全部楼层 |阅读模式

civ4xqriemy64047019237.gif

civ4xqriemy64047019237.gif

/ H+ a: b* @# G$ j. V- |# U' l6 r点击上方蓝色字体,关注我们
% {0 g# c  w  W; C) X+ q: P3 a) h5 r: |( ?$ D$ B8 k( x0 K5 t
通过这种方式,数据可以直接通过内存访问,而无需通过系统调用来传递数据,从而提升了文件操作效率。接下来,我们深入探讨其工作原理、关键函数以及其在不同应用场景中的优势和劣势。: ]0 u5 k1 s0 p9 l$ q

  u( w0 d$ U% d  o, ]& |存储映射 I/O 基于内存区域的概念,文件的内容被映射到内存后,应用程序可以像访问普通内存一样直接访问文件内容。读写文件的操作可以通过对内存的读取和写入来实现,省去了使用 read() 和 write() 函数在内核空间和用户空间之间来回传输数据的开销。
$ M9 z0 g" {& t- v1 o
- v" k6 D6 [$ X关键特点  d) B0 R  W# s  T$ k: H
  • 直接内存操作:读取文件内容只需访问内存,写入文件则只需将数据写入内存。
  • 减少系统调用开销:无需频繁调用 read() 和 write() 系统调用,减少了 I/O 的复杂度。
  • 提高大文件操作效率:适用于需要频繁或大量数据交互的场景。% n% `! q& H% N6 P' Z
    1
    % ?) d- T" z! w/ l# P& wmmap() 和 munmap() 函数# s& T: m/ S' Z- }& e' m' h
    存储映射 I/O 的核心函数是 mmap(),用于将文件映射到进程地址空间中,并使用 munmap() 解除该映射。' @" l) t, f' @7 t$ l. f

    " u) p0 C# `1 a; v# \0 y' xmmap() 函数原型如下:
    / j: v" W( R9 }! i' [
    7 D+ Y: ?  ^; z. Y' t8 b9 a/ P: |
  • void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);参数详解' I" c0 O2 D* N6 t1 P4 |
  • addr:指定映射的起始地址。通常设置为 NULL,表示由系统选择起始地址。
  • length:映射长度(字节数),决定文件映射的大小区域。
  • offset:文件偏移量,通常为 0,表示从文件头开始映射。
  • fd:文件描述符,指示要映射的文件。
  • prot:映射区的保护权限,可设置为:       
    2 l) C+ l7 I+ E. i
  • PROT_EXEC:可执行;
  • PROT_READ:可读;
  • PROT_WRITE:可写;
  • PROT_NONE:不可访问。
      T+ |4 g1 `0 B! X9 S, v
  • flags:映射区的属性标志。常见设置有:       
    ! T5 Y5 y; g9 ^4 n
  • MAP_SHARED:共享映射区的更改会写入文件中,可供其他进程共享。
  • MAP_PRIVATE:私有映射,写入数据仅对当前进程可见,不会影响文件本身。
    8 _5 L1 D- @0 Q) ~* u: h; `
    $ ^3 R, E' R! q7 J# J
    返回值:成功时返回映射区的起始地址;失败时返回 -1,通常使用 MAP_FAILED 表示,并设置 errno。5 K9 ?; L" k- b7 ?- Y

    " h$ P. P2 ]3 u9 c* h7 \注意事项:addr 和 offset 通常需为系统页大小的整数倍。可以使用 sysconf(_SC_PAGE_SIZE) 获取系统页大小。# _0 ~2 D6 ?* x8 H
    munmap() 函数原型如下:
    . A6 A+ c9 {3 H( @3 |( X1 g/ Y
    ; D1 r: e+ O9 e. j5 N
  • int munmap(void *addr, size_t length);参数详解* t9 j* \; P" |* d* [2 P1 e0 ^
  • addr:映射的起始地址。
  • length:解除映射的长度,需为页大小的整数倍。  b' A+ F: E1 f9 h: m; v/ X
    + Z8 k$ F  L) F6 ^+ Q0 `
    8 ~. Z# q: Y( t) \/ J$ p" q/ p2 @
    返回值:成功时返回 0;失败时返回 -1,并设置 errno。, z( j2 H8 c. O1 `4 P# J& r/ V
    2
    7 h/ _% @2 n0 U0 X; |其他相关函数
    ( j# T: S- r/ r& D* Y9 d3 G在使用 mmap() 映射文件时,还可以通过以下系统调用对映射区进行管理。$ w3 o' K1 d# z

    $ d) U# }6 K# ]/ I$ Pmprotect() 用于更改映射区的保护属性,函数原型如下:
    & F( N( w2 m1 q5 ?3 H; ]
    + S. T1 d+ ]2 o
  • int mprotect(void *addr, size_t len, int prot);
    ( o- J0 |7 Y- \( t9 D7 {5 b. P- ?
    + U0 G+ J4 m" h9 C5 v: _
    参数
    8 v9 z# f3 Q7 A3 ^/ v
  • addr 和 len 定义了需要更改保护属性的地址范围。
  • prot 为新的保护属性(与 mmap() 的 prot 参数相同)。
    0 P4 w4 N; S- h3 ]; l

    0 _. Q% s/ r0 R+ y  l/ }! s. {0 G5 Pmsync() 确保映射区的数据同步到磁盘文件中,类似于 fsync(),以确保数据一致性。函数原型如下:
    ) Z! ^, \6 a; g' c
    # x8 i; S, x( o2 B$ X( Z" r( D
  • int msync(void *addr, size_t length, int flags);参数
    * V* X& v7 a. j$ ]3 \# e( b
  • addr 和 length:指定需同步的内存区域。
  • flags:       
    6 N* n/ I; s4 g0 f
  • MS_ASYNC:异步同步。
  • MS_SYNC:同步方式。* d6 p1 [  Y8 ^! [4 g! x
  • MS_INVALIDATE:请求使同一文件的其他映射无效,以便用新值更新。/ B5 y( ?+ i, A$ p, r7 C3 _
    3
    & j/ y  R8 u' H9 t4 P' P! |8 s  G信号与异常处理
    ( F. a4 j& n$ S" `' N+ b& [  v存储映射 I/O 的使用过程中可能引发的信号主要包括 SIGSEGV 和 SIGBUS。4 M' @0 S/ `# w, N! r+ J6 |! l5 s
  • SIGSEGV:当映射区被设为只读,而进程尝试写入该映射区时触发。
  • SIGBUS:当映射区的某一部分已不存在时触发,如文件被截断导致映射区域超出文件范围。" ], N- U* d  P( t" H# M" N
    4
    # U+ P7 K. b/ c1 L7 v存储映射 I/O 和普通 I/O 的对比/ g% J" S! o7 _, W- Q) T7 V* W

    krdjtxmhlqp64047019338.png

    krdjtxmhlqp64047019338.png

    9 w6 Y8 g/ A' W: o& Q% p. m

    utn1ye04d3z64047019438.png

    utn1ye04d3z64047019438.png
    ( t) @& y5 I" w0 ]( t. W$ \' c
    ; G' j8 \# P2 q0 R+ c

    gek4y2gfsxz64047019538.png

    gek4y2gfsxz64047019538.png
    # z& N& R. v; g8 b
    5# H) E! O& Y" z+ `, y
    应用场景和限制/ X+ h( R& r# g7 p
    优势应用场景:- R3 ?" q; r. w& {3 ?; R
  • 大数据处理:适合用于频繁访问大文件或连续数据的场景,如视频编辑和图像处理。
  • 共享内存:mmap() 类似于进程间共享内存,可以用于实现进程间的高效数据共享。
    ; Q: @. H/ l& ~/ A) @/ k0 w限制:' C2 j: ^! `5 c8 K8 n# ^
  • 文件大小限制:文件的映射区域固定,无法超过文件实际大小。
  • 页大小约束:映射区域的起始地址、偏移量和长度通常需为页大小的整数倍。
  • 数据一致性:需注意文件的写入同步,如需保证数据实时更新,可使用 msync()。- u  w3 j/ H( u4 B% P! A/ e
    Linux 存储映射 I/O 是一种高效的 I/O 方式,特别适用于大数据场景。
    3 W6 G7 W( |5 o2 ?8 \2 w4 O9 }' R# G8 k9 F+ Y
    在应用场景中,它通过将文件直接映射到进程的虚拟内存中,显著降低了 I/O 操作的延迟和系统调用的频率,使得高效的数据共享和文件访问成为可能。
    $ |  i& L& @4 ^" ]- o9 [
    - M1 \1 E* g. r* j( Q: ~! Z然而,受限于文件大小、页大小对齐以及数据同步等条件,开发者需在使用时根据应用场景合理选择存储映射 I/O 或普通 I/O。
    ' }! i) |2 L/ h: \% i4 u/ v

    wfkxpk0rnfw64047019638.jpg

    wfkxpk0rnfw64047019638.jpg
    & _7 U5 D# b$ `" d/ S

    a5xn3d2p5jy64047019738.gif

    a5xn3d2p5jy64047019738.gif

    7 [. S$ Z3 K2 C点击阅读原文,更精彩~
  • 回复

    使用道具 举报

    发表回复

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则


    联系客服 关注微信 下载APP 返回顶部 返回列表