千家信息网

如何进行lxcfs read /proc/meminfo源码流程的解析

发表于:2024-10-22 作者:千家信息网编辑
千家信息网最后更新 2024年10月22日,本篇文章为大家展示了如何进行lxcfs read /proc/meminfo源码流程的解析,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。git repo: h
千家信息网最后更新 2024年10月22日如何进行lxcfs read /proc/meminfo源码流程的解析

本篇文章为大家展示了如何进行lxcfs read /proc/meminfo源码流程的解析,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

git repo: https://git-sa.nie.netease.com/whale/lxcfs

首先,lxcfs作为用户态的文件系统,所有对文件的操作定义在 lxcfs.c

const struct fuse_operations lxcfs_ops = { .getattr = lxcfs_getattr, .readlink = NULL, .getdir = NULL, .mknod = NULL, .mkdir = lxcfs_mkdir, .unlink = NULL, .rmdir = lxcfs_rmdir, .symlink = NULL, .rename = NULL, .link = NULL, .chmod = lxcfs_chmod, .chown = lxcfs_chown, .truncate = lxcfs_truncate, .utime = NULL, .open = lxcfs_open, .read = lxcfs_read, .release = lxcfs_release, .write = lxcfs_write, .statfs = NULL, .flush = lxcfs_flush, .fsync = lxcfs_fsync, .setxattr = NULL, .getxattr = NULL, .listxattr = NULL, .removexattr = NULL, .opendir = lxcfs_opendir, .readdir = lxcfs_readdir, .releasedir = lxcfs_releasedir, .fsyncdir = NULL, .init = NULL, .destroy = NULL, .access = lxcfs_access, .create = NULL, .ftruncate = NULL, .fgetattr = NULL,};

此处我们分析一个完整的读 /proc/meminfo 的流程

lxcfs_read

// 在这个函数根据参数 *path 判断,执行 do_cg_read 还是 do_proc_readstatic int lxcfs_read(const char *path, char *buf, size_t size, off_t offset,  struct fuse_file_info *fi){ int ret; fprintf(stderr, "lxcfs_read ...... path: %s\r\n", path); if (strncmp(path, "/cgroup", 7) == 0) {  up_users();  ret = do_cg_read(path, buf, size, offset, fi);  down_users();  return ret; } if (strncmp(path, "/proc", 5) == 0) {  up_users();  ret = do_proc_read(path, buf, size, offset, fi);  down_users();  return ret; } return -EINVAL;}

do_proc_read --> proc_read

// 根据 fuse_file_info判断 f->type 执行对 proc_meminfo_read、proc_cpuinfo_read、proc_uptime_read、proc_stat_read、proc_diskstats_read、proc_swaps_read、proc_loadavg_read 相应的文件进行读操作 int proc_read(const char *path, char *buf, size_t size, off_t offset,  struct fuse_file_info *fi){ struct file_info *f = (struct file_info *) fi->fh; fprintf(stderr, "proc_read  ...... path: %s, file_info: %c \r\n", path, f->type); switch (f->type) { case LXC_TYPE_PROC_MEMINFO:  return proc_meminfo_read(buf, size, offset, fi); case LXC_TYPE_PROC_CPUINFO:  return proc_cpuinfo_read(buf, size, offset, fi); case LXC_TYPE_PROC_UPTIME:  return proc_uptime_read(buf, size, offset, fi); case LXC_TYPE_PROC_STAT:  return proc_stat_read(buf, size, offset, fi); case LXC_TYPE_PROC_DISKSTATS:  return proc_diskstats_read(buf, size, offset, fi); case LXC_TYPE_PROC_SWAPS:  return proc_swaps_read(buf, size, offset, fi); case LXC_TYPE_PROC_LOADAVG:  return proc_loadavg_read(buf, size, offset, fi); default:  return -EINVAL; }}

proc_meminfo_read

proc_meminfo_read(char *buf, size_t size, off_t offset,  struct fuse_file_info *fi) // 如果在容器中 cat /proc/meminfo,这里的 initpid为容器/sbin/init 进程号, // 如果在主机中 cat /usr/local/var/lib/lxcfs/proc/meminfo  initpid为主机的进程号1, 这里getpid为lxcfs进程号 fprintf(stderr, "proc_meminfo_read .... initpid:%d, pid:%d, getpid:%d \r\n", initpid, fc->pid, getpid()); cg = get_pid_cgroup(initpid, "memory"); fprintf(stderr, "proc_meminfo_read .... CG: %s\n", cg); if (!cg)  return read_file("/proc/meminfo", buf, size, d); prune_init_slice(cg); // 获取cgroup目录及其子目录中 memory.limit_in_bytes的最小值 memlimit = get_min_memlimit(cg, "memory.limit_in_bytes"); if (!cgfs_get_value("memory", cg, "memory.usage_in_bytes", &memusage_str))  goto err; if (!cgfs_get_value("memory", cg, "memory.stat", &memstat_str))  goto err;...   中间省略各种 meminfo数据获取并计算的逻辑... // 打印结果就是cat取到的内容 fprintf(stderr, "proc_meminfo_read .... buf: %s\n", buf); rv = total_len;

get_min_memlimit

在bindings.c 实现了所有 proc_meminfo_read、proc_cpuinfo_read、proc_uptime_read、proc_stat_read、proc_diskstats_read、proc_swaps_read、proc_loadavg_read的逻辑。

//获取cgroup目录及其子目录中 memory.limit_in_bytes的最小值static unsigned long get_min_memlimit(const char *cgroup){ char *copy = strdupa(cgroup);@@ -2951,12 +2952,20 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, pid_t initpid = lookup_initpid_in_store(fc->pid); if (initpid <= 0)  initpid = fc->pid;      //如果在容器中cat /proc/meminfo,则这里initpid为容器/sbin/init进程号,如果在主机中cat /usr/local/var/lib/lxcfs/proc/meminfo    //initpid为主机的进程号1,  这里的getpid为lxcfs进程号 cg = get_pid_cgroup(initpid, "memory");  if (!cg)  return read_file("/proc/meminfo", buf, size, d);  prune_init_slice(cg); memlimit = get_min_memlimit(cg); //获取cgroup目录及其子目录中 memory.limit_in_bytes的最小值 if (!cgfs_get_value("memory", cg, "memory.usage_in_bytes", &memusage_str))  goto err; if (!cgfs_get_value("memory", cg, "memory.stat", &memstat_str)) d->size = total_len; if (total_len > size ) total_len = size; memcpy(buf, d->buf, total_len);  //打印结果就是cat获取到的内容    //fprintf(stderr, "zy test .....buf:%s\n", buf); rv = total_len;err: if (f)

修改lxcfs的动态链接库路径的方法

在 ./configure 阶段 加--prefix /home/cld 就可以指定动态链接库的路径 为 /home/cld/var/lxcfs/liblxcfs.so

上述内容就是如何进行lxcfs read /proc/meminfo源码流程的解析,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注行业资讯频道。

0