共計 4616 個字符,預(yù)計需要花費 12 分鐘才能閱讀完成。
本篇文章為大家展示了如何進行 lxcfs read /proc/meminfo 源碼流程的解析,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。
git repo: https://git-sa.nie.netease.com/whale/lxcfs
首先,lxcfs 作為用戶態(tài)的文件系統(tǒng),所有對文件的操作定義在 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
// 在這個函數(shù)根據(jù)參數(shù) *path 判斷,執(zhí)行 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
// 根據(jù) fuse_file_info 判斷 f- type 執(zhí)行對 proc_meminfo_read、proc_cpuinfo_read、proc_uptime_read、proc_stat_read、proc_diskstats_read、proc_swaps_read、proc_loadavg_read 相應(yīng)的文件進行讀操作
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 數(shù)據(jù)獲取并計算的邏輯
// 打印結(jié)果就是 cat 取到的內(nèi)容
fprintf(stderr, proc_meminfo_read .... buf: %s\n , buf);
rv = total_len;
get_min_memlimit
在 bindings.c 實現(xiàn)了所有 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);
// 打印結(jié)果就是 cat 獲取到的內(nèi)容
//fprintf(stderr, zy test .....buf:%s\n , buf);
rv = total_len;
if (f)
修改 lxcfs 的動態(tài)鏈接庫路徑的方法
在 ./configure 階段 加 --prefix /home/cld 就可以指定動態(tài)鏈接庫的路徑 為 /home/cld/var/lxcfs/liblxcfs.so
上述內(nèi)容就是如何進行 lxcfs read /proc/meminfo 源碼流程的解析,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注丸趣 TV 行業(yè)資訊頻道。
正文完