2018年02月09日 情報科学類 オペレーティングシステム II 筑波大学 システム情報系 新城 靖 <yas@cs.tsukuba.ac.jp>
このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~yas/coins/os2-2017/2018-02-09
あるいは、次のページから手繰っていくこともできます。
http://www.coins.tsukuba.ac.jp/~yas/
http://www.cs.tsukuba.ac.jp/~yas/
試験について
Linux では、割り込みの処理を2つに分ける。
図? 割り込み処理の前半部分と後半部分
割り込みハンドラ(前半部)と後半部の役割分担の目安。
注意1: Tasklet は、task 構造体とはまったく関係ない。名前がよくない。
注意2: Softirq という用語を、割り込み処理の後半部という意味で使う人もい る。
注意3: 伝統的なUnixでは、top half は、システム・コールから派生する上位 層の処理、bottom half は、割り込みから派生する下位層の処理の意味で使わ れることがある。Linux では、top half, bottom half は、割り込み処理の前 半部分と後半部分の意味に使う。
Tasklet で1つの仕事は次のような、struct tasklet_struct で表現される。
linux-4.14.12/include/linux/interrupt.h 537: struct tasklet_struct 538: { 539: struct tasklet_struct *next; 540: unsigned long state; 541: atomic_t count; 542: void (*func)(unsigned long); 543: unsigned long data; 544: };
図? Taskletにおける仕事のキュー
DECLARE_TASKLET(name, func, data) 有効な(count==0) の struct tasklet_struct を宣言する DECLARE_TASKLET_DISABLED(name, func, data) 無効な(count==1) の struct tasklet_struct を宣言する
void tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data);その他に、生成消滅有効無効に関して次のような操作がある。
void tasklet_handler(unsigned long data) { ... }
void tasklet_schedule(struct tasklet_struct *t) Tasklet t を通常の優先度でスケジュールする void tasklet_hi_schedule(struct tasklet_struct *t) Tasklet t を高優先度でスケジュールするすると、それは「そのうちに」1度だけ実行される。
linux-4.14.12/drivers/net/wireless/ath/ath9k/ath9k.h 994: struct ath_softc { ... 1002: struct tasklet_struct intr_tq; 1003: struct tasklet_struct bcon_tasklet; ... 1091: }; linux-4.14.12/drivers/net/wireless/ath/ath9k/init.c 595: static int ath9k_init_softc(u16 devid, struct ath_softc *sc, 596: const struct ath_bus_ops *bus_ops) 597: { ... 677: tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); 678: tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, 679: (unsigned long)sc); ... 737: }
linux-4.14.12/drivers/net/wireless/ath/ath9k/main.c 480: irqreturn_t ath_isr(int irq, void *dev) 481: { ... 498: struct ath_softc *sc = dev; ... 501: enum ath9k_int status; ... 503: bool sched = false; ... 523: ath9k_hw_getisr(ah, &status, &sync_cause); /* NB: clears ISR too */ ... 542: if (status & SCHED_INTR) 543: sched = true; ... 556: if (status & ATH9K_INT_SWBA) 557: tasklet_schedule(&sc->bcon_tasklet); ... 584: if (sched) { 585: /* turn off every interrupt */ 586: ath9k_hw_kill_interrupts(ah); 587: tasklet_schedule(&sc->intr_tq); 588: } 589: 590: return IRQ_HANDLED; ... 593: } linux-4.14.12/drivers/net/wireless/ath/ath9k/main.c 370: void ath9k_tasklet(unsigned long data) 371: { ... 478: } linux-4.14.12/drivers/net/wireless/ath/ath9k/beacon.c 388: void ath9k_beacon_tasklet(unsigned long data) 389: { ... 508: }
図? Work Queueにおける仕事のキュー
キューにつながれる仕事は、Tasklet の仕事とほとんど同じで、関数へのポイ ンタ func と data からなる。処理の主体が、ワーカ・スレッドと呼ばれるカー ネル・レベルのスレッドである所が違う。
$ ps alx|egrep events
1 0 19 2 20 0 0 0 worker S ? 0:12 [events/0]
1 0 20 2 20 0 0 0 worker S ? 0:08 [events/1]
1 0 21 2 20 0 0 0 worker S ? 0:08 [events/2]
1 0 22 2 20 0 0 0 worker S ? 0:10 [events/3]
0 1013 3242 2450 20 0 105236 900 pipe_w S+ pts/3 0:00 egrep events
$
汎用の Work Queue のワーカ・スレッドの他に、専用のワーカ・スレッドを作
ることもできる。
linux-4.14.12/include/linux/workqueue.h 20: typedef void (*work_func_t)(struct work_struct *work); 101: struct work_struct { 102: atomic_long_t data; 103: struct list_head entry; 104: work_func_t func; ... 108: };
struct work_struct my_work; ... INIT_WORK(&my_work,my_work_handler);
void my_work_handler(struct work_struct *work) { ... }
schedule_work(&work);この結果、INIT_WORK() で設定したハンドラがワーカ・スレッドにより「その うち」に呼び出される。
schedule_work() では、即座に実行される可能性もある。少し後に実行したい (間を取りたい)時には、次の関数を呼ぶ。
schedule_delayed_work(&work,ticks);ticks は、どのくらい間をとるか。単位は、 ticks (jiffiesの単位)。 多くのシステムで10ミリ秒-1ミリ秒で、設定によって異なる。
解決策:
図? 層構造を用いたファイル・システムの実装
解決策
$ ls -l /usr/bin/{perl,perl5.10.1}
-rwxr-xr-x. 2 root root 13304 Mar 22 2017 /usr/bin/perl
-rwxr-xr-x. 2 root root 13304 Mar 22 2017 /usr/bin/perl5.10.1
$ ls -li /usr/bin/{perl,perl5.10.1}
1844831 -rwxr-xr-x. 2 root root 13304 Mar 22 2017 /usr/bin/perl
1844831 -rwxr-xr-x. 2 root root 13304 Mar 22 2017 /usr/bin/perl5.10.1
$
$ grep -v '#' /etc/fstab
UUID=9cfbc67e-781c-48d1-8303-1dde8ce87ee9 / ext4 defaults 1 1
UUID=bab1faf1-5f5b-4a2a-b24f-e850a2b0b82d /boot ext4 defaults 1 2
UUID=a1f61ff2-2c99-4c54-8c3e-2178eed3ec10 swap swap defaults 0 0
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
pentas-fs:/vol0/home /home nfs rw,hard,bg,nfsvers=3,intr 0 0
pentas-fs:/vol0/web /var/www nfs rw,hard,bg,nfsvers=3,intr 0 0
pentas-fs:/vol0/local3 /usr/local3 nfs rw,hard,bg,nfsvers=3,intr 0 0
$ df /
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda3 49071944 6721604 39857568 15% /
$ blkid /dev/sda3
/dev/sda3: UUID="9cfbc67e-781c-48d1-8303-1dde8ce87ee9" TYPE="ext4"
$ ls -l /dev/sda3
brw-rw----. 1 root disk 8, 3 Feb 2 10:50 /dev/sda3
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 50G 0 disk
|-sda1 8:1 0 512M 0 part /boot
|-sda2 8:2 0 2G 0 part [SWAP]
`-sda3 8:3 0 47.6G 0 part /
sr0 11:0 1 1024M 0 rom
$ ls -l /dev/sda
brw-rw----. 1 root disk 8, 0 Feb 2 10:50 /dev/sda
$
$ grep cd /etc/auto.misc
cd -fstype=iso9660,ro,nosuid,nodev :/dev/cdrom
$
STAT(2) Linux Programmer's Manual STAT(2) ... int stat(const char *path, struct stat *buf); ... struct stat { dev_t st_dev; /* ID of device containing file */ ino_t st_ino; /* inode number */ mode_t st_mode; /* protection */ nlink_t st_nlink; /* number of hard links */ uid_t st_uid; /* user ID of owner */ gid_t st_gid; /* group ID of owner */ dev_t st_rdev; /* device ID (if special file) */ off_t st_size; /* total size, in bytes */ blksize_t st_blksize; /* blocksize for filesystem I/O */ blkcnt_t st_blocks; /* number of blocks allocated */ time_t st_atime; /* time of last access */ time_t st_mtime; /* time of last modification */ time_t st_ctime; /* time of last status change */ };stat コマンドを使うと stat システム・コールで返される値に近いものが表示 される。
$ ls -l .bashrc
-rw-r--r--. 1 yas prof 240 Jun 16 2017 .bashrc
$ stat .bashrc
File: `.bashrc'
Size: 240 Blocks: 16 IO Block: 65536 regular file
Device: 14h/20d Inode: 29984943 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1013/ yas) Gid: ( 510/ prof)
Access: 2018-01-24 15:34:38.000000000 +0900
Modify: 2017-06-16 10:29:16.005481000 +0900
Change: 2018-01-24 15:19:45.000219000 +0900
$
'
図? スーパーブロック、inode、dentry、file
int fd1 = open("file1",O_RDONLY); int fd2 = open("file1",O_RDONLY);ファイル名 "file1" で表現されるファイルの inode 構造体は、1 個でも、 file 構造体は、2 個割り当てられる。
ディスク上には対応するデータ構造は存在しない。
linux-4.14.12/include/linux/fs.h 852: struct file { ... 857: struct path f_path; 858: struct inode *f_inode; /* cached value */ 859: const struct file_operations *f_op; ... 867: atomic_long_t f_count; ... 869: fmode_t f_mode; ... 871: loff_t f_pos; ... 881: void *private_data; ... 888: struct address_space *f_mapping; ... 890: } __randomize_layout 891: __attribute__((aligned(4))); /* lest something weird decides that 2 is OK */ linux-4.14.12/include/linux/path.h 8: struct path { 9: struct vfsmount *mnt; 10: struct dentry *dentry; 11: } __randomize_layout;
図? C言語によるオブジェクト指向の継承・委譲の実装方法。共通インスタンス変数・関数、固有インスタンス変数関数の置き方
struct fileの操作は、たとえば次のような形で行われる。 第1引数は、struct file *。
struct file *file; file->f_op->read(file, buf, count, pos);f_op には、次のような手続きがある。各ファイルシステム (ext4,nfs,tmpfs,...) ごとに、手続きの実体は異なるが、インタフェースは同じ。
linux-4.14.12/include/linux/fs.h 1692: struct file_operations { 1693: struct module *owner; 1694: loff_t (*llseek) (struct file *, loff_t, int); 1695: ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); 1696: ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); 1697: ssize_t (*read_iter) (struct kiocb *, struct iov_iter *); 1698: ssize_t (*write_iter) (struct kiocb *, struct iov_iter *); 1699: int (*iterate) (struct file *, struct dir_context *); 1700: int (*iterate_shared) (struct file *, struct dir_context *); 1701: unsigned int (*poll) (struct file *, struct poll_table_struct *); 1702: long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); 1703: long (*compat_ioctl) (struct file *, unsigned int, unsigned long); 1704: int (*mmap) (struct file *, struct vm_area_struct *); 1705: int (*open) (struct inode *, struct file *); 1706: int (*flush) (struct file *, fl_owner_t id); 1707: int (*release) (struct inode *, struct file *); 1708: int (*fsync) (struct file *, loff_t, loff_t, int datasync); 1709: int (*fasync) (int, struct file *, int); 1710: int (*lock) (struct file *, int, struct file_lock *); 1711: ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); 1712: unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); 1713: int (*check_flags)(int); 1714: int (*flock) (struct file *, int, struct file_lock *); 1715: ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); 1716: ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); 1717: int (*setlease)(struct file *, long, struct file_lock **, void **); 1718: long (*fallocate)(struct file *file, int mode, loff_t offset, 1719: loff_t len); 1720: void (*show_fdinfo)(struct seq_file *m, struct file *f); 1721: #ifndef CONFIG_MMU 1722: unsigned (*mmap_capabilities)(struct file *); 1723: #endif 1724: ssize_t (*copy_file_range)(struct file *, loff_t, struct file *, 1725: loff_t, size_t, unsigned int); 1726: int (*clone_file_range)(struct file *, loff_t, struct file *, loff_t, 1727: u64); 1728: ssize_t (*dedupe_file_range)(struct file *, u64, u64, struct file *, 1729: u64); 1730: } __randomize_layout;主な手続きの意味
linux-4.14.12/include/linux/dcache.h 90: struct dentry { ... 95: struct dentry *d_parent; /* parent directory */ 96: struct qstr d_name; 97: struct inode *d_inode; /* Where the name belongs to - NULL is 98: * negative */ 99: unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */ 100: 101: /* Ref lookup also touches following */ 102: struct lockref d_lockref; /* per-dentry lock and refcount */ 103: const struct dentry_operations *d_op; 104: struct super_block *d_sb; /* The root of the dentry tree */ ... 106: void *d_fsdata; /* fs-specific data */ ... 112: struct list_head d_child; /* child of parent list */ 113: struct list_head d_subdirs; /* our children */ .. 122: } __randomize_layout; 287: static inline unsigned d_count(const struct dentry *dentry) 288: { 289: return dentry->d_lockref.count; 290: } 33: #define HASH_LEN_DECLARE u32 hash; u32 len 47: struct qstr { 48: union { 49: struct { 50: HASH_LEN_DECLARE; 51: }; 52: u64 hash_len; 53: }; 54: const unsigned char *name; 55: }; 84: # define DNAME_INLINE_LEN 40 /* 128 bytes */
linux-4.14.12/include/linux/fs.h 570: struct inode { 571: umode_t i_mode; 572: unsigned short i_opflags; 573: kuid_t i_uid; 574: kgid_t i_gid; ... 582: const struct inode_operations *i_op; 583: struct super_block *i_sb; ... 603: dev_t i_rdev; 604: loff_t i_size; 605: struct timespec i_atime; 606: struct timespec i_mtime; 607: struct timespec i_ctime; 608: spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ 609: unsigned short i_bytes; 610: unsigned int i_blkbits; ... 619: unsigned long i_state; ... 625: struct hlist_node i_hash; ... 643: atomic_t i_count; ... 672: void *i_private; /* fs or device private pointer */ 673: } __randomize_layout; 674:
struct inode *inode; ... inode->i_op->create(inode, name, mode, true);i_op には、次のような手続きがある。各ファイルシステム (ext4,nfs,tmpfs,...) ごとに、手続きの実体は異なるが、インタフェースは同じ。
linux-4.14.12/include/linux/fs.h 1732: struct inode_operations { 1733: struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int); 1734: const char * (*get_link) (struct dentry *, struct inode *, struct delayed_call *); 1735: int (*permission) (struct inode *, int); 1736: struct posix_acl * (*get_acl)(struct inode *, int); 1737: 1738: int (*readlink) (struct dentry *, char __user *,int); 1739: 1740: int (*create) (struct inode *,struct dentry *, umode_t, bool); 1741: int (*link) (struct dentry *,struct inode *,struct dentry *); 1742: int (*unlink) (struct inode *,struct dentry *); 1743: int (*symlink) (struct inode *,struct dentry *,const char *); 1744: int (*mkdir) (struct inode *,struct dentry *,umode_t); 1745: int (*rmdir) (struct inode *,struct dentry *); 1746: int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t); 1747: int (*rename) (struct inode *, struct dentry *, 1748: struct inode *, struct dentry *, unsigned int); 1749: int (*setattr) (struct dentry *, struct iattr *); 1750: int (*getattr) (const struct path *, struct kstat *, u32, unsigned int); 1751: ssize_t (*listxattr) (struct dentry *, char *, size_t); 1752: int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, 1753: u64 len); 1754: int (*update_time)(struct inode *, struct timespec *, int); 1755: int (*atomic_open)(struct inode *, struct dentry *, 1756: struct file *, unsigned open_flag, 1757: umode_t create_mode, int *opened); 1758: int (*tmpfile) (struct inode *, struct dentry *, umode_t); 1759: int (*set_acl)(struct inode *, struct posix_acl *, int); 1760: } ____cacheline_aligned;
linux-4.14.12/include/linux/fs.h 1337: struct super_block { ... 1342: loff_t s_maxbytes; /* Max file size */ ... 1343: struct file_system_type *s_type; 1344: const struct super_operations *s_op; ... 1351: struct dentry *s_root; ... 1376: void *s_fs_info; /* Filesystem private info */ ... 1426: struct list_lru s_dentry_lru ____cacheline_aligned_in_smp; 1427: struct list_lru s_inode_lru ____cacheline_aligned_in_smp; ... 1440: struct list_head s_inodes; /* all inodes */ ... 1444: } __randomize_layout;
p->files->fdt->fd[fd]
の struct file を表
す。開いているファイルの数が小さい時は、
p->files->fd_array[fd]
と同じ。
多くのファイルを開くプロセスでは、
p->files->fd_array[NR_OPEN_DEFAULT]
で足りなくなった時は、
expand_files(), expand_fdtable() で拡張する。
これらの関数では、kmalloc() 等でメモリを割り当てる。
linux-4.14.12/include/linux/sched.h 519: struct task_struct { ... 775: struct files_struct *files; ... 1116: }; 47: struct files_struct { ... 55: struct fdtable __rcu *fdt; 56: struct fdtable fdtab; ... 65: struct file __rcu * fd_array[NR_OPEN_DEFAULT]; 66: }; linux-4.14.12/include/linux/fdtable.h 25: struct fdtable { 26: unsigned int max_fds; 27: struct file __rcu **fd; /* current fd array */ ... 32: }; 23: #define NR_OPEN_DEFAULT BITS_PER_LONG linux-4.14.12/include/asm-generic/bitsperlong.h 8: #ifdef CONFIG_64BIT 9: #define BITS_PER_LONG 64 10: #else 11: #define BITS_PER_LONG 32 12: #endif /* CONFIG_64BIT */
図? task_struct、ファイル記述子、file構造体、その他
linux-4.14.12/fs/read_write.c 566: SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) 567: { 568: struct fd f = fdget_pos(fd); 569: ssize_t ret = -EBADF; 570: 571: if (f.file) { 572: loff_t pos = file_pos_read(f.file); 573: ret = vfs_read(f.file, buf, count, &pos); 574: if (ret >= 0) 575: file_pos_write(f.file, pos); 576: fdput_pos(f); 577: } 578: return ret; 579: } linux-4.14.12/include/linux/file.h 30: struct fd { 31: struct file *file; 32: unsigned int flags; 33: };
linux-4.14.12/fs/read_write.c 432: ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) 433: { 434: ssize_t ret; 435: 436: if (!(file->f_mode & FMODE_READ)) 437: return -EBADF; 438: if (!(file->f_mode & FMODE_CAN_READ)) 439: return -EINVAL; 440: if (unlikely(!access_ok(VERIFY_WRITE, buf, count))) 441: return -EFAULT; 442: 443: ret = rw_verify_area(READ, file, pos, count); 444: if (!ret) { 445: if (count > MAX_RW_COUNT) 446: count = MAX_RW_COUNT; 447: ret = __vfs_read(file, buf, count, pos); 448: if (ret > 0) { 449: fsnotify_access(file); 450: add_rchar(current, ret); 451: } 452: inc_syscr(current); 453: } 454: 455: return ret; 456: } 407: ssize_t __vfs_read(struct file *file, char __user *buf, size_t count, 408: loff_t *pos) 409: { 410: if (file->f_op->read) 411: return file->f_op->read(file, buf, count, pos); 412: else if (file->f_op->read_iter) 413: return new_sync_read(file, buf, count, pos); 414: else 415: return -EINVAL; 416: } 390: static ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos) 391: { ... 401: ret = call_read_iter(filp, &kiocb, &iter); ... 403: *ppos = kiocb.ki_pos; 404: return ret; 405: } linux-4.14.12/include/linux/fs.h 1762: static inline ssize_t call_read_iter(struct file *file, struct kiocb *kio, 1763: struct iov_iter *iter) 1764: { 1765: return file->f_op->read_iter(kio, iter); 1766: }
linux-4.14.12/fs/ext4/file.c 713: const struct file_operations ext4_file_operations = { 714: .llseek = ext4_llseek, 715: .read_iter = ext4_file_read_iter, 716: .write_iter = ext4_file_write_iter, 717: .unlocked_ioctl = ext4_ioctl, 718: #ifdef CONFIG_COMPAT 719: .compat_ioctl = ext4_compat_ioctl, 720: #endif 721: .mmap = ext4_file_mmap, 722: .open = ext4_file_open, 723: .release = ext4_release_file, 724: .fsync = ext4_sync_file, 725: .get_unmapped_area = thp_get_unmapped_area, 726: .splice_read = generic_file_splice_read, 727: .splice_write = iter_file_splice_write, 728: .fallocate = ext4_fallocate, 729: }; 730: 731: const struct inode_operations ext4_file_inode_operations = { ... 738: }; linux-4.14.12/fs/ext4/super.c 1302: static const struct super_operations ext4_sops = { ... 1322: };
linux-4.14.12/fs/ext4/ext4.h 955: struct ext4_inode_info { ... 1022: struct inode vfs_inode; ... 1095: }; 1537: static inline struct ext4_inode_info *EXT4_I(struct inode *inode) 1538: { 1539: return container_of(inode, struct ext4_inode_info, vfs_inode); 1540: } linux-4.14.12/include/linux/kernel.h 920: /** 921: * container_of - cast a member of a structure out to the containing structure 922: * @ptr: the pointer to the member. 923: * @type: the type of the container struct this is embedded in. 924: * @member: the name of the member within the struct. 925: * 926: */ 927: #define container_of(ptr, type, member) ({ \ 928: void *__mptr = (void *)(ptr); \ 929: BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ 930: !__same_type(*(ptr), void), \ 931: "pointer type mismatch in container_of()"); \ 932: ((type *)(__mptr - offsetof(type, member))); }) 933:
図? Ext4 ファイルシステムで使う構造体 ext4_inode_info での struct inode の保持
63: static ssize_t ext4_file_read_iter(struct kiocb *iocb, struct iov_iter *to) 64: { ... 75: return generic_file_read_iter(iocb, to); 76: }
linux-4.14.12/mm/filemap.c 2200: ssize_t 2201: generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) 2202: { ... 2251: retval = generic_file_buffered_read(iocb, iter, retval); 2252: out: 2253: return retval; 2254: }
1939: static ssize_t generic_file_buffered_read(struct kiocb *iocb, 1940: struct iov_iter *iter, ssize_t written) 1941: { 1942: struct file *filp = iocb->ki_filp; 1943: struct address_space *mapping = filp->f_mapping; 1944: struct inode *inode = mapping->host; 1945: struct file_ra_state *ra = &filp->f_ra; 1946: loff_t *ppos = &iocb->ki_pos; 1947: pgoff_t index; ... 1950: unsigned long offset; /* offset into pagecache page */ ... 1952: int error = 0; ... 1958: index = *ppos >> PAGE_SHIFT; ... 1962: offset = *ppos & ~PAGE_MASK; ... 1964: for (;;) { 1965: struct page *page; ... 1968: unsigned long nr, ret; ... 1971: find_page: ... 1977: page = find_get_page(mapping, index); 1978: if (!page) { ... 1981: page_cache_sync_readahead(mapping, 1982: ra, filp, 1983: index, last_index - index); 1984: page = find_get_page(mapping, index); 1985: if (unlikely(page == NULL)) 1986: goto no_cached_page; 1987: } ... 2026: page_ok: ... 2044: nr = PAGE_SIZE; ... 2052: nr = nr - offset; ... 2074: ret = copy_page_to_iter(page, offset, nr, iter); 2075: offset += ret; 2076: index += offset >> PAGE_SHIFT; 2077: offset &= ~PAGE_MASK; ... 2080: put_page(page); 2081: written += ret; 2082: if (!iov_iter_count(iter)) 2083: goto out; ... 2090: page_not_up_to_date: ... 2096: page_not_up_to_date_locked: ... 2110: readpage: ... 2152: readpage_error: ... 2157: no_cached_page: ... 2178: } ... 2182: out: ... 2187: *ppos = ((loff_t)index << PAGE_SHIFT) + offset; 2188: file_accessed(filp); 2189: return written ? written : error; 2190: }
void f(int arg1, int arg2) { 省略; }これを実現するために、どのような Tasklet のハンドラと初期化コードを書け ばよいか。以下の空欄を埋めなさい。
void tasklet_handler(unsigned long data) { /* Tasklet ハンドラ */ int arg1, arg2; arg1 = 省略; arg2 = 省略; /*空欄(a)*/ その他の仕事; } DECLARE_TASKLET(/*空欄(b)*/, /*空欄(c)*/, 0); /* 構造体の初期化 */注意: 構造体の名前は、次の問題の解答で利用する。それらしいものを付けな さい。
irqreturn_t irq_handler(int irq, void *dev) { /*空欄(d)*/ return IRQ_HANDLED; }
int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync) { struct inode *inode = file->f_mapping->host; if (!file->f_op->/*空欄(e)*/) return -EINVAL; /*中略*/ return file->f_op->/*空欄(f)*/(/*空欄(g)*/, start, end, datasync); }