三、make menuconfig图形配置界面
1、进入到内核源码路径下,然后输入make menuconfig即可打开此界面。
2、make menuconfig图形化界面的操作
1)搜索功能
输入“/”即可弹出搜索界面,然后输入需要搜索的内容即可。
2)配置驱动的状态
(1)把驱动编译成模块,用M表示。
(2)把驱动编译到内核中,用*表示。
(3)不编译
3、退出
退出分为保存退出和不保存退出
4、make menuconfig有关的文件
Makefile
里面是编译规则。菜的做法。
Kconfig
内核配置的选项,相当于饭店吃饭服务员给的菜单
.config
配置完成内核之后生成的配置选项。相当于点完的菜。
5、make menuconfig会读取哪个目录下的Kconfig文件arch/$ARCH/目录下的Kconfig
/arch/arm/configs#下面有好多配置文件,相当于饭点的特色菜。
6、为什么要复制成.config而不复制成其他文件呢?
肯定不行,因为内核默认读取的Linux内核根目录下的.config作为默认配置选项的。
7、复制的.config不完全符合要求怎么办?
需要使用make menuconfig点菜,调出菜单。配置完成之后自己更新到.config中
8、怎么和Makefile文件建立关系?
当make menuconfig保存退出之后,Linux会将所以的配置选项以宏定义的形式保存在include/generated下面的autoconf.h中。
四、Linux三大设备驱动
字符设备:IO的传输过程是以字符为单位的,没有缓冲。比如IIC,SPI都是字符设备。
块设备:IO的传输过程都是以块为单位的。跟存储相关的都是属于块设备,比如,tf卡
网络设备:与前面两个不一样,是以socket套接字来访问的。
1、杂项设备驱动
杂项设备驱动是字符设备的一种,可以自动生成设备结点。
系统中有许多杂项设备。
cat /proc/misc命令来查看。
2、杂项设备除了比字符设备代码简单,还有什么区别吗?
杂项设备的主设备号是相同的,均为10,次设备号是不同的,主设备号相同就可以节省内核的资源。
3、主设备号和次设备号是什么?
主设备号包含次设备号,主设备号在linux中是唯一的,次设备号不一定唯一。
设备号是计算机识别设备的一种方式,主设备相同的就被视为同一类设备。
主设备号可以必做成电话号码的区号,比如安徽是0551。
次设备号可以比作电话号码。
主设备号可以通过命令cat /proc/devices来查看。
4、杂项设备驱动描述
定义在内核源码路径: vi include/linux/miscdevice.h
struct miscdevice {
int minor;//次设备号
const char \*name;//设备节点的名字
const struct file\_operations \*fops;//文件操作集
struct list\_head list;
struct device \*parent;
struct device \*this_device;
const struct attribute\_group \*\*groups;
const char \*nodename;
umode\_t mode;
};
file_operations *fops;//文件操作集在vi include/linux/fs.h下。
一个结构体成员都要对应一个调用。
注册杂项设备
extern int misc\_register(struct miscdevice \*misc);
注销杂项设备
extern int misc\_deregister(struct miscdevice \*misc);
5 注册杂项设备的流程。
(1)填充miscdevice这个结构体的成员。
(2)填充file_operation这个结构体。
(3)注册杂项设备并且生成设备节点。
自主分配设备号:
五、实践课
目标:按照杂项设备的注册流程注册一个杂项设备,并且生成设备节点。
创建misc.c的源文件
#include<linux/init.h>
#include<linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
struct file\_operations misc_fops =
{
.owner = THIS_MODULE
};
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\_register is error\n");
return -1;
}
printk("misc\_register is successful\n");
return 0;
}
static int misc\_exit(void)
{
misc\_deregister(&misc_dev);//卸载
printk("bye bye");
return 0;
}
module\_init(misc_init);
module\_exit(misc_exit);
MODULE\_LICENSE("GPL");
在make之后,将ko文件挂载到nfs下,使用insmod挂载设备驱动。
应用层和内核层的数据传输
Linux一切皆文件!!!
文件对应的操作有打开,关闭,读写。
设备结点对应的操作有打开,关闭,读写。
1、如果在应用层使用系统IO对设备结点进行打开,关闭,读写操作等会发生什么呢?
当在应用层read设备节点的时候,就会触发驱动里面的read这个函数。
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
当在应用层write设备节点的时候,就会触发驱动里面的write这个函数。
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
当在应用层poll/select设备节点的时候,就会触发驱动里面的poll这个函数。
unsigned int (*poll) (struct file *, struct poll_table_struct *);
当在应用层ioctl设备节点的时候,就会触发驱动里面的ioctl这个函数。
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
当在应用层open设备节点的时候,就会触发驱动里面的open这个函数。
int (*open) (struct inode *, struct file *);
当在应用层close设备节点的时候,就会触发驱动里面的close这个函数。
int (*release) (struct inode *, struct file *);
open、release、read、write驱动代码测试
在file_operation结构体中添加如下代码,make完成。
#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\_close(struct inode \*inode,struct file \*file)
{
printk("bye bye\n");
return 0;
}
int misc\_read(struct file \*file,char __user \*ubuf,size\_t size,loff\_t \*loff\_t)
{
char kbuf[64] = "hello";
if(copy\_to\_user(ubuf,kbuf,sizeof(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\n");
return -1;
}
printk("kbuf is %s\n",kbuf);
return 0;
}
struct file\_operations misc_fops ={
.owner = THIS_MODULE,
.open = misc_open,
.release = misc_close,
.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\_register is error\n");
return -1;
}
printk("misc\_register is successful\n");
return 0;
}
static void misc\_exit(void)
{
misc\_deregister(&misc_dev);//卸载
printk("bye bye");
}
module\_init(misc_init);
module\_exit(misc_exit);
MODULE\_LICENSE("GPL");
open、close、read、write应用代码测试
应用层代码如下
#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];
fd = open("/dev/hello\_misc",O_RDWR);
if (fd < 0)
{
printf("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 -static
复制到nfs目录下调用./app实现对驱动代码的调用~~!!!
实验现象
首先insmod加载驱动代码:之后运行./app,打印数据信息,
将kbuf中的数据打印出来。
六、小结
1、调用关系
上层应用 设备节点 底层驱动
设备节点就是连接上层应用和底层的桥梁。
2、假如file_operations里面没有read,在应用层read设备节点会发生什么?
什么也不会发生,也不会报错。
3、应用层和内核层不能直接进行数据传输的。
打开include/asm-generic
copy_from_user 用户层向内核层传递数据。
static inline long copy\_from\_user(void \*to,const void __user \* from, unsigned long n)
{
might\_fault();
if (access\_ok(VERIFY_READ, from, n))
return \_\_copy\_from\_user(to, from, n);
else
return n;
}
copy_to_user 内核层向应用层传递数据。
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新!!
存中…(img-S5gN4W2q-1715840583305)]
[外链图片转存中…(img-yRT1SuzI-1715840583306)]
[外链图片转存中…(img-JC8PTYeD-1715840583306)]
[外链图片转存中…(img-U3VHfE8Z-1715840583307)]
[外链图片转存中…(img-C2LDcFYA-1715840583308)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新!!