【10.0】linux驱动

自动创建/dev设备节点

因为在linux里面有两种设备文件系统,devfs和sysfs 
devfs 
1) 需要手动创建设备节点mknod fasync_dev c 250 0 
2) 或者在fasync_dev_init函数中添加: 
#ifdef CONFIG_DEVFS_FS //支持devfs文件系统,在内核里面配置 
devfs_mk_cdev(设备号, S_IFCHR | S_IRUGO | S_IWUSR, 设备名称) 
#endif

sysfs 
sysfs通过class_create和device_create在设备树中创建相应的设备,应用层udev会自动根据设备树的变化生成相应的设备节点。

cdev注册

1、申请设备号

动态 int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, unsigned const char *name)

静态 int register_chrdev_region(dev_t from, unsigned count ,const char *name)

 都使用注销  void unregister_chrdev_region(dev_t from, unsigned count)

2、申请内存空间

struct cdev *cdev_alloc(void)

3、初始化cdev结构体

void cdev_init(struct cdev *cdev, const struct file_operations *fops)

4、添加cdev

int cdev_add(struct cdev *p, dev_T dev, unsigned count)

5、删除cdev

void cdev_del(struct cdev *p)

pdev

1、找到节点

static inline struct device_node *of_find_node_by_path(const char *path)

pdev的节点为pdev->dev.of_node。

of_property_read_s32(pdev->dev.of_node, const char *propname, s32 *out_value);

2、找到节点中属性

static inline struct property *of_find_property(const struct device_node *np,
                       const char *name,
                        int *lenp)

3、读取属性中的32位值,或者字符串

读一个:

static inline int of_property_read_s32(const struct device_node *np,
                       const char *propname,
                       s32 *out_value)

static inline int of_property_read_string(const struct device_node *np,
                      const char *propname,
                      const char **out_string)

读一串:

of_property_read_string_array(const struct device_node * np,

                      const char * propname,

                      const char * * out_strs, size_t sz)

static inline int of_property_read_u32_array(const struct device_node *np,
                         const char *propname,
                         u32 *out_values, size_t sz)

设备树替代pdev

pdev通过platform_driver中的id_table和platform_device的name匹配执行probe

const struct platform_device_id *id_table;

platform_match_id(pdrv->id_table, pdev)
    if (strcmp(pdev->name, id->name) == 0)

dts通过platform_driver中driver成员的of_match_table和dts中节点的compatible匹配执行probe

static const struct of_device_id of_match_leds[] = {
	{ .compatible = ""},
};

struct platform_driver led_drv = {
	.probe		= led_probe,
	.remove		= led_remove,
	.driver		= {
		.name	= "myled",
		.of_match_table = of_match_leds, /* 能支持哪些来自于dts的platform_device */
	}
};

https://www.cnblogs.com/zhu-g5may/p/10316990.html

1、Linux中引入模块机制有什么好处?

首先,模块是预先注册自己以便服务于将来的某个请求,然后他的初始化函数就立即结束。换句话说,模块初始化函数的任务就是为以后调用函数预先作准备

好处:

1) 应用程序在退出时,可以不管资源的释放或者其他的清除工作,但是模块的退出函数却必须仔细此撤销初始化函数所作的一切。

2) 该机制有助于缩短模块的开发周期。即:注册和卸载都很灵活方便。

2、Linux设备中字符设备与块设备有什么主要的区别?请分别列举一些实际的设备说出它们是属于哪一类设备。

字符设备:字符设备是个能够像字节流(类似文件)一样被访问的设备,只能一个一个字节读写数据,不能随机读取设备内存的数据。字符设备驱动程序通常至少实现open,close,read和write系统调用。字符终端、串口、鼠标、键盘、摄像头、声卡和显卡等就是典型的字符设备。

块设备:可以从设备的任意位置读取一定长度数据的设备。硬盘、磁盘、U盘、SD卡都属于块设备。

3、查看驱动模块中打印信息应该使用什么命令?如何查看内核中已有的字符设备的信息?如何查看正在使用的有哪些中断号?

1) 查看驱动模块中打印信息的命令:dmesg。

2) 查看字符设备信息可以用lsmod modprobe,lsmod可以查看模块的依赖关系,modprobe在加载模块时会加载其他依赖的模块。

3) 显示当前使用的中断号cat /proc/interrupt。

4、insmod 一个驱动模块,会执行模块中的哪个函数?rmmod呢?这两个函数在设计上要注意哪些?遇到过卸载驱动出现异常没?是什么问题引起的?

insmod调用init函数,rmmod调用exit函数。这两个函数在设计时要注意什么?卸载模块时曾出现卸载失败的情形,原因是存在进程正在使用模块,检查代码后发现产生了死锁的问题。

要注意在init函数中申请的资源在exit函数中要释放,包括存储,ioremap,定时器,工作队列等等。也就是一个模块注册进内核,退出内核时要清理所带来的影响,带走一切不留下一点痕迹。

5、驱动中操作物理绝对地址为什么要先ioremap?

因为内核没有办法直接访问物理内存地址,必须先通过ioremap获得对应的虚拟地址

6、内核函数mmap的实现原理,机制?

         mmap函数实现把一个文件映射到一个内存区域,从而我们可以像读写内存一样读写文件,他比单纯调用read/write也要快上许多。在某些时候我们可以把内存的内容拷贝到一个文件中实现内存备份,当然,也可以把文件的内容映射到内存来恢复某些服务。另外,mmap实现共享内存也是其主要应用之一,mmap系统调用使得进程之间通过映射同一个普通文件实现共享内存

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值