本篇文章为大家展示了如何进行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 的流程
// 在这个函数根据参数 *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;
}
// 根据 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(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;
在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)
在 ./configure 阶段 加--prefix /home/cld 就可以指定动态链接库的路径 为 /home/cld/var/lxcfs/liblxcfs.so
上述内容就是如何进行lxcfs read /proc/meminfo源码流程的解析,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注亿速云行业资讯频道。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/markz0928/blog/3206871