owned this note
owned this note
Published
Linked with GitHub
Linux Virtual File System
=====
###### tags: `Linux Kernel`
[Linux 核心設計](https://beta.hackfoldr.org/linux/)
from [H03: fibdrv](https://hackmd.io/@sysprog/linux2020-fibdrv#-%E4%BD%9C%E6%A5%AD%E8%A6%81%E6%B1%82)
# Most important Object: superblock, inode, dentry, file object
- The superblock object:
- Represents a specific mounted filesystem.
- linux-4.4.60/include/fs/fs.h `struct super_block`
- linux-4.4.60/fs/super.c
- The inode object, which represents a specific file.
- Each object in the filesystem is represented by an inode
- linux-4.4.60/include/linux/fs.h `struct inode`
- [inode structure 影片](https://www.youtube.com/watch?v=tMVj22EWg6A)
- The dentry object:
- linux-4.4.60/include/linux/dcache.h `struct dentry`
- Represents a directory entry, which is a single component of a path.
- The file object:
- Represents an open file as associated with a process.
- linux-4.4.60/include/linux/fs.h `struct file`
Above 4 [objects relationships](https://www.ibm.com/developerworks/library/l-virtual-filesystem-switch/index.html#fig7)
- Roadmap for open file:
inode => cdev => simple_char_dev (a super-class of cdev containging device related data) => file
- [My Sample code](https://github.com/ldotrg/practical_coding/blob/master/kernel_module/char_devices/simple_char.c)

#### Driver `init_fib_dev` 前置準備
- `alloc_chrdev_region`: 向核心註冊Device Number, 或動態由核心分配拿到 Device Number(major_number+minor_number)
- 第三個參數是向核心要 N 個 minor_numbers
- `class_create()`: Populate sysfs entries `ls /sys/class`
- `device_create()`: will create the device file. (`/dev/`)
- `cdev_alloc()`: create cdev structure
- `cdev_init`: 初始化 cdev , 將 cdev 與 file_opreations 綁住
- `cdev_add()` 會將 cdev 與 Device Number 綁一起
```clike=
struct class *my_class;
struct cdev my_cdev[N_MINORS];
dev_t dev_num;
static int __init my_init(void)
{
int i;
dev_t curr_dev;
/* Request the kernel for N_MINOR devices */
alloc_chrdev_region(&dev_num, 0, N_MINORS, "my_driver");
/* Create a class : appears at /sys/class */
my_class = class_create(THIS_MODULE, "my_driver_class");
/* Initialize and create each of the device(cdev) */
for (i = 0; i < N_MINORS; i++) {
/* Associate the cdev with a set of file_operations */
cdev_init(&my_cdev[i], &fops);
/* Build up the current device number. To be used further */
curr_dev = MKDEV(MAJOR(dev_num), MINOR(dev_num) + i);
/* Create a device node for this device. Look, the class is
* being used here. The same class is associated with N_MINOR
* devices. Once the function returns, device nodes will be
* created as /dev/my_dev0, /dev/my_dev1,... You can also view
* the devices under /sys/class/my_driver_class.
*/
device_create(my_class, NULL, curr_dev, NULL, "my_dev%d", i);
/* Now make the device live for the users to access */
cdev_add(&my_cdev[i], curr_dev, 1);
}
return 0;
}
```
#### User space 操作
- 當 User space open file 時, 最終會呼叫到 KERNEL `chrdev_open()`
- `chrdev_open` 會利用 inode 的資訊(device number)找到對應的`cdev`,並填入`inode->i_cdev`
> inode->i_rdev 是什麼時候填入device number??
> cdev_map 是什麼?
```clike
static int chrdev_open(struct inode *inode, struct file *filp)
{
...
p = inode->i_cdev;
if (!p) {
struct kobject *kobj;
int idx;
spin_unlock(&cdev_lock);
kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx);
if (!kobj)
return -ENXIO;
new = container_of(kobj, struct cdev, kobj);
...
}
```
# Simple subdirectory in sysfs
[Sample kobject implementation](https://elixir.bootlin.com/linux/latest/source/samples/kobject/kobject-example.c)
# procfs
- [procfs sample code](https://github.com/ldotrg/linux-device-driver-programming-book/blob/master/chap6/procfs2/main.c)
:::warning
create_proc_entry()函數已經被proc_create()函數取代
Please reference Documentation/filesystems/seq_file.txt
此 sample code 已過時老舊 請參閱下一個
:::
- [CREATING A PROC FILE AND INTERFACING WITH USER SPACE](http://devarea.com/linux-kernel-development-creating-a-proc-file-and-interfacing-with-user-space/#.XJLaZqR-XDs)
```clike
struct proc_dir_entry *proc_mkdir(const char *, struct proc_dir_entry *);
struct proc_dir_entry *proc_create(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct file_operations *proc_fops);
int remove_proc_subtree(const char *, struct proc_dir_entry *);
```
## Reference
- [ ] [Linux 核心設計: 檔案系統概念及實作手法](https://hackmd.io/@sysprog/linux-file-system#Linux-%E6%A0%B8%E5%BF%83%E8%A8%AD%E8%A8%88-%E6%AA%94%E6%A1%88%E7%B3%BB%E7%B5%B1%E6%A6%82%E5%BF%B5%E5%8F%8A%E5%AF%A6%E4%BD%9C%E6%89%8B%E6%B3%95)
- [ ] [8. The Linux Virtual File System](https://www.win.tue.nl/~aeb/linux/lk/lk-8.html)
- [ ] [Anatomy of the Linux virtual file system switch](https://www.ibm.com/developerworks/library/l-virtual-filesystem-switch/index.html)
- [ ] [Chapter 13. The Virtual Filesystem](https://notes.shichao.io/lkd/ch13/)
- [ ] [Linux Virtual File System example: Proc File System](https://likegeeks.com/linux-virtual-file-system/#proc-File-System)
- [ ] [Software structure of a device driver](http://rts.lab.asu.edu/web_438_Fall_2014/ESP_F14_2_Linux_Kernel_driver.pptx)
- [ ] [linux-cdev-vs-register-chrdev](https://stackoverflow.com/questions/27174404/linux-cdev-vs-register-chrdev)