您的位置:首页 > 运维架构 > Linux

Linux对io端口的管理——为什么要申请IO才能使用

2017-09-29 18:23 211 查看
2017年10月1号

(1)外设IO寄存器地址独立编址的CPU,这时该称外设IO寄存器为IO端口,访问IO寄存器可通过ioport_map将其映射到虚拟地址空间,但实际上这是给开发人员制造的一个“”假象”,并没有映射到内核虚拟地址,仅仅是为了可以使用和IO内存一样的接口访问IO寄存器

例如:x86平台普通使用了名为内存映射的技术,IO设备端口被映射到内存空间,映射后,CPU访问IO端口就如同访问内存一样。

(2)外设IO寄存器地址统一编址的CPU,这时应该称外设IO寄存器为IO内存,访问IO寄存器可通过ioremap将其映射到虚拟地址空间,然后在使用read/write接口访问

访问的方法:首先调用request()申请资源,接着将寄存器地址通过ioremap()映射到内核空间的虚拟地址,之后就可以Linux设备访问编程接口访问这些寄存器了,访问完成后,使用ioremap()对申请的虚拟地址进行释放,并释放release()申请的io内存资源

个人的错误理解:内核想要访问所以的4G物理地址空间,但是又没有一一对应的地址空间,因为软件虚拟出来的4G只有1G给了内核,所以内核采用了一种机制(高端内存地址映射),使这1G(一部分直接访问,一部分间接访问)访问所有物理地址空间,这种方式实际执行这段虚拟空间时,会对应实际的物理地址空间,我们可以在虚拟地址空间去操作实际的物理地址空间,而操作是代码,执行代码是需要内存的,申请io,就叫IO内存资源,我们申请后,这段物理内存我们使用时,不会有其他程序在这段内存空间使用

比如:蜂鸣器使用了这个IO口,他就需要申请,如果在它之前有别的设备使用的这个IO,比如LED之前申请过,这个时候还想用蜂鸣器申请这个IO则会ret =1,request函数里面有lock,所以下面对寄存器的操作应该无效,我觉得;

        ret = gpio_request(S5PV210_GPH0(1), "GPH0");

if(ret)
printk("button-x210: request gpio GPH0(1) fail");
s3c_gpio_setpull(S5PV210_GPH0(1), S3C_GPIO_PULL_UP);
s3c_gpio_cfgpin(S5PV210_GPH0(1), S3C_GPIO_SFN(0));

当我们卸载这个模块时,会释放这个IO,蜂鸣器就能再次申请这个IO,不过伴随着实际的硬件设备也要换成蜂鸣器

gpio_free(unsigned gpio)

很多时候,我们在结构体函数里面使用结构体指针(4个字节),实际使用时,在里面实例化,用alloc()申请内存不也是在堆吗,用完就释放,不使用函数申请直接定义局部变量就会放在栈中,会栈溢出。

2017年12月18日补充

(1)这里涉及到动态映射和静态映射,比如某个公司开发可一块板子,针对linux2.6.35移植内核,该公司在内核里面添加针对自己板子物理地址对应虚拟地址的静态映射表,也就是4G的虚拟地址的某个地址(如0xFDF000240)对应的实际板子IO寄存器物理地址(0xE0001234),这个虚拟地址被静态绑定对应的物理地址后,我们的内核代码使用动态映射时无法在使用这个虚拟地址虚拟地址4G,实际物理可能只有256M,我们编写代码时,是想象有4G能使用,其实,很多时候是动态映射,如虚拟地址0xFF000000动态映射到物理地址0xEE000000,使用了这个地址的寄存器运算,因为我们写代码时想象有4G,所以虚拟地址用的很奢侈,0到4G的范围使用,就想在虚拟地址0xFFF0000F再对应一个新的物理地址,想一一对应,可是物理地址没有这么大,这个时候,0xFFF0000F对应的还是物理地址0xEE000000,上一个设备模块使用完后,释放了,映射关系被销毁,也有一些内存是直接一一对应映射的,虚拟等于物理,因为速度的要求和别的原因,因为建了动态映射,需要内核管理(申请,销毁等步骤),耗用时间,才换来了内存。静态映射只是绑定了虚拟地址到物理地址(动态映射是在这里耗费了时间,比如给一个物理地址你还要通过函数得到一个虚拟地址,之后都是一样的),并不是将虚拟地址空间同时分配占用了物理运行内存。

(2)上面说到的蜂鸣器补充:蜂鸣器绑定了一个物理地址,无法改变,当我们的代码申请虚拟地址后(只有申请到的虚拟地址,才有对应物理内存给你运行代码,并对你要操作的蜂鸣器所对应的物理地址所在寄存器赋值,这时,这个虚拟地址没有释放前,就像静态映射一样,当然也占用着同等大小对应物理内存运行它,别人是无法通过其他虚拟地址及占用其他物理运行内存去操控这个蜂鸣器,这个虚拟地址所用到的运行内存在运算,还将最后的值绑定似的赋给蜂鸣器所在物理地址,当释放后,这个虚拟地址被释放,对应占用的物理内存空间也被释放。程序再次用蜂鸣器物理地址申请蜂鸣器IO时,ioremap()返回一个新的空闲的虚拟地址,当然会有相应的物理内存提供这个虚拟地址的代码去运行,再去操作。)

(3)虚拟地址说的是虚拟地址空间,虚拟地址空间申请到后,会同时分配物理运行内存让其运行,这时可以理解虚拟地址空间就是物理运行内存空间,不同虚拟地址空间能在不同时刻对应相同的物理运行内存,这就是模拟出4G的原理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: