进为什么程申请io操作可能不发生硬件的io操作

扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
关于Windows系统下硬件IO的若干问题
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口用心创造滤镜
扫码下载App
汇聚2000万达人的兴趣社区下载即送20张免费照片冲印
扫码下载App
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
&(2)访问IO端口:  在驱动成功请求到I/O 端口后,就可以读写这些端口了。大部分硬件会将8位、16位和32位端口区分开,无法像访问内存那样混淆使用。驱动程序必须调用不同的函数来访问不同大小的端口。  Linux 内核头文件(体系依赖的头文件&asm/io.h&) 定义了下列内联函数来存取I/O端口:/* inb/outb:读/写字节端口(8位宽)。有些体系将port参数定义为unsigned long;而有些平台则将它定义为unsigned short。inb的返回类型也是依赖体系的 */unsigned inb(unsigned port);void outb(unsigned char byte, unsigned port);/* inw/outw:读/写字端口(16位宽) */unsigned inw(unsigned port);void outw(unsigned short word, unsigned port);/* inl/outl:读/写32位端口。longword也是依赖体系的,有的体系为unsigned long;而有的为unsigned int */unsigned inl(unsigned port);void outl(unsigned longword, unsigned port);&(3)释放IO端口:/* 用完I/O端口后(可能在模块卸载时),应当调用release_region将I/O端口返还给系统。参数start和n应与之前传递给request_region一致 */void release_region(unsigned long start, unsigned long n);&3.操作IO内存(申请,映射,访问,释放):  尽管 I/O 端口在x86世界中非常流行,但是用来和设备通讯的主要机制是通过内存映射的寄存器和设备内存,两者都称为I/O 内存,因为寄存器和内存之间的区别对软件是透明的。  I/O 内存仅仅是一个类似于RAM 的区域,处理器通过总线访问该区域,以实现对设备的访问。同样,读写这个区域是有边际效应。  根据计算机体系和总线不同,I/O 内存可分为可以或者不可以通过页表来存取。若通过页表存取,内核必须先重新编排物理地址,使其对驱动程序可见,这就意味着在进行任何I/O操作之前,你必须调用ioremap;如果不需要页表,I/O内存区域就类似于I/O端口,你可以直接使用适当的I/O函数读写它们。  由于边际效应的缘故,不管是否需要 ioremap,都不鼓励直接使用I/O内存指针,而应使用专门的I/O内存操作函数。这些I/O内存操作函数不仅在所有平台上是安全,而且对直接使用指针操作 I/O 内存的情况进行了优化。(1)申请I/O 内存:&  I/O 内存区在使用前必须先分配。分配内存区的函数接口在&linux/ioport.h&定义中:/* request_mem_region分配一个开始于start,len字节的I/O内存区。分配成功,返回一个非NULL指针;否则返回NULL。系统当前所有I/O内存分配信息都在/proc/iomem文件中列出,你分配失败时,可以看看该文件,看谁先占用了该内存区 */struct resource *request_mem_region(unsigned long start, unsigned long len, char *name);&(2)映射:  在访问I/O内存之前,分配I/O内存并不是唯一要求的步骤,你还必须保证内核可存取该I/O内存。访问I/O内存并不只是简单解引用指针,在许多体系中,I/O 内存无法以这种方式直接存取。因此,还必须通过ioremap 函数设置一个映射。/* ioremap用于将I/O内存区映射到虚拟地址。参数phys_addr为要映射的I/O内存起始地址,参数size为要映射的I/O内存的大小,返回值为被映射到的虚拟地址 */void *ioremap(unsigned long phys_addr, unsigned long size);&(3)访问IO内存:  经过 ioremap之后,设备驱动就可以存取任何I/O内存地址。注意,ioremap返回的地址不可以直接解引用;相反,应当使用内核提供的访问函数。访问I/O内存的正确方式是通过一系列专门用于实现此目的的函数:#include &asm/io.h&/* I/O内存读函数。参数addr应当是从ioremap获得的地址(可能包含一个整型偏移); 返回值是从给定I/O内存读取到的值 */unsigned int ioread8(void *addr);unsigned int ioread16(void *addr);unsigned int ioread32(void *addr);/* I/O内存写函数。参数addr同I/O内存读函数,参数value为要写的值 */void iowrite8(u8 value, void *addr);void iowrite16(u16 value, void *addr);void iowrite32(u32 value, void *addr);/* 以下这些函数读和写一系列值到一个给定的 I/O 内存地址,从给定的buf读或写count个值到给定的addr。参数count表示要读写的数据个数,而不是字节大小 */void ioread8_rep(void *addr, void *buf, unsigned long count);void ioread16_rep(void *addr, void *buf, unsigned long count);void ioread32_rep(void *addr, void *buf, unsigned long count);void iowrite8_rep(void *addr, const void *buf, unsigned long count);void iowrite16_rep(void *addr, const void *buf, unsigned long count);void iowrite32_rep(void *addr,,onst void *buf,,nsigned long count);/* 需要操作一块I/O 地址时,使用下列函数(这些函数的行为类似于它们的C库类似函数): */void memset_io(void *addr, u8 value, unsigned int count);void memcpy_fromio(void *dest, void *source, unsigned int count);void memcpy_toio(void *dest, void *source, unsigned int count);/* 旧的I/O内存读写函数,不推荐使用 */unsigned readb(address);unsigned readw(address);unsigned readl(address); void writeb(unsigned value, address);void writew(unsigned value, address);void writel(unsigned value, address);&(4)释放IO内存步骤:void iounmap(void * addr); /* iounmap用于释放不再需要的映射 */void release_mem_region(unsigned long start, unsigned long len); /* iounmap用于释放不再需要的映射 */&4、像IO内存一样使用端口  一些硬件有一个有趣的特性: 有些版本使用 I/O 端口;而有些版本则使用 I/O 内存。不管是I/O 端口还是I/O 内存,处理器见到的设备寄存器都是相同的,只是访问方法不同。为了统一编程接口,使驱动程序易于编写,2.6 内核提供了一个ioport_map函数:/* ioport_map重新映射count个I/O端口,使它们看起来I/O内存。此后,驱动程序可以在ioport_map返回的地址上使用ioread8和同类函数。这样,就可以在编程时,消除了I/O 端口和I/O 内存的区别 */void *ioport_map(unsigned long port, unsigned int count);void ioport_unmap(void *addr);/* ioport_unmap用于释放不再需要的映射 */注意,I/O 端口在重新映射前必须使用request_region分配分配所需的I/O 端口。&5、ARM体系的IO操作接口  s3c24x0处理器使用的是I/O内存,也就是说:s3c24x0处理器使用统一编址方式,I/O寄存器和内存使用的是单一地址空间,并且读写I/O寄存器和读写内存的指令是相同的。所以推荐使用I/O内存的相关指令和函数。但这并不表示I/O端口的指令在s3c24x0中不可用。如果你注意过s3c24x0关于I/O方面的内核源码,你就会发现:其实I/O端口的指令只是一个外壳,内部还是使用和I/O内存一样的代码。注意以下几点:  1)所有的读写指令(I/O操作函数)所赋的地址必须都是虚拟地址,你有两种选择:使用内核已经定义好的地址,如在include/asm-arm/arch-s3c2410/regs-xxx.h中定义了s3c2410处理器各外设寄存器地址(其他处理器芯片也可在类似路径找到内核定义好的外设寄存器的虚拟地址;另一种方法就是使用自己用ioremap映射的虚拟地址。绝对不能使用实际的物理地址,否则会因为内核无法处理地址而出现oops。  2)在使用I/O指令时,可以不使用request_region和request_mem_region,而直接使用outb、ioread等指令。因为request的功能只是告诉内核端口被谁占用了,如再次request,内核会制止(资源busy)。但是不推荐这么做,这样的代码也不规范,可能会引起并发问题(很多时候我们都需要独占设备)。  3)在使用I/O指令时,所赋的地址数据有时必须通过强制类型转换为 unsigned long ,不然会有警告。  4)在include\asm-arm\arch-s3c2410\hardware.h中定义了很多io口的操作函数,有需要可以在驱动中直接使用,很方便。
阅读(2615)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_',
blogTitle:'IO端口与IO内存',
blogAbstract:'从CPU连出来一把线:数据总线、地址总线、控制总线,这把线上挂着N个接口,有相同的,有不同的,名字叫做存储器接口、中断控制接口、DMA接口、并行接口、串行接口、AD接口……一个设备要想接入,就用自己的接口和总线上的某个匹配接口对接……于是总线上出现了各种设备:内存、硬盘,鼠标、键盘,显示器……对于CPU而言,如果它要发数据到某个设备,其实是发到对应的接口,接口电路里有多个寄存器(也称为端口),访问设备实际上是访问相',
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:0,
publishTime:1,
permalink:'blog/static/',
commentCount:1,
mainCommentCount:1,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'',
hmcon:'1',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}要求 1) 编写一个简单的块设备驱动程序,该块设备包括打开、IO控制与释放三个基本操作。 2) 一个测试程序_百度知道
要求 1) 编写一个简单的块设备驱动程序,该块设备包括打开、IO控制与释放三个基本操作。 2) 一个测试程序
要求:1) 编写一个简单的块设备驱动程序,该块设备包括打开、IO控制与释放三个基本操作。2) 编写一个测试程序,测试字符设备驱动程序的正确性。紧急!!!!要是符合,本人将会追加100分!!
环境要求:Linux (ubuntu)10.04谢谢大家。谢谢了。
提问者采纳
我有一个。。。也是作业题...用来给应用程序读写IO端口的。。。你自己拿去编译吧...(留下邮箱阿,给你发源文件,贴出来的可能会出问题)应用程序和驱动模块都在...空间里面有模块的代码和应用程序,满足你的要求。加载驱动之后,执行应用程序,此时在串口的4、7引脚上接个LED(你找个有串口的机器测试,引脚搭上就能看到),可以看到LED的闪烁。。。说明:apps_serial.c是控制串口的应用程序,LDE接到4和7脚,就可以看到闪烁现象cioport.c是驱动程序,编译和安装方法如下: 1.编译。
编译完成之后,会生成一个cioport.ko(不同的机器上,必须重新编译,内核模块对版本的依赖强) 2.安装内核模块,必须有root权限
insmod cioport.ko
mknod /dev/test_device c 1000 0 3.测试
gcc apps_serial.c test1 执行必须有root权限
./test1 此时将LED的引脚接到9针串口的4和7针,可以观察到LDE的闪烁下面是Makefile,你保存成文件名:Makefileobj-m:=cioport.oKERNELDIR ?=/lib/modules/$(shell uname -r)/buildPWD :=$(shell pwd)default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules下面是应用程序:#include &stdio.h&#include &stdlib.h&#include &unistd.h&#include &fcntl.h&#include &linux/ioctl.h&//使用下面的宏#define DEVICE_NAME &/dev/test_device&#define TEST_MAGIC_NUM 'k'#define PORT_SET _IOW(TEST_MAGIC_NUM,1,int)#define PORT_GET _IO(TEST_MAGIC_NUM,2)#define PORT_LOCK _IO(TEST_MAGIC_NUM,3)int main(void){ char buf[64]; int retcode=0; int fd=open(DEVICE_NAME,O_RDWR); if(fd & 0) {
perror(&open device&);
exit(fd); } char sec=0,min=0,hou=0; int i=0; int port=0; for(i=0;i&30;i++) { ioctl(fd, PORT_SET,0x3fc); buf[0]=1;//DTR=0;RTS=1; write(fd,(void *)buf,1); sleep(1); buf[0]=2;//DTR=1;RTS=0; write(fd,(void *)buf,1); sleep(1); } close(retcode); return 0;}下面是驱动程序,保存成cioport.c:#include &linux/module.h&#include &linux/kernel.h&#include &linux/fs.h&#include &linux/types.h&#include &linux/fcntl.h&#include &linux/slab.h&#include &linux/mm.h&#include &asm/uaccess.h&#include &linux/cdev.h&#include &linux/moduleparam.h&#include &linux/proc_fs.h&#include &asm/io.h&#include &linux/wait.h&#include &asm/current.h&#include &linux/sched.h&#include &linux/ioctl.h&//ioctl的命令字定义#define TEST_MAGIC_NUM 'k'#define PORT_SET _IOW(TEST_MAGIC_NUM,1,int)#define PORT_GET _IO(TEST_MAGIC_NUM,2)#define PORT_LOCK _IO(TEST_MAGIC_NUM,3)#define PORT_UNLOCK _IO(TEST_MAGIC_NUM,4)#define MAXBUF 512 //自定义数据区大小为512#define DEVICE_NAME &/dev/test_device&#define DEVICE_SCCUESS 0#define PORT_LOCKED -2//全局变量尽量采用static变量,避免“污染”内核的变量的命名空间static int major_number = 1000;static int minor_number = 0;static int port_number = 0x70;module_param(major_number , int , S_IRUGO);module_param(minor_number , int , S_IRUGO);//module_param(port_number
, long , S_IRUGO);static dev_t device_
//设备号static struct cdev *my_cdev=NULL;static void *pdev=NULL;
//自定义区域,open的时候分配一片区域//内核信号量,等待队列,用于实现读写的同步static struct semaphore g_//static unsigned buf_flag=0;static unsigned int port_flag = 0;static DECLARE_WAIT_QUEUE_HEAD(g_queue);//打开和读写操作,读写操作将实现阻塞I/O,为防止读写冲突,设备只允许一个进程的一个操作int test_open(struct inode * inode ,struct file *filp){ printk(&device open OK,process name %s,process ID %i\n&,current-&comm,current-&pid); return DEVICE_SCCUESS;}int test_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos){ int i=0; printk(&operation: read device&); if(down_interruptible(&g_sem))//获得锁 {
printk(KERN_WARNING &Get semaphore error\n&);
return -1; } while(port_flag)//端口被占用,等待 {
up(&g_sem);
if(filp-&f_flags & O_NONBLOCK)
return -EAGAIN;
if(wait_event_interruptible(g_queue,0 == port_flag))
return -ERESTARTSYS;//可能是信号使得进程被唤醒
if(down_interruptible(&g_sem))
return -ERESTARTSYS; } //此时已经获得锁,且操作可以执行
//做标记,不允许修改端口 port_flag=1; for(i=0;i&i++)
((char*)pdev)[i]=inb(port_number); port_flag=0;//不再占用端口 up(&g_sem);//释放信号量 wake_up_interruptible(&g_queue);//唤醒等待队列中的进程 i=copy_to_user((void*)buf,pdev,count);//读出的数据拷贝给应用程序 if(i&0) {
printk( KERN_WARNING &copy to user error\n&);
return -EFAULT; } return count-i;}long test_ioctl(struct file *filp,unsigned int cmd, unsigned long arg){ int retval=0; printk(&in test_ioctl\n&);
switch(cmd) {
case PORT_SET:
if(port_flag )
retval = PORT_LOCKED;
//没有其他进程在IO
port_number=
retval = DEVICE_SCCUESS;
printk(&port number changed\n&);
case PORT_GET:
retval = port_
printk(&port number returned\n&);
default: } }int test_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos){ int i=0,j=0; printk(&operation: write device\n&); i=_copy_from_user(pdev,(void*)buf,count);//数据拷贝过来并,并将指定端口 if(i&0) {
printk( KERN_WARNING &copy to user error\n&);
return -EFAULT; }if(down_interruptible(&g_sem))//获得锁 {
printk(KERN_WARNING &Get semaphore error\n&);
return -1; } while(port_flag)//操作无法执行,等待 {
up(&g_sem);
if(filp-&f_flags & O_NONBLOCK)
return -EAGAIN;
if(wait_event_interruptible(g_queue,0 == port_flag))
return -ERESTARTSYS;//可能是信号使得进程被唤醒
if(down_interruptible(&g_sem))
return -ERESTARTSYS; } //此时已经获得锁,且操作可以执行 port_flag=1; for(j=0;j&count-i;j++)
outb(((char*)pdev)[j],port_number); port_flag=0; up(&g_sem); wake_up_interruptible(&g_queue);return (count-i);}//用户空间进程设备关闭时执行,也就是对应的close操作int test_release(struct inode *inode, struct file* filp){ return 0;}static struct file_operations test_ops = { .owner = THIS_MODULE, .read = test_read, .write = test_write, .release = test_release, .open = test_open, .unlocked_ioctl=test_ioctl,};int test_init(void) //内核装载时执行,注册设备和分配自由存储区{ int err=0; //分配一块缓冲区 pdev = kmalloc(MAXBUF,GFP_KERNEL); if(NULL == pdev) {
printk(KERN_WARNING &kernel cannot mallocate memory\n&);
return -1; }//注册设备 device_number = MKDEV(major_number,minor_number); err = register_chrdev_region(device_number,1,DEVICE_NAME); if( 0 & err) {
printk( KERN_WARNING &cannot register device ,major %d,minor %d\n&,major_number,minor_number);
kfree(pdev);//先撤销之前的动作
} //分配一个cdev my_cdev = cdev_alloc(); if(NULL == my_cdev) {
printk(KERN_WARNING &cannot allocate cdev structure\n&);
kfree(pdev);
unregister_chrdev_region(device_number,1);
return -1; } //添加设备 my_cdev-&ops= &test_ my_cdev-&owner = THIS_MODULE; err=cdev_add(my_cdev,device_number,1);//添加一个设备 if(0 & err) {
printk(KERN_WARNING&cannot add the device\n&);
kfree(pdev);
unregister_chrdev_region(device_number,1);
cdev_del(my_cdev);
} //初始化信号量,等待队列已经初始化 sema_init(&g_sem,1); //设置标志 //buf_flag=0; port_flag=0; printk(&init io driver OK\n&); return DEVICE_SCCUESS; }void test_exit(void) //内核卸载时候执行,注销设备和释放自由存储区{ printk(&remove the test module\n&); unregister_chrdev_region(device_number,1); cdev_del(my_cdev); kfree(pdev); printk(& common io driver unload\n&);} module_init(test_init);module_exit(test_exit);MODULE_LICENSE(&GPL&);
谢谢啊,这个貌似是字符驱动啊??加QQ聊吧。.
额..没看清题..给整成介个了..块设备驱动....块设备..设备....备.....临时写来不及了,下面这个链接里面包含了不少你要的...代码应该是拿过来就可以直接编译的。。。。。博主还有不少相关的文章,代码看样子是08年的,内核版本跟现在不太一样了,内核代码不晓得能不能直接编译了。。。
前辈,这个不符合要求。麻烦你能不能帮我做个更加符合的呢?我也是受人之托,食言不好啊。拜托了!
给个邮箱,搞定发给你....之前的字符设备可以作为第二题的答案。。。我才看到需要两个题目阿..
尽量快些,谢了!
已发,查收....内核版本是2.6.39.编译通过..编译不通过的话,给说下..
提问者评价
虽然没用上,但是谢谢了。
其他类似问题
为您推荐:
其他2条回答
一、散热不良:显示器、电源和CPU在工作中发热量非常大,因此保持良好的通风状况非常重要,如果显示器过热将会导致色彩、图象失真甚至缩短显示器寿命。工作时间太长也会导致电源或显示器散热不畅而造成电脑死机。CPU的散热是关系到电脑运行的稳定性的重要问题,也是散热故障发生的“重灾区”。
二、移动不当:在电脑移动过程中受到很大振动常常会使机器内部器件松动,从而导致接触不良,引起电脑死机,所以移动电脑时应当避免剧烈振动。
三、灰尘杀手:机器内灰尘过多也会引起死机故障。如软驱磁头或光驱激光头沾染过多灰尘后,会导致读写错误,严重的会引起电脑死机。
四、设备不匹配:如主板主频和CPU主频不匹配,老主板超频时将外频定得太高,可能就不能保证运行的稳定性,因而导致频繁死机。
您好,这样的情况建议您可以升级到最新版本试一下,或是联系一下官网客服比较好。
您可能关注的推广回答者:回答者:
驱动程序的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁关于Windows系统下硬件IO的若干问题_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
关于Windows系统下硬件IO的若干问题
W​i​n​d​o​w​s​ ​D​D​K​驱​动​编​程​的​相​关​内​容​,​设​计​内​存​映​射​、​端​口​访​问​、​D​M​A​操​作​等
阅读已结束,如果下载本文需要使用
想免费下载本文?
你可能喜欢浅谈无缓存IO操作和标准IO文件操作区别_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
浅谈无缓存IO操作和标准IO文件操作区别
浅​谈​无​缓​存​I​O​操​作​和​标​准​I​O​文​件​操​作​区​别
阅读已结束,如果下载本文需要使用
想免费下载本文?
你可能喜欢}

我要回帖

更多关于 ios8删除自带程序 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信