LXC1.0.7-- lxc-start 源码分析 04
来源:互联网 发布:淘宝为什么打压外贸店 编辑:程序博客网 时间:2024/05/22 15:12
lxc start部分的源码的大致工作流程已经熟悉,那么就要关注他的核心内容了,就是关于namespace 和 cgroup的内容了。
根据前面的分析已经知道,lxc根据一些配置会自动将flag设置成CLONE_NEWXXX,然后会通过cgroup init 来初始化一堆 cgroup。我们先来看一下。
首先通过cgroup_create 来创建 cgroup,前面介绍都是有个ops 指向函数指针,这里先假设我们用的cgfs,理论上应该和cgroupmanager是一样的方式,可能细节有区别而已。
那么顺理成章create指向cgfs_create,后面就直接说函数指针的位置了。
函数内部通过调用lxc_cgroupfs_create。那么就要从create a newcgroup
static struct cgroup_process_info *lxc_cgroupfs_create(const char*name, const char *path_pattern, struct cgroup_meta_data *meta_data, const char*sub_pattern)
char**cgroup_path_components = NULL;
char **p = NULL;
char *path_so_far = NULL;
char **new_cgroup_paths =NULL;
char **new_cgroup_paths_sub =NULL;
struct cgroup_mount_point*mp;
struct cgroup_hierarchy *h;
struct cgroup_process_info*base_info = NULL;
struct cgroup_process_info*info_ptr;
int saved_errno;
int r;
unsigned suffix = 0;
bool had_sub_pattern = false;
size_t i;
if (!is_valid_cgroup(name)){ //判断name 是否有效
ERROR("Invalidcgroup name: '%s'", name);
errno = EINVAL;
return NULL;
}
if (!strstr(path_pattern,"%n")) {
ERROR("Invalidcgroup path pattern: '%s'; contains no %%n for specifying container name",path_pattern);
errno = EINVAL;
return NULL;
}
根据privilege 和unprivilege container的不同读取到proc 下面的pid的不同来确定不同的cgroup 信息。
base_info = (path_pattern[0]== '/') ?
lxc_cgroup_process_info_get_init(meta_data) :
lxc_cgroup_process_info_get_self(meta_data);
if (!base_info)
return NULL;
new_cgroup_paths =calloc(meta_data->maximum_hierarchy + 1, sizeof(char *));
if (!new_cgroup_paths)
goto out_initial_error;
在自己机子上面,看到的cgroup:
gudh@lxc-D3F2-CM:~$ cat/proc/self/cgroup
11:name=systemd:/user/1004.user/5.session
10:hugetlb:/user/1004.user/5.session
9:perf_event:/user/1004.user/5.session
8:blkio:/user/1004.user/5.session
7:freezer:/user/1004.user/5.session
6:devices:/user/1004.user/5.session
5:memory:/user/1004.user/5.session
4:cpuacct:/user/1004.user/5.session
3:cpu:/user/1004.user/5.session
2:cpuset:/user/1004.user/5.session
gudh@lxc-D3F2-CM:~$ id
uid=1004(gudh)gid=1004(gudh) groups=1004(gudh),0(root),4(adm)
gudh@lxc-D3F2-CM:~$ cat/proc/1/cgroup
11:name=systemd:/
10:hugetlb:/
9:perf_event:/
8:blkio:/
7:freezer:/
6:devices:/
5:memory:/
4:cpuacct:/
3:cpu:/
2:cpuset:/
然后就是分配path的大小
new_cgroup_paths_sub =calloc(meta_data->maximum_hierarchy + 1, sizeof(char *));
if (!new_cgroup_paths_sub)
goto out_initial_error;
查找可以挂载的点,然后创建。
/* find mount points we canuse */
for (info_ptr = base_info; info_ptr;info_ptr = info_ptr->next) {
h = info_ptr->hierarchy;
mp = lxc_cgroup_find_mount_point(h,info_ptr->cgroup_path, true);
if (!mp) {
ERROR("Could not find writablemount point for cgroup hierarchy %d while trying to create cgroup.",h->index);
goto out_initial_error;
}
info_ptr->designated_mount_point =mp;
if (lxc_string_in_array("ns",(const char **)h->subsystems))
continue;
if (handle_cgroup_settings(mp,info_ptr->cgroup_path) < 0) {
ERROR("Could not setclone_children to 1 for cpuset hierarchy in parent cgroup.");
goto out_initial_error;
}
}
cgroup_path_components = lxc_normalize_path(path_pattern);
if (!cgroup_path_components)
goto out_initial_error;
然后根据normalize的path去创建他们。
/* go through the pathcomponents to see if we can create them */
for (p = cgroup_path_components; *p ||(sub_pattern && !had_sub_pattern); p++) {
/* we only want to create the samecomponent with -1, -2, etc.
* if the component contains thecontainer name itself, otherwise
* it's not an error if it alreadyexists
*/
char *p_eff = *p ? *p : (char*)sub_pattern;
bool contains_name = strstr(p_eff,"%n");
char *current_component = NULL;
char *current_subpath = NULL;
char *current_entire_path = NULL;
char *parts[3];
size_t j = 0;
i = 0;
/* if we are processing the subpattern, we want to make sure
* loop is ended the next time around
*/
if (!*p) {
had_sub_pattern = true;
p--;
}
然后就到find_name_on_this_level,这里面pattern 应该是/lxc/%n
goto find_name_on_this_level;
find_name_on_this_level:
/* determine name of the path componentwe should create */
if (contains_name && suffix> 0) {
char *buf = calloc(strlen(name) +32, 1);
if (!buf)
goto out_initial_error;
snprintf(buf, strlen(name) + 32,"%s-%u", name, suffix);
current_component =lxc_string_replace("%n", buf, p_eff);
free(buf);
} else {
current_component = contains_name ?lxc_string_replace("%n", name, p_eff) : p_eff;
}
parts[0] = path_so_far;
parts[1] = current_component;
parts[2] = NULL;
current_subpath = path_so_far ?lxc_string_join("/", (const char **)parts, false) :current_component;
紧接着创建相应的cgroup
for (i = 0, info_ptr =base_info; info_ptr; info_ptr = info_ptr->next, i++) {
char *parts2[3];
if(lxc_string_in_array("ns", (const char**)info_ptr->hierarchy->subsystems))
continue;
current_entire_path = NULL;
parts2[0] =!strcmp(info_ptr->cgroup_path, "/") ? "" :info_ptr->cgroup_path;
parts2[1] = current_subpath;
parts2[2] = NULL;
current_entire_path = lxc_string_join("/",(const char **)parts2, false);
if (!*p) {
/* we are processing thesubpath, so only update that one */
free(new_cgroup_paths_sub[i]);
new_cgroup_paths_sub[i] =strdup(current_entire_path);
if (!new_cgroup_paths_sub[i])
goto cleanup_from_error;
} else {
/* remember which path was usedon this controller */
free(new_cgroup_paths[i]);
new_cgroup_paths[i] =strdup(current_entire_path);
if (!new_cgroup_paths[i])
goto cleanup_from_error;
}
r =create_cgroup(info_ptr->designated_mount_point, current_entire_path);
这样就完成相应的代码设置。
对于pattern 为/lxc/%n 就分两次不同创建在相应的目录,这样cgroup subpath 也同时受到顶层/lxc 的控制,cgroup就成功创建了。
然后就到cgroup_create_legacy最终调用lxc_cgroup_create_legacy
直接看注释
/*
* if cgroup is mounted at/cgroup and task is in cgroup /ab/, pid 2375 and
* name is c1,
* dir: /ab
* fulloldpath =/cgroup/ab/2375
* fullnewpath =/cgroup/ab/c1
* newname = /ab/c1
*/
如果老名字为/sys/cgroup/cpu/lxc/android/2375
那么就改成/sys/cgroup/cpu/lxc/android/android?
加入cgroup一些创建file的 capability
cgroup_setup_limits 名字很明显设置限额 with_device是false
将在config中加入的device.allow 和device.deny 配置
手动设置的地方
然后就是cgfs_enter 最后到lxc_cgroupfs_enter
lxc_cgroup_find_mount_point 查找path下面的mount point
cgroup_to_absolute_path absolute path
lxc_write_to_file然后将pid写入到cgroup的absolutepath下面
这样就将pid 与cgroup成功绑定。
cgroup_chown chown的指针目前是NULL 暂时不分析
后面又来了一次 cgroup_setup_limits 这是with_device 是true
此时应该就完成了cgroup的相关设置
- LXC1.0.7-- lxc-start 源码分析 04
- LXC1.0.7-- lxc-start 源码分析 01
- LXC1.0.7-- lxc-start 源码分析 02
- LXC1.0.7-- lxc-start 源码分析 03
- LXC quick start
- start.s源码分析
- lxc源码-- 序
- lxc源码安装
- lxc-console流程分析
- s3c2410 u-boot源码分析start.S
- s3c2410 u-boot源码分析start.S
- s3c2410 u-boot start.s源码分析
- U-boot源码分析之start.s
- s3c2410 u-boot源码分析start.S
- s3c2410 u-boot源码分析start.S
- s3c2410 u-boot源码分析start.S
- s3c2410 u-boot源码分析start.S
- pmon 源码分析之start.S
- popupwindow全屏幕显示被状态栏挡住如何解决+Android获取状态栏高度
- Liunx创建SWAP的步骤
- 风雨
- 含羞草
- 自己总结的web前端知识体系大全【欢迎补充】
- LXC1.0.7-- lxc-start 源码分析 04
- iOS开发如何判断字符串是否是整数,浮点数,纯数字
- std::string用法总结
- 插入排序
- 简单的用户信息管理
- 代理——AOP框架实例
- Android 以流的形式复制集合所有元素到另一个集合
- Oracle(十二)PL/SQL 触发器
- SSL/TLS的Java实现--JSSE