2013年02月19日
情報科学類 オペレーティングシステム II
筑波大学 システム情報工学研究科
コンピュータサイエンス専攻, 電子・情報工学系
新城 靖
<yas@cs.tsukuba.ac.jp>
このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~yas/coins/os2-2012/2013-02-19
あるいは、次のページから手繰っていくこともできます。
http://www.coins.tsukuba.ac.jp/~yas/
http://www.cs.tsukuba.ac.jp/~yas/
試験について
解決策:

図? ファイル・システム実現に置ける層構造
ディスク・キャッシュの層もある。解決策
$ ls -l /bin/{gunzip,gzip,zcat}
-rwxr-xr-x 3 root root 62872 Jan 21 2010 /bin/gunzip
-rwxr-xr-x 3 root root 62872 Jan 21 2010 /bin/gzip
-rwxr-xr-x 3 root root 62872 Jan 21 2010 /bin/zcat
$ ls -li /bin/{gunzip,gzip,zcat}
5636134 -rwxr-xr-x 3 root root 62872 Jan 21 2010 /bin/gunzip
5636134 -rwxr-xr-x 3 root root 62872 Jan 21 2010 /bin/gzip
5636134 -rwxr-xr-x 3 root root 62872 Jan 21 2010 /bin/zcat
$
$ cat /etc/fstab
LABEL=/ / ext3 defaults 1 1
tmpfs /dev/shm tmpfs defaults 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
sysfs /sys sysfs defaults 0 0
proc /proc proc defaults 0 0
LABEL=SWAP-sda3 swap swap defaults 0 0
130.158.86.2:/vol/vol1/home /home nfs rw,hard,bg,nfsvers=3,intr 0 0
130.158.86.2:/vol/vol5/local3 /usr/local3 nfs rw,hard,bg,nfsvers=3,intr 0 0
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda2 222G 13G 198G 6% /
tmpfs 2.0G 0 2.0G 0% /dev/shm
130.158.86.2:/vol/vol1/home
4.0T 1.5T 2.5T 38% /home
130.158.86.2:/vol/vol5/local3
80G 4.9G 76G 7% /usr/local3
$

図? スーパーブロック、inode、dentry、file
linux-3.6.8/include/linux/fs.h
1022: struct file {
...
1031: struct path f_path;
1032: #define f_dentry f_path.dentry
...
1044: atomic_long_t f_count;
...
1046: fmode_t f_mode;
1047: loff_t f_pos;
...
1057: void *private_data;
...
1068: };

図? C言語によるオブジェクト指向の継承の実装方法。共通インスタンス変数・関数、固有インスタンス変数関数の置き方
struct fileの操作は、たとえば次のような形で行われる。 第1引数は、struct file *。
struct file *file;
file->f_op->read(file, buf, count, pos);
f_op には、次のような手続きがある。各ファイルシステム
(ext4,nfs,tmpfs,...) ごとに、手続きの実体は異なるが、インタフェースは同じ。
linux-3.6.8/include/linux/fs.h
1777: struct file_operations {
1778: struct module *owner;
1779: loff_t (*llseek) (struct file *, loff_t, int);
1780: ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
1781: ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
1782: ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
1783: ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
1784: int (*readdir) (struct file *, void *, filldir_t);
1785: unsigned int (*poll) (struct file *, struct poll_table_struct *);
1786: long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
1787: long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
1788: int (*mmap) (struct file *, struct vm_area_struct *);
1789: int (*open) (struct inode *, struct file *);
1790: int (*flush) (struct file *, fl_owner_t id);
1791: int (*release) (struct inode *, struct file *);
1792: int (*fsync) (struct file *, loff_t, loff_t, int datasync);
1793: int (*aio_fsync) (struct kiocb *, int datasync);
1794: int (*fasync) (int, struct file *, int);
1795: int (*lock) (struct file *, int, struct file_lock *);
1796: ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
1797: unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
1798: int (*check_flags)(int);
1799: int (*flock) (struct file *, int, struct file_lock *);
1800: ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
1801: ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
1802: int (*setlease)(struct file *, long, struct file_lock **);
1803: long (*fallocate)(struct file *file, int mode, loff_t offset,
1804: loff_t len);
1805: };
主な手続きの意味
linux-3.6.8/include/linux/dcache.h
103: struct dentry {
...
108: struct dentry *d_parent; /* parent directory */
109: struct qstr d_name;
110: struct inode *d_inode; /* Where the name belongs to - NULL is
...
115: unsigned int d_count; /* protected by d_lock */
...
117: const struct dentry_operations *d_op;
118: struct super_block *d_sb; /* The root of the dentry tree */
...
120: void *d_fsdata; /* fs-specific data */
...
130: struct list_head d_subdirs; /* our children */
...
132: };
30: #define HASH_LEN_DECLARE u32 hash; u32 len;
42: struct qstr {
...
45: HASH_LEN_DECLARE;
...
49: const unsigned char *name;
50: };
...
99: # define DNAME_INLINE_LEN 40 /* 128 bytes */
linux-3.6.8/include/linux/fs.h
782: struct inode {
783: umode_t i_mode;
784: unsigned short i_opflags;
785: kuid_t i_uid;
786: kgid_t i_gid;
...
794: const struct inode_operations *i_op;
795: struct super_block *i_sb;
...
803: unsigned long i_ino;
...
812: const unsigned int i_nlink;
...
815: dev_t i_rdev;
816: loff_t i_size;
817: struct timespec i_atime;
818: struct timespec i_mtime;
819: struct timespec i_ctime;
820: spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
821: unsigned short i_bytes;
822: unsigned int i_blkbits;
823: blkcnt_t i_blocks;
...
830: unsigned long i_state;
...
835: struct hlist_node i_hash;
...
840: struct hlist_head i_dentry;
...
844: atomic_t i_count;
...
870: void *i_private; /* fs or device private pointer */
871: };
struct inode *inode;
...
inode->i_op->truncate(inode);
i_op には、次のような手続きがある。各ファイルシステム
(ext3,nfs,tmpfs,...) ごとに、手続きの実体は異なるが、インタフェースは同じ。
linux-3.6.8/include/linux/fs.h
1807: struct inode_operations {
1808: struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
1809: void * (*follow_link) (struct dentry *, struct nameidata *);
1810: int (*permission) (struct inode *, int);
1811: struct posix_acl * (*get_acl)(struct inode *, int);
1812:
1813: int (*readlink) (struct dentry *, char __user *,int);
1814: void (*put_link) (struct dentry *, struct nameidata *, void *);
1815:
1816: int (*create) (struct inode *,struct dentry *, umode_t, bool);
1817: int (*link) (struct dentry *,struct inode *,struct dentry *);
1818: int (*unlink) (struct inode *,struct dentry *);
1819: int (*symlink) (struct inode *,struct dentry *,const char *);
1820: int (*mkdir) (struct inode *,struct dentry *,umode_t);
1821: int (*rmdir) (struct inode *,struct dentry *);
1822: int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t);
1823: int (*rename) (struct inode *, struct dentry *,
1824: struct inode *, struct dentry *);
1825: void (*truncate) (struct inode *);
1826: int (*setattr) (struct dentry *, struct iattr *);
1827: int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
1828: int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
1829: ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
1830: ssize_t (*listxattr) (struct dentry *, char *, size_t);
1831: int (*removexattr) (struct dentry *, const char *);
1832: int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
1833: u64 len);
1834: int (*update_time)(struct inode *, struct timespec *, int);
1835: int (*atomic_open)(struct inode *, struct dentry *,
1836: struct file *, unsigned open_flag,
1837: umode_t create_mode, int *opened);
1838: } ____cacheline_aligned;
p->files->fd_array[fd] の struct file を表
す。
linux-3.6.8/include/linux/sched.h
1234: struct task_struct {
...
1400: struct files_struct *files;
...
1592: };
linux-3.6.8/include/linux/fdtable.h
66: struct files_struct {
...
80: struct file __rcu * fd_array[NR_OPEN_DEFAULT];
81: };
![図? p->files->fd_array[fd]](images/task-files-file-dentry-inode.png)
図? task_struct、ファイル記述子、file構造体、その他
linux-3.6.8/fs/read_write.c
462: SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
463: {
464: struct file *file;
465: ssize_t ret = -EBADF;
466: int fput_needed;
467:
468: file = fget_light(fd, &fput_needed);
469: if (file) {
470: loff_t pos = file_pos_read(file);
471: ret = vfs_read(file, buf, count, &pos);
472: file_pos_write(file, pos);
473: fput_light(file, fput_needed);
474: }
475:
476: return ret;
477: }
linux-3.6.8/fs/read_write.c
366: ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
367: {
368: ssize_t ret;
369:
370: if (!(file->f_mode & FMODE_READ))
371: return -EBADF;
372: if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read))
373: return -EINVAL;
374: if (unlikely(!access_ok(VERIFY_WRITE, buf, count)))
375: return -EFAULT;
376:
377: ret = rw_verify_area(READ, file, pos, count);
378: if (ret >= 0) {
379: count = ret;
380: if (file->f_op->read)
381: ret = file->f_op->read(file, buf, count, pos);
382: else
383: ret = do_sync_read(file, buf, count, pos);
384: if (ret > 0) {
385: fsnotify_access(file);
386: add_rchar(current, ret);
387: }
388: inc_syscr(current);
389: }
390:
391: return ret;
392: }
linux-3.6.8/fs/ext4/file.c
307: const struct file_operations ext4_file_operations = {
308: .llseek = ext4_llseek,
309: .read = do_sync_read,
310: .write = do_sync_write,
311: .aio_read = generic_file_aio_read,
312: .aio_write = ext4_file_write,
313: .unlocked_ioctl = ext4_ioctl,
314: #ifdef CONFIG_COMPAT
315: .compat_ioctl = ext4_compat_ioctl,
316: #endif
317: .mmap = ext4_file_mmap,
318: .open = ext4_file_open,
319: .release = ext4_release_file,
320: .fsync = ext4_sync_file,
321: .splice_read = generic_file_splice_read,
322: .splice_write = generic_file_splice_write,
323: .fallocate = ext4_fallocate,
324: };
326: const struct inode_operations ext4_file_inode_operations = {
...
337: };
linux-3.1.3/fs/ext4/super.c
1256: static const struct super_operations ext4_sops = {
...
1275: };
linux-3.6.8/fs/ext4/ext4.h
818: struct ext4_inode_info {
...
878: struct inode vfs_inode;
...
930: };
1304: static inline struct ext4_inode_info *EXT4_I(struct inode *inode)
1305: {
1306: return container_of(inode, struct ext4_inode_info, vfs_inode);
1307: }
linux-3.6.8/include/linux/kernel.h
684: /**
685: * container_of - cast a member of a structure out to the containing structure
686: * @ptr: the pointer to the member.
687: * @type: the type of the container struct this is embedded in.
688: * @member: the name of the member within the struct.
689: *
690: */
691: #define container_of(ptr, type, member) ({ \
692: const typeof( ((type *)0)->member ) *__mptr = (ptr); \
693: (type *)( (char *)__mptr - offsetof(type,member) );}
)

図? Ext4 ファイルシステムで使う構造体 ext4_inode_info での struct inode の保持
ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
{
....
ret = rw_verify_area(WRITE, file, pos, count);
if (file->f_op->/*空欄(a)*/)
ret = file->f_op->/*空欄(b)*/(/*空欄(c)*/, buf, count, pos);
...
}
return ret;
}