Linux系统调用mmap

embedded/2024/11/15 8:23:38/

0 前言

    《Linux系统调用》整体介绍了系统调用,本文重点分析其中mmap的实现与使用方法。

1 定义

1.1 x86

(1)linux-2.6.31-

    采用老式定义方法:

asmlinkage long sys_mmap(unsigned long addr, unsigned long len,unsigned long prot, unsigned long flags,unsigned long fd, unsigned long off)
{long error;struct file *file;error = -EINVAL;if (off & ~PAGE_MASK)goto out;error = -EBADF;file = NULL;flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);if (!(flags & MAP_ANONYMOUS)) {file = fget(fd);if (!file)goto out;}   down_write(&current->mm->mmap_sem);error = do_mmap_pgoff(file, addr, len, prot, flags, off >> PAGE_SHIFT);up_write(&current->mm->mmap_sem);if (file)fput(file);
out:return error;
}
// @file: linux-2.6.31/arch/x86/kernel/sys_x86_64.c

(2) linux-2.6.32

    改用SYSCALL_DEFINE6宏进行定义:

SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,unsigned long, prot, unsigned long, flags,unsigned long, fd, unsigned long, off)
{long error;struct file *file;error = -EINVAL;if (off & ~PAGE_MASK)goto out;error = -EBADF;file = NULL;flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);if (!(flags & MAP_ANONYMOUS)) {file = fget(fd);if (!file)goto out;}down_write(&current->mm->mmap_sem);error = do_mmap_pgoff(file, addr, len, prot, flags, off >> PAGE_SHIFT);up_write(&current->mm->mmap_sem);if (file)fput(file);
out:return error;
}
// @file: linux-2.6.32/arch/x86/kernel/sys_x86_64.c

(3)linux-2.6.33 ~ 4.16

    linux-2.6.33新增sys_mmap_pgoff()并将主要移致其中:

SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,unsigned long, prot, unsigned long, flags,unsigned long, fd, unsigned long, off)
{long error;error = -EINVAL;if (off & ~PAGE_MASK)goto out;error = sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
out:return error;
}
// @file: linux-2.6.33/arch/x86/kernel/sys_x86_64.c

(4)linux-4.17+

    sys_mmap_pgoff更名为ksys_mmap_pgoff:

SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,unsigned long, prot, unsigned long, flags,unsigned long, fd, unsigned long, off)
{long error;error = -EINVAL;if (off & ~PAGE_MASK)goto out;error = ksys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
out:return error;
}
// @file: linux-4.17/arch/x86/kernel/sys_x86_64.c

1.2 arm

    旧内核采用汇编定义,后面逐渐改用C定义:

(1)linux-2.6.12 ~ 2.6.32

/** Note: off_4k (r5) is always units of 4K.  If we can't do the requested* offset, we return EINVAL.*/
sys_mmap2:
#if PAGE_SHIFT > 12tst r5, #PGOFF_MASKmoveq   r5, r5, lsr #PAGE_SHIFT - 12streq   r5, [sp, #4]beq do_mmap2mov r0, #-EINVALRETINSTR(mov,pc, lr)
#elsestr r5, [sp, #4]b   do_mmap2
#endif
// @file: linux-2.6.12/arch/arm/kernel/entry-common.S

    可见具体实现为do_mmap2,它是一个C函数:

/* common code for old and new mmaps */
inline long do_mmap2(unsigned long addr, unsigned long len,unsigned long prot, unsigned long flags,unsigned long fd, unsigned long pgoff)
{int error = -EINVAL;struct file * file = NULL;flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);if (flags & MAP_FIXED && addr < FIRST_USER_ADDRESS)goto out;error = -EBADF;if (!(flags & MAP_ANONYMOUS)) {file = fget(fd);if (!file)goto out;}down_write(&current->mm->mmap_sem);error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);up_write(&current->mm->mmap_sem);if (file)fput(file);
out:return error;
}
// @file: linux-2.6.12/arch/arm/kernel/sys_arm.c

(2)linux-2.6.33+

    将具体实现由do_mmap2改为sys_mmap_pgoff:

/** Note: off_4k (r5) is always units of 4K.  If we can't do the requested* offset, we return EINVAL.*/
sys_mmap2:
#if PAGE_SHIFT > 12tst r5, #PGOFF_MASKmoveq   r5, r5, lsr #PAGE_SHIFT - 12streq   r5, [sp, #4]beq sys_mmap_pgoffmov r0, #-EINVALmov pc, lr
#elsestr r5, [sp, #4]b   sys_mmap_pgoff
#endif
ENDPROC(sys_mmap2)
// @file: linux-2.6.33/arch/arm/kernel/entry-common.S

1.3 arm64 

(1)linux-4.18

    采用老式定义方法:

asmlinkage long sys_mmap(unsigned long addr, unsigned long len,unsigned long prot, unsigned long flags,unsigned long fd, off_t off)
{if (offset_in_page(off) != 0)return -EINVAL;return ksys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
}
// @file: linux-4.18/arch/arm64/kernel/sys.c

(2)linux-4.19+

    改用SYSCALL_DEFINE6宏定义:


http://www.ppmy.cn/embedded/39188.html

相关文章

Java 多线程补充

线程池 Java线程池是一种能够有效管理线程资源的机制&#xff0c;它可以显著提高应用性能并降低资源消耗。 线程池的主要优点包括&#xff1a; 资源利用高效&#xff1a;通过重用已存在的线程&#xff0c;减少了频繁创建和销毁线程带来的系统开销。响应速度提升&#xff1a;…

uniapp遍历数组对象的常见方法

在 UniApp 中&#xff0c;遍历数组对象的方法与在普通 JavaScript 中是相同的。UniApp 是一个使用 Vue.js 开发所有前端应用的框架&#xff0c;因此你可以使用 Vue.js 和 JavaScript 的语法来遍历数组对象。 以下是一些常见的遍历数组对象的方法&#xff1a; 使用 for 循环 …

100000订单直接拒掉,君子爱财,取之有道

近一个月询盘可谓寥寥无几&#xff0c;成交率为0&#xff0c;今天好不容易接了一个客户询盘&#xff0c;订单总价高达100000&#xff0c;听完细节直接拒掉&#xff0c;至于原因懂的都懂&#xff0c;不懂得等我慢慢道来。 前两天有2个询盘&#xff0c;其中一个是二次开发&#x…

AT_abc351_c [ABC351C] Merge the balls 题解

题目传送门 题目大意 你有一个空序列和 N N N 个球。第 i i i 个球 ( 1 ≤ i ≤ N ) (1 \leq i \leq N) (1≤i≤N) 的大小是 2 A i 2^{A_i} 2Ai​。 计算 N N N 操作后序列中剩余的球的个数。 你将进行 N N N 次运算。 在第 i i i 次操作中&#xff0c;你将第 i i…

【完美解决】使用git时候出现error setting certificate verify locations: CAfile:问题

1、出现场景&#xff1a; 在使用idea的时候&#xff0c;进行git下的push&#xff0c;出现下面的错误&#xff1a; 2、原因分析&#xff1a; 可能因为重装过系统&#xff0c;或者是安装git的位置发生了变化等情况出现。 3、解决方案&#xff1a; 找到git的安装路径&#xf…

多维点分布的均匀性评估方法(NDD和Voronoi 图法)

评估多维点分布的均匀性是统计学和数据科学中的一个重要问题&#xff0c;特别是在模拟、空间分析和样本设计等领域。下面&#xff0c;我将详细介绍2种评估多维点分布均匀性的方法&#xff0c;包括它们的数学原理、实现公式以及各自的优缺点。 1. 最近邻距离法&#xff08;Neare…

【Leetcode】 top100 round2 需要加强版

知识补充 python赋值的执行顺序&#xff1a; 在41中&#xff0c;对于测试案例[-1,4,3,1] 当i1时&#xff0c;以下两条语句的执行结果不一致&#xff1a; “nums[nums[i]-1], nums[i] nums[i], nums[nums[i]-1]” “nums[i], nums[nums[i]-1] nums[nums[i]-1], nums[i]” 解析…

最长连续序列(Lc128)——哈希表

给定一个未排序的整数数组 nums &#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1&#xff1a; 输入&#xff1a;nums [100,4,200,1,3,2] 输出&#xff1a;4 …