最新のオペレーティング システムでは、仮想ファイル システムはほぼ遍在する機能であるため、最新のオペレーティング システムの動作メカニズムについて議論することは避けられません。
この記事では、Linux 2.6.x.x
これが革新的なバージョンであることを意味します。メモリ管理、プロセス管理、ファイル管理、デバイス管理のいずれにおいても、画期的な変更が加えられているため、このバージョンで検討する必要があります。
排水:最新のオペレーティング システムのメモリ管理原則: Linux2.6.xx を例に挙げて
仮想ファイルシステムの概要
root@huawei linux-version # df [0]
Filesystem 1K-blocks Used Available Use% Mounted on
udev 1967860 0 1967860 0% /dev
tmpfs 402568 1580 400988 1% /run
/dev/vda1 41020640 26749836 12157372 69% /
tmpfs 2012832 0 2012832 0% /dev/shm
tmpfs 5120 4 5116 1% /run/lock
tmpfs 2012832 0 2012832 0% /sys/fs/cgroup
tmpfs 402564 40 402524 1% /run/user/122
tmpfs 402564 0 402564 0% /run/user/0
前述したように、tmpfs
はメモリベースの仮想ファイル システムであり、仮想とは、ファイル システム内のファイルがハード ディスク上のどのファイルにも対応しないことを意味します。(論理ファイルシステムという言葉があります)
従来、ファイル システムはブロック デバイス上の永続ストレージに使用されてきましたが、ファイル システムは、ブロック デバイスに保存されずカーネルによって動的に生成できる情報を整理、提供、交換するためにも使用できます。(この文面からすると、proc
通常のファイルシステムもこれらと同等の関係にあるように思えますので、とりあえず論理ファイルシステムと呼ぶことにします)
proc
、tmpfs
、 などの一般的なものsysfs
ここで、論理ファイルシステムとファイルシステム、ディスクファイルシステムとメモリファイルシステムの違いに注意する必要がありますが、
特定の仮想ファイルシステムは単なる中間層であり、次の種類があります。
proc
: オペレーティング システム自体とアプリケーション間の通信に安全なインターフェイスを提供します。devfs
: 2.6 カーネルより前に使用され、ディレクトリにあるすべてのデバイスdevfs
を管理するファイルのような方法を提供しました。/dev
sysfs
:sysfs
ファイル システムは、システムに接続されているデバイスとバスを階層ファイルに編成します。ユーザー空間プログラムは、この情報を使用して、通常は の代わりにカーネルと対話することもできますdevfs
。sysfs
ファイル システムは、現在のシステム上の実際のデバイス ツリーを直感的に反映したもので、kobject
サブシステムを通じてこの情報を構築します。ファイル システムがkobject
作成されると、対応するファイルとディレクトリも作成されます。tmpfs
:Linux
独自のファイル システム。標準のマウント ポイントは で/dev/shm
、デフォルトのサイズは実際のメモリの半分です。物理メモリまたはスワップ領域tmpfs
を使用できます。swap
これは、ファイルを整理するための一般的な仮想ファイル システムです。利点: 一時的、高速な読み取りと書き込み、動的縮小特定のファイル システム:
minix
、などディスク ファイル システム: ファイル システムはディスク内にあり、速度は遅くなりますext3
メモリファイル システム: ファイル システムはメモリ内にあり、速度は高速ですext4
ファイル システムの種類: ディスク ベースのファイル システムDisk-based Filesystem
、仮想ファイル システムはVirtual Filesystem
カーネルで生成され、ユーザー アプリケーションがユーザーと通信するための方法です。ネットワーク ファイル システムは、Network Filesystem
ディスク ベースのファイル システムと仮想ファイル システムの間の妥協点です。
VFS
ファイル システムのメソッドと抽象化を提供するだけでなく、ファイル システム内のオブジェクト (またはファイル) の統一されたビューもサポートします。
inode
メンバーは次のカテゴリに属します。
- ファイルのステータスを説明するメタデータ。たとえば、アクセス権や最終変更日などです。
- 実際のファイルの内容を保持するデータセグメント
- このディレクトリ エントリのデータが存在する i ノードの番号
- ファイルまたはディレクトリの名前
以下は検索/usr/bin/emacs
プロセスです
すべてはファイルです。
カーネルによってエクスポートされ、ユーザー プログラムによって使用されるほとんどの関数は、VFS
定義されたファイル インターフェイスを通じてアクセスできます。以下は、主な通信手段としてファイルを使用するカーネル サブシステムの一部です: キャラクタ デバイスとブロック デバイス、プロセス間のパイプ、すべてのネットワーク プロトコル用のソケット、対話型入出力用の端末、および対話型の入出力用のターミナル。
VFS
ファイルとファイルシステムの 2 つの部分で構成されます。
struct inode {
struct hlist_node i_hash;
struct list_head i_list; // 链接iNode
struct list_head i_sb_list;
struct list_head i_dentry;
unsigned long i_ino; // inode唯一编号
atomic_t i_count; // 引用技术
unsigned int i_nlink; // 硬链接总数
uid_t i_uid; // 用户ID
gid_t i_gid; // 组ID
dev_t i_rdev; // 表示设备特殊文件的专用指针
unsigned long i_version; //
loff_t i_size; // 文件大小
#ifdef __NEED_I_SIZE_ORDERED
seqcount_t i_size_seqcount;
#endif
struct timespec i_atime; // 最后访问的时间
struct timespec i_mtime; // 最后修改的时间
struct timespec i_ctime; // 最后修改iNode的时间
unsigned int i_blkbits;
blkcnt_t i_blocks; // 文件按块计算的长度
unsigned short i_bytes; // 文件按字节计算的长度
umode_t i_mode; // 文件类型
spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
struct mutex i_mutex; // 互斥量
struct rw_semaphore i_alloc_sem;
const struct inode_operations *i_op; // inode操作数据结构
const struct file_operations *i_fop; /* inode默认操作结构 */
struct super_block *i_sb;
struct file_lock *i_flock;
struct address_space *i_mapping;
struct address_space i_data;
#ifdef CONFIG_QUOTA
struct dquot *i_dquot[MAXQUOTAS];
#endif
struct list_head i_devices; // 利用该成员作为链表元素,使得块设备或字符设备可以维护一个inode的链表,每个inode表示一个设备文件,通过设备文件可以访问对应的设备
union {
struct pipe_inode_info *i_pipe; // 于实现管道的inode的相关信息
struct block_device *i_bdev; // 块设备
struct cdev *i_cdev; // 字符设备
};
int i_cindex;
__u32 i_generation;
#ifdef CONFIG_DNOTIFY
unsigned long i_dnotify_mask; /* Directory notify events */
struct dnotify_struct *i_dnotify; /* for directory notifications */
#endif
#ifdef CONFIG_INOTIFY
struct list_head inotify_watches; /* watches on this inode */
struct mutex inotify_mutex; /* protects the watches list */
#endif
unsigned long i_state;
unsigned long dirtied_when; /* jiffies of first dirtying */
unsigned int i_flags;
atomic_t i_writecount;
#ifdef CONFIG_SECURITY
void *i_security;
#endif
void *i_private; /* fs or device private pointer */
};
iNode
操作の場合はi_op
メンバーを使用して指定します
struct inode_operations {
int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
int (*link) (struct dentry *,struct inode *,struct dentry *);
int (*unlink) (struct inode *,struct dentry *);
int (*symlink) (struct inode *,struct dentry *,const char *);
int (*mkdir) (struct inode *,struct dentry *,int);
int (*rmdir) (struct inode *,struct dentry *);
int (*mknod) (struct inode *,struct dentry *,int,dev_t);
int (*rename) (struct inode *, struct dentry *,
struct inode *, struct dentry *);
int (*readlink) (struct dentry *, char __user *,int);
void * (*follow_link) (struct dentry *, struct nameidata *);
void (*put_link) (struct dentry *, struct nameidata *, void *);
void (*truncate) (struct inode *);
int (*permission) (struct inode *, int, struct nameidata *);
int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
int (*removexattr) (struct dentry *, const char *);
void (*truncate_range)(struct inode *, loff_t, loff_t);
long (*fallocate)(struct inode *inode, int mode, loff_t offset, loff_t len);
};
このようなファイルシステムの場合proc
、その管理オブジェクトはプロセスですtask_struct
struct task_struct {
// ...
int link_count, total_link_count; // 文件系统信息 查找环形链表时防止无限循环
// ...
struct fs_struct *fs; // 文件系统信息
struct files_struct *files; // 打开文件系统
struct nsproxy *nsproxy; // 命名空间
// ...
};
files
現在のプロセスの各ファイル記述子が含まれます
struct files_struct {
/*
* read mostly part
*/
atomic_t count;
struct fdtable *fdt;
struct fdtable fdtab;
/*
* written part on a separate cache line in SMP
*/
spinlock_t file_lock ____cacheline_aligned_in_smp;
int next_fd; // 表示下一次打开新文件时使用的文件描述符
struct embedded_fd_set close_on_exec_init; // 位图
struct embedded_fd_set open_fds_init; // 位图
struct file * fd_array[NR_OPEN_DEFAULT];
};
struct embedded_fd_set {
unsigned long fds_bits[1];
};
デフォルトでは、カーネルは各プロセスがNR_OPEN_DEFAULT
ファイルを開くことを許可します。開くことを許可されるファイルの初期数は 32 です。64 ビット システムは同時に 64 個のファイルを処理できます
#define BITS_PER_LONG 32
#define NR_OPEN_DEFAULT BITS_PER_LONG
そして、のために
struct fdtable {
unsigned int max_fds;
struct file ** fd; // 每个数组项指向一个file结构的实例,管理一个打开文件的所有信息
fd_set *close_on_exec; // 一个指向位域的指针,该位域保存了所有在exec系统调用时将要关闭的文件描述符的信息
fd_set *open_fds; //一个指向位域的指针,该位域管理着当前所有打开文件的描述符。
struct rcu_head rcu;
struct fdtable *next;
};
その他は今のところまとめません
プロシージャ
proc
ブロックデバイスから情報を読み取ることができず、ファイル内容を読み取った場合にのみ対応する情報が動的に生成される論理ファイルシステムです。
ファイル システムを使用するとproc
、カーネルのさまざまなサブシステムに関する情報 (メモリ使用率、接続されている周辺機器など) を取得でき、カーネル ソース コードを再コンパイルしたりシステムを再起動したりせずに、カーネルの動作を変更できます。
これに関連するのがシステム制御メカニズムですsysctl system control mechanism
。通常、プロセス データ ファイル システムはprocfs
にマウントされ/proc
、その略称が であるproc FS
ため、この名前が付けられています。
proc
ファイル システムの容量はシステムによって異なりますが、それでも多くの深くネストされたディレクトリ、ファイル、リンクが含まれています。ただし、この情報は、メモリ管理、システム プロセスの特性データ、ファイル システム、デバイス ドライバー、システム バス、電源管理、端末およびシステム制御パラメーターのカテゴリに分類できます。
一部のプロセスに関する情報は「/proc」で確認できます。
root@huawei 2194 # cat cmdline
/usr/libexec/at-spi-bus-launcher#
root@huawei 2194 # pwd
/proc/2194
一般的なシステム情報
root@huawei /proc # cat stat [0]
cpu 12211193 7303 2174437 538380117 370471 0 21859 0 0 0
cpu0 6128342 3721 1085295 269120499 127141 0 7760 0 0 0
cpu1 6082850 3582 1089142 269259618 243329 0 14099 0 0 0
intr 1278733850 0 9 0 0 2566 0 3 0 0 0 277238 28 15 0 0 0 0 0 0 0 0 0 0 0 0 27 0 4839272 5689436 0 4780 5813 0 18799006 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 2490275942
btime 1663128233
processes 8110805
procs_running 1
procs_blocked 0
softirq 903628053 0 295168408 202239 20129044 18142070 0 22983 280585352 13555 289364402
データ構造
proc
の各データ項目はproc_dir_entry
次のように
struct proc_dir_entry {
unsigned int low_ino; // inode编号
unsigned short namelen; // 文件名的长度
const char *name; // 指向存储文件名的字符串的指针
mode_t mode; // 文件类型
nlink_t nlink; // 目录中子目录和符号链接的数目
uid_t uid; // 用户ID
gid_t gid; // 组ID
loff_t size; // 大小
const struct inode_operations *proc_iops; // 对iNode的操作
const struct file_operations *proc_fops; // 对文件的操作
get_info_t *get_info; // 相关子系统中返回所需数据的例程
struct module *owner; // 模块拥有者
struct proc_dir_entry *next, *parent, *subdir; // parent指向父目录的指针 subdir和next支持文件和目录的层次化布置
void *data; // 保存的数据
read_proc_t *read_proc; // 支持从/向内核读取/写入数据
write_proc_t *write_proc;
atomic_t count; /* 计数器 */
int pde_users; /* number of callers into module in progress */
spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */
struct completion *pde_unload_completion;
shadow_proc_t *shadow_proc;
};
カーネルは、オブジェクト指向の方法でファイル システム データ項目の表示proc_inode
をサポートするデータ構造を提供します。inode
proc
union proc_op {
int (*proc_get_link)(struct inode *, struct dentry **, struct vfsmount **);
int (*proc_read)(struct task_struct *task, char *page);
};
struct proc_inode {
// 该结构用来将特定于proc的数据与VFS层的inode数据关联起来
struct pid *pid;
int fd;
union proc_op op;
struct proc_dir_entry *pde; // 指针 指向关联的proc_dir_entry实例
struct inode vfs_inode; // 实际数据
};
言い換えれば、各構造インスタンスがproc
ファイル システムに関連付けられる前にinode
、対応するインスタンスに属するメモリ内に追加データが存在しproc_inode
、その情報に従ってメカニズムを取得inode
できます。container_of
proc_inode
static inline struct proc_inode *PROC_I(const struct inode *inode)
{
return container_of(inode, struct proc_inode, vfs_inode);
}
初期化してロードする
proc
ファイルシステムをマウントする
/proc
マウントは非仮想ファイル システムとほぼ同じです。唯一の違いは、デバイス ファイルを使用する代わりに、データ ソースとして適切なキーワード (通常はproc
または) を指定することです。none
プロセス関連情報
システム プロセスに関連する情報の出力は、proc
ファイル システムの元の設計の主要なタスクの 1 つです。
システム制御情報
カーネルの動作は、システム制御を通じて実行時に変更できます。制御パラメータは、マシンを再起動することなくユーザー空間からカーネルに転送されます。カーネルの動作を操作する従来の方法はsysctl
システムコールです
ユニオンファイルシステム UnionFS
Linux 3.18
カーネル コンテナー テクノロジーをサポートするために追加されたカーネル機能。
UnionFS
現在サポートされDocker
ているユニオン ファイル システムにはOverlayFS
、、、、、およびが含まれます。 AUFS
Btrfs
VFS
ZFS
Device Mapper
ユニオンマウントテクノロジー
通常、特定のファイル システムを介してコンテンツをマウント ポイントにマウントすると、マウント ポイント ディレクトリ内の元のコンテンツは非表示になり、元のコンテンツが非表示になるUnion Mount
代わりにダウンロードしたコンテンツを統合し、統合されたコンテンツの統一されたファイル システム ビューを提供しますmerge
。
COW コピーオンライト テクノロジー
COW
これは、既存のファイル システムのコンテンツを決して上書きせず、COW
ファイル システムを通じて 2 つのファイル システムをマージすることを意味します。エンド ユーザーの観点からは、すべてのコンテンツを含むマージされたファイル システムになります (Linux
カーネルの観点から区別できます)。 、ユーザーのlower
ファイル システム (コンテンツには読み取り権限があり、upper
ファイル システムのコンテンツには読み取りおよび書き込み権限があります)
実験内容は以下から抜粋: Docker の深層学習 – Joint File System OverlayFS
# 创建四个文件夹
mkdir upper lower merged work
# 存放内容
echo "I'm from lower!" > lower/in_lower.txt
echo "I'm from upper!" > upper/in_upper.txt
echo "In both. I'm from lower!" > lower/in_both.txt
echo "In both. I'm from upper!" > upper/in_both.txt
# 建立UnionFS
sudo mount -t overlay overlay \
-o lowerdir=./lower, upperdir=./upper,workdir=./work \
./merged
sysfs
sysfs
kobject
これは、カーネル オブジェクトをユーザー空間にエクスポートするファイル システムです。カーネルの内部データ構造を表示する機能を提供するだけでなく、システムのすべてのデバイスとバスがシステムのハードウェア トポロジの表現も提供しますsysfs
。 。
struct kobject
データ構造
kobject
階層型組織に含まれます。最も重要なことは、それらが親オブジェクトを持つことができ、その 1 つのオブジェクトに含めることができるということですkset
。これにより、階層内のどこにkobject
表示されるかが決まります。親オブジェクトが存在する場合は、親オブジェクトに対応するディレクトリに新しいエントリを作成する必要があります。sysfs
それ以外の場合は、kobject
それが属する対応するディレクトリに配置しますkset
。kobject
- 各
kobject
in はsysfs
ディレクトリとして表されます。このディレクトリに表示されるファイルは、オブジェクトのプロパティです。プロパティのエクスポートと設定の操作は、オブジェクトが属するサブシステムによって提供されます。 - バス、デバイス、ドライバー、およびクラスは、このメカニズムを使用する主要なカーネル オブジェクトであり、したがって、カーネル内のほぼすべてのデータ項目
kobject
を占めます。sysfs
それぞれがノードsysfs_dirent
を表しますsysfs
struct sysfs_dirent {
atomic_t s_count; // 引用计数
atomic_t s_active; // 活动
struct sysfs_dirent *s_parent; // 父节点
struct sysfs_dirent *s_sibling; // 子节点
const char *s_name; // 文件、目录或符号链接的名称
union {
struct sysfs_elem_dir s_dir;
struct sysfs_elem_symlink s_symlink;
struct sysfs_elem_attr s_attr;
struct sysfs_elem_bin_attr s_bin_attr;
};
unsigned int s_flags; // 设置sysfs数据项的类型
ino_t s_ino;
umode_t s_mode;
struct iattr *s_iattr;
};
カーネルオブジェクト
C
カーネルには、言語内の構造のインスタンスを追跡する必要がある場所が数多くあります。これらのオブジェクトの使用法はまったく異なりますが、参照カウントなどの一部の操作は、異なるサブシステム間でも非常に似ています。その結果、コードが重複してしまいました。これは悪い問題だったので、カーネル バージョン 2.5 の開発中に、カーネルはカーネル オブジェクトの管理に一般的なアプローチを採用しました。
一般的なカーネル オブジェクト メカニズムを使用して、次のオブジェクト操作を実行できます。
- 参照カウント;
- 管理オブジェクトのリンク リスト (コレクション);
- コレクションロック。
- オブジェクトのプロパティをユーザー空間にエクスポートします (
sysfs
ファイル システム経由)。
struct kobject {
const char * k_name; // 对象的文本名称
struct kref kref; // struct kref 简化引用计数的管理
struct list_head entry; // 链表元素
struct kobject * parent; // 指向父对象的指针
struct kset * kset; // kset
struct kobj_type * ktype; // 其他信息
struct sysfs_dirent * sd;
wait_queue_head_t poll;
};
参照カウント
struct kref {
atomic_t refcount;
};
void kref_init(struct kref *kref);
void kref_get(struct kref *kref);
int kref_put(struct kref *kref, void (*release) (struct kref *kref));
オブジェクト コレクション: 多くの場合、さまざまなカーネル オブジェクトをコレクション (たとえば、All Character Devices コレクションや All Based PCI
Devices コレクション)にグループ化する必要があります。
struct kset {
struct kobj_type *ktype; // kset中各个内核对象公用的kobj_type结构
struct list_head list; // 所有属于当前集合的内核对象的链表
spinlock_t list_lock;
struct kobject kobj;
struct kset_uevent_ops *uevent_ops; // 若干函数指针,用于将集合的状态信息传递给用户层
};
extern void kset_init(struct kset * k);
extern int __must_check kset_add(struct kset * k);
extern int __must_check kset_register(struct kset * k);
extern void kset_unregister(struct kset * k);
udevとdevfsの違い
2.6 カーネルより前に使用されていたのは、ディレクトリにマウントするdevfs
ことで、/dev ディレクトリにあるすべてのデバイスを管理するファイルのような方法が提供されるということでした。ディレクトリ内の各ファイルがデバイスに対応していることがわかっています。デバイスが現在存在するかどうか、およびこれらの特殊ファイルはルート ファイル システムに配置されており、これらのデバイス ファイルはファイル システムを作成するときにすでに作成されているため、これらの特殊ファイルを操作することでカーネルとの通信を実現できます。evfs
/dev
/dev
しかし、devfs
次のようなデメリットもあります。
- デバイスのマッピングが不確実です。デバイスによってマッピングされたデバイス ファイルが異なる場合があります。たとえば、USB フラッシュ ドライブが
sda
対応している場合がありますsdb
。 - 十分なプライマリ/セカンダリ デバイス番号がありません。デバイスが多すぎると明らかに問題になります。
/dev
ディレクトリ内のファイルが多すぎるため、現在のシステム上の実際のデバイスを表すことができません。- 命名には十分な柔軟性がなく、任意に指定することはできません
したがって、まさに上記の問題のため、udev 公式 Web サイトのソース コードがudev
作成されました。
linux2.6
カーネルの後、ディレクトリにsysfs
マウントされる新しいファイル システムが導入され、 devfs と同様に仮想ファイル システムであり、システム デバイスの管理にも使用されます。/sys
root@huawei /sys # df .
Filesystem 1K-blocks Used Available Use% Mounted on
sysfs 0 0 0 - /sys
実際にシステムに接続されているデバイスとバスを階層ファイルに編成します。ユーザー空間プログラムは、この情報を使用してカーネルと対話することもできます。このファイル システムは、現在のシステム上の実際のデバイス ツリーを直感的に反映しています。
この情報はサブシステムを通じて確立されますkobject
。kobject が作成されると、対応するファイルとディレクトリも作成され、以下の/sys
関連ディレクトリに配置されます。各デバイスsysfs
には固有の対応するディレクトリがあるため、ユーザー空間で読み書きすることができます。
ユーザー空間ツールは、提供された情報udev
を使用して、すべての devfs 機能を実装します。sysfs
udev
アドバンテージ:
-
動的管理: デバイスが追加/削除されると、
udev
デーモン プロセスはカーネルからの情報をリッスンし、それを使用してデバイス ファイルをuevent
追加または削除します。そのため、大量の何も生成されずに、接続されたデバイスに対してデバイス ファイルのみが生成されます。デバイス ファイル: ホットプラグが発生すると、デバイスの変更に関する関連情報がカーネル (sysfs ファイル システム) に出力され、その情報は対応するデバイス ノードの管理に使用されます。/dev
udev
/dev/
/sys
udev
sysfs
-
カスタマイズされた命名規則: 規則ファイルを通じて、
udev
カーネル/dev/
デバイス名がすべてのデバイスに対して定義されます/dev/sda,/dev/hda,/dev /fd
(これらはドライバー層によって定義されたデバイス名です) など。ユーザー空間で実行されるためudev
、Linux
ユーザーは独自のルール ファイルを定義し、識別性の高いデバイス ファイル (など) を生成できます/dev /boot_disk,/dev/root_disk,/dev/color_printer
。 -
デバイスの権限と所有者/グループを設定します。また、ルール ファイルでは、デバイス関連の権限と所有者/グループを自分で定義できます。
root@huawei tun # pwd
/sys/dev/char/10:1/subsystem/tun
root@huawei tun # ls
dev power subsystem uevent
root@huawei tun # cat dev
10:200
root@huawei tun # cat uevent
MAJOR=10 # 主设备号
MINOR=200 # 副设备号
DEVNAME=net/tun # 对应设备
Cグループ
最後に、Cgroup
ファイル システムのリストを見ると、Cgroup
カーネル内のファイル システムの半分を占めていることがわかりますが、fs
これについて話すのは少し無理があるように思えます。
# ...
cgroup 0 0 0 - /sys/fs/cgroup/cpu,cpuacct
cgroup 0 0 0 - /sys/fs/cgroup/devices
cgroup 0 0 0 - /sys/fs/cgroup/blkio
cgroup 0 0 0 - /sys/fs/cgroup/freezer
cgroup 0 0 0 - /sys/fs/cgroup/memory
cgroup 0 0 0 - /sys/fs/cgroup/net_cls,net_prio
cgroup 0 0 0 - /sys/fs/cgroup/rdma
cgroup 0 0 0 - /sys/fs/cgroup/cpuset
cgroup 0 0 0 - /sys/fs/cgroup/perf_event
cgroup 0 0 0 - /sys/fs/cgroup/pids
cgroup 0 0 0 - /sys/fs/cgroup/hugetlb
# ...
Cgroup
データ構造を表示する
struct cgroup {
unsigned long flags; // 标识当前cgroup的状态
atomic_t count; // 引用计数器,表示有多少个进程在使用这个cgroup
struct list_head sibling; // 所有的兄弟节点
struct list_head children; // 所有子节点
struct cgroup *parent; // 父节点
struct dentry *dentry; // cgroup是层级的一个目录,该字段用于描述该目录
struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT]; // 提供给各个子系统存放其限制进程组使用资源的统计数据
struct cgroupfs_root *root; // 保存层级的一些数据
struct cgroup *top_cgroup; // 层级的根节点
struct list_head css_sets;
struct list_head release_list;
};
各サブシステムには独自のリソース制御統計構造があります。
struct cgroup_subsys_state {
struct cgroup *cgroup; // 指向了这个资源控制统计信息所属的 cgroup
atomic_t refcnt; // 引用计数器
unsigned long flags; // 标志位
};
struct mem_cgroup {
struct cgroup_subsys_state css;
struct res_counter res;
struct mem_cgroup_lru_info info;
int prev_priority;
struct mem_cgroup_stat stat;
};
凡例の由来: cgroup 図の
Cgroup
システム凡例プロセスは、リソース制御のために (異なるレベルに属している場合に限り) 異なるプロセスに同時に
追加でき、これらには異なるリソース制御サブシステムが接続されます。したがって、プロセスがサブシステムを通じて対応するサブシステムのリソース制御統計を迅速に見つけられるように、これらのサブシステムのリソース制御統計を収集するには構造を使用する必要があり、これを行うために構造が使用されます。 cgroup
cgroup
cgroup
ID
css_set
struct css_set {
struct kref ref; // 引用计数器,用于计算有多少个进程在使用
struct list_head list; // 用于连接所有 css_set
struct list_head tasks; // 由于可能存在多个进程同时受到相同的 cgroup 控制,所以用此字段把所有使用此 css_set 的进程连接起来
struct list_head cg_links;
struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT]; //用于收集各种子系统的统计信息结构
};
CGroup
cgroup_subsys
各サブシステムは構造を通じて動作し、各サブシステムはそのような構造を実装する必要があります。
struct cgroup_subsys {
struct cgroup_subsys_state *(*create)(struct cgroup_subsys *ss,
struct cgroup *cgrp);
void (*pre_destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp);
void (*destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp);
int (*can_attach)(struct cgroup_subsys *ss,
struct cgroup *cgrp, struct task_struct *tsk);
void (*attach)(struct cgroup_subsys *ss, struct cgroup *cgrp,
struct cgroup *old_cgrp, struct task_struct *tsk);
void (*fork)(struct cgroup_subsys *ss, struct task_struct *task);
void (*exit)(struct cgroup_subsys *ss, struct task_struct *task);
int (*populate)(struct cgroup_subsys *ss,
struct cgroup *cgrp);
void (*post_clone)(struct cgroup_subsys *ss, struct cgroup *cgrp);
void (*bind)(struct cgroup_subsys *ss, struct cgroup *root);
int subsys_id; // 表示了子系统的ID
int active; // 子系统是否被激活
int disabled; // 子系统是否被禁止
int early_init;
const char *name; // 子系统名称
struct cgroupfs_root *root; // 被附加到的层级挂载点
struct list_head sibling; // 用于连接被附加到同一个层级的所有子系统
void *private; // 私有数据
};
メモリ サブシステムは、mem_cgroup_subsys
と呼ばれるcgroup_subsys
構造を定義します。
struct cgroup_subsys mem_cgroup_subsys = {
.name = "memory",
.subsys_id = mem_cgroup_subsys_id,
.create = mem_cgroup_create,
.pre_destroy = mem_cgroup_pre_destroy,
.destroy = mem_cgroup_destroy,
.populate = mem_cgroup_populate,
.attach = mem_cgroup_move_task,
.early_init = 0,
};
さらに、Linux
カーネルは、すべてのサブシステムの構造を保存するためのcgroup_subsys
構造の配列も定義します。 subsys
cgroup_subsys
static struct cgroup_subsys *subsys[]
#ifdef CONFIG_CPUSETS
SUBSYS(cpuset)
#endif
#ifdef CONFIG_CGROUP_DEBUG
SUBSYS(debug)
#endif
#ifdef CONFIG_CGROUP_NS
SUBSYS(ns)
#endif
#ifdef CONFIG_FAIR_CGROUP_SCHED
SUBSYS(cpu_cgroup)
#endif
#ifdef CONFIG_CGROUP_CPUACCT
SUBSYS(cpuacct)
#endif
メモリ制限
root@huawei memory # ls
cgroup.clone_children memory.failcnt memory.kmem.slabinfo memory.kmem.usage_in_bytes memory.oom_control memory.usage_in_bytes tasks
cgroup.event_control memory.force_empty memory.kmem.tcp.failcnt memory.limit_in_bytes memory.pressure_level memory.use_hierarchy user.slice
cgroup.procs memory.kmem.failcnt memory.kmem.tcp.limit_in_bytes memory.max_usage_in_bytes memory.soft_limit_in_bytes notify_on_release
cgroup.sane_behavior memory.kmem.limit_in_bytes memory.kmem.tcp.max_usage_in_bytes memory.move_charge_at_immigrate memory.stat release_agent
docker memory.kmem.max_usage_in_bytes memory.kmem.tcp.usage_in_bytes memory.numa_stat memory.swappiness system.slice
root@huawei memory # pwd
/sys/fs/cgroup/memory
root@huawei memory # cat memory.limit_in_bytes # 限制使用的内存大小
9223372036854771712 # 9223372036854771712字节
root@huawei memory # head tasks # 限制使用的进程编号
1 2 3 4 6 9 10 112 13
プロセッサーの使用制限
root@huawei cpu # ls [0]
cgroup.clone_children cpuacct.stat cpuacct.usage_percpu cpuacct.usage_sys cpu.cfs_quota_us docker system.slice
cgroup.procs cpuacct.usage cpuacct.usage_percpu_sys cpuacct.usage_user cpu.shares notify_on_release tasks
cgroup.sane_behavior cpuacct.usage_all cpuacct.usage_percpu_user cpu.cfs_period_us cpu.stat release_agent user.slice
root@huawei cpu # cat cpuacct.stat
user 12278762
system 2208080
root@huawei cpu # cat cpuacct.usage
154089159888977
root@huawei cpu # cat cpu.stat
nr_periods 0
nr_throttled 0
throttled_time 0
root@huawei cpu # head tasks
1 2 3 4 6 9 10 11 12 13
最後に、ここで難しい点を記録しておきます
tty0
: 現在の仮想端末のエイリアス
tty1-ttyn
:tty1-6
テキスト コンソール (仮想端末)、グラフィカル コンソール (グラフィック ターミナル)tty7
:シリアル ターミナル: コンソール ターミナル (コンピュータ モニタ) :擬似端末x-window
ttyS0
console
pts
誰と競争するのか?私の世代が先頭に立っていきます!