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

図? 割り込み処理の前半部分と後半部分
割り込みハンドラ(前半部)と後半部の役割分担の目安。
注意1: Tasklet は、task 構造体とはまったく関係ない。名前がよくない。
注意2: Softirq という用語を、割り込み処理の後半部という意味で使う人もい る。
注意3: 伝統的なUnixでは、top half は、システム・コールから派生する上位 層の処理、bottom half は、割り込みから派生する下位層の処理の意味で使わ れることがある。Linux では、top half, bottom half は、割り込み処理の前 半部分と後半部分の意味に使う。
Tasklet で1つの仕事は次のような、struct tasklet_struct で表現される。
linux-3.18.1/include/linux/interrupt.h
465: struct tasklet_struct
466: {
467: struct tasklet_struct *next;
468: unsigned long state;
469: atomic_t count;
470: void (*func)(unsigned long);
471: unsigned long data;
472: };

図? 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-3.18.1/drivers/net/wireless/ath/ath9k/ath9k.h
950: struct ath_softc {
...
957: struct tasklet_struct intr_tq;
958: struct tasklet_struct bcon_tasklet;
...
1041: };
linux-3.18.1/drivers/net/wireless/ath/ath9k/init.c
567: tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
568: tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet,
569: (unsigned long)sc);
linux-3.18.1/drivers/net/wireless/ath/ath9k/main.c
475: irqreturn_t ath_isr(int irq, void *dev)
476: {
...
496: enum ath9k_int status;
...
524: ath9k_hw_getisr(ah, &status, &sync_cause); /* NB: clears ISR too */
...
526: status &= ah->imask; /* discard unasked-for bits */
...
538: if (status & SCHED_INTR)
539: sched = true;
...
562: if (status & ATH9K_INT_SWBA)
563: tasklet_schedule(&sc->bcon_tasklet);
...
590: if (sched) {
591: /* turn off every interrupt */
592: ath9k_hw_disable_interrupts(ah);
593: tasklet_schedule(&sc->intr_tq);
594: }
595:
596: return IRQ_HANDLED;
...
599: }
358: void ath9k_tasklet(unsigned long data)
359: {
...
473: }
linux-3.18.1/drivers/net/wireless/ath/ath9k/beacon.c
315: void ath9k_beacon_tasklet(unsigned long data)
316: {
...
435: }

図? 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-3.18.1/include/linux/workqueue.h
19: typedef void (*work_func_t)(struct work_struct *work);
99: struct work_struct {
100: atomic_long_t data;
101: struct list_head entry;
102: work_func_t func;
...
106: };
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 Nov 12 18:11 /usr/bin/perl
-rwxr-xr-x. 2 root root 13304 Nov 12 18:11 /usr/bin/perl5.10.1
$ ls -li /usr/bin/{perl,perl5.10.1}
1837781 -rwxr-xr-x. 2 root root 13304 Nov 12 18:11 /usr/bin/perl
1837781 -rwxr-xr-x. 2 root root 13304 Nov 12 18:11 /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 /
$ 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 241 Jun 20 2014 .bashrc
$ stat .bashrc
File: `.bashrc'
Size: 241 Blocks: 16 IO Block: 65536 regular file
Device: 13h/19d Inode: 34824159 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1013/ yas) Gid: ( 510/ prof)
Access: 2015-02-04 06:45:47.000000000 +0900
Modify: 2014-06-20 10:54:23.001388000 +0900
Change: 2014-06-20 10:54:23.001388000 +0900
$

図? スーパーブロック、inode、dentry、file
int fd1 = open("file1",O_RDONLY);
int fd2 = open("file1",O_RDONLY);
ファイル名 "file1" で表現されるファイルの inode 構造体は、1 個でも、
file 構造体は、2 個割り当てられる。
ディスク上には対応するデータ構造は存在しない。
linux-3.18.1/include/linux/fs.h
786: struct file {
...
791: struct path f_path;
792: #define f_dentry f_path.dentry
793: struct inode *f_inode; /* cached value */
794: const struct file_operations *f_op;
...
801: atomic_long_t f_count;
...
803: fmode_t f_mode;
...
805: loff_t f_pos;
...
815: void *private_data;
...
822: struct address_space *f_mapping;
...
829: unsigned char f_handle[0];
830: };

図? C言語によるオブジェクト指向の継承の実装方法。共通インスタンス変数・関数、固有インスタンス変数関数の置き方
struct fileの操作は、たとえば次のような形で行われる。 第1引数は、struct file *。
struct file *file;
file->f_op->read(file, buf, count, pos);
f_op には、次のような手続きがある。各ファイルシステム
(ext4,nfs,tmpfs,...) ごとに、手続きの実体は異なるが、インタフェースは同じ。
linux-3.18.1/include/linux/fs.h
1486: struct file_operations {
1487: struct module *owner;
1488: loff_t (*llseek) (struct file *, loff_t, int);
1489: ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
1490: ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
1491: ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
1492: ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
1493: ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
1494: ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
1495: int (*iterate) (struct file *, struct dir_context *);
1496: unsigned int (*poll) (struct file *, struct poll_table_struct *);
1497: long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
1498: long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
1499: int (*mmap) (struct file *, struct vm_area_struct *);
1500: int (*open) (struct inode *, struct file *);
1501: int (*flush) (struct file *, fl_owner_t id);
1502: int (*release) (struct inode *, struct file *);
1503: int (*fsync) (struct file *, loff_t, loff_t, int datasync);
1504: int (*aio_fsync) (struct kiocb *, int datasync);
1505: int (*fasync) (int, struct file *, int);
1506: int (*lock) (struct file *, int, struct file_lock *);
1507: ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
1508: unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
1509: int (*check_flags)(int);
1510: int (*flock) (struct file *, int, struct file_lock *);
1511: ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
1512: ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
1513: int (*setlease)(struct file *, long, struct file_lock **, void **);
1514: long (*fallocate)(struct file *file, int mode, loff_t offset,
1515: loff_t len);
1516: int (*show_fdinfo)(struct seq_file *m, struct file *f);
1517: };
主な手続きの意味
linux-3.18.1/include/linux/dcache.h
108: struct dentry {
...
113: struct dentry *d_parent; /* parent directory */
114: struct qstr d_name;
115: struct inode *d_inode; /* Where the name belongs to - NULL is
116: * negative */
117: unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */
...
120: struct lockref d_lockref; /* per-dentry lock and refcount */
121: const struct dentry_operations *d_op;
122: struct super_block *d_sb; /* The root of the dentry tree */
...
124: void *d_fsdata; /* fs-specific data */
...
127: struct list_head d_child; /* child of parent list */
128: struct list_head d_subdirs; /* our children */
...
136: };
318: static inline unsigned d_count(const struct dentry *dentry)
319: {
320: return dentry->d_lockref.count;
321: }
30: #define HASH_LEN_DECLARE u32 hash; u32 len;
44: struct qstr {
...
47: HASH_LEN_DECLARE;
...
51: const unsigned char *name;
52: };
102: # define DNAME_INLINE_LEN 40 /* 128 bytes */
linux-3.18.1/include/linux/fs.h
538: struct inode {
539: umode_t i_mode;
540: unsigned short i_opflags;
541: kuid_t i_uid;
542: kgid_t i_gid;
...
550: const struct inode_operations *i_op;
551: struct super_block *i_sb;
...
559: unsigned long i_ino;
...
571: dev_t i_rdev;
572: loff_t i_size;
573: struct timespec i_atime;
574: struct timespec i_mtime;
575: struct timespec i_ctime;
576: spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
577: unsigned short i_bytes;
578: unsigned int i_blkbits;
579: blkcnt_t i_blocks;
...
586: unsigned long i_state;
...
591: struct hlist_node i_hash;
...
596: struct hlist_head i_dentry;
...
600: atomic_t i_count;
...
626: void *i_private; /* fs or device private pointer */
627: };
struct inode *inode;
...
inode->i_op->create(inode, name, mode, true);
i_op には、次のような手続きがある。各ファイルシステム
(ext4,nfs,tmpfs,...) ごとに、手続きの実体は異なるが、インタフェースは同じ。
linux-3.18.1/include/linux/fs.h
1519: struct inode_operations {
1520: struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
1521: void * (*follow_link) (struct dentry *, struct nameidata *);
1522: int (*permission) (struct inode *, int);
1523: struct posix_acl * (*get_acl)(struct inode *, int);
1524:
1525: int (*readlink) (struct dentry *, char __user *,int);
1526: void (*put_link) (struct dentry *, struct nameidata *, void *);
1527:
1528: int (*create) (struct inode *,struct dentry *, umode_t, bool);
1529: int (*link) (struct dentry *,struct inode *,struct dentry *);
1530: int (*unlink) (struct inode *,struct dentry *);
1531: int (*symlink) (struct inode *,struct dentry *,const char *);
1532: int (*mkdir) (struct inode *,struct dentry *,umode_t);
1533: int (*rmdir) (struct inode *,struct dentry *);
1534: int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t);
1535: int (*rename) (struct inode *, struct dentry *,
1536: struct inode *, struct dentry *);
1537: int (*rename2) (struct inode *, struct dentry *,
1538: struct inode *, struct dentry *, unsigned int);
1539: int (*setattr) (struct dentry *, struct iattr *);
1540: int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
1541: int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
1542: ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
1543: ssize_t (*listxattr) (struct dentry *, char *, size_t);
1544: int (*removexattr) (struct dentry *, const char *);
1545: int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
1546: u64 len);
1547: int (*update_time)(struct inode *, struct timespec *, int);
1548: int (*atomic_open)(struct inode *, struct dentry *,
1549: struct file *, unsigned open_flag,
1550: umode_t create_mode, int *opened);
1551: int (*tmpfile) (struct inode *, struct dentry *, umode_t);
1552: int (*set_acl)(struct inode *, struct posix_acl *, int);
1553:
1554: /* WARNING: probably going away soon, do not use! */
1555: int (*dentry_open)(struct dentry *, struct file *, const struct cred *);
1556: } ____cacheline_aligned;
linux-3.18.1/include/linux/fs.h
1198: struct super_block {
...
1203: loff_t s_maxbytes; /* Max file size */
1204: struct file_system_type *s_type;
1205: const struct super_operations *s_op;
...
1211: struct dentry *s_root;
...
1220: struct list_head s_inodes; /* all inodes */
...
1234: void *s_fs_info; /* Filesystem private info */
...
1282: struct list_lru s_dentry_lru ____cacheline_aligned_in_smp;
1283: struct list_lru s_inode_lru ____cacheline_aligned_in_smp;
...
1290: };
p->files->fd_array[fd] の struct file を表
す。
linux-3.18.1/include/linux/sched.h
1235: struct task_struct {
...
1416: struct files_struct *files;
...
1664: };
linux-3.18.1/include/linux/fdtable.h
45: struct files_struct {
...
59: struct file __rcu * fd_array[NR_OPEN_DEFAULT];
60: };
22: #define NR_OPEN_DEFAULT BITS_PER_LONG
linux-3.18.1/include/asm-generic/bitsperlong.h
7: #ifdef CONFIG_64BIT
8: #define BITS_PER_LONG 64
9: #else
10: #define BITS_PER_LONG 32
11: #endif /* CONFIG_64BIT */
図? task_struct、ファイル記述子、file構造体、その他
linux-3.18.1/fs/read_write.c
562: SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
563: {
564: struct fd f = fdget_pos(fd);
565: ssize_t ret = -EBADF;
566:
567: if (f.file) {
568: loff_t pos = file_pos_read(f.file);
569: ret = vfs_read(f.file, buf, count, &pos);
570: if (ret >= 0)
571: file_pos_write(f.file, pos);
572: fdput_pos(f);
573: }
574: return ret;
575: }
linux-3.18.1/include/linux/file.h
29: struct fd {
30: struct file *file;
31: unsigned int flags;
32: };
linux-3.18.1/fs/read_write.c
415: ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
416: {
417: ssize_t ret;
418:
419: if (!(file->f_mode & FMODE_READ))
420: return -EBADF;
421: if (!(file->f_mode & FMODE_CAN_READ))
422: return -EINVAL;
423: if (unlikely(!access_ok(VERIFY_WRITE, buf, count)))
424: return -EFAULT;
425:
426: ret = rw_verify_area(READ, file, pos, count);
427: if (ret >= 0) {
428: count = ret;
429: if (file->f_op->read)
430: ret = file->f_op->read(file, buf, count, pos);
431: else if (file->f_op->aio_read)
432: ret = do_sync_read(file, buf, count, pos);
433: else
434: ret = new_sync_read(file, buf, count, pos);
435: if (ret > 0) {
436: fsnotify_access(file);
437: add_rchar(current, ret);
438: }
439: inc_syscr(current);
440: }
441:
442: return ret;
443: }
linux-3.18.1/fs/ext4/file.c
584: const struct file_operations ext4_file_operations = {
585: .llseek = ext4_llseek,
586: .read = new_sync_read,
587: .write = new_sync_write,
588: .read_iter = generic_file_read_iter,
589: .write_iter = ext4_file_write_iter,
590: .unlocked_ioctl = ext4_ioctl,
591: #ifdef CONFIG_COMPAT
592: .compat_ioctl = ext4_compat_ioctl,
593: #endif
594: .mmap = ext4_file_mmap,
595: .open = ext4_file_open,
596: .release = ext4_release_file,
597: .fsync = ext4_sync_file,
598: .splice_read = generic_file_splice_read,
599: .splice_write = iter_file_splice_write,
600: .fallocate = ext4_fallocate,
601: };
603: const struct inode_operations ext4_file_inode_operations = {
...
613: };
linux-3.18.1/fs/ext4/super.c
1103: static const struct super_operations ext4_sops = {
...
1122: };
linux-3.18.1/fs/ext4/ext4.h
816: struct ext4_inode_info {
...
874: struct inode vfs_inode;
...
946: };
1351: static inline struct ext4_inode_info *EXT4_I(struct inode *inode)
1352: {
1353: return container_of(inode, struct ext4_inode_info, vfs_inode);
1354: }
linux-3.18.1/include/linux/kernel.h
788: /**
789: * container_of - cast a member of a structure out to the containing structure
790: * @ptr: the pointer to the member.
791: * @type: the type of the container struct this is embedded in.
792: * @member: the name of the member within the struct.
793: *
794: */
795: #define container_of(ptr, type, member) ({ \
796: const typeof( ((type *)0)->member ) *__mptr = (ptr); \
797: (type *)( (char *)__mptr - offsetof(type,member) );})

図? Ext4 ファイルシステムで使う構造体 ext4_inode_info での struct inode の保持
linux-3.18.1/fs/read_write.c
394: ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
395: {
396: struct iovec iov = { .iov_base = buf, .iov_len = len };
397: struct kiocb kiocb;
398: struct iov_iter iter;
399: ssize_t ret;
400:
401: init_sync_kiocb(&kiocb, filp);
402: kiocb.ki_pos = *ppos;
403: kiocb.ki_nbytes = len;
404: iov_iter_init(&iter, READ, &iov, 1, len);
405:
406: ret = filp->f_op->read_iter(&kiocb, &iter);
407: if (-EIOCBQUEUED == ret)
408: ret = wait_on_sync_kiocb(&kiocb);
409: *ppos = kiocb.ki_pos;
410: return ret;
411: }
linux-3.18.1/mm/filemap.c
694: ssize_t
1695: generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
1696: {
1697: struct file *file = iocb->ki_filp;
1698: ssize_t retval = 0;
1699: loff_t *ppos = &iocb->ki_pos;
1700: loff_t pos = *ppos;
...
1738: retval = do_generic_file_read(file, ppos, iter, retval);
1739: out:
1740: return retval;
1741: }
1467: static ssize_t do_generic_file_read(struct file *filp, loff_t *ppos,
1468: struct iov_iter *iter, ssize_t written)
1469: {
1470: struct address_space *mapping = filp->f_mapping;
1471: struct inode *inode = mapping->host;
...
1473: pgoff_t index;
...
1476: unsigned long offset; /* offset into pagecache page */
...
1478: int error = 0;
1479:
1480: index = *ppos >> PAGE_CACHE_SHIFT;
...
1484: offset = *ppos & ~PAGE_CACHE_MASK;
1485:
1486: for (;;) {
1487: struct page *page;
...
1490: unsigned long nr, ret;
...
1494: page = find_get_page(mapping, index);
1495: if (!page) {
1496: page_cache_sync_readahead(mapping,
1497: ra, filp,
1498: index, last_index - index);
1499: page = find_get_page(mapping, index);
...
1502: }
...
1539: /* nr is the maximum number of bytes to copy from this page */
1540: nr = PAGE_CACHE_SIZE;
...
1548: nr = nr - offset;
...
1570: ret = copy_page_to_iter(page, offset, nr, iter);
1571: offset += ret;
1572: index += offset >> PAGE_CACHE_SHIFT;
1573: offset &= ~PAGE_CACHE_MASK;
...
1576: page_cache_release(page);
1577: written += ret;
1578: if (!iov_iter_count(iter))
1579: goto out;
1584: continue;
...
1674: }
1675:
1676: out:
...
1681: *ppos = ((loff_t)index << PAGE_CACHE_SHIFT) + offset;
1682: file_accessed(filp);
1683: return written ? written : error;
1684: }
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;
}
ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
{
ssize_t ret;
...
ret = rw_verify_area(WRITE, file, pos, count);
if (ret >= 0) {
count = ret;
file_start_write(file);
if (file->f_op->/*空欄(e)*/)
ret = file->f_op->/*空欄(f)*/(/*空欄(g)*/, buf, count, pos);
...
inc_syscw(current);
file_end_write(file);
}
return ret;
}