仮想ファイル システム (永続ストレージを持たないファイル システム)、例として proc と sysfs を使用

最新のオペレーティング システムでは、仮想ファイル システムはほぼ遍在する機能であるため、最新のオペレーティング システムの動作メカニズムについて議論することは避けられません。

この記事では、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通常のファイルシステムもこれらと同等の関係にあるように思えますので、とりあえず論理ファイルシステムと呼ぶことにします)

proctmpfs、 などの一般的なものsysfs

ここで、論理ファイルシステムとファイルシステム、ディスクファイルシステムとメモリファイルシステムの違いに注意する必要がありますが、
特定の仮想ファイルシステムは単なる中間層であり、次の種類があります。

  • proc: オペレーティング システム自体とアプリケーション間の通信に安全なインターフェイスを提供します。
  • devfs: 2.6 カーネルより前に使用され、ディレクトリにあるすべてのデバイスdevfsを管理するファイルのような方法を提供しました。/dev
  • sysfs:sysfsファイル システムは、システムに接続されているデバイスとバスを階層ファイルに編成します。ユーザー空間プログラムは、この情報を使用して、通常は の代わりにカーネルと対話することもできますdevfssysfsファイル システムは、現在のシステム上の実際のデバイス ツリーを直感的に反映したもので、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をサポートするデータ構造を提供します。inodeproc

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_ofproc_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、、、、、およびが含まれます AUFSBtrfs VFSZFS 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

sysfskobjectこれは、カーネル オブジェクトをユーザー空間にエクスポートするファイル システムです。カーネルの内部データ構造を表示する機能を提供するだけでなく、システムのすべてのデバイスとバスがシステムのハードウェア トポロジの表現も提供しますsysfs。 。

struct kobjectデータ構造

  • kobject階層型組織に含まれます。最も重要なことは、それらが親オブジェクトを持つことができ、その 1 つのオブジェクトに含めることができるということですksetこれにより、階層内のどこにkobject表示されるかが決まります。親オブジェクトが存在する場合は、親オブジェクトに対応するディレクトリに新しいエントリを作成する必要があります。sysfsそれ以外の場合は、kobjectそれが属する対応するディレクトリに配置しますksetkobject
  • kobjectin は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 PCIDevices コレクション)にグループ化する必要があります。

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 ファイル システム) に出力され、その情報は対応するデバイス ノードの管理に使用されます。/devudev/dev//sysudevsysfs

  • カスタマイズされた命名規則: 規則ファイルを通じて、udevカーネル/dev/デバイス名がすべてのデバイスに対して定義されます/dev/sda,/dev/hda,/dev /fd(これらはドライバー層によって定義されたデバイス名です) など。ユーザー空間で実行されるためudevLinuxユーザーは独自のルール ファイルを定義し、識別性の高いデバイス ファイル (など) を生成できます/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システム凡例プロセスは、リソース制御のために (異なるレベルに属している場合に限り) 異なるプロセスに同時に
ここに画像の説明を挿入します
追加でき、これらには異なるリソース制御サブシステムが接続されます。したがって、プロセスがサブシステムを通じて対応するサブシステムのリソース制御統計を迅速に見つけられるように、これらのサブシステムのリソース制御統計を収集するには構造を使用する必要があり、これを行うために構造が使用されます。 cgroupcgroup cgroupIDcss_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構造の配列も定義します。 subsyscgroup_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

誰と競争するのか?私の世代が先頭に立っていきます!

おすすめ

転載: blog.csdn.net/qq_48322523/article/details/127343346