char device driver

// 三個最重要的數據結構。

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 (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
 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 (*dir_notify)(struct file *filp, unsigned long arg);
 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);
};


struct file {
 /*
  * fu_list becomes invalid after file_free is called and queued via
  * fu_rcuhead for RCU freeing
  */
 union {
  struct list_head fu_list;
  struct rcu_head  fu_rcuhead;
 } f_u;
 struct path  f_path;
#define f_dentry f_path.dentry
#define f_vfsmnt f_path.mnt
 const struct file_operations *f_op;
 atomic_t  f_count;
 unsigned int   f_flags;
 mode_t   f_mode;
 loff_t   f_pos;
 struct fown_struct f_owner;
 unsigned int  f_uid, f_gid;
 struct file_ra_state f_ra;

 unsigned long  f_version;
#ifdef CONFIG_SECURITY
 void   *f_security;
#endif
 /* needed for tty driver, and maybe others */
 void   *private_data;

#ifdef CONFIG_EPOLL
 /* Used by fs/eventpoll.c to link all the hooks to this file */
 struct list_head f_ep_links;
 spinlock_t  f_ep_lock;
#endif /* #ifdef CONFIG_EPOLL */
 struct address_space *f_mapping;
};


struct inode {
 struct hlist_node i_hash;
 struct list_head i_list;
 struct list_head i_sb_list;
 struct list_head i_dentry;
 unsigned long  i_ino;
 atomic_t  i_count;
 unsigned int  i_nlink;
 uid_t   i_uid;
 gid_t   i_gid;
 dev_t   i_rdev;
 unsigned long  i_version;
 loff_t   i_size;
#ifdef __NEED_I_SIZE_ORDERED
 seqcount_t  i_size_seqcount;
#endif
 struct timespec  i_atime;
 struct timespec  i_mtime;
 struct timespec  i_ctime;
 unsigned int  i_blkbits;
 blkcnt_t  i_blocks;
 unsigned short          i_bytes;
 umode_t   i_mode;
 spinlock_t  i_lock; /* i_blocks, i_bytes, maybe i_size */
 struct mutex  i_mutex;
 struct rw_semaphore i_alloc_sem;
 const struct inode_operations *i_op;
 const struct file_operations *i_fop; /* former ->i_op->default_file_ops */
 struct super_block *i_sb;
 struct file_lock *i_flock;
 struct address_space *i_mapping;
 struct address_space i_data;
#ifdef CONFIG_QUOTA
 struct dquot  *i_dquot[MAXQUOTAS];
#endif
 struct list_head i_devices;
 union {
  struct pipe_inode_info *i_pipe;
  struct block_device *i_bdev;
  struct cdev  *i_cdev;
 };
 int   i_cindex;

 __u32   i_generation;

#ifdef CONFIG_DNOTIFY
 unsigned long  i_dnotify_mask; /* Directory notify events */
 struct dnotify_struct *i_dnotify; /* for directory notifications */
#endif

#ifdef CONFIG_INOTIFY
 struct list_head inotify_watches; /* watches on this inode */
 struct mutex  inotify_mutex; /* protects the watches list */
#endif

 unsigned long  i_state;
 unsigned long  dirtied_when; /* jiffies of first dirtying */

 unsigned int  i_flags;

 atomic_t  i_writecount;
#ifdef CONFIG_SECURITY
 void   *i_security;
#endif
 void   *i_private; /* fs or device private pointer */
};


//----------------------------------------------------------------------
// <linux/dev.h>

struct cdev {
 struct kobject kobj;
 struct module *owner;
 const struct file_operations *ops;  // 操作的函數
 struct list_head list;  
 dev_t dev;                          // 設備編號
 unsigned int count;                 // 設備的數目
};

 

 

 

/**
 * cdev_init() - initialize a cdev structure
 * @cdev: the structure to initialize
 * @fops: the file_operations for this device
 *
 * Initializes @cdev, remembering @fops, making it ready to add to the
 * system with cdev_add().
 */
void cdev_init(struct cdev *cdev, const struct file_operations *fops)
{
 memset(cdev, 0, sizeof *cdev);
 INIT_LIST_HEAD(&cdev->list);
 cdev->kobj.ktype = &ktype_cdev_default;
 kobject_init(&cdev->kobj);
 cdev->ops = fops;
}

 

 


/**
 * cdev_add() - add a char device to the system
 * @p: the cdev structure for the device
 * @dev: the first device number for which this device is responsible
 * @count: the number of consecutive minor numbers corresponding to this
 *         device
 *
 * cdev_add() adds the device represented by @p to the system, making it
 * live immediately.  A negative error code is returned on failure.
 */
int cdev_add(struct cdev *p, dev_t dev, unsigned count)
{
 p->dev = dev;
 p->count = count;
 return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章