2020年02月07日
情報科学類 オペレーティングシステム II
筑波大学 システム情報系
新城 靖
<yas@cs.tsukuba.ac.jp>
このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~yas/coins/os2-2019/2020-02-07
あるいは、次のページから手繰っていくこともできます。
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-5.4.7/include/linux/interrupt.h
592: struct tasklet_struct
593: {
594: struct tasklet_struct *next;
595: unsigned long state;
596: atomic_t count;
597: void (*func)(unsigned long);
598: unsigned long data;
599: };
図? 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-5.4.7/drivers/net/wireless/ath/ath9k/ath9k.h
982: struct ath_softc {
...
990: struct tasklet_struct intr_tq;
991: struct tasklet_struct bcon_tasklet;
...
1077: };
linux-5.4.7/drivers/net/wireless/ath/ath9k/init.c
651: static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
652: const struct ath_bus_ops *bus_ops)
653: {
...
731: tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
732: tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet,
733: (unsigned long)sc);
...
791: }
linux-5.4.7/drivers/net/wireless/ath/ath9k/main.c
481: irqreturn_t ath_isr(int irq, void *dev)
482: {
...
499: struct ath_softc *sc = dev;
...
504: bool sched = false;
...
524: ath9k_hw_getisr(ah, &status, &sync_cause); /* NB: clears ISR too */
...
543: if (status & SCHED_INTR)
544: sched = true;
...
557: if (status & ATH9K_INT_SWBA)
558: tasklet_schedule(&sc->bcon_tasklet);
...
585: if (sched) {
586: /* turn off every interrupt */
587: ath9k_hw_kill_interrupts(ah);
588: tasklet_schedule(&sc->intr_tq);
589: }
590:
591: return IRQ_HANDLED;
...
594: }
linux-5.4.7/drivers/net/wireless/ath/ath9k/main.c
371: void ath9k_tasklet(unsigned long data)
372: {
...
479: }
linux-5.4.7/drivers/net/wireless/ath/ath9k/beacon.c
388: void ath9k_beacon_tasklet(unsigned long data)
389: {
...
508: }
図? Work Queueにおける仕事のキュー
キューにつながれる仕事は、Tasklet の仕事とほとんど同じで、関数へのポイ ンタ func と data からなる。処理の主体が、ワーカ・スレッドと呼ばれるカー ネル・レベルのスレッドである所が違う。
汎用の Work Queue デフォルトのワーカ・スレッドは、kworker/n (nはプロセッ サ番号) とよばれ、プロセッサごとに作られる。1つのスレッドで、様々な要 求元の仕事をこなす。下の例では、1つのプロセッサに5個のスレッドが 作られている。そのうち2つは、nice 値が -20 で高優先度。
$ ps alx|grep worker|wc
22 289 1881
$ ps alx|grep 'worker.*/0'
1 0 4779 2 20 0 0 0 worker S ? 0:00 [kworker/0:2]
1 0 5276 2 20 0 0 0 worker S ? 0:00 [kworker/0:1]
1 0 5479 2 20 0 0 0 worker S ? 0:00 [kworker/0:0]
5 0 12906 2 0 -20 0 0 worker S< ? 0:59 [kworker/0:1H]
5 0 30659 2 0 -20 0 0 worker S< ? 0:07 [kworker/0:0H]
0 1013 5803 5611 20 0 117076 1016 pipe_w S+ pts/2 0:00 grep --color=auto worker.*/0
$
汎用の Work Queue のワーカ・スレッドの他に、専用のワーカ・スレッドを作
ることもできる。
linux-5.4.7/include/linux/workqueue.h
21: typedef void (*work_func_t)(struct work_struct *work);
102: struct work_struct {
103: atomic_long_t data;
104: struct list_head entry;
105: work_func_t func;
...
109: };
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{,5.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{,5.10.1}
1846686 -rwxr-xr-x. 2 root root 13304 Mar 22 2017 /usr/bin/perl
1846686 -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 システム・コールで返される値に近いものが表示
される。
$ stat .bashrc
File: `.bashrc'
Size: 240 Blocks: 16 IO Block: 65536 regular file
Device: 14h/20d Inode: 50700660 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1013/ yas) Gid: ( 510/ prof)
Access: 2019-01-27 15:29:58.000000000 +0900
Modify: 2018-06-08 10:46:57.004451000 +0900
Change: 2018-06-08 10:46:57.004451000 +0900
$
図? スーパーブロック、inode、dentry、file
int fd1 = open("file1",O_RDONLY);
int fd2 = open("file1",O_RDONLY);
ファイル名 "file1" で表現されるファイルの inode 構造体は、1 個でも、
file 構造体は、2 個割り当てられる。
ディスク上には対応するデータ構造は存在しない。
linux-5.4.7/include/linux/fs.h
935: struct file {
...
940: struct path f_path;
941: struct inode *f_inode; /* cached value */
942: const struct file_operations *f_op;
...
950: atomic_long_t f_count;
951: unsigned int f_flags;
952: fmode_t f_mode;
...
954: loff_t f_pos;
...
964: void *private_data;
...
971: struct address_space *f_mapping;
...
973: } __randomize_layout
974: __attribute__((aligned(4))); /* lest something weird decides that 2 is OK */
linux-5.4.7/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-5.4.7/include/linux/fs.h
1821: struct file_operations {
1822: struct module *owner;
1823: loff_t (*llseek) (struct file *, loff_t, int);
1824: ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
1825: ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
1826: ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
1827: ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
1828: int (*iopoll)(struct kiocb *kiocb, bool spin);
1829: int (*iterate) (struct file *, struct dir_context *);
1830: int (*iterate_shared) (struct file *, struct dir_context *);
1831: __poll_t (*poll) (struct file *, struct poll_table_struct *);
1832: long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
1833: long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
1834: int (*mmap) (struct file *, struct vm_area_struct *);
1835: unsigned long mmap_supported_flags;
1836: int (*open) (struct inode *, struct file *);
1837: int (*flush) (struct file *, fl_owner_t id);
1838: int (*release) (struct inode *, struct file *);
1839: int (*fsync) (struct file *, loff_t, loff_t, int datasync);
1840: int (*fasync) (int, struct file *, int);
1841: int (*lock) (struct file *, int, struct file_lock *);
1842: ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
1843: unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
1844: int (*check_flags)(int);
1845: int (*flock) (struct file *, int, struct file_lock *);
1846: ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
1847: ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
1848: int (*setlease)(struct file *, long, struct file_lock **, void **);
1849: long (*fallocate)(struct file *file, int mode, loff_t offset,
1850: loff_t len);
1851: void (*show_fdinfo)(struct seq_file *m, struct file *f);
1852: #ifndef CONFIG_MMU
1853: unsigned (*mmap_capabilities)(struct file *);
1854: #endif
1855: ssize_t (*copy_file_range)(struct file *, loff_t, struct file *,
1856: loff_t, size_t, unsigned int);
1857: loff_t (*remap_file_range)(struct file *file_in, loff_t pos_in,
1858: struct file *file_out, loff_t pos_out,
1859: loff_t len, unsigned int remap_flags);
1860: int (*fadvise)(struct file *, loff_t, loff_t, int);
1861: } __randomize_layout;
主な手続きの意味
linux-5.4.7/include/linux/dcache.h
89: struct dentry {
...
94: struct dentry *d_parent; /* parent directory */
95: struct qstr d_name;
96: struct inode *d_inode; /* Where the name belongs to - NULL is
97: * negative */
98: unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */
99:
100: /* Ref lookup also touches following */
101: struct lockref d_lockref; /* per-dentry lock and refcount */
102: const struct dentry_operations *d_op;
103: struct super_block *d_sb; /* The root of the dentry tree */
...
105: void *d_fsdata; /* fs-specific data */
...
111: struct list_head d_child; /* child of parent list */
112: struct list_head d_subdirs; /* our children */
...
121: } __randomize_layout;
284: static inline unsigned d_count(const struct dentry *dentry)
285: {
286: return dentry->d_lockref.count;
287: }
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: };
83: # define DNAME_INLINE_LEN 40 /* 128 bytes */
linux-5.4.7/include/linux/fs.h
628: struct inode {
629: umode_t i_mode;
630: unsigned short i_opflags;
631: kuid_t i_uid;
632: kgid_t i_gid;
...
640: const struct inode_operations *i_op;
641: struct super_block *i_sb;
...
649: unsigned long i_ino;
...
658: const unsigned int i_nlink;
...
661: dev_t i_rdev;
662: loff_t i_size;
663: struct timespec64 i_atime;
664: struct timespec64 i_mtime;
665: struct timespec64 i_ctime;
666: spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
667: unsigned short i_bytes;
668: u8 i_blkbits;
669: u8 i_write_hint;
670: blkcnt_t i_blocks;
...
683: struct hlist_node i_hash;
...
697: struct hlist_head i_dentry;
...
701: atomic_t i_count;
...
737: void *i_private; /* fs or device private pointer */
738: } __randomize_layout;
struct inode *inode;
...
inode->i_op->create(inode, name, mode, true);
i_op には、次のような手続きがある。各ファイルシステム
(ext4,nfs,tmpfs,...) ごとに、手続きの実体は異なるが、インタフェースは同じ。
linux-5.4.7/include/linux/fs.h
1863: struct inode_operations {
1864: struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
1865: const char * (*get_link) (struct dentry *, struct inode *, struct delayed_call *);
1866: int (*permission) (struct inode *, int);
1867: struct posix_acl * (*get_acl)(struct inode *, int);
1868:
1869: int (*readlink) (struct dentry *, char __user *,int);
1870:
1871: int (*create) (struct inode *,struct dentry *, umode_t, bool);
1872: int (*link) (struct dentry *,struct inode *,struct dentry *);
1873: int (*unlink) (struct inode *,struct dentry *);
1874: int (*symlink) (struct inode *,struct dentry *,const char *);
1875: int (*mkdir) (struct inode *,struct dentry *,umode_t);
1876: int (*rmdir) (struct inode *,struct dentry *);
1877: int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t);
1878: int (*rename) (struct inode *, struct dentry *,
1879: struct inode *, struct dentry *, unsigned int);
1880: int (*setattr) (struct dentry *, struct iattr *);
1881: int (*getattr) (const struct path *, struct kstat *, u32, unsigned int);
1882: ssize_t (*listxattr) (struct dentry *, char *, size_t);
1883: int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
1884: u64 len);
1885: int (*update_time)(struct inode *, struct timespec64 *, int);
1886: int (*atomic_open)(struct inode *, struct dentry *,
1887: struct file *, unsigned open_flag,
1888: umode_t create_mode);
1889: int (*tmpfile) (struct inode *, struct dentry *, umode_t);
1890: int (*set_acl)(struct inode *, struct posix_acl *, int);
1891: } ____cacheline_aligned;
linux-5.4.7/include/linux/fs.h
1424: struct super_block {
...
1429: loff_t s_maxbytes; /* Max file size */
1430: struct file_system_type *s_type;
1431: const struct super_operations *s_op;
...
1438: struct dentry *s_root;
...
1469: void *s_fs_info; /* Filesystem private info */
...
1533: struct list_lru s_dentry_lru;
1534: struct list_lru s_inode_lru;
...
1547: struct list_head s_inodes; /* all inodes */
...
1551: } __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-5.4.7/include/linux/sched.h
624: struct task_struct {
...
908: struct files_struct *files;
...
1286: };
linux-5.4.7/include/linux/fdtable.h
24: #define NR_OPEN_DEFAULT BITS_PER_LONG
...
48: struct files_struct {
...
56: struct fdtable __rcu *fdt;
57: struct fdtable fdtab;
...
66: struct file __rcu * fd_array[NR_OPEN_DEFAULT];
67: };
linux-5.4.7/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-5.4.7/fs/read_write.c
595: SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
596: {
597: return ksys_read(fd, buf, count);
598: }
576: ssize_t ksys_read(unsigned int fd, char __user *buf, size_t count)
577: {
578: struct fd f = fdget_pos(fd);
579: ssize_t ret = -EBADF;
580:
581: if (f.file) {
582: loff_t pos, *ppos = file_ppos(f.file);
583: if (ppos) {
584: pos = *ppos;
585: ppos = &pos;
586: }
587: ret = vfs_read(f.file, buf, count, ppos);
588: if (ret >= 0 && ppos)
589: f.file->f_pos = pos;
590: fdput_pos(f);
591: }
592: return ret;
593: }
linux-5.4.7/include/linux/file.h
34: struct fd {
35: struct file *file;
36: unsigned int flags;
37: };
linux-5.4.7/fs/read_write.c
446: ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
447: {
448: ssize_t ret;
449:
450: if (!(file->f_mode & FMODE_READ))
451: return -EBADF;
452: if (!(file->f_mode & FMODE_CAN_READ))
453: return -EINVAL;
454: if (unlikely(!access_ok(buf, count)))
455: return -EFAULT;
456:
457: ret = rw_verify_area(READ, file, pos, count);
458: if (!ret) {
459: if (count > MAX_RW_COUNT)
460: count = MAX_RW_COUNT;
461: ret = __vfs_read(file, buf, count, pos);
462: if (ret > 0) {
463: fsnotify_access(file);
464: add_rchar(current, ret);
465: }
466: inc_syscr(current);
467: }
468:
469: return ret;
470: }
421: ssize_t __vfs_read(struct file *file, char __user *buf, size_t count,
422: loff_t *pos)
423: {
424: if (file->f_op->read)
425: return file->f_op->read(file, buf, count, pos);
426: else if (file->f_op->read_iter)
427: return new_sync_read(file, buf, count, pos);
428: else
429: return -EINVAL;
430: }
403: static ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
404: {
405: struct iovec iov = { .iov_base = buf, .iov_len = len };
...
411: kiocb.ki_pos = (ppos ? *ppos : 0);
412: iov_iter_init(&iter, READ, &iov, 1, len);
413:
414: ret = call_read_iter(filp, &kiocb, &iter);
...
416: if (ppos)
417: *ppos = kiocb.ki_pos;
418: return ret;
419: }
linux-5.4.7/include/linux/fs.h
1893: static inline ssize_t call_read_iter(struct file *file, struct kiocb *kio,
1894: struct iov_iter *iter)
1895: {
1896: return file->f_op->read_iter(kio, iter);
1897: }
linux-5.4.7/fs/ext4/file.c
512: const struct file_operations ext4_file_operations = {
513: .llseek = ext4_llseek,
514: .read_iter = ext4_file_read_iter,
515: .write_iter = ext4_file_write_iter,
516: .unlocked_ioctl = ext4_ioctl,
517: #ifdef CONFIG_COMPAT
518: .compat_ioctl = ext4_compat_ioctl,
519: #endif
520: .mmap = ext4_file_mmap,
521: .mmap_supported_flags = MAP_SYNC,
522: .open = ext4_file_open,
523: .release = ext4_release_file,
524: .fsync = ext4_sync_file,
525: .get_unmapped_area = thp_get_unmapped_area,
526: .splice_read = generic_file_splice_read,
527: .splice_write = iter_file_splice_write,
528: .fallocate = ext4_fallocate,
529: };
531: const struct inode_operations ext4_file_inode_operations = {
...
538: };
linux-5.4.7/fs/ext4/super.c
1410: static const struct super_operations ext4_sops = {
...
1438: };
linux-5.4.7/fs/ext4/ext4.h
952: struct ext4_inode_info {
...
1019: struct inode vfs_inode;
...
1095: };
1560: static inline struct ext4_inode_info *EXT4_I(struct inode *inode)
1561: {
1562: return container_of(inode, struct ext4_inode_info, vfs_inode);
1563: }
linux-5.4.7/include/linux/kernel.h
985: /**
986: * container_of - cast a member of a structure out to the containing structure
987: * @ptr: the pointer to the member.
988: * @type: the type of the container struct this is embedded in.
989: * @member: the name of the member within the struct.
990: *
991: */
992: #define container_of(ptr, type, member) ({ \
993: void *__mptr = (void *)(ptr); \
994: BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \
995: !__same_type(*(ptr), void), \
996: "pointer type mismatch in container_of()"); \
997: ((type *)(__mptr - offsetof(type, member))); })
998:

図? Ext4 ファイルシステムで使う構造体 ext4_inode_info での struct inode の保持
linux-5.4.7/fs/ext4/file.c
65: static ssize_t ext4_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
66: {
...
77: return generic_file_read_iter(iocb, to);
78: }
linux-5.4.7/mm/filemap.c
2274: generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
2275: {
...
2324: retval = generic_file_buffered_read(iocb, iter, retval);
2325: out:
2326: return retval;
2327: }
linux-5.4.7/mm/filemap.c
2009: static ssize_t generic_file_buffered_read(struct kiocb *iocb,
2010: struct iov_iter *iter, ssize_t written)
2011: {
2012: struct file *filp = iocb->ki_filp;
2013: struct address_space *mapping = filp->f_mapping;
2014: struct inode *inode = mapping->host;
2015: struct file_ra_state *ra = &filp->f_ra;
2016: loff_t *ppos = &iocb->ki_pos;
2017: pgoff_t index;
...
2020: unsigned long offset; /* offset into pagecache page */
...
2022: int error = 0;
...
2028: index = *ppos >> PAGE_SHIFT;
...
2032: offset = *ppos & ~PAGE_MASK;
2033:
2034: for (;;) {
2035: struct page *page;
...
2038: unsigned long nr, ret;
...
2041: find_page:
...
2047: page = find_get_page(mapping, index);
2048: if (!page) {
2049: if (iocb->ki_flags & IOCB_NOWAIT)
2050: goto would_block;
2051: page_cache_sync_readahead(mapping,
2052: ra, filp,
2053: index, last_index - index);
2054: page = find_get_page(mapping, index);
2055: if (unlikely(page == NULL))
2056: goto no_cached_page;
2057: }
...
2096: page_ok:
...
2114: nr = PAGE_SIZE;
...
2122: nr = nr - offset;
...
2144: ret = copy_page_to_iter(page, offset, nr, iter);
2145: offset += ret;
2146: index += offset >> PAGE_SHIFT;
2147: offset &= ~PAGE_MASK;
...
2150: put_page(page);
2151: written += ret;
2152: if (!iov_iter_count(iter))
2153: goto out;
...
2160: page_not_up_to_date:
...
2166: page_not_up_to_date_locked:
...
2180: readpage:
...
2227: no_cached_page:
...
2248: }
...
2252: out:
...
2257: *ppos = ((loff_t)index << PAGE_SHIFT) + offset;
2258: file_accessed(filp);
2259: return written ? written : error;
2260: }
linux-5.4.7/fs/namei.c
3844: SYSCALL_DEFINE2(mkdir, const char __user *, pathname, umode_t, mode)
3845: {
3846: return do_mkdirat(AT_FDCWD, pathname, mode);
3847: }
3814: long do_mkdirat(int dfd, const char __user *pathname, umode_t mode)
3815: {
3816: struct dentry *dentry;
3817: struct path path;
3818: int error;
3819: unsigned int lookup_flags = LOOKUP_DIRECTORY;
3820:
3821: retry:
3822: dentry = user_path_create(dfd, pathname, &path, lookup_flags);
...
3830: error = vfs_mkdir(path.dentry->d_inode, dentry, mode);
...
3836: return error;
3837: }
linux-5.4.7/fs/namei.c
3788: int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
3789: {
...
3796: if (!dir->i_op->mkdir)
3797: return -EPERM;
3798:
3799: mode &= (S_IRWXUGO|S_ISVTX);
...
3807: error = dir->i_op->mkdir(dir, dentry, mode);
...
3810: return error;
3811: }
void f(int arg1, int arg2) {
省略;
}
これを実現するために、どのような Tasklet のハンドラと初期化コードを書け
ばよいか。以下の空欄を埋めなさい。
static struct tasklet_struct tl1;
void tasklet_handler(unsigned long data) { /* Tasklet ハンドラ */
int arg1, arg2;
arg1 = 省略;
arg2 = 省略;
/*空欄(a)*/
その他の仕事;
}
初期化
{
/*空欄(b)*/(&tl1, /*空欄(c)*/, 0 );
}
irqreturn_t irq_handler(int irq, void *dev) {
/*空欄(d)*/
return IRQ_HANDLED;
}
SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
{
struct fd f = fdget(fd);
...
if (f.file->f_op->/*空欄(e)*/)
error = f.file->f_op->/*空欄(f)*/(/*空欄(g)*/,
(can_sleep) ? F_SETLKW : F_SETLK,
lock);
else
error = 省略;
...
fdput(f);
...
return error;
}
int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
{
...
if (!dir->i_op->/*空欄(h)*/)
return -EPERM;
...
error = dir->i_op->/*空欄(h)*/(/*空欄(j)*/, dentry, oldname);
...
return error;
}