Linux下/dev/mem和/dev/kmem的区别:
/dev/mem: 物理内存的全镜像。可以用来访问物理内存。
/dev/kmem: kernel看到的虚拟内存的全镜像。可以用来访问kernel的内容。
作用:
前者用来访问物理IO设备,比如X用来访问显卡的物理内存,或嵌入式中访问GPIO。用法一般就是open,然后mmap,接着可以使用map之后的地址来访问物理内存。这其实就是实现用户空间驱动的一种方法。
后者一般可以用来查看kernel的变量,或者用作rootkit之类的。参考1和2描述了用来查看kernel变量这个问题。
Linux 下操作gpio:
对于在不支持虚拟内存的操作系统和根本就没有使用操作系统的系统里操作GPIO直接读写对应的GPIO寄存器就可以啦,但是在linux这样的操作系统下,内核层和应用层都是处于虚拟地址中,而GPIO的寄存器都是处于物理地址中,你必须编写一个操作GPIO的驱动,或者是使用一些变通的技巧来操作GPIO.
目前我所知道的在linux下操作GPIO有两种方法:
1. 编写驱动,这当然要熟悉linux下驱动的编写方法和技巧,在驱动里都是虚拟地址,可以使用ioremap函数获得GPIO物理基地址指针,然后使用这个指针根据ioctl命令进行GPIO寄存器的读写,并把结果回送到应用层。这里提供一点程序片断供大家参考:
int init_module(void){
printk(KERN_ALERT "ioctl load.\r\n");
register_chrdev(254,"ioreg",&fops);
stb_gpio = (STBX25XX_GPIO_REG *)ioremap(GPIO_BASE,GPIO_LEN);
if(stb_gpio == NULL){
printk(KERN_ALERT "can''t get io base.\r\n");
return -1;
}
return 0;
}
int io_ioctl (struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg){
unsigned long uGpio;
printk(KERN_ALERT "io_ioctl cmd=%04x,arg=%04x.\r\n",cmd,(int)arg);
switch(cmd){
case SET_IO_DIR:{
printk(KERN_ALERT "SET_IO_DIR\r\n");
break;
}
case SET_IO_VALUE:{
printk(KERN_ALERT "SET_IO_VALUE\r\n");
break;
}
case GET_IO_VALUE:{