当前位置: 首页 > news >正文

wordpress实训广州seo黑帽培训

wordpress实训,广州seo黑帽培训,云南网站备案难吗,美术设计与制作在前面的文章中#xff0c;我们探讨了容器底层 cgroup 的数据结构与代码实现#xff0c;本期是 cgroup 系列的最后一篇文章#xff0c;我们将继续探讨在 mount 成功后#xff0c;我们如何使用 cgroup 来实现进程限制。在 mount 成功后#xff0c;cgroup_root 已经存在了我们探讨了容器底层 cgroup 的数据结构与代码实现本期是 cgroup 系列的最后一篇文章我们将继续探讨在 mount 成功后我们如何使用 cgroup 来实现进程限制。在 mount 成功后cgroup_root 已经存在了也就是说 cgroup 层级结构已经搭建好了接下来我们就可以使用 cgroup 了。测试环境版本与之前一致1. cgroup 的 mkdirmkdir 比 mount 的过程稍简单由 cgroup_mkdir 函数实现主要逻辑如下int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name, umode_t mode) {struct cgroup *parent, *cgrp;parent cgroup_kn_lock_live(parent_kn, false); //1cgrp cgroup_create(parent, name, mode); //2ret cgroup_kn_set_ugid(cgrp-kn);ret css_populate_dir(cgrp-self); //3ret cgroup_apply_control_enable(cgrp);kernfs_activate(cgrp-kn);ret 0;return ret; 第 1 步获得父目录对应的 cgroup。无论是 cgroup_setup_root 还是接下来要说的cgroup_create在创建文件的时候都将 cgroup 赋值给了 kernfs_node 的 priv。所以这里其实就是返回 parent_kn-priv 字段不过要经过参数检查。第 2 步调用 cgroup_create创建 cgroup调用 kernfs_create_dir 创建目录建立新cgroup 和父 cgroup 的父子关系。第 3 步和 mount 的时候一样css_populate_dir 和 cgroup_apply_control_enable 会为我们创建 cftype 对应的文件不过有两点区别首先带 CFTYPE_ONLY_ON_ROOT 标志的 cftype 不会出现在这里比如cgroup.sane_behavior 和 release_agent。其次mount 的时候新 cgroup_root.cgrp 复用了原 cgroup_root.cgrp 相关的cssrebind_subsystems第二篇这里新建了一个 cgroupcgroup_apply_control_enable 需要为我们创建新的 cssss-css_alloc(parent_css)并建立 cgroup 和 ss 的多对多关系init_and_link_css和online_css。 mount 的时候cpuset 的 css_alloc 返回的是全局的 top_cpuset.css这里创建一个新的 cpuset 对象并初始化如下struct cgroup_subsys_state * cpuset_css_alloc(struct cgroup_subsys_state *parent_css) { struct cpuset *cs;if (!parent_css)    //mount的时候返回top_cpuset.cssreturn top_cpuset.css;cs kzalloc(sizeof(*cs), GFP_KERNEL); alloc_cpumasks(cs, NULL);    //#1set_bit(CS_SCHED_LOAD_BALANCE, cs-flags); nodes_clear(cs-mems_allowed); nodes_clear(cs-effective_mems);    //#2 fmeter_init(cs-fmeter); cs-relax_domain_level -1;return cs-css 注意标号 #1 和 #2新 cs 的 cpus_allowed 和 mems_allowed 都被清零此时读取cpuset.cpus 和 cpuset.mems 也是没有内容的也就是说对 cpu 和 memory 的限制并不能从父目录继承在使用前必须正确设置它们。2. 限制资源我们在第一篇的例子中通过 echo 0-2 cpuset.cpus 和 echo 0 cpuset.mems 限制 /cpuset0 管理的进程使用的 cpu 和 memory node以 cpuset.cpus 为例它的 cftype 如下{.name cpus,.seq_show cpuset_common_seq_show,.write cpuset_write_resmask,.max_write_len (100U 6 * NR_CPUS),.private FILE_CPULIST, },最终调用的是 cpuset_write_resmask后者调用 update_cpumask。update_cpumask 的目的是更新我们在 mkdir 时创建的 cpusetcpuset_css_alloc当然了之前已经配置过的 cpuset 重新配置也可以。我们关心以下几点 不能更改top_cpuset的设置这就是第一篇的课堂作业第一题的答案。目标cpuset的资源必须是父目录cpuset的子集而且是子目录cpuset的超集由validate_change函数实现这是课堂作业第二题的答案。配置的资源最终更新cpuset的cpus_allowed字段。可以看到类似课堂作业中描述的类似限制是需要 ss 自行实现的cgroup 本身并不保证这点尝试开发新的 ss 的时候需要注意这点。3. 管理进程我们在例子中将进程号写到 tasks 文件echo $$ tasks以限制进程只能使用 /cpuset0 配置的 cpu 和 memory node。实际上写 cgroup.procs 文件也是可以的。它们的 cftype 文件定义如下{.name tasks,.seq_start cgroup_pidlist_start,.seq_next cgroup_pidlist_next,.seq_stop cgroup_pidlist_stop,.seq_show cgroup_pidlist_show,.private CGROUP_FILE_TASKS,.write cgroup1_tasks_write, }, {.name cgroup.procs,.seq_start cgroup_pidlist_start,.seq_next cgroup_pidlist_next,.seq_stop cgroup_pidlist_stop,.seq_show cgroup_pidlist_show,.private CGROUP_FILE_PROCS,.write cgroup1_procs_write, },两个文件的 write 分别是 cgroup1_tasks_write 和 cgroup1_procs_write它们都是调用__cgroup1_procs_write 实现的区别仅在于最后一个参数 threadgroup 不同前者为false后者为 true。看名字就知道为 false 的情况下仅作用于目标进程线程为 true 的情况下作用于线程组。这里对线程组稍作说明。线程组是属于同一个进程的线程的集合同一个线程组的线程它们的 task_struct 都通过 thread_group 字段链接到同一个链表中链表的头为线程组领导进程的 task_struct 的 thread_group 字段可以据此来遍历线程组。__cgroup1_procs_write 可以分成以下 3 步第1步调用 cgroup_kn_lock_live 获得文件所在的目录的 cgroup实际上就是kernfs_node-parent-privkernfs_node-parent 是文件所在目录的 kernfs_nodepriv 就是目标 cgroup。第2步调用 cgroup_procs_write_start 根据用户空间传递的进程 id 参数获得目标进程的 task_structthreadgroup 为 true 的情况下获得的是线程组领导进程的task_struct。第3步调用 cgroup_attach_task 将进程 attach 到依附于或者连接cgroup。cgroup 和 ss 之间是对等的关系使用的是 bind称之为绑定进程和 cgroup 之间并不是对等的关系使用的是 attach称之为依附。 请注意我们举例中仅涉及 cpuset并不意味着某个进程只与 cpuset 有关进程和cgroup 的关系是通过 css_set 实现的也就是说是一组 cgroup。我们没有更改其他cgroup 层级结构的配置这意味着进程关联的是它们的 cgroup_root并不是没有关联。先不论进程被创建后“辗转”了几组cgroup进程被创建时就已经attach cgroup了。进程创建的过程在书里已经详细地分析过了这里仅讨论与cgroup相关的部分。首先被调用的是cgroup_fork如下void cgroup_fork(struct task_struct *child) { RCU_INIT_POINTER(child-cgroups, init_css_set); INIT_LIST_HEAD(child-cg_list); }直接指向了 init_css_set不过这有可能是暂时的。child-cg_list 是空的说明新进程还没有 attach 到任何 cgroup。其次是 cgroup_can_fork它调用 ss-can_fork由 ss 判断是否可以创建新进程如果答案是否整个 fork 会失败。最后是 cgroup_post_fork做最后的调整主要逻辑如下void cgroup_post_fork(struct task_struct *child) { struct cgroup_subsys *ss; struct css_set *cset;if (likely(child-pid)) {WARN_ON_ONCE(!list_empty(child-cg_list));cset task_css_set(current); /* current is childs parent */get_css_set(cset);cset-nr_tasks;css_set_move_task(child, NULL, cset, false); }do_each_subsys_mask(ss, i, have_fork_callback) {ss-fork(child); } while_each_subsys_mask(); }首先current 是新进程 child 的父进程先获得父进程的 css然后调用css_set_move_task 将新进程转移到该 css 上。css_set_move_task 的第二个参数是原css这里是 NULL 是因为还没有 attach 到任何 cgroupcss_set上。css_set_move_task 会将 child-cg_list 插入 css-tasks 链表上child-cg_list 不再为空。也就是说新进程在创建时会被 attach 到与父进程同一组 cgroup 上。其次如果 ss 定义了 fork调用 ss-fork以 cpuset 为例它会为新进程复制父进程的设置如下void cpuset_fork(struct task_struct *task) { if (task_css_is_root(task, cpuset_cgrp_id))return;set_cpus_allowed_ptr(task, current-cpus_ptr); task-mems_allowed current-mems_allowed; }回顾下第一篇的例子我们在 cpuset 下创建的 cpuset0 目录配置资源管理进程。修改下在 cpuset 下再创建一个 cpuset1 目录进程先 attach 到 /cpuset0然后migrate 到 /cpuset1上以此为例分析 migrate 的过程love_ccyahua:/sys/fs/cgroup/cpuset$ sudo mkdir cpuset0 love_ccyahua:/sys/fs/cgroup/cpuset$ sudo mkdir cpuset1 love_ccyahua:/sys/fs/cgroup/cpuset$ cd cpuset0/ rootyahua:/sys/fs/cgroup/cpuset/cpuset0# echo 0-2 cpuset.cpus rootyahua:/sys/fs/cgroup/cpuset/cpuset0# echo 0 cpuset.mems rootyahua:/sys/fs/cgroup/cpuset/cpuset0# echo $$ tasks rootyahua:/sys/fs/cgroup/cpuset/cpuset0# cat tasks 2682 2690 rootyahua:/sys/fs/cgroup/cpuset/cpuset0# cd ../cpuset1/ rootyahua:/sys/fs/cgroup/cpuset/cpuset1# echo 0-1 cpuset.cpus rootyahua:/sys/fs/cgroup/cpuset/cpuset1# echo 0 cpuset.mems rootyahua:/sys/fs/cgroup/cpuset/cpuset1# echo $$ tasks rootyahua:/sys/fs/cgroup/cpuset/cpuset1# cat tasks 2682 2713 rootyahua:/sys/fs/cgroup/cpuset/cpuset1# cat ../cpuset0/tasks #没有省略内容空的继续讨论之前先理一下目前的状况我们在 __cgroup1_procs_write 函数的第 3 步cgroup_attach_task之前的两步我们已经获得了目标 cgroup也就是 /cpuset1和进程的 task_struct。cgroup_attach_task 的目的是将进程 attach 到目标 cgroup逻辑上至少包括进程和原group detach 和进程和目标 cgroup attach 两部分。三个要素src、dst 和 migrate正好对应三个函数 cgroup_migrate_add_src、cgroup_migrate_prepare_dst 和cgroup_migrate。首先被调用的是 cgroup_migrate_add_srcthreadgroup 为 true 的情况下对线程组的每个线程调用一次否则调用一次即可它的主要逻辑如下void cgroup_migrate_add_src(struct css_set *src_cset,struct cgroup *dst_cgrp,struct cgroup_mgctx *mgctx) { struct cgroup *src_cgrp;src_cgrp cset_cgroup_from_root(src_cset, dst_cgrp-root);src_cset-mg_src_cgrp src_cgrp; src_cset-mg_dst_cgrp dst_cgrp; get_css_set(src_cset); list_add_tail(src_cset-mg_preload_node, mgctx-preloaded_src_csets);第一个参数 src_cset 表示进程原来的 css_set也就是 task_struct 的 cgroups 字段。首先要做的就是在目标 cgroupdst_cgrp也就是 /cpuset1所属的 cgroup_root 中找到原 cgroupsrc_cgrp也就是 /cpuset0它跟目标 cgroup 属于同一个cgroup_root查找的过程就变成找到 src_cset 对应的某个 cgroup它的 root 字段与dst_cgrp-root 相等如下list_for_each_entry(link, cset-cgrp_links, cgrp_link) {struct cgroup *c link-cgrp;if (c-root root) {res c;    //res就是我们要找的break;} }提醒下任何一个 cgroup 层级结构中进程只能关联其中一个 cgroup所以与 /cpuset1 属于同一个 cgroup_root 的只能是 /cpuset0 。另外我们分析的只是一种情况前面说的 Ubuntu mount cpuset 的时候进程从默认的层级结构迁移到 cpuset 上原 cgroup 和目标 cgroup 实际上属于不同的cgroup_root返回的是目标 cgroup_root 的 cgrp。cgroup_migrate_add_src 的第三个参数 mgctx 是 cgroup_attach_task 的局部变量函数结束前将 src_cset 插入到 mgctx-preloaded_src_csets 等待后续处理。cgroup_migrate_prepare_dst 遍历 mgctx-preloaded_src_csets上的 src_cset根据src_cset 和 src_cset-mg_dst_cgrp 查找当前已经存在的 css_set 是否有某个 css_set与期望一致没有则创建新的 css_set 并赋以期望值。期望一致两方面。怎么描述我们的期望呢进程只是从 /cpuset0 移到 /cpuset1 上关联的其他 cgroup 层级结构的 cgroup 并没有变化所以以原 css_set 作为模板调整 cpuset 层级结构上的css 即可实际的代码也大致如此如下for_each_subsys(ss, i) {if (root-subsys_mask (1UL i)) {template[i] cgroup_e_css_by_mask(cgrp, ss);} else {template[i] old_cset-subsys[i];} }root 就是发生变动的层级结构的 cgroup_root在我们的例子中就是 cpuset至于cgroup_e_css_by_mask这里的 e 是 effective不考虑 cgroup v2 的情况下也可以理解为 cgroup_css(cgrp, ss)也就是 /cpuset1 和 cpuset ss 对应的 css 。某个 css_set简称 cset与我们的期望一致需要满足以下两点。首先cset-subsys 与 template 一致其实还是与 v2 有关。其次cset 的 csscgrp_links字段中属于当前 cgroup_root 的关联的 cgroup 是目标值也就是 /cpuset1不属于当前 cgroup_root 的与 old_cset 关联的 cgroup 相等。css_set 的 subsys 和 cgrp_links 都表示它关联的 css二者有什么区别subsys 在css_set 被创建后不会改变cgrp_links 可以动态调整。比如 cgroup_setup_root 中调用的 link_css_set修改的只是 cgrp_links。如果找不到一致的 css_set创建一个新的按照要求的两点给它赋值。接下来就是 cgroup_migrate 了它的实现代码较多但逻辑都是直来直去我们就不直接分析代码了主要分以下几步调用 cgroup_migrate_add_task 将需要迁移的进程放入 mgctx-tset然后调用cgroup_migrate_execute 函数实际的 migrate 过程由它完成。回调有变动的 ss 的 ss-can_attach 函数判断是否合法。遍历需要 migrate 的进程调用 css_set_move_task(task, from_cset, to_cset, true)进程的 css_set 得到更新。回调有变动的 ss 的 ss-attachmigrate 正式生效。cpuset 的 attach 由 cpuset_attach 函数实现核心逻辑如下cgroup_taskset_for_each(task, css, tset) {WARN_ON_ONCE(set_cpus_allowed_ptr(task, cpus_attach));cpuset_change_task_nodemask(task, cpuset_attach_nodemask_to);cpuset_update_task_spread_flag(cs, task); }遍历进程使 cpu 和 memory node 的限制生效。我们分析的限制进程使用 cpu 由 set_cpus_allowed_ptr 调用 __set_cpus_allowed_ptr 实现主要逻辑如下int __set_cpus_allowed_ptr(struct task_struct *p,const struct cpumask *new_mask, bool check) { const struct cpumask *cpu_valid_mask cpu_active_mask; unsigned int dest_cpu; struct rq_flags rf; struct rq *rq;rq task_rq_lock(p, rf); update_rq_clock(rq);if (cpumask_equal(p-cpus_ptr, new_mask))    //1goto out;dest_cpu cpumask_any_and(cpu_valid_mask, new_mask);    //2 if (dest_cpu nr_cpu_ids) {ret -EINVAL;goto out; }do_set_cpus_allowed(p, new_mask);    //3if (cpumask_test_cpu(task_cpu(p), new_mask))    //4goto out;if (task_running(rq, p) || p-state TASK_WAKING) {    //5struct migration_arg arg { p, dest_cpu };task_rq_unlock(rq, p, rf);stop_one_cpu(cpu_of(rq), migration_cpu_stop, arg);return 0; } else if (task_on_rq_queued(p)) {rq move_queued_task(rq, rf, p, dest_cpu); } out: task_rq_unlock(rq, p, rf); return ret;}满屏都是进程调度章节的内容在此解释如下第1步如果没有改变直接退出。第2步指定的资源是否合法如果不合法返回错误。第3步do_set_cpus_allowed 会调用 p-sched_class-set_cpus_allowed 由具体的调度类实现调度类一般会更新 task_struct 的 cpus_mask 字段。第4步进程当前所在的 cpu 是否在限制范围内如果在不需要额外处理。第5步进程被限制不能使用当前所在的 cpu如果正在运行则停止并 migrate如果正在等待执行移到其他 cpu 上。cgroup v1 的讨论差不多了绝大部分篇幅集中讨论最常用的操作但实际上还不完整其余操作大家可以自行继续当前的思路阅读。作者介绍姜亚华《精通 Linux 内核——智能设备开发核心技术》的作者一直从事与 Linux 内核和 Linux 编程相关的工作研究内核代码十多年对多数模块的细节如数家珍。曾负责华为手机 Touch、Sensor 的驱动和软件优化包括 Mate、荣耀等系列以及 Intel 安卓平台 Camera 和 Sensor 的驱动开发包括 Baytrail、Cherrytrail、Cherrytrail CR、Sofia 等。现负责 DMA、Interrupt、Semaphore 等模块的优化与验证包括 Vega、Navi 系列和多款 APU 产品。推荐阅读社区抗议LibreOffice商业化开源就不能赚钱MySQL也替换了master、slave开撕“谷歌违反协议”一个方案搞定模型量化到端侧部署全流程GitHub上持续冲榜ElasticJob重启
http://www.zqtcl.cn/news/675470/

相关文章:

  • 做透水砖的网站西充县企业网站建设
  • 29网站建设全部厦门建设网站建站
  • 列出网站开发建设的步骤高端品牌女装连衣裙
  • 长沙设计网站建设搜索引擎优化平台
  • 网站建设 可以吗打开浏览器的网站
  • 惠州定制网站制作推荐chinacd wordpress第三性
  • 网站建设从初级到精通网站开发成本预算价目表
  • 网站程序开发上海高端网站开发站霸网络
  • 企业网站对网络营销的意义环保材料 技术支持 东莞网站建设
  • 房地产网站建设价格买卖网站
  • 网站宣传方案开发专业网站
  • 电子商务+网站建设wordpress首页幻灯
  • 网站建设表格的属性学校网站建设命名
  • 清远网站建设自学网站开发要多久
  • 可信网站 quot 验证能防范哪些安全.教育类app开发价格表
  • 网站设计服务流程深圳网站设计公司费用大概多少
  • 邮件网站怎么做的本地计算机做网站服务器
  • 自己建的网站打不开html5 手机网站 模版
  • 网站建设跟网站结构如何提高网站排名的方法
  • 网站模板 缓存商标网上开店创业计划书
  • 沧州网站建设微艾薇怎样给企业做网站
  • 如何做淘宝客的网站个人网站设计与制作代码
  • 信用门户网站建设观摩惠州专业做网站
  • wordpress打开网站前广告佛山百度推广seo服务
  • 松北建设局网站vps 用ip可以访问网站么
  • 网站图片内容免费开源crm
  • wordpress调用分类栏目wordpress文章优化
  • 建站公司上海企业官网模板下载
  • 网站建设推广话术wordpress 不显示缩略图
  • 企业电子商务网站建设和一般百拓公司做网站怎么样