Linux硬件设备访问

本文详细介绍了Linux中使用mmap进行设备操作,包括mmap系统调用的参数解析、虚拟内存区域、vm_area_struct结构以及如何通过remap_pfn_range建立页表。此外,还探讨了硬件访问的差异,如寄存器与内存的区别、I/O空间与内存空间,并展示了如何操作I/O端口和内存。最后,提到了混杂设备驱动和LED驱动程序设计的基本概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、mmap设备操作

1、mmap系统调用

void *mmap(void * addr, size_t len, int prot, int flags, int fd, off_t offset)

返回值:内存映射的首地址(虚拟映射区首地址)。

功能:内存映射函数mmap,负责把文件内容映射到进程的虚拟内存空间,通过对这段内存的读取和修改(使用指针),来实现对文件的读取和修改,而不需要再调用read,write等操作。实际上内核和应用程序都是使用的虚拟地址,我们不会对物理地址直接操作,而是通过映射将物理地址转化为虚拟地址,然后对虚拟地址操作来实现对物理地址的操作。

参数:addr:指定映射的起始地址,通常设为NULL,由系统指定。

len:映射到内存的文件长度

prot:映射区的保护方式,可以是:

PROT_EXEC:映射区可被执行

PROT_READ:映射区可被读取

PROT_WRITE:映射区可被写入

flags:映射区的特性,可以是:

MAP_SHARED:写入映射区的数据会复制回文件,且允许其他映射该文件的进程共享。

MAP_PRIVATE:对映射区的写入操作会产生一个映射区的复制(copy-on-write),对此区域所做的修改不会写回原文件。

fd:由open返回的文件描述符,代表要映射的文件

offset:以文件开始处的偏移量,必须是分页大小的整数倍,通常为0,表示从文件头开始映射。

解除映射

int munmap(void *start, size_t length)

功能:取消参数start所指向的映射内存,参数length表示欲取消的内存大小。

返回值:解除成功返回0,否则返回-1,错误原因存于errno中。

实例分析:mmap系统调用

//printf输入输出函数需要的头文件
#include <stdio.h>

//open系统调用需要的头文件
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>


//close需要的头文件
#include<unistd.h>

//mmap/munmap需要的头文件
#include<sys/mman.h>

//strcpy需要的头文件
#include<string.h>

int main()
{
int fd;
char *start;
char buf[100];

/*打开文件*/
fd = open("testfile",O_RDWR);
        
start=mmap(NULL,100,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); //注意:mmap不会改变原有文件的长度,也就是说原有文件有多长,我们才能写入多长,多出来的部分,会被舍弃。

/* 读出数据 */
strcpy(buf,start);
printf("buf = %s\n",buf);

/* 写入数据 */
strcpy(start,"Buf Is Not Null!"); //mmap不会影响原有文件的长度;所以原来有多长,就会写入多长

munmap(start,100); /*解除映射*/
close(fd);  

return 0; 
}

2、虚拟内存区域

虚拟内存区域是进程的虚拟地址空间中的一个同质区间,即具有同样特性的连续地址范围。一个进程的内存映像由下面几个部分组成:程序代码、数据、BSS和栈区域,以及内存映射的区域。

一个进程的内存区域可以通过查看/proc/pid(1)/maps

001f6000-00231000 r-xp 00000000 fd:00 263878     /lib/libsepol.so.1
00231000-00232000 rw-p 0003a000 fd:00 263878     /lib/libsepol.so.1
00232000-0023c000 rw-p 00232000 00:00 0 
0023e000-00253000 r-xp 00000000 fd:00 263879     /lib/libselinux.so.1
00253000-00255000 rw-p 00015000 fd:00 263879     /lib/libselinux.so.1
00451000-00452000 r-xp 00451000 00:00 0          [vdso]
009a2000-009bb000 r-xp 00000000 fd:00 263818     /lib/ld-2.5.so
009bb000-009bc000 r--p 00019000 fd:00 263818     /lib/ld-2.5.so
009bc000-009bd000 rw-p 0001a000 fd:00 263818     /lib/ld-2.5.so

每一行的域为:

start_end perm offset major:minor inode

start:该区域起始虚拟地址

end:该区域结束

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值