Linux 2.6.36以后file_operations…

来源:互联网 发布:超市收银机和软件 编辑:程序博客网 时间:2024/06/06 11:00

今天尝试在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(structsemaphore *sem);
void init_MUTEX_LOCKED(structsemaphore *sem);

可通过以下初始:

void sema_init(struct semaphore*sem, int val);

2,后备缓存:include/linux/slab.h

kmem_cache_t 类型已改为:

struct kmem_cache

 

创建缓存对象函数

kmem_cache_t *kmem_cache_create(constchar *name, size_t size,
size_t offset,
unsigned long flags,
void (*constructor)(void *, kmem_cache_t *,
unsigned long flags), void (*destructor)(void *, kmem_cache_t *,unsigned long flags));
已改为(参数少了一个,返回值内型变化):

struct kmem_cache *kmem_cache_create(constchar *name, size_t size,
size_t offset,
unsigned long flags,
void (*)(void ));

 

 

 

2, file_operations结构体有了一些变化,它去掉了:

  int(*ioctl) (struct inode *, struct file *, unsigned int, unsignedlong);

另外添加了:

 

   long (*fallocate)(struct file *file, int mode,loff_t offset,loff_t len);

 


这是2.6.36的内核里的定义include/linux/fs.h:

 

struct file_operations {

    structmodule *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, unsignedlong);

    long(*compat_ioctl) (struct file *, unsigned int, unsignedlong);

    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);

    unsignedlong (*get_unmapped_area)(struct file *, unsigned long, unsignedlong, 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)(structfile *file, int mode, loff_toffset, loff_tlen);  从2.6.38内核开始添加该项,2.6.37以下无

};


下面是Linux-2.6.35里的file_operations

 

struct file_operations {

    structmodule *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, unsignedlong);

    long(*unlocked_ioctl) (struct file *, unsigned int, unsignedlong);

    long(*compat_ioctl) (struct file *, unsigned int, unsignedlong);

    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);

    unsignedlong (*get_unmapped_area)(struct file *, unsigned long, unsignedlong, 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, unsignedlong);

            ioctl: int(*ioctl)(struct inode*,struct file *, unsigned int, unsigned long);

 

 

    The 'inode'value that was passed to 'ioctl' function is available for use withthe 'unlocked_ioctl' function by way offilp->d_entry->d_inode:

    long(*unlocked_ioctl) (struct file *filp, unsigned intcmd, unsigned long arg);
    ...
    struct inode*inode =filp->f_path.dentry->d_inode

There is a nice explanation of this at http://lwn.net/Articles/119652/

 


如:

 

static longdev_ioctl(struct file *file, unsigned int cmd, unsigned longarg)

{

   int  index =NUM(file->f_path.dentry->d_inode->i_rdev);

  .....

}

 

--------------------------------------

 

在file_operations 结构体中,会看到许多函数指针所指向的函数都必须传进structfile 结构体指针struct file* 作为参数。structfile 结构体定义在<linux/fs.h> 中,完整如下:

引用

struct file {
       
        
union {
               
struct list_head        fu_list;
               
struct rcu_head        fu_rcuhead;
        
} f_u;
        
struct path             f_path;
#definef_dentry       f_path.dentry
#definef_vfsmnt       f_path.mnt
        
const struct file_operations    *f_op;
        
spinlock_t             f_lock;
        
atomic_long_t           f_count;
        
unsigned int           f_flags;
        
fmode_t                f_mode;
        
loff_t                 f_pos;
        
struct fown_struct      f_owner;
        
const struct cred       *f_cred;
        
struct file_ra_state    f_ra;

        
u64                    f_version;
#ifdefCONFIG_SECURITY
        
void                   *f_security;
#endif
       
        
void                   *private_data;

#ifdefCONFIG_EPOLL
       
        
struct list_head        f_ep_links;
#endif
        
struct address_space    *f_mapping;
#ifdefCONFIG_DEBUG_WRITECOUNT
        
unsigned long f_mnt_write_state;
#endif
};


在设备驱动中,structfile 结构体也是一个非常重要的数据结构。注意的是,这里的file 和应用程序中的FILE 流指针没有什么关系,FILE 定义在C 库中,它永远不会出现在内核代码中。

file structure 结构代表一个打开的文件(openfile).(打开的文件并没有确切的指定到哪个设备驱动,实际上每个打开的文件都与内核空间中的structfile 结构相关联)。

filestructure 结构在调用open 打开一个文件时由内核创建,并会被传递给任一个对这个打开文件进行操作的函数;当所有事情都做完后,会调用close() 关闭掉文件,此时内核释放这个数据结构。

一般地,在内核源码中,structfile 结构体的指针往往写成filp 

structfile 中的几个重要成员

mode_tf_mode;
文件模式根据FMMODE_READ 和FMODE_WRITE 位来识别文件是否可读或可写,或是可读可写。在read() 和write() 系统调用中,没有必要对此权限进行检查,因为内核已经在你的系统调用之前已经做了检查。如果文件没有相应的读或写权限,那么如果尝试读写都将被拒绝,驱动程序甚至对此情况毫无知觉。

loff_tf_pos;
此变量表示当前的文件读写位置。loff_t 在所有的平台上都是64 位的变量(long long 型,gcc 专用术语)。驱动程序如果想知道当前在文件中所处位置,那么可以通过读取此变量得知,但是一般地不应直接对此进行更改。通过llseek() 方法可以改变文件位置。

unsigned intf_flags;
这是表示如O_RDONLY,O_NONBLOCK与O_SYNC 这样的标志。一个驱动程序应该检查O_NONBLOCK 标志,以查看是否有非阻塞操作的请求。其它的标志用得比较少。需要注意的是,检查read/write 权限应该是通过检查f_mode 得到而不是f_flags 。所有的标志定义在头文件linux/fcntl.h 中可以看到。

structfile_operations*f_op;
内核安排这个指针作为它的open 实现的一部分,当需要分派什么操作时,会读取它。filp->f_op 因为不会被内核保存起来以在其后之用,所以我们可以改变我们对相关文件的操作,在对文件使用新的操作方法时,我们就会转移到相应调用上。

void*private_data;
在对驱动调用open 方法之前,open() 系统调用会这个指针设置为NULL 。用户可以自由使用这个域,或者对其忽略。可以使用这个域之想分配的数据空间,但必须记得在内核销毁filestructure 之前在release 方法里释放掉原来分配的内存。private_data 对于系统调用之间信息的保存会显得非常有用。

structdentry*f_dentry;
目录入口(dentry) 结构与文件相关。一般的,除了在以filp->f_dentry->d_inode 来访问inode 结构时,我们不太关心dentry 这个结构。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 入职体检高血糖怎么办 睾丸捏一下很疼怎么办 小孩睾丸受外力红肿该怎么办 睾丸炎症怎么办啊会不会不育呢 腰疼连着睾丸疼怎么办 为什么结石会睾丸疼怎么办 感觉自己睾丸变小了怎么办 宝宝小丁丁肿了怎么办 两岁宝宝高低肩怎么办 参军体检视力不过关怎么办 验兵视力不过关怎么办 军检了感冒了怎么办 双侧附睾头囊肿怎么办 睾丸上面长疙瘩很痒都抓烂了怎么办 睾丸小引起精子数量少怎么办 睾丸发育不完全精子存活率低怎么办 踢到睾丸很痛怎么办 兔子的睾丸烂了怎么办 梗阻性无精穿刺取得精子不好怎么办 甲状腺做完穿刺后是恶性怎么办 硬了之后睾丸痛怎么办 腋下胯间颜色深怎么办 当兵前上班有社保怎么办 别人背后害我我怎么办 左侧胸明显大于右侧胸怎么办 婴儿拉大便次数多怎么办 公鸽子不会踩蛋怎么办 生殖器套东西取不下来怎么办 婴儿成蛋蛋的皮好长怎么办 丈夫总要害自己该怎么办 脚背踢肿了怎么办很疼 踢沙袋脚背伤了怎么办 脚y子烂了怎么办 掐喉咙那会痒会咳嗽怎么办 掐到婴儿脖子了怎么办 孩子胳膊不小心烫破皮了怎么办 孩子嘴角磕破了怎么办 电话不小心拒接了怎么办 手机微信不小心碰到语言英文怎么办 手机微信不小心碰到英文说话怎么办 不小心碰到宝宝卤门怎么办