今天编译发现一个error: “asm/semaphore.h: No such file or directory” ,发现2.6.19和2.6.31对这个信号量声明并不相同 [patch] include linux/semaphore.h for kernel 2.6.26 and onwards DescriptionThe kernel/xpp/xpd.h includes <asm/semaphore.h> As of Linux kernel version 2.6.26, the asm/semaphore.h has been deprecated, favoring an include of <linux/semaphore.h> instead. When attempting to compile zaptel in Linux 2.6.27, as the current sources are, we get an error 'unable to include <asm/semaphore.h> (because it has been removed now) This patch performs the check for Linux kernel version 2.6.26, if the version is before this, the existing #include <asm/semaphore.h> is still used, but if Linux kernel version >= 2.6.26 is found, then #include <linux/semaphore.h> is used instead. 一些参考文章: 声明一个信号量,使用DECLARE_MUTEX(ADC_LOCK)或DEFINE_SEMAPHORE(ADC_LOCK),这很好懂,但是这 个宏到底做了些什么呢?这就要深入到这个宏定义所在文件中研究了(在<linux/semaphore.h>文件中)。 对于这两宏,想说几句,因为最近一次移植新版本的内核(2.6.37.3),就是因为DECLARE_MUTEX不再使用而导致我浪费了几天的时间。据本人考查,最早说要将DECLARE_MUTEX改为DEFINE_SEMAPHORE是在08年10月底,参见地址http:///Articles/304725/。而在Linux Cross Reference(网站如http://lxr./等等)中发现,直到2.6.36才出现DEFINE_SEMAPHORE,而且这个版本中两个宏同时存在。但是到了2.6.37,DECLARE_MUTEX这个宏却不存在了。 不由得想到某个论坛的签名,原文是英文的,原文及出自一时不知道去哪找了。大意是说UNIX最好的地方是什么?答曰有社区,再问UNIX不好的地方 是什么?答曰有太多的社区。像Linux内核这东西,版本更新太快了,各种结构体名称变化、成员变化及新增函数、删除函数,让人目不暇接。虽说一味追求新 版本不好,但是心理作用,还是选择新的版本来移植。新的东西当然有它的好,像买台android的手机,就得不停的刷机,不断折腾,这跟搞Linux在某 种程度上是一样的。 http://www./embedded-linux/127-mutil-channel-adc-of-s3c2410-write.html Linux 2.6.36以后file_operations和DECLARE_MUTEX 和kmem_cache_create的变化 今天尝试在2.6.39内核上编译一个驱动, 在编译驱动时发现从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 在运行时初始化得变化(动态分配): 以去除: void
init_MUTEX(struct semaphore *sem); 可通过以下初始: void sema_init(struct semaphore *sem, int val); kmem_cache_t 类型已改为: struct kmem_cache 创建缓存对象函数 kmem_cache_t *kmem_cache_create(const char *name, size_t size, struct kmem_cache *kmem_cache_create(const char *name, size_t size, 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:///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
中的几个重要成员: |
|
来自: WUCANADA > 《embedded》