当系统调用读取了接收帧后,释放该节点空间,使设备驱动程序可以重新使用该节点。
2.4 服务于I/O请求的设备驱动程序部分
这部分实际上是应用程序唯一可见的,应用程序通过系统来调用这部分程序,是设备驱动程序对应用程序的接口。本驱动程序提供文件操作接口。Linux系统中,字符型设备驱动程序提供的文件操作入口点由一个结构来向系统说明,此结构定义为:
struct file_operations {
int (*lseek)(struct inode *inode,struct file *filp, off_t off,int pos);
int (*read)(struct inode *inode,struct file *filp, char *buf, int count);
int (*write)(struct inode *inode,struct file *filp, char *buf,int count);
int (*readdir)(struct inode *inode,struct file *filp,struct dirent *dirent,int count);
int (*select)(struct inode *inode,struct file *filp, int sel_type,select_table *wait);
int (*ioctl) (struct inode *inode,struct file *filp, unsigned int cmd,unsigned int arg);
int (*mmap) (void);
int (*open) (struct inode *inode, struct file *filp);
void (*release) (struct inode *inode, struct file *filp); int (*fsync) (struct inode *inode, struct file *filp);
};
该结构定义了10个操作入口点,但是驱动程序没有必要对每个入口点进行定义。根据需要,本驱动程序定义了如下的入口点。
can_open(struct inode *inode, struct file *filp)入口点负责打开can设备,检查can卡是否已被打开,完成can卡的初始化,设置设备的占用标志。can_release(struct inode *inode, struct file *filp)入口点负责关闭can设备。
can_read(struct inode *, struct file *, off_t, int) 入口点负责检查设备有没有接收到完整的帧,can_read函数只是判断是否有完整的数据帧可读。要获取数据帧,可以使用ioctl 的CAN_READFRAME命令。can_write(struct inode*, struct file *, const char *, int) 入口点负责向CAN发送数据。如果发送队列有足够的空间,则向设备传送数据,也可以使用ioctl的CAN_WRITEFRAME命令来实现can_write。
can_ioctl(struct inode *, struct file *, unsigned int cmd, unsigned long arg)入口点负责向CAN设备下发各种操作命令,命令代码通过cmd参数传送,命令参数通过arg参数传送。本驱动程序提供了一些命令,配合can_read()和can_write() 可以实现对CAN通信卡的控制。CAN_IOCREADFRAME命令可以从CAN通信卡上读取数据帧;CAN_IOCWRITEFRAME命令可以向CAN通信卡发送数据;CAN_IOCSETCONF命令可以设置CAN通信卡的运行参数;CAN_IOCGETCONF命令可以获取CAN控制器的运行参数;CAN_IOCQUERYBUSSTATE命令可以查询CAN总线状态;CAN_IOCCLEARBUF命令可以清除CAN通信卡的收发缓冲区。
本设备驱动程序考虑到CAN通信卡的特点和CAN网络传输数据的特点,设计了合理的数据结构和缓存管理方法,使得当有大量数据进出CAN通信卡时,既可以保证数据帧丢失和出错几率在允许范围内,又可以保证数据帧能被快速下发和接收,实际应用中性能很好。Linux擅长通信,支持大多数以太网卡。如果将CAN通信卡的设备驱动程序加入到Linux系统,由于Linux的可裁减性和对硬件资源要求低的特点,可以用小硬盘、小内存和低档CPU构成通信机连接高速以太网和低速现场总线CAN网络,经济实惠而且实用。