今天尝试移植了2.6.38的内核到AT91SAM9260上,在编译驱动时发现从2.6.36的内核开始,include/linux/semaphore.h 和 include/linux/fs.h中有了两处变化与驱动相关: 1, 在include/linux/semaphore.h 中 将#define DECLARE_MUTEX(name) 改成了 #define DEFINE_SEMAPHORE(name)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) DECLARE_MUTEX(led_sem); #else DEFINE_SEMAPHORE(led_sem); #endif
2, file_operations结构体有了一些变化,它去掉了: int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); 另外添加了: long (*fallocate)(struct file *file, int mode, loff_t offset,loff_t len);
这是2.6.36的内核里的定义include/linux/fs.h: 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 (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t); int (*readdir) (struct file *, void *, filldir_t); unsigned int (*poll) (struct file *, struct poll_table_struct *); //从2.6.36开始删除ioctl(), 2.6.35中有 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 (*open) (struct inode *, struct file *); int (*flush) (struct file *, fl_owner_t id); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, 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 **); // long (*fallocate)(struct file *file, int mode, loff_t offset, loff_t len); 从2.6.38内核开始添加该项,2.6.37以下无 };
下面是Linux-2.6.35里的file_operations 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 (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t); int (*readdir) (struct file *, void *, filldir_t); unsigned int (*poll) (struct file *, struct poll_table_struct *); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); 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 (*open) (struct inode *, struct file *); int (*flush) (struct file *, fl_owner_t id); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, struct dentry *, 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 **); };
[guowenxue@localhost at91sam9260]$ make make[1]: Entering directory `/usr/.devices_group/guowenxue/l350-dev06/src/kernel/linux-2.6.38' CC [M] /usr/.devices_group/guowenxue/embedded_project/drivers/at91sam9260/dev_skeleton.o /usr/.devices_group/guowenxue/embedded_project/drivers/at91sam9260/dev_skeleton.c:93: error: unknown field 'ioctl' specified in initializer /usr/.devices_group/guowenxue/embedded_project/drivers/at91sam9260/dev_skeleton.c:93: warning: initialization from incompatible pointer type make[2]: *** [/usr/.devices_group/guowenxue/embedded_project/drivers/at91sam9260/dev_skeleton.o] Error 1 make[1]: *** [_module_/usr/.devices_group/guowenxue/embedded_project/drivers/at91sam9260] Error 2 make[1]: Leaving directory `/usr/.devices_group/guowenxue/l350-dev06/src/kernel/linux-2.6.38' make: *** [modules] Error 2
参考别的字符设备的驱动drivers/char/ppdev.c: static const struct file_operations pp_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .read = pp_read, .write = pp_write, .poll = pp_poll, .unlocked_ioctl = pp_ioctl, .open = pp_open, .release = pp_release, }; 这里ioctl()已使用unlocked_ioctl代替。
但这里不是一个简单的替换,要注意unlocked_ioctl和ioctl的函数原型并不一致。
unlocked_ioctl: long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
The 'inode' value that was passed to 'ioctl' function is available for use with the 'unlocked_ioctl' function by way of filp->d_entry->d_inode: long (*unlocked_ioctl) (struct file *filp, unsigned int cmd, unsigned long arg); There is a nice explanation of this at http://lwn.net/Articles/119652/
如: static long dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int index = NUM(file->f_path.dentry->d_inode->i_rdev); /*Which LED*/ ..... } -------------------------------------- 在file_operations 结构体中,会看到许多函数指针所指向的函数都必须传进struct file 结构体指针struct file * 作为参数。struct file 结构体定义在<linux/fs.h> 中,完整如下: 引用 struct file {
struct file 中的几个重要成员:
转自:http://hi.baidu.com/kkernel/blog/item/6213dc9797ed7f7a55fb962e.html |