标签:27 认知 T1 static 内核 驱动 root pin4
1.Linux系统框图
1.1整体架构
- 架构图
- 我们在编写上层应用程序的时候,会调用到各种函数,这些函数由标志C库提供.而C库就通过系统调用接口进而进入内核调用系统函数
- linux系统通过虚拟文件系统将不同设备映射成文件(一切皆文件),存在于
/dev
目录下.既然是文件,那么就可以用open打开.例如打开某个引脚fd = open("/dev/pin1", O_RDWR)
,会返回一个文件描述符,之后我们对引脚的操作就对应于对文件描述符的操作. - 但是系统是怎么通过open函数操作具体引脚呢?其一是通过
/dev
下的文件名或者通过驱动框架寻找,其二是通过设备号寻找
# 主设备号, 次设备号
crw------- 1 root root 10, 175 8月 27 08:27 agpgart
crw-r--r-- 1 root root 10, 235 8月 27 08:27 autofs
drwxr-xr-x 2 root root 260 8月 27 09:27 block
drwxr-xr-x 2 root root 80 8月 27 09:27 bsg
crw-rw---- 1 root disk 10, 234 8月 27 08:27 btrfs-control
drwxr-xr-x 3 root root 60 8月 27 08:26 bus
lrwxrwxrwx 1 root root 3 8月 27 08:27 cdrom -> sr0
lrwxrwxrwx 1 root root 3 8月 27 08:27 cdrw -> sr0
drwxr-xr-x 2 root root 3580 8月 27 09:27 char
- 系统驱动是通过驱动链表管理,我们所做的就是添加驱动和调用驱动
- open--->(软中断0x80)--->sys_call--->VFS--->sys_open(通过设备号寻找)-->驱动函数--->寄存器
- 驱动包含设备名,设备号,设备驱动函数(寄存器相关)
2.驱动框架代码
2.1驱动框架
#include <linux/fs.h> /*file_operations声明*/
#include <linux/module.h> /*module_init,module_exit声明*/
#include <linux/init.h> /*__init,__exit宏定义声明*/
#include <linux/device.h> /*class.device声明*/
#include <linux/uaccess.h> /*copy_from_user的头文件*/
#include <linux/types.h> /*设备号dev_t类型声明*/
#include <linux/io.h> /*ioremap iounmap头文件*/
static struct class *pin4_class;
static struct device *pin4_class_dev;
static dev_t devno; /*设备号*/
static int major = 231; /*主设备号*/
static int minor = 0; /*次设备号*/
static char *module_name = "pin4"; /*模块名*/
static int pin4_open(struct inode *inode, struct file *file)
{
printk("pin4_open\n");/*内核打印函数*/
return 0;
}
static ssize_t pin4_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
printk("pin4_write\n");
return 0;
}
/*
struct Test{
int a;
int b;
int c;
int d;
};
struct Test test1 = {
.a = 1;
.c = 2;
.d = 3;
}
*/
static struct file_operations pin4_flops = {
.owner = THIS_MODULE,
.open = pin4_open, /*对应上层open函数*/
.write = pin4_write, /*对应上层write函数*/
};
static int __init pin4_drv_init(void)
{
int ret;
devno = MKDEV(major, minor);/*创建设备号*/
ret = register_chrdev(major, module_name, &pin4_fops);/*注册驱动,告诉内核将此驱动加入驱动链表*/
pin4_class = class_create(THIS_MODULE, "my first demo");/*自动由代码在/dev下生成设备*/
pin4_class_dev = device_create(pin4_class, NULL, devno, NULL, module_name);/*创建设备文件*/
return 0;
}
static void __exit pin4_drv_exit(void)
{
device_destroy(pin4_class, devno);
class_destroy(pin4_class);
unregister_chrdev(major, module_name);/*卸载驱动*/
}
module_init(pin4_drv_init);/*内核驱动入口*/
module_exit(pin4_drv_exit);
MODULE_LICENSE("GPL v2");
3.嵌入式系统启动流程
3.1启动过程
- 对于嵌入式系统,其内有内存(DDR)区与emmc(flash)区域
- 内存是运行代码的区域,而emmc区域则存放uboot二进制文件,内核二进制文件,根文件系统二进制文件
- 上电的时候uboot会被加载到内存区域运行,将内核引导到内存里面,之后挂载根文件系统
- linux3.0之后uboot在运行的时候也会加载dtb(设备树文件)
3.2设备树文件(dtb)
- dtb用于描述整个系统的外设信息,供内核调用驱动使用
4.驱动常识
4.1驱动代码形式
- 驱动代码在编译之前大部分是C代码,编译后为
.ko
(kernel object)文件或者uImage
uImage
方式是将驱动代码直接编译进内核,成为了内核的一部分.在内核启动的时候执行.ko
方式则是将驱动作为一个独立模块,与内核分离.此法可动态加载驱动,灵活的较高,容易管理,减小内核体积
4.2.ko
文件编写流程
- 编写C代码
- 编译
.ko
文件 - 装载
.ko
文件,此步骤在内核启动之后执行,即只能在内核启动之后才能动态加载内核
5.驱动代码编写
5.1编写工具
- source insight
5.2驱动代码组成
- 头文件
- 驱动模块装载与卸载函数入口声明
- 实现模块装载和卸载函数
- GPL声明
标签:27,认知,T1,static,内核,驱动,root,pin4 来源: https://www.cnblogs.com/Meiyangyang945/p/15092710.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。