> 文章列表 > 嵌入式Linux(4):应用层和内核层数据传输

嵌入式Linux(4):应用层和内核层数据传输

嵌入式Linux(4):应用层和内核层数据传输

文章目录

  • 简介
  • 1、如果在应用层使用系统IO对设备节点进行打开,关闭,读写等操作会发生什么呢?
  • 写个例子
  • 2、假如驱动层的file_operations里面没有实现read之类的操作函数,会发生什么?
  • 3、应用层和内核层室不能直接进行数据传输的

简介

Linux一切皆文件!
文件对应的操作有打开,关闭,读写。
设备节点对应的操作也有打开,关闭,读写。

嵌入式Linux(4):应用层和内核层数据传输

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.oall:make -C $(KERN_DIR) M=$(PWD) modulesclean: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

跑完上面的代码后更加深刻理解下面这个图。设备节点就是应用层和内核层的沟通的桥梁。

嵌入式Linux(4):应用层和内核层数据传输

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;
}