fs/ext4fs/ext4/Kconfigfs/ext4/Makefilefs/ext4/code.c
(Aus fs/ext4/Kconfig)
config leitet eine Konfigurationsoption ein, dahinter der Bezeichner der Optiontristate bezeichnet den Typ der Option (tristate, bool, int, string, …)select wählt zusätzliche Optionen, wenn diese Option aktiviert wirdhelp ist selbst erklärenddepends → Beschreibt Abhängigkeiten zu anderen OptionenCONFIG_ zur Verfügungobj-y += foo.o: Übersetze Datei foo.c immerobj-m += foo.o: Übersetze Datei foo.c, wenn die Modulunterstützung aktiv istobj-$(CONFIG_FOO) += foo.ofoo.c, wenn Konfigurationsoption CONFIG_FOO entweder y oder m ist(Aus fs/Makefile)
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for the linux ext4-filesystem routines.
#
obj-$(CONFIG_EXT4_FS) += ext4.o
ext4-y := balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \
extents_status.o file.o fsmap.o fsync.o hash.o ialloc.o \
indirect.o inline.o inode.o ioctl.o mballoc.o migrate.o \
mmp.o move_extent.o namei.o page-io.o readpage.o resize.o \
super.o symlink.o sysfs.o xattr.o xattr_hurd.o xattr_trusted.o \
xattr_user.o fast_commit.o orphan.o
ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o
# [....]
obj-$(CONFIG_EXT4_KUNIT_TESTS) += ext4-inode-test.o
# [....](Aus fs/ext4/Makefile)
ext4.o besteht aus mehreren Quellcodedateienext4-y :=(gdb) bt
#0 universe_read (file=0xffff88800453b700,
buf=0x7f9b78c4a000 <error: Cannot access memory at address 0x7f9b78c4a000>,
count=42, ppos=0xffffc90000507ef0) at drivers/sst/sst_chrdev.c:25
#1 0xffffffff812a5579 in vfs_read (file=file@entry=0xffff88800453b700,
buf=buf@entry=0x7f9b78c4a000 <error: Cannot access memory at address 0x7f9b78c4a000>,
count=count@entry=131072, pos=pos@entry=0xffffc90000507ef0) at fs/read_write.c:468
#2 0xffffffff812a60e3 in ksys_read (fd=<optimized out>,
buf=0x7f9b78c4a000 <error: Cannot access memory at address 0x7f9b78c4a000>,
count=131072) at fs/read_write.c:613
#3 0xffffffff812a6179 in __do_sys_read (count=<optimized out>, buf=<optimized out>,
fd=<optimized out>) at fs/read_write.c:623
#4 __se_sys_read (count=<optimized out>, buf=<optimized out>, fd=<optimized out>)
at fs/read_write.c:621
#5 __x64_sys_read (regs=<optimized out>) at fs/read_write.c:621
#6 0xffffffff81b1b055 in do_syscall_x64 (nr=<optimized out>, regs=0xffffc90000507f58)
at arch/x86/entry/common.c:50
#7 do_syscall_64 (regs=0xffffc90000507f58, nr=<optimized out>)
at arch/x86/entry/common.c:80
#8 0xffffffff81c0006a in entry_SYSCALL_64 () at arch/x86/entry/entry_64.S:120ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{
ssize_t ret;
if (!(file->f_mode & FMODE_READ))
return -EBADF;
if (!(file->f_mode & FMODE_CAN_READ))
return -EINVAL;
if (unlikely(!access_ok(buf, count)))
return -EFAULT;
// [...]
if (file->f_op->read)
ret = file->f_op->read(file, buf, count, pos);
else if (file->f_op->read_iter)
ret = new_sync_read(file, buf, count, pos);
else
ret = -EINVAL;
if (ret > 0) {
fsnotify_access(file);
add_rchar(current, ret);
}
inc_syscr(current);
return ret;
}(Aus fs/read_write.c:468)
UNIX-Paradigma
struct file_operations:struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
// [...]
} __randomize_layout;(Aus include/linux/fs.h:2109)
struct filestruct file {
// [...]
struct path f_path;
struct inode *f_inode; /* cached value */
const struct file_operations *f_op;
// [...]
unsigned int f_flags;
fmode_t f_mode;
struct mutex f_pos_lock;
loff_t f_pos;
// [...]
/* needed for tty driver, and maybe others */
void *private_data;
// [...]
} __randomize_layout
__attribute__((aligned(4))); /* lest something weird decides that 2 is OK */(Aus include/linux/fs.h:940)
printf() (Formatstring, Argumente, …)printk(), Semantik ist aber gleich!pr_err, pr_info, pr_debug, …printk_ratelimited() 🤔vmalloc/vfree
kmalloc/kfree
kmalloc-Flags
GFP_KERNEL: „Allocate normal kernel ram. May sleep.”GFP_NOWAIT: „Allocation will not sleep.”GFP_ATOMIC: „Allocation will not sleep. May use emergency pools.”clone(), wie beim Systemaufruf fork()Thread erstellen:
struct *task_struct kthread_create(int (*threadfn)(void *data), void *data, const char namefmt[],...)
Erstellten Thread aufwecken:
int wake_up_process(struct task_struct *tsk)
Warten bis der Thread sich beendet:
int kthread_stop(struct task_struct *tsk)
Soll der Thread anhalten?
bool kthread_should_stop(void)
Weitere Funktionen und „Dokumentation” finden sich in include/linux/kthread.h
#include <linux/kthread.h>
char *text = "Hello from the other side!";
struct task_struct *faden;
static int work_fn(void *arg) {
char *text = (char*)arg;
while (!kthread_should_stop()) {
printk("Working: %s\n", text);
ssleep(1);
}
return 0;
}
static init __init module_init(void) {
faden = kthread_create(work_fn, (void*)text, "ein-name");
if (IS_ERR(faden)) {
pr_err("Error\n");
}
return 0;
wake_up_process(faden);
return 0;
}
// kthread_stop(faden);(Siehe Kapitel 10 in „Linux Kernel Development” [2])
spin_lock/spin_unlock_bh, _irq, _irqsavedown/up (Besser: down_interruptible)mutex_lock/mutex_unlockdrivers/sst/sst_common.c in Zeile 146 bzw. 171)BoundedBuffer aus unserem Treiber. Fragt gerne nach.)get_random_uX() – siehe include/linux/random.hstrcpy(), strcmp(), … (Dokumentation)kstrtol() (Dokumentation) oder sscanf() (Dokumentation)→ Im Zweifel eine Ausgabe und einen Fehlercode zurückgegeben