Linux character Device Driver Analysis

Source: Internet
Author: User

Linux character Device Driver Analysis

1. character device description struct cdev

Struct cdev indicates the internal structure of the character device kernel.

struct cdev { struct kobject kobj; struct module *owner; const struct file_operations *ops; struct list_head list; dev_t dev; unsigned int count;};

2. Three Important structures:

struct file、struct inode、struct file_operations。
<1> struct file indicates an open file, which is created once each time it is opened. It is created when the kernel is open and passed to all functions operated on the file until the final close function. The kernel releases the data structure only when all instances of the file are closed. Filp is usually used to indicate a pointer to this structure.

Struct file {
/*
* Fu_list becomes invalid after file_free is called and queued
* 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; // file-related operations
Spinlock_t f_lock;/* f_ep_links, f_flags, no IRQ */
Atomic_long_t f_count;
Unsigned int f_flags; // file flag: o_rdonly, o_nonblock, o_sync
Fmode_t f_mode;
Loff_t f_pos; // The current read/write location
Struct fown_struct f_owner;
Const struct cred * f_cred;
Struct file_ra_state f_ra;

U64 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;
# Endif/* # ifdef config_epoll */
Struct address_space * f_mapping;
# Ifdef config_debug_writecount
Unsigned long f_mnt_write_state;
# Endif
};

The struct inode structure is used to record the physical information of a file. The kernel uses the kernel inode structure to internally represent a file, which represents the opened file descriptor,

Struct inode {
Struct hlist_node I _hash;
Struct list_head I _list;/* backing Dev Io 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; // indicates the inode STRUCTURE OF THE DEVICE file. This field contains the real device number.
U64 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;
Blkcnt_t I _blocks;
Unsigned int I _blkbits;
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; // struct cdev indicates the kernel structure of the character device kernel. When inode points to a character device file, this field includes a pointer to the struct cdev structure.
};

_ U32 I _generation;

# Ifdef config_fsnotify
_ U32 I _fsnotify_mask;/* all events this inode cares about */
Struct hlist_head I _fsnotify_mark_entries;/* fsnotify mark entries */
# 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
# Ifdef config_fs_posix_acl
Struct posix_acl * I _acl;
Struct posix_acl * I _default_acl;
# Endif
Void * I _private;/* FS or device private pointer */
};

The struct file_operations structure is a collection of function pointers that define the operations that can be performed on the device and the corresponding relational table (convert the corresponding operations in the application to the corresponding functions in the 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 (* sendpage) (struct file *, struct page *, Int, size_t, loff_t *, INT );
Unsigned long (* get_unmapped_area) (struct file *, 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 **);
};

Read and Write Functions in the Virtual File System in the kernel (read_write.c)

ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos){ssize_t ret;if (!(file->f_mode & FMODE_READ))return -EBADF;if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read))return -EINVAL;if (unlikely(!access_ok(VERIFY_WRITE, buf, count)))return -EFAULT;ret = rw_verify_area(READ, file, pos, count);if (ret >= 0) {count = ret;if (file->f_op->read)ret = file->f_op->read(file, buf, count, pos);elseret = do_sync_read(file, buf, count, pos);if (ret > 0) {fsnotify_access(file->f_path.dentry);add_rchar(current, ret);}inc_syscr(current);}return ret;}

 

 

ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos){ ssize_t ret; if (!(file->f_mode & FMODE_WRITE))  return -EBADF; if (!file->f_op || (!file->f_op->write && !file->f_op->aio_write))  return -EINVAL; if (unlikely(!access_ok(VERIFY_READ, buf, count)))  return -EFAULT; ret = rw_verify_area(WRITE, file, pos, count); if (ret >= 0) {  count = ret;  if (file->f_op->write)   ret = file->f_op->write(file, buf, count, pos);  else   ret = do_sync_write(file, buf, count, pos);  if (ret > 0) {   fsnotify_modify(file->f_path.dentry);   add_wchar(current, ret);  }  inc_syscw(current); } return ret;}


 

 

 

 

 

 

 

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.