目录
linux一切皆文件
文件对应的操作有打开,关闭,读取
设备节点对应的操作有打开,关闭,读取
当对设备节点进行read
例如当对设备节点进行open时,会调用这个驱动里的文件操作集结构体里的open成员
int (*open) (struct inode *,struct file *);
现在将第五章的misc代码文件操作集中的read实现
#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
int misc_open(struct inode * inode,struct file * file)
{
printk("hello misc_open\n");
return 0;
}
struct const file_operation misc_fops = {
.owner = THIS_MODULE,
.open = misc_open
};
struct miscdevice misc_dev = {
.minor = MISC_DYNAMIC_MINOR,//动态分配
.name ="hellomisc",//设备节点名字
.fops =&misc_fops
};
static int misc_init(void)
{
int ret;
ret = misc_register(&misc_dev);
if(ret<0)
{
printk("misc registe is error\n");
return -1;
}
printk("misc registe is success\n");
return 0;
}
static void misc_exit(void)
{
misc_deregister(&misc_dev);
printk("misc goodbye");
}
module_init(misc_init);
module_exit(misc_exit);
MODULE_LICENSE("GPL");
将其编译成模块然后加载,并新建一个.c打开设备节点来测试
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char * argv)
{
int fd;
fd = open("/dev/hellomisc",O_RDWR);
if (fd<0)
{
perror("open error\n");
return fd;
}
close(fd);
return 0;
}
用交叉编译放到板子上,运行就会输出 hello misc_open
其他的也是这么实现
假如没有实现相对应的函数
假如没有实现相对应的函数,但又对设备节点做出对应的函数操作,就不会有任何反应
应用层和数据层传数据
应用层和数据层不能直接传数据,有两个函数可以实现,只能在驱动中使用,定义在源码目录中的include/asm-generic/uaccess.h里
static inline long copy_from_user(void *to,const void _user *from, unsigned long n)
static inline long copy_to_user(void _user *to,const void *from, unsigned long n)
- copy_from_user:应用层到内核层
- copy_to_user:内核层到应用层
参数:
- to:传到哪里去
- from:数据从哪里来
- n:数据大小
copy_from_user例子
修改上面misc驱动代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
int misc_open(struct inode * inode,struct file * file)
{
printk("hello misc_open\n");
return 0;
}
int misc_read(struct file *file,char _user *ubuf,size_t size,loff_t *loff_t)
{
char kbuf[64] = "heheh";
if( copy_to_user(ubuf,kbuf,strlen(kbuf))!=0)
{
printk("copy_to_user error\n");
return -1;
}
return 0;
}
struct const file_operation misc_fops = {
.owner = THIS_MODULE,
.open = misc_open,
.read = misc_read
};
struct miscdevice misc_dev = {
.minor = MISC_DYNAMIC_MINOR,//动态分配
.name ="hellomisc",//设备节点名字
.fops =&misc_fops
};
static int misc_init(void)
{
int ret;
ret = misc_register(&misc_dev);
if(ret<0)
{
printk("misc registe is error\n");
return -1;
}
printk("misc registe is success\n");
return 0;
}
static void misc_exit(void)
{
misc_deregister(&misc_dev);
printk("misc goodbye");
}
module_init(misc_init);
module_exit(misc_exit);
MODULE_LICENSE("GPL");
修改测试.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char * argv)
{
int fd;
char buf[64] = {0};
fd = open("/dev/hellomisc",O_RDWR);
if (fd<0)
{
perror("open error\n");
return fd;
}
read(fd,buf,sizeof(buf));
printf("buf is %s\n",buf);
close(fd);
return 0;
}
进行交叉编译和重新加载模块,运行后会打印出buf is heheh
copy_to_user例子
和上面操作一样,修改驱动代码和测试.c
驱动文件
#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
int misc_open(struct inode * inode,struct file * file)
{
printk("hello misc_open\n");
return 0;
}
int misc_read(struct file *file,char _user *ubuf,size_t size,loff_t *loff_t)
{
char kbuf[64] = "heheh";
if( copy_to_user(ubuf,kbuf,strlen(kbuf))!=0)
{
printk("copy_to_user error\n");
return -1;
}
return 0;
}
int misc_write(struct file *file,const char _user *ubuf,size_t size,loff_t *loff_t)
{
char kbuf[64] = {0};
if( copy_from_user(kbuf,ubuf,size)!=0)
{
printk("copy_from_user error\n");
return -1;
}
printk("kbuf is %s\n",kbuf);
return 0;
}
struct const file_operation misc_fops = {
.owner = THIS_MODULE,
.open = misc_open,
.write= misc_write,
.read = misc_read
};
struct miscdevice misc_dev = {
.minor = MISC_DYNAMIC_MINOR,//动态分配
.name ="hellomisc",//设备节点名字
.fops =&misc_fops
};
static int misc_init(void)
{
int ret;
ret = misc_register(&misc_dev);
if(ret<0)
{
printk("misc registe is error\n");
return -1;
}
printk("misc registe is success\n");
return 0;
}
static void misc_exit(void)
{
misc_deregister(&misc_dev);
printk("misc goodbye");
}
module_init(misc_init);
module_exit(misc_exit);
MODULE_LICENSE("GPL");
测试.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char * argv)
{
int fd;
char buf[64] = "heheh";
fd = open("/dev/hellomisc",O_RDWR);
if (fd<0)
{
perror("open error\n");
return fd;
}
write(fd,buf,sizeof(buf));
close(fd);
return 0;
}
进行交叉编译和重新加载模块,运行后会打印出kbuf is heheh