Linux系列文章记录自己学习Linux开发的历程。最近终于把迅为4412开发环境搞定了,先吐槽一波迅为,版本太**的多了,安卓Linux搞在一起,还有那个硬件原理图,画的啥玩意,无语。为了省钱,板子是在咸鱼上淘来的,咨询淘宝客服说要订单号,不给我网盘地址。好在,同学也买了这板子,嘻嘻!说偏了,我就是想吐槽一下迅为。
经过这一周的折腾终于搞定了开发环境搭建,可以跑一个最简单的Led字符设备驱动,可以超级中断串口控制led.第一个Linux设备驱动也算完成了。我完全没有使用迅为搭建好的环境,都是自己一步步搭建的,只是使用他们提供的软件资源。最好一步步来,不要我问为什么/狗头。写完这个led驱动程序也算入门了,“微弱的一小步往往的思考的一大步”。最简单的led提供最基本最本质的设备驱动开发思想,有点像当年第一次用C语言打印“Hello World”一样。调试图如下,
以上例子运行原理流程:
记录这个流程!!!
我理解的就是,一种可以使各个硬件协同充分发挥出其硬件性能的程序。硬件物理实体只会处理高低电平和各种器件,只有软件和算法才能成分发挥物理硬件的性能。设备驱动属于OS内核的一部分,运行态处于内核空间,主要任务是帮助OS操纵硬件。Linux设备驱动就是基于Linux系统的开发硬件相关的驱动程序,基于Linux就是要再Linux系统的框架、协约下进行程序编写。So,一定要懂Linux系统,至少最基本的知识、原理、过程和工具要熟悉。这些网上资料很多了。
好了,分析一下上面的led字符驱动程序,程序运行空间分为两个空间——用户态和内核态,app应用程序一般就在用户态使用OS提供的系统服务即API。设备驱动程序运行再内核空间,即本身属于OS的一部分,当然也要遵守OS下的规则和约定,因Linux使用广泛,大部分开发都属于Linux设备驱动,广泛延申以下,很多RTOS也可以,如:RT_Thread.
字符设备是最简单也是最常用的一类设备,有简单的,低级的,也有高级的复杂的。Linux 系统中一切皆文件,耳熟能详,这句话本质的内涵什么意思?就是Linux这个人把属于它范围内的所有对象看成“文件”,如何理解“看成”?Abstract——抽象,是的,只是把所有的设备看成文件而已,无论是字符设备、块设备还是网络设备都是文件。这样的好处——便于系统设计!好了一切皆文件,对象只有一个,好处理多了。基本操作:open()、write()、read()、close(),基本属性:操作权限、大小、索引等等。我个人认为Linux中“一切皆文件”的说法是一种系统设计与实现的指导思想罢了,实现水到渠成而已。
回到以上例子,用户空间app程序调用C库函数,C库又调用系统接口函数,接口函数又映射到Led驱动程序,进而驱动程序去操作硬件,就这么简单,so easy!
不贴代码,只记录自己的思考过程,实现都使用伪代码。贴代码只会影响眼睛的观察,并没多大用。
编写设备驱动程序首先要有一种对Linux的分析方法和思维,分层设计、面向对象在Linux当中无处不在,尤其是面向对象。
内核当中一个很重要的结构体:
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
int (*iterate) (struct file *, struct dir_context *);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*mremap)(struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *, fl_owner_t id);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, loff_t, loff_t, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
int (*setlease)(struct file *, long, struct file_lock **, void **);
long (*fallocate)(struct file *file, int mode, loff_t offset,
loff_t len);
void (*show_fdinfo)(struct seq_file *m, struct file *f);
#ifndef CONFIG_MMU
unsigned (*mmap_capabilities)(struct file *);
#endif
};
实现结构体的几个成员函数,设备的行为就获得了。不过要符合函数指针的签名。
具体的硬件控制逻辑放在每个实现函数中,最后顶一个file_opertation对象注册,然后加载到内核,编译、烧写。
Linux设备驱动程序
Linux网络编程
Linux最小系统制作
Linux开发环境搭建
Linux系统烧写几种方式
Linux开发工具
Linux开发确实很难,比起单片机要补充很多知识。单片机在控制领域无可比拟,一般系统设计中,单片机会作从机从板子系统控制,Linux一般作主控板因为需要实现很多上层应用逻辑。没有好坏之分,只有符合最好的平衡系统设计。