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

71次阅读
没有评论

共计 4616 个字符,预计需要花费 12 分钟才能阅读完成。

本篇文章为大家展示了如何进行 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_read
static 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- 
 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- 
 
 // 如果在容器中 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;
 if (f)

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

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

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

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-16发表,共计4616字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)