免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 31926 | 回复: 4
打印 上一主题 下一主题

[进程管理] copy_thread函数的一些不理解的地方,求助大家? [复制链接]

求职 : 通讯/电信开
论坛徽章:
2
2015亚冠之鹿岛鹿角
日期:2015-07-08 11:58:2615-16赛季CBA联赛之佛山
日期:2015-12-21 17:28:04
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-06-16 19:19 |只看该作者 |倒序浏览
本帖最后由 九阳神功爱喝茶 于 2015-06-16 19:28 编辑

小弟研究copy_thread函数的时候遇到些问题,还要麻烦各位前辈多多指导,万分感谢。问题见红色标注的地方

  1. int copy_thread(unsigned long clone_flags, unsigned long sp,
  2.         unsigned long unused,
  3.         struct task_struct *p, struct pt_regs *regs)
  4. {
  5.         struct pt_regs *childregs;
  6.         struct task_struct *tsk;
  7.         int err;
  8.     //这儿是在内核栈的栈顶开辟8个字节的内存空间,我很不理解这里有什么作用?
  9.         childregs = task_pt_regs(p);
  10.         //保存父寄存器的值到自己存器中;
  11.         *childregs = *regs;
  12.         //修改子进程寄存器的相关值;childregs占用了17*4个字节,但是只开辟了8字节的内核空间,这样的话不是破坏了原来的thread_info结构体的内容了吗?
  13.         childregs->ax = 0;
  14.         childregs->sp = sp;
  15.         p->thread.sp = (unsigned long) childregs;
  16.         p->thread.sp0 = (unsigned long) (childregs+1);

  17.         p->thread.ip = (unsigned long) ret_from_fork;

  18.         task_user_gs(p) = get_user_gs(regs);

  19.         tsk = current;
  20.         if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) {
  21.                 p->thread.io_bitmap_ptr = kmemdup(tsk->thread.io_bitmap_ptr,
  22.                                                 IO_BITMAP_BYTES, GFP_KERNEL);
  23.                 if (!p->thread.io_bitmap_ptr) {
  24.                         p->thread.io_bitmap_max = 0;
  25.                         return -ENOMEM;
  26.                 }
  27.                 set_tsk_thread_flag(p, TIF_IO_BITMAP);
  28.         }

  29.         err = 0;

  30.         /*
  31.          * Set a new TLS for the child thread?
  32.          */
  33.         if (clone_flags & CLONE_SETTLS)
  34.                 err = do_set_thread_area(p, -1,
  35.                         (struct user_desc __user *)childregs->si, 0);

  36.         if (err && p->thread.io_bitmap_ptr) {
  37.                 kfree(p->thread.io_bitmap_ptr);
  38.                 p->thread.io_bitmap_max = 0;
  39.         }

  40.         clear_tsk_thread_flag(p, TIF_DS_AREA_MSR);
  41.         p->thread.ds_ctx = NULL;

  42.         clear_tsk_thread_flag(p, TIF_DEBUGCTLMSR);
  43.         p->thread.debugctlmsr = 0;

  44.         return err;
  45. }
复制代码
代码里面的文字不能标示红色,只能在最后写下问题了:
   //这你是在内核栈的栈顶开辟8个字节的内存空间,我很不理解这里有什么作用?
        childregs = task_pt_regs(p);
第二个是:
//修改子进程寄存器的相关值;childregs占用了17*4个字节,但是只开辟了8字节的内核空间,这样的话不是破坏了原来的thread_info结构体的内容了吗?
        childregs->ax = 0;
        childregs->sp = sp;

还请各位多多指导。


论坛徽章:
0
2 [报告]
发表于 2016-12-21 17:16 |只看该作者

cu发博文进编译页面无法显示文字内容

本帖最后由 wangcong02345 于 2016-12-21 17:17 编辑

1. 楼主的这几个问题其实是一个问题,就是childreg指代的内存是什么的问题。

2. 上面 childregs = task_pt_regs(p);  实际上是--> childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p)) - 1;
也就是说childregs指向 “子进程的栈顶 减去 一个sizeof(struct pt_regs)的大小 的地方”,如下图所示:

​上图出自《linux内核情景分析》P306


3. 其它的都好理解了:
这里参数p=0xf7dee000,在do_fork中新分配的2页内存用作子进程的task_struct
  • int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
  •     unsigned long unused, struct task_struct * p, struct pt_regs * regs)
  • {
  •     struct pt_regs * childregs;
  • //这儿稍不留神就会看错-->这儿是先转为struct pt_regs后再减1
  • //这是在栈顶留出一个struct pt_regs的大
  •     childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p)) - 1;
  • //先将父进程的全部regs复制过来,然后再作调整
  •     struct_cpy(childregs, regs);    //即memcpy(childregs, regs, sizeof(*(regs)));
  •     childregs->eax = 0;             //child的eax=0,这也就是为什么fork后子进程返回0的原因
  •     childregs->esp = esp;           //这个esp是在sys_clone时的regs.ecx=0x78
  •     p->thread.esp = (unsigned long) childregs;       //执行后p->thread.esp=0xf7deffc4=(p-sizeof(pt_regs))​
  •     p->thread.esp0 = (unsigned long) (childregs+1);  //执行后p->thread.esp0=0xf7df0000=(p),即将两页内存的最高端作为栈​顶
  •     p->thread.eip = (unsigned long) ret_from_fork;   //下次调度时子进程执行的命令是ret_form_fork
  •     savesegment(fs,p->thread.fs);
  •     savesegment(gs,p->thread.gs);
  •     unlazy_fpu(current);
  •     struct_cpy(&p->thread.i387, &current->thread.i387);
  •     return 0;
  • }

为啥从博客复制过来就变成这个样子了?

论坛徽章:
9
程序设计版块每日发帖之星
日期:2016-02-13 06:20:00数据库技术版块每日发帖之星
日期:2016-06-15 06:20:00数据库技术版块每日发帖之星
日期:2016-06-16 06:20:00数据库技术版块每日发帖之星
日期:2016-06-18 06:20:00程序设计版块每日发帖之星
日期:2016-06-27 06:20:00程序设计版块每日发帖之星
日期:2016-07-09 06:20:00IT运维版块每日发帖之星
日期:2016-07-15 06:20:00IT运维版块每日发帖之星
日期:2016-07-27 06:20:00程序设计版块每日发帖之星
日期:2016-08-18 06:20:00
3 [报告]
发表于 2016-12-25 16:24 |只看该作者
顶 顶 顶 顶 顶 顶 顶 顶 顶 顶 顶 顶 顶 顶 顶 顶 顶 顶 顶

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
4 [报告]
发表于 2016-12-26 16:06 |只看该作者
有图就好理解多了,赞!

论坛徽章:
0
5 [报告]
发表于 2021-05-04 09:52 |只看该作者
本帖最后由 aweii 于 2021-05-04 10:12 编辑

内核堆栈顶部留出8字节,是保证内核态下发生中断时,regs->esp、regs->xss是可访问的。否则,由于此时ess、esp不压栈(ring0->ring0),所以*regs实际包含了thread_union以外的8字节。我观察了下,2.6.11以前的内核都没有这个8字节预留,当然也没出什么问题(因为都在内核的892M空间内,有映射)。2.6.24有了这个task_pt_regs(p),也许是防患于未然吧。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP