文章目录
- 简介
- 1、如果在应用层使用系统IO对设备节点进行打开,关闭,读写等操作会发生什么呢?
- 写个例子
- 2、假如驱动层的file_operations里面没有实现read之类的操作函数,会发生什么?
- 3、应用层和内核层室不能直接进行数据传输的
简介
Linux一切皆文件!
文件对应的操作有打开,关闭,读写。
设备节点对应的操作也有打开,关闭,读写。
1、如果在应用层使用系统IO对设备节点进行打开,关闭,读写等操作会发生什么呢?
文件操作集的描述在:include/linux/fs.h
应用层调用函数对设备节点进行操作 | 驱动层对应的函数 |
---|---|
read() | ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); |
write() | ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); |
poll()/select() | __poll_t (*poll) (struct file *, struct poll_table_struct *); |
ioctl() | long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); |
open() | int (*open) (struct inode *, struct file *); |
close() | int (*release) (struct inode *, struct file *); |
写个例子
file_operatiion.c
#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;
}
int misc_release(struct inode* inode, struct file* file)
{
printk("misc_release bye\n");
return 0;
}
ssize_t misc_read(struct file *file, char __user *ubuf, \
size_t size, loff_t *loff_t)
{
printk("misc_read\n");
return 0;
}
ssize_t misc_write(struct file *file, char __user *ubuf, \
size_t size, loff_t *loff_t)
{
printk("misc_write\n");
return 0;
}
struct file_operations misc_fops = {
.owner = THIS_MODULE,
.open = misc_open,
.release = misc_release,
.read = misc_read,
.write = misc_write
};
struct miscdevice misc_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "hello_misc",
.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 ok\n");
return 0;
}
static void misc_exit(void)
{
misc_deregister(&misc_dev);
printk("Bye Misc\n");
}
module_init(misc_init);
module_exit(misc_exit);
/* 模块声明 */
MODULE_LICENSE("GPL");
Makefile
# 定义内核源码的目录
KERN_DIR ?=/home/liefyuan/Liefyuan/bingpi-v3s/linux-zero-5.2.y
# 定义当前目录
PWD :=$(shell pwd)
# 要生成的内核模块
obj-m +=file_operation.o
all:
make -C $(KERN_DIR) M=$(PWD) modules
clean:
rm -rf *.order *o *.symvers *.mod.c *.mod *.ko
编译模块:
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
make
复制到开发板上去安装模块:
$ insmod file_operation.ko
测试应用:
app.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/hello_misc", O_RDWR);
if(fd < 0)
{
perror("open error\n");
return fd;
}
//read(fd, buf, sizeof(buf));
write(fd, buf, sizeof(buf));
close(fd);
return 0;
}
编译应用:
arm-linux-gnueabihf-gcc app.c -o app.armelf
复制到开发板上去运行。
./app.armelf
跑完上面的代码后更加深刻理解下面这个图。设备节点就是应用层和内核层的沟通的桥梁。
2、假如驱动层的file_operations里面没有实现read之类的操作函数,会发生什么?
什么也不会发生,也不会报错。
3、应用层和内核层室不能直接进行数据传输的
函数声明的位置: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);
照着上面改一下:
增加头文件:
#include <linux/uaccess.h>
ssize_t misc_read(struct file *file, char __user *ubuf, \
size_t size, loff_t *loff_t)
{
char kbuf[64] = "liefyuan1994";
if(copy_to_user(ubuf, kbuf, strlen(kbuf)) != 0)
{
printk("copy_to_user error!\n");
return -1;
}
printk("misc_read\n");
return 0;
}
ssize_t misc_write(struct file *file, 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);
printk("misc_write\n");
return 0;
}
测试应用:
#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] = "12345";
fd = open("/dev/hello_misc", O_RDWR);
if(fd < 0)
{
perror("open error\n");
return fd;
}
// read(fd, buf, sizeof(buf));
// printf("buf is %s\n", buf);
write(fd, buf, sizeof(buf));
close(fd);
return 0;
}