免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: littlenewer

为什么copy_mm的时候子进程不设置指向内核空间的页表项 [复制链接]

论坛徽章:
16
2015亚冠之吉达阿赫利
日期:2015-08-17 11:21:462015年迎新春徽章
日期:2015-03-04 09:58:11酉鸡
日期:2014-12-07 09:06:19水瓶座
日期:2014-11-04 14:23:29天秤座
日期:2014-03-02 08:57:52双鱼座
日期:2014-02-22 13:07:56午马
日期:2014-02-14 11:08:18双鱼座
日期:2014-02-13 11:09:37卯兔
日期:2014-02-06 15:10:34子鼠
日期:2014-01-20 14:48:19戌狗
日期:2013-12-19 09:37:46射手座
日期:2013-12-19 09:33:47
发表于 2012-04-24 14:26 |显示全部楼层
回复 20# fayewangfans


好象是找不到,反正我不知怎么能找到,如果涉及到汇编我就直接用lxr看!


   

论坛徽章:
0
发表于 2012-04-24 14:27 |显示全部楼层
回复 12# littlenewer


直接这样使用带CLONE_VM的clone(),程序貌似的确会出问题的。
不过一般使用clone()都会传递一个已经map好的空间作为child_stack(clone的第二个参数),子进程的栈会使用这块空间,而不是和父进程共用。

论坛徽章:
16
2015亚冠之吉达阿赫利
日期:2015-08-17 11:21:462015年迎新春徽章
日期:2015-03-04 09:58:11酉鸡
日期:2014-12-07 09:06:19水瓶座
日期:2014-11-04 14:23:29天秤座
日期:2014-03-02 08:57:52双鱼座
日期:2014-02-22 13:07:56午马
日期:2014-02-14 11:08:18双鱼座
日期:2014-02-13 11:09:37卯兔
日期:2014-02-06 15:10:34子鼠
日期:2014-01-20 14:48:19戌狗
日期:2013-12-19 09:37:46射手座
日期:2013-12-19 09:33:47
发表于 2012-04-24 15:09 |显示全部楼层
回复 22# kouu


>直接这样使用带CLONE_VM的clone(),程序貌似的确会出问题的。

默认clone()不就是应该有CLONE_VM表示吗??

>不过一般使用clone()都会传递一个已经map好的空间作为child_stack(clone的第二个参数),子进程的栈会使用这块空间,而不是和父进程共用。

这个是从哪里看出来的,pthread_create实现的源码?







   

论坛徽章:
0
发表于 2012-04-24 15:55 |显示全部楼层
回复 23# embeddedlwp


clone的标志是可以随意选择的,不一定非要有CLONE_VM。貌似现在glic里面的fork函数是调用clone()系统调用来实现的,而不是fork()系统调用。


要看clone的child_stack参数,写个pthread程序,然后strace一下就能看到了。

论坛徽章:
16
2015亚冠之吉达阿赫利
日期:2015-08-17 11:21:462015年迎新春徽章
日期:2015-03-04 09:58:11酉鸡
日期:2014-12-07 09:06:19水瓶座
日期:2014-11-04 14:23:29天秤座
日期:2014-03-02 08:57:52双鱼座
日期:2014-02-22 13:07:56午马
日期:2014-02-14 11:08:18双鱼座
日期:2014-02-13 11:09:37卯兔
日期:2014-02-06 15:10:34子鼠
日期:2014-01-20 14:48:19戌狗
日期:2013-12-19 09:37:46射手座
日期:2013-12-19 09:33:47
发表于 2012-04-24 16:35 |显示全部楼层
本帖最后由 embeddedlwp 于 2012-04-24 16:36 编辑

回复 24# kouu

恩,pthread_create程序调用clone的时候确实指定了child_stack,用strace查看如下:
  1. clone(child_stack=0xb78cb494, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0xb78cbbd8, {entry_number:6, base_addr:0xb78cbb70, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}, child_tidptr=0xb78cbbd8) = 14909
复制代码
但是fork函数没看到调用clone啊,貌似strace的时候还有个vfork什么的!!!
源程序:
  1. hacker@hacker:~/test$ cat test.c
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include <sys/wait.h>
  6. #include <sys/types.h>

  7. int main()
  8. {
  9.         int a = 2, pid;
  10.         pid = vfork();
  11.     if(pid > 0){
  12.                 wait(NULL);
  13.                 printf("This is parent a=%d\n", a);
  14.         }
  15.         else
  16.                 if(pid == 0){
  17.                         a = 3;
  18.                         printf("This is child a=%d\n",a);
  19.                         exit(0);
  20.                 }
  21.         else
  22.                 exit(1);
  23.         exit(0);
  24. }
复制代码
运行结果:
  1. hacker@hacker:~/test$ ./test
  2. This is child a=3
  3. This is parent a=3
复制代码
strace查看:
  1. hacker@hacker:~/test$ strace ./test
  2. execve("./test", ["./test"], [/* 50 vars */]) = 0
  3. brk(0)                                  = 0x923a000
  4. access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
  5. mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb771c000
  6. access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
  7. open("/etc/ld.so.cache", O_RDONLY)      = 3
  8. fstat64(3, {st_mode=S_IFREG|0644, st_size=67614, ...}) = 0
  9. mmap2(NULL, 67614, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb770b000
  10. close(3)                                = 0
  11. access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
  12. open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY) = 3
  13. read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0p\222\1\0004\0\0\0"..., 512) = 512
  14. fstat64(3, {st_mode=S_IFREG|0755, st_size=1544392, ...}) = 0
  15. mmap2(NULL, 1554968, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x6fa000
  16. mmap2(0x870000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x176) = 0x870000
  17. mmap2(0x873000, 10776, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x873000
  18. close(3)                                = 0
  19. mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb770a000
  20. set_thread_area({entry_number:-1 -> 6, base_addr:0xb770a8d0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
  21. mprotect(0x870000, 8192, PROT_READ)     = 0
  22. mprotect(0x8049000, 4096, PROT_READ)    = 0
  23. mprotect(0xe22000, 4096, PROT_READ)     = 0
  24. munmap(0xb770b000, 67614)               = 0
  25. vfork(This is child a=3
  26. )                                 = 14826
  27. --- SIGCHLD (Child exited) @ 0 (0) ---
  28. wait4(-1, NULL, 0, NULL)                = 14826
  29. write(1, "T", 1T)                        = 1
  30. write(1, "his is parent a=3\n", 18his is parent a=3
  31. )     = 18
  32. exit_group(0)                           = ?
复制代码

论坛徽章:
0
发表于 2012-04-24 16:42 |显示全部楼层
回复 25# embeddedlwp


    {:3_191:} 你的代码里面写的是vfork,不是fork呀... 最终当然是使用vfork系统调用了。

论坛徽章:
16
2015亚冠之吉达阿赫利
日期:2015-08-17 11:21:462015年迎新春徽章
日期:2015-03-04 09:58:11酉鸡
日期:2014-12-07 09:06:19水瓶座
日期:2014-11-04 14:23:29天秤座
日期:2014-03-02 08:57:52双鱼座
日期:2014-02-22 13:07:56午马
日期:2014-02-14 11:08:18双鱼座
日期:2014-02-13 11:09:37卯兔
日期:2014-02-06 15:10:34子鼠
日期:2014-01-20 14:48:19戌狗
日期:2013-12-19 09:37:46射手座
日期:2013-12-19 09:33:47
发表于 2012-04-24 16:47 |显示全部楼层
回复 26# kouu


不好意思哈, 改成fork了,确实是最终调用clone,不过这样各种情况都清楚了,fork,pthread_create glic最终调用的是sys_clone,vfork最终还是调用sys_vfork,感谢kouu
  1. hacker@hacker:~/test$ strace ./test
  2. execve("./test", ["./test"], [/* 50 vars */]) = 0
  3. brk(0)                                  = 0x8dcb000
  4. access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
  5. mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7893000
  6. access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
  7. open("/etc/ld.so.cache", O_RDONLY)      = 3
  8. fstat64(3, {st_mode=S_IFREG|0644, st_size=67614, ...}) = 0
  9. mmap2(NULL, 67614, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7882000
  10. close(3)                                = 0
  11. access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
  12. open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY) = 3
  13. read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0p\222\1\0004\0\0\0"..., 512) = 512
  14. fstat64(3, {st_mode=S_IFREG|0755, st_size=1544392, ...}) = 0
  15. mmap2(NULL, 1554968, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x613000
  16. mmap2(0x789000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x176) = 0x789000
  17. mmap2(0x78c000, 10776, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x78c000
  18. close(3)                                = 0
  19. mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7881000
  20. set_thread_area({entry_number:-1 -> 6, base_addr:0xb78818d0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
  21. mprotect(0x789000, 8192, PROT_READ)     = 0
  22. mprotect(0x8049000, 4096, PROT_READ)    = 0
  23. mprotect(0xf41000, 4096, PROT_READ)     = 0
  24. munmap(0xb7882000, 67614)               = 0
  25. clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb7881938) = 15071
  26. wait4(-1, This is child a=3
  27. NULL, 0, NULL)                = 15071
  28. --- SIGCHLD (Child exited) @ 0 (0) ---
  29. fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
  30. mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7892000
  31. write(1, "This is parent a=2\n", 19This is parent a=2
  32. )    = 19
  33. exit_group(0)                           = ?
复制代码

论坛徽章:
16
2015亚冠之吉达阿赫利
日期:2015-08-17 11:21:462015年迎新春徽章
日期:2015-03-04 09:58:11酉鸡
日期:2014-12-07 09:06:19水瓶座
日期:2014-11-04 14:23:29天秤座
日期:2014-03-02 08:57:52双鱼座
日期:2014-02-22 13:07:56午马
日期:2014-02-14 11:08:18双鱼座
日期:2014-02-13 11:09:37卯兔
日期:2014-02-06 15:10:34子鼠
日期:2014-01-20 14:48:19戌狗
日期:2013-12-19 09:37:46射手座
日期:2013-12-19 09:33:47
发表于 2012-04-24 16:59 |显示全部楼层
本帖最后由 embeddedlwp 于 2012-04-24 17:00 编辑

回复 26# kouu

但是clone的两个参数我有个疑问,《独辟蹊径品内核》对do_fork函数parent_tidptr和child_tidptr的解释是:

parent_tidptr用户态内存指针,当CLONE_PARENT_SETTID被设置时,内核会把新建立的子进程ID通过parent_tidptr返回。
child_tidptr用户态内存指针,当CLONE_CHILD_SETTID被设置时,内核会把新建立的子进程ID通过child_tidptr返回。

可是从strace的信息来看,貌似调用clone的时候都指定好了,而不是返回的啊!
  1. clone(child_stack=0xb78cb494, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0xb78cbbd8, {entry_number:6, base_addr:0xb78cbb70, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}, child_tidptr=0xb78cbbd8) = 14909
复制代码
求指点!

   

论坛徽章:
0
发表于 2012-04-24 17:11 |显示全部楼层
回复 22# kouu

你说的child_stack在内核里面是哪个参数,我怎么没找到
   

论坛徽章:
0
发表于 2012-04-24 17:13 |显示全部楼层
回复 28# embeddedlwp


    parent_tidptr和child_tidptr指针所指向的空间是在用户态分配的,调用系统调用的时候把指针的值传递进去,系统调用中再把pid值填到对应的内存中。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP