分类: LINUX
2008-11-04 21:47:52
Lkd学习
对象模型学习:
struct kobject {
char *k_name;
char name[KOBJ_NAME_LEN];
struct kref kref;
struct list_head entry;
struct kobject *parent;
struct kset *kset;
struct kobj_type *ktype;
struct dentry *dentry;
};
k_name代表了在个kobject的名字;
如果k_name的长度小于KOBJ_NAME_LEN,这样的话名字就存储在name里面,而k_name则指向这里(这倒是一个好办法,只多了一个指针就能处理所有的情况,而且还在多数情况下用name而不会造成多少空间的浪费,高明!);
Parent成员是用来指向它的父亲的,这样就形成了一个树型结构;
Dentry成员指向它在sysfs中的dentry结构也就是目录信息;
Kref类型:
struct kref {
atomic_t refcount;
};
表示对这个object的引用数目,当这个数为0
的时候就会被释放内存(调用的函数是ktype指向的release函数);
使用它之前需要初始化:
void kref_init(struct kref *kref)
{
atomic_set(&kref->refcount, 1);
}
//以下是增加对kref的引用;
void kref_get(struct kref *kref)
{
WARN_ON(!atomic_read(&kref->refcount));
atomic_inc(&kref->refcount);
}
//以下是减少对kref的引用;
void kref_put(struct kref *kref, void (*release) (struct kref *kref))
{
WARN_ON(release == NULL);
WARN_ON(release == (void (*)(struct kref *))kfree);
if (atomic_dec_and_test(&kref->refcount))
release(kref);
}
Ktype的类型:
struct kobj_type {
void
(*release)(struct kobject *);//当kobject的引用为0的时候就会被执行,用于释放内存等等;
struct
sysfs_ops *sysfs_ops;//这里的描述请见后面
struct
attribute **default_attrs;//这里就是一些属性,如果通过sysfs查看的话就是那些在文件目录下的文件,里面是设置的值,最后一个entry必须为null;
};
struct sysfs_ops类型:
struct sysfs_ops {
/* method invoked on read of a sysfs file */
ssize_t (*show) (struct kobject *kobj,
struct attribute *attr,
char *buffer);
/* method invoked on write of a sysfs file */
ssize_t (*store) (struct kobject *kobj,
struct attribute *attr,
const char *buffer,
size_t size);
};
这里的show函数在用户调用read的时候会被调用,比如用户调用cat /sys/***的时候就会调用这个函数;
同样store就是实现的那个写的函数;
struct attribute的类型:
struct attribute {
char *name; /* attribute's name */
struct module *owner; /* owning module, if any */
mode_t mode; /* permissions */
};
这个函数用来创建一个特定的属性,也就是我们看到的sys目录下的某个特定的文件:
int sysfs_create_file(struct kobject *kobj, const struct attribute *attr);
相反的动作是由:
void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr);
来完成的;
Kset的类型:
struct kset {
struct subsystem *subsys;
struct kobj_type *ktype;
struct list_head list;
struct kobject kobj;
struct kset_hotplug_ops *hotplug_ops;
};
它的存在的目的是想把这个kobject归于某一类,从list这个成员就可以看出,它将要被链在一个链表中去的;
struct subsystem的类型:
struct subsystem {
struct kset kset;
struct rw_semaphore rwsem;
};
struct cdev {
struct kobject kobj;
struct module *owner;
struct file_operations *ops;
struct list_head list;
dev_t dev;
unsigned int count;
};
这里是想说明kobject对象本身并不那么重要,它只是寄存在别人的身上;
Kobject的使用例子:
kobj = kmalloc(sizeof (*kobj), GFP_KERNEL);
if (!kobj)
return -ENOMEM;
memset(kobj, 0, sizeof (*kobj));
kobj->kset = kset;
kobj->parent = parent_kobj;
kobject_init(kobj);
//然后就是设置名字,调用函数:
int kobject_set_name(struct kobject * kobj, const char * fmt, ...);
//以下是去增加一个kobject的引用记数的;
struct kobject * kobject_get(struct kobject *kobj);
//以下是去减少一个kobject的引用记数的;
void kobject_put(struct kobject *kobj);
kobject的生成并不会直接export到sysfs,而需要调用下面这个函数:
int kobject_add(struct kobject *kobj);
这个kobject的位置是由它里面的
parent成员决定的,如果它不存在则由成员kset里面的kobject来决定的,也就是说会自动加到它的parent的子目录里面去的,如果这两个成员都为null则认为它是根设备了;
一般情况下你只需要调用
int kobject_register(struct kobject *kobj)
就完成了kobject的初始化和加入到sysfs中去的工作;
同样的
void kobject_del(struct kobject *kobj);//从sysfs去掉
和
kobject_put()//释放kobject
两个函数的功能就等同于
void kobject_unregister(struct kobject * kobj)
事件模型
Kernel用netlink来实现内核和用户层之间的交互;
也就是用户只需要调用socket传AF_NETLINK作为参数就可以监听和传递内核消息了;
从内核里面向用户空间发送消息只需要调用:
int kobject_uevent(struct kobject *kobj,
enum kobject_action action,
struct attribute *attr);
这个版本是可以睡眠的,而不能睡眠的版本是:
int kobject_uevent_atomic(struct kobject *kobj,
enum kobject_action action,
struct attribute *attr);
VFS的学习
Unix提供了四种抽象:
文件,目录,i节点,挂载点;
在linu里面目录也是文件;
I节点主要是存储file metadata;
而超块存储的是fs metadata,也包括单独的文件信息;
The four primary object types of the VFS are
· The superblock object, which represents a specific mounted filesystem.
· The inode object, which represents a specific file.
· The dentry object, which represents a directory entry, a single component of a path.
· The file object, which represents an open file as associated with a process.
我觉得这段话说得非常清楚!
也就是说:
超块是描述特定的挂载的文件系统;
I节点描述一个特定的文件;
目录结构代表一个路径的实体;
File结构代表一个打开的文件相关联于一个特定的进程;
· The super_operations object, which contains the methods that the kernel can invoke on a specific filesystem, such as read_inode() and sync_fs().
· The inode_operations object, which contains the methods that the kernel can invoke on a specific file, such as create() and link().
· The dentry_operations object, which contains the methods that the kernel can invoke on a specific directory entry, such as d_compare() and d_delete().
· The file object, which contains the methods that a process can invoke on an open file, such as read() and write().
这段话的意思是说:
对于超块的操作都由超块本身提供,比如read_inode,sync_fs;
对于inode的操作都由inode来提供,比如create,link;
对于dentry的操作由dentry来提供,比如d_compare,d_delete;
对于file的操作是由file来提供,比如read,write;
这也说明了vfs的实现都是面向对象风格的;
下面分别讲解这几个数据结构:
struct super_block {
struct list_head s_list; /* list of all superblocks */
dev_t s_dev; /* identifier */
unsigned long s_blocksize; /* block size in bytes */
unsigned long s_old_blocksize; /* old block size in bytes */
unsigned char s_blocksize_bits; /* block size in bits */
unsigned char s_dirt; /* dirty flag */
unsigned long long s_maxbytes; /* max file size */
struct file_system_type s_type; /* filesystem type */
struct super_operations s_op; /* superblock methods */
struct dquot_operations *dq_op; /* quota methods */
struct quotactl_ops *s_qcop; /* quota control methods */
struct export_operations *s_export_op; /* export methods */
unsigned long s_flags; /* mount flags */
unsigned long s_magic; /* filesystem's magic number */
struct dentry *s_root; /* directory mount point */
struct rw_semaphore s_umount; /* unmount semaphore */
struct semaphore s_lock; /* superblock semaphore */
int s_count; /* superblock ref count */
int s_syncing; /* filesystem syncing flag */
int s_need_sync_fs; /* not-yet-synced flag */
atomic_t s_active; /* active reference count */
void *s_security; /* security module */
struct list_head s_dirty; /* list of dirty inodes */
struct list_head s_io; /* list of writebacks */
struct hlist_head s_anon; /* anonymous dentries */
struct list_head s_files; /* list of assigned files */
struct block_device *s_bdev; /* associated block device */
struct list_head s_instances; /* instances of this fs */
struct quota_info s_dquot; /* quota-specific options */
char s_id[32]; /* text name */
void *s_fs_info; /* filesystem-specific info */
struct semaphore s_vfs_rename_sem; /* rename semaphore */
};
超块分配:
alloc_super();
超块最重要的操作函数列表:
struct super_operations {
struct inode *(*alloc_inode) (struct super_block *sb);
void (*destroy_inode) (struct inode *);
void (*read_inode) (struct inode *);
void (*dirty_inode) (struct inode *);
void (*write_inode) (struct inode *, int);
void (*put_inode) (struct inode *);
void (*drop_inode) (struct inode *);
void (*delete_inode) (struct inode *);
void (*put_super) (struct super_block *);
void (*write_super) (struct super_block *);
int (*sync_fs) (struct super_block *, int);
void (*write_super_lockfs) (struct super_block *);
void (*unlockfs) (struct super_block *);
int (*statfs) (struct super_block *, struct statfs *);
int (*remount_fs) (struct super_block *, int *, char *);
void (*clear_inode) (struct inode *);
void (*umount_begin) (struct super_block *);
int (*show_options) (struct seq_file *, struct vfsmount *);
};
I节点的成员:
struct inode {
struct hlist_node i_hash; /* hash list */
struct list_head i_list; /* list of inodes */
struct list_head i_dentry; /* list of dentries *///i节点对应的dentry,有可能有连接存在所以是一个链表;
unsigned long i_ino; /* inode number */
atomic_t i_count; /* reference counter */
umode_t i_mode; /* access permissions */
unsigned int i_nlink; /* number of hard links */
uid_t i_uid; /* user id of owner */
gid_t i_gid; /* group id of owner */
kdev_t i_rdev; /* real device node */
loff_t i_size; /* file size in bytes */
struct timespec i_atime; /* last access time */
struct timespec i_mtime; /* last modify time */
struct timespec i_ctime; /* last change time */
unsigned int i_blkbits; /* block size in bits */
unsigned long i_blksize; /* block size in bytes */
unsigned long i_version; /* version number */
unsigned long i_blocks; /* file size in blocks */
unsigned short i_bytes; /* bytes consumed */
spinlock_t i_lock; /* spinlock */
struct rw_semaphore i_alloc_sem; /* nests inside of i_sem */
struct semaphore i_sem; /* inode semaphore */
struct inode_operations *i_op; /* inode ops table */
struct file_operations *i_fop; /* default inode ops */
struct super_block *i_sb; /* associated superblock */
struct file_lock *i_flock; /* file lock list */
struct address_space *i_mapping; /* associated mapping */
struct address_space i_data; /* mapping for device */
struct dquot *i_dquot[MAXQUOTAS]; /* disk quotas for inode */
struct list_head i_devices; /* list of block devices */
struct pipe_inode_info *i_pipe; /* pipe information */
struct block_device *i_bdev; /* block device driver */
unsigned long i_dnotify_mask; /* directory notify mask */
struct dnotify_struct *i_dnotify; /* dnotify */
unsigned long i_state; /* state flags */
unsigned long dirtied_when; /* first dirtying time */
unsigned int i_flags; /* filesystem flags */
unsigned char i_sock; /* is this a socket? */
atomic_t i_writecount; /* count of writers */
void *i_security; /* security module */
__u32 i_generation; /* inode version number */
union {
void *generic_ip; /* filesystem-specific info */
} u;
};
I节点的操作函数;
struct inode_operations {
int (*create) (struct inode *, struct dentry *,int);
struct dentry * (*lookup) (struct inode *, struct dentry *);
int (*link) (struct dentry *, struct inode *, struct dentry *);
int (*unlink) (struct inode *, struct dentry *);
int (*symlink) (struct inode *, struct dentry *, const char *);
int (*mkdir) (struct inode *, struct dentry *, int);
int (*rmdir) (struct inode *, struct dentry *);
int (*mknod) (struct inode *, struct dentry *, int, dev_t);
int (*rename) (struct inode *, struct dentry *,
struct inode *, struct dentry *);
int (*readlink) (struct dentry *, char *, int);
int (*follow_link) (struct dentry *, struct nameidata *);
int (*put_link) (struct dentry *, struct nameidata *);
void (*truncate) (struct inode *);
int (*permission) (struct inode *, int);
int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);
int (*setxattr) (struct dentry *, const char *,
const void *, size_t, int);
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
int (*removexattr) (struct dentry *, const char *);
};
struct dentry {
atomic_t d_count; /* usage count */
unsigned long d_vfs_flags; /* dentry cache flags */
spinlock_t d_lock; /* per-dentry lock */
struct inode *d_inode; /* associated inode */
struct list_head d_lru; /* unused list */
struct list_head d_child; /* list of dentries within */
struct list_head d_subdirs; /* subdirectories */
struct list_head d_alias; /* list of alias inodes */
unsigned long d_time; /* revalidate time */
struct dentry_operations *d_op; /* dentry operations table */
struct super_block *d_sb; /* superblock of file */
unsigned int d_flags; /* dentry flags */
int d_mounted; /* is this a mount point? */
void *d_fsdata; /* filesystem-specific data */
struct rcu_head d_rcu; /* RCU locking */
struct dcookie_struct *d_cookie; /* cookie */
struct dentry *d_parent; /* dentry object of parent */
struct qstr d_name; /* dentry name */
struct hlist_node d_hash; /* list of hash table entries */
struct hlist_head *d_bucket; /* hash bucket */
unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* short name */
};
Dentry有三种状态,used,unused,negative;
·
Lists
of "used" dentries that are linked off their associated inode via the
i_dentry
field of the inode object. Because a given inode can have multiple links, there
might be multiple dentry objects; consequently, a list is used.
·
A
doubly linked "least recently used" list of unused and negative
dentry objects. The list is insertion sorted by time, such that entries toward
the head of the list are newest. When the kernel must remove entries to reclaim
memory, the entries are removed from the tail; those are the oldest and
presumably have the least chance of being used in the near future.
·
A hash
table and hashing function used to quickly resolve a given path into the
associated dentry object.
Dentry操作函数:
struct dentry_operations {
int (*d_revalidate) (struct dentry *, int);
int (*d_hash) (struct dentry *, struct qstr *);
int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);
int (*d_delete) (struct dentry *);
void (*d_release) (struct dentry *);
void (*d_iput) (struct dentry *, struct inode *);
};
The file object is
used to represent a file opened by a process.
struct file {
struct list_head f_list; /* list of file objects */
struct dentry *f_dentry; /* associated dentry object */
struct vfsmount *f_vfsmnt; /* associated mounted fs */
struct file_operations *f_op; /* file operations table */
atomic_t f_count; /* file object's usage count */
unsigned int f_flags; /* flags specified on open */
mode_t f_mode; /* file access mode */
loff_t f_pos; /* file offset (file pointer) */
struct fown_struct f_owner; /* owner data for signals */
unsigned int f_uid; /* user's UID */
unsigned int f_gid; /* user's GID */
int f_error; /* error code */
struct file_ra_state f_ra; /* read-ahead state */
unsigned long f_version; /* version number */
void *f_security; /* security module */
void *private_data; /* tty driver hook */
struct list_head f_ep_links; /* list of eventpoll links */
spinlock_t f_ep_lock; /* eventpoll lock */
struct address_space *f_mapping; /* page cache mapping */
};
File结构的操作函数:
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, char *, size_t, loff_t);
ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
ssize_t (*aio_write) (struct kiocb *, const char *, size_t, 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);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, struct dentry *, int);
int (*aio_fsync) (struct kiocb *, int);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*readv) (struct file *, const struct iovec *,
unsigned long, loff_t *);
ssize_t (*writev) (struct file *, const struct iovec *,
unsigned long, loff_t *);
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 flags);
int (*dir_notify) (struct file *filp, unsigned long arg);
int (*flock) (struct file *filp, int cmd, struct file_lock *fl);
};
文件系统类型:
struct file_system_type {
const char *name; /* filesystem's name */
struct subsystem subsys; /* sysfs subsystem object */
int fs_flags; /* filesystem type flags */
/* the following is used to read the superblock off the disk */
struct super_block *(*get_sb) (struct file_system_type *, int,
char *, void *);
/* the following is used to terminate access to the superblock */
void (*kill_sb) (struct super_block *);
struct module *owner; /* module owning the filesystem */
struct file_system_type *next; /* next file_system_type in list */
struct list_head fs_supers; /* list of superblock objects */
};
The get_sb() function is used to read the superblock from the disk and populate the superblock object when the filesystem is loaded.
它的意思是说,get_sb是被用来读取超块的;
struct vfsmount {
struct list_head mnt_hash; /* hash table list */
struct vfsmount *mnt_parent; /* parent filesystem */
struct dentry *mnt_mountpoint; /* dentry of this mount point */
struct dentry *mnt_root; /* dentry of root of this fs */
struct super_block *mnt_sb; /* superblock of this filesystem */
struct list_head mnt_mounts; /* list of children */
struct list_head mnt_child; /* list of children */
atomic_t mnt_count; /* usage count */
int mnt_flags; /* mount flags */
char *mnt_devname; /* device file name */
struct list_head mnt_list; /* list of descriptors */
struct list_head mnt_fslink; /* fs-specific expiry list */
struct namespace *mnt_namespace /* associated namespace */
};
进程相关的数据结构:
struct files_struct {
atomic_t count; /* structure's usage count */
spinlock_t file_lock; /* lock protecting this structure */
int max_fds; /* maximum number of file objects */
int max_fdset; /* maximum number of file descriptors */
int next_fd; /* next file descriptor number */
struct file **fd; /* array of all file objects */
fd_set *close_on_exec; /* file descriptors to close on exec() */
fd_set *open_fds; /* pointer to open file descriptors */
fd_set close_on_exec_init; /* initial files to close on exec() */
fd_set open_fds_init; /* initial set of file descriptors */
struct file *fd_array[NR_OPEN_DEFAULT]; /* default array of file objects */
};
struct fs_struct {
atomic_t count; /* structure usage count */
rwlock_t lock; /* lock protecting structure */
int umask; /* default file permissions*/
struct dentry *root; /* dentry of the root directory */
struct dentry *pwd; /* dentry of the current directory */
struct dentry *altroot; /* dentry of the alternative root */
struct vfsmount *rootmnt; /* mount object of the root directory */
struct vfsmount *pwdmnt; /* mount object of the current directory */
struct vfsmount *altrootmnt; /* mount object of the alternative root */
};
名字空间:
struct namespace {
atomic_t count; /* structure usage count */
struct vfsmount *root; /* mount object of root directory */
struct list_head list; /* list of mount points */
struct rw_semaphore sem; /* semaphore protecting the namespace */
};