信号驱动IO
【1】信号驱动IO
应用程序:1)应用程序要捕捉SIGIO信号
signal(SIGIO, handler);
2)应用程序要指定进程为文件的属主,设置当前的文件描述为当前的调用进程
fcntl(STDIN_FILENO, F_SETOWN, getpid());
与之对应,在驱动,在struct file结构体,f_owner被设置成当前进程
3)应用程序通过fcntl函数在设备中设置FASYNC标志
oflags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, oflags | FASYNC);
驱动: 1)支持F_SETOWN命令,能在这个控制命令处理中设置filp->f_owner为对应进程ID。
不过此项工作已由内核完成,设备驱动无须处理。
2)支持F_SETFL命令的处理,每当FASYNC标志改变时,驱动程序中的fasync()函数将得以执行。
因此,驱动中应该实现fasync()函数。
int (*fasync) (int, struct file *, int);
int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp)
功能:将fd添加或删除,到异步通知队列
void kill_fasync(struct fasync_struct **fp, int sig, int band)
功能:发送信号
参数:fp 异步通知队列
sig 信号的类型
band 位掩码 POLLIN 可以读
POLLOUT 可以写
【2】Linux设备模型 platform
linux设备模型,分为三个实体:驱动,设备,总线
集成在SOC中读的设备,都可以称之为platform设备,通过总线将驱动和设备完成匹配,当向内核注册设备,通过总线匹配对应驱动程序
当内核注册驱动,通过总线匹配相对应的设备
总线:
总线可以是物理存在的,也可以是虚拟的。内核中对应的结构为struct bus_type。
struct bus_type {
const char *name; 总线名称
int (*match)(struct device *dev, struct device_driver *drv); 匹配方式
设备:
设备是连接到某条物理或者虚拟总线上的对象。可能是真正物理对象,也可能是虚拟对象。内核中对应的结构为struct device。
struct device {
struct bus_type *bus;
struct device_driver *driver; /* which driver has allocated this
驱动:
驱动是用来和设备通信的软件程序。驱动可以从设备中获取数据,也可以把相应数据发给设备进行处理。内核中对应的结构为struct devicc_driver
platform架构:
总线
struct bus_type platform_bus_type = {
.name = "platform", 总线
.dev_groups = platform_dev_groups,
.match = platform_match, 匹配方式
驱动
struct platform_driver {
int (*probe)(struct platform_device *); 回调函数,一旦设备与驱动匹配成功,调用此函数
int (*remove)(struct platform_device *); 移除函数
struct device_driver driver; 继承device_driver
const struct platform_device_id *id_table; 匹配表
};
设备
struct platform_device {
const char *name; 设备名称
int id; 设备名的后缀
struct device dev; 继承
u32 num_resources; 资源的数量
struct resource *resource; 设备资源
const struct platform_device_id *id_entry; 匹配表
};
描述硬件资源
struct resource {
resource_size_t start; 设备的起始地址
resource_size_t end; 设备的末尾地址
const char *name;
unsigned long flags; 标志位
struct resource *parent, *sibling, *child;
};
#define IORESOURCE_MEM 0x00000200
#define IORESOURCE_IRQ 0x00000400
platform驱动开发流程:
1)定义注册总线
2)定义注册设备
int platform_device_register(struct platform_device *pdev)
int platform_device_unregister(struct platform_device *pdev)
3)定义注册驱动
#define platform_driver_register(drv) \
__platform_driver_register(drv, THIS_MODULE
int __platform_driver_register(struct platform_driver *drv,
struct module *owner)
void platform_driver_unregister(struct platform_driver *drv)