免费注册 查看新帖 |

Chinaunix

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

关于D进程和Z进程 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-05 16:15 |只看该作者 |倒序浏览

  1. int
  2. main(void)
  3. {
  4.         int i = 0;

  5. //      if (!fork()) {
  6.         if (!vfork()) {
  7.                 sleep(10);
  8.         }

  9.         return 0;
  10. }
复制代码
执行此程序后不断产生Z进程:

daniel@Daniel:/usr/local/src/testsuits/0007_tiny$ ps aux | grep a.out
daniel    6548  0.0  0.0   1696   268 pts/4    D+   15:15   0:00 ./a.out
daniel    6549  0.0  0.0      0     0 pts/4    Z+   15:15   0:00 [a.out] <defunct>
daniel    6575  0.0  0.0      0     0 pts/4    Z+   15:15   0:00 [a.out] <defunct>
daniel    6601  0.0  0.0      0     0 pts/4    Z+   15:15   0:00 [a.out] <defunct>
daniel    6628  0.0  0.0      0     0 pts/4    Z+   15:16   0:00 [a.out] <defunct>
daniel    6654  0.0  0.0      0     0 pts/4    Z+   15:16   0:00 [a.out] <defunct>
daniel    6680  0.0  0.0      0     0 pts/4    Z+   15:16   0:00 [a.out] <defunct>
daniel    6697  0.0  0.0      0     0 pts/4    Z+   15:16   0:00 [a.out] <defunct>
daniel    6750  0.0  0.0      0     0 pts/4    Z+   15:16   0:00 [a.out] <defunct>
daniel    6753  0.0  0.0   1696   268 pts/4    S+   15:16   0:00 ./a.out
daniel    6755  0.0  0.0   4148   864 pts/8    S+   15:16   0:00 grep --color=auto a.out

请教:这里为什么vfork后sleep就D了,并且不断产生Z进程?

论坛徽章:
0
2 [报告]
发表于 2011-12-05 16:19 |只看该作者
daniel@Daniel:/usr/local/src/testsuits/0007_tiny$ ps aux --forest | grep a.out
daniel    7457  0.0  0.0   1696   264 pts/8    D    16:19   0:00      \_ ./a.out
daniel    7458  0.0  0.0      0     0 pts/8    Z    16:19   0:00      |   \_ [a.out] <defunct>
daniel    7462  0.0  0.0      0     0 pts/8    Z    16:19   0:00      |   \_ [a.out] <defunct>
daniel    7466  0.0  0.0   1696   264 pts/8    S    16:19   0:00      |   \_ ./a.out
daniel    7468  0.0  0.0   4148   864 pts/8    S+   16:19   0:00      \_ grep --color=auto a.out

论坛徽章:
0
3 [报告]
发表于 2011-12-05 16:41 |只看该作者
本帖最后由 J_O_H_N 于 2011-12-05 16:43 编辑

执行vfork系统调用后,父进程将进入TASK_UNINTERRUPTIBLE状态,直到子进程调用exit或exec

自问自答了,看的这个
http://blog.csdn.net/lizhiguo0532/article/details/6315819

但还是不懂为什么总是不断产生Z进程

论坛徽章:
0
4 [报告]
发表于 2011-12-05 17:22 |只看该作者
(From  POSIX.1)  The  vfork()  function  has  the  same effect as fork(2), except that the behavior is undefined if the process created by vfork() either modifies any data other than a variable of type pid_t used to store the return  value from vfork(), or returns from the function in which vfork() was called, or calls any other function before successfully calling _exit(2) or one of the exec(3) family of functions.

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
5 [报告]
发表于 2011-12-05 17:26 |只看该作者
本帖最后由 zylthinking 于 2011-12-05 17:27 编辑

居然能维持栈平衡, 真他妈神奇。。。。什么样的代码能导致这个栈还能保持平衡呢???

论坛徽章:
0
6 [报告]
发表于 2011-12-05 17:41 |只看该作者
strace了一下,嘿嘿...

daniel@Daniel:/usr/local/src/testsuits/0007_tiny$ strace ./a.out
execve("./a.out", ["./a.out"], [/* 44 vars */]) = 0
brk(0)                                  = 0x89b2000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb779f000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 4
fstat64(4, {st_mode=S_IFREG|0644, st_size=74325, ...}) = 0
mmap2(NULL, 74325, PROT_READ, MAP_PRIVATE, 4, 0) = 0xb778c000
close(4)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY) = 4
read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\220o\1\0004\0\0\0"..., 512) = 512
fstat64(4, {st_mode=S_IFREG|0755, st_size=1434180, ...}) = 0
mmap2(NULL, 1444360, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 4, 0) = 0x704000
mprotect(0x85e000, 4096, PROT_NONE)     = 0
mmap2(0x85f000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 4, 0x15a) = 0x85f000
mmap2(0x862000, 10760, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x862000
close(4)                                = 0                                                                                                                             
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb778b000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb778b8d0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1})\
= 0
mprotect(0x85f000, 8192, PROT_READ)     = 0
mprotect(0x8049000, 4096, PROT_READ)    = 0
mprotect(0x25d000, 4096, PROT_READ)     = 0
munmap(0xb778c000, 74325)               = 0
vfork(line 0
)                                 = 9139
vfork(line 1
)                                 = 9145
--- SIGCHLD (Child exited) @ 0 (0) ---
vfork(line 2
)                                 = 9151
vfork()                                 = ? ERESTARTNOINTR (To be restarted)
--- SIGCHLD (Child exited) @ 0 (0) ---
vfork(line 3
)                                 = 9158
--- SIGCHLD (Child exited) @ 0 (0) ---
vfork(line 4

)                                 = 9164
vfork()                                 = ? ERESTARTNOINTR (To be restarted)
--- SIGCHLD (Child exited) @ 0 (0) ---
vfork(line 5
)                                 = 9171
--- SIGCHLD (Child exited) @ 0 (0) ---
vfork(line 6
)                                 = 9177
vfork()                                 = ? ERESTARTNOINTR (To be restarted)
--- SIGCHLD (Child exited) @ 0 (0) ---
vfork(line 7
)                                 = 9185
vfork()                                 = ? ERESTARTNOINTR (To be restarted)
--- SIGCHLD (Child exited) @ 0 (0) ---
vfork(  C-c C-c <unfinished ...>

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
7 [报告]
发表于 2011-12-05 17:55 |只看该作者
居然能维持栈平衡, 真他妈神奇。。。。什么样的代码能导致这个栈还能保持平衡呢???
zylthinking 发表于 2011-12-05 17:26


知道为啥能栈平衡了
  1. 0x00144b53 <__libc_start_main+227>:        call   *0x8(%ebp)
  2. 0x00144b56 <__libc_start_main+230>:        mov    %eax,(%esp)
  3. 0x00144b59 <__libc_start_main+233>:        call   0x15d0a0 <exit>
  4. 0x00144b5e <__libc_start_main+238>:        xor    %ecx,%ecx
  5. 0x00144b60 <__libc_start_main+240>:        jmp    0x144aa0 <__libc_start_main+48>
  6. 0x00144b65 <__libc_start_main+245>:        mov    0x37f4(%ebx),%eax
复制代码
但为啥僵尸进程会一直存在呢???

论坛徽章:
0
8 [报告]
发表于 2011-12-05 18:06 |只看该作者
回复 7# zylthinking


    能解释一下如何栈平衡的问题吗? :-)

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
9 [报告]
发表于 2011-12-05 18:31 |只看该作者
回复  zylthinking


    能解释一下如何栈平衡的问题吗? :-)
J_O_H_N 发表于 2011-12-05 18:06


你首先要知道 vfork 和 fork 的区别, 简而言之就是 父进程保证子进程退出后再运行; 并且子进程操纵的是父进程内存空间
因此, 当子进程 return 0 时从main 返回, 对堆栈进行弹出操作, 修改的实际上时父进程的栈, 因此, 父进程栈被破坏。
当父进程醒来执行时,  esp 并没有受子进程修改他的栈的影响, 因为他的 esp, eip 等是保存再内核栈上的, 但他栈上的内容有可能被改写。 因此, 所谓行为不确定就是指栈被别人改写了, 但他不知道。
可能被改写有一条, 就是 main 的返回地址, 因为子进程 return 时, 肯定会将它弹出到 eip 中, 然后, 这个东西会不会被改成新值, 就看子进程后面干了什么了

0x00144b53 <__libc_start_main+227>:        call   *0x8(%ebp)
0x00144b56 <__libc_start_main+230>:        mov    %eax,(%esp)
0x00144b59 <__libc_start_main+233>:        call   0x15d0a0 <exit>
0x00144b5e <__libc_start_main+238>:        xor    %ecx,%ecx
0x00144b60 <__libc_start_main+240>:        jmp    0x144aa0 <__libc_start_main+48>

这段代码, 第一句是 call main, 会在栈上压下第二句的地址
子进程退出时, 将压下的返回地址弹出, 然后又 call exit, 将第四句的地址压下
子进程不会返回来了, 在exit中就灰飞烟灭了
父进程唤醒, 由于他的 esp 是从保存的地址中恢复的, esp 的值不会变, 因此他也能执行 if(!vfork()) 这个判断, 虽然局部变量可能被修改了, 但这段代码没有引用局部变量, 没问题。
他也执行 return, 但它的返回地址已经被修改成了第三句了, 就是 xor    %ecx,%ecx, 然后执行 jmp    0x144aa0, 往回跳
于是这个结果就是
1。 它的返回地址被修改, 导致它错过了 exit, 因此它不会退出
2。 它向回跳, 导致重新执行main
3。 仔细观察, 栈真的是平衡的, 只是它的返回地址被修改了而已, 因此, 无论执行多少遍, 栈都不会乱, 他会无限这么搞下去(如果不考虑子进程数量及其他资源限制)

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
10 [报告]
发表于 2011-12-05 19:56 |只看该作者
执行此程序后不断产生Z进程:

daniel@Daniel:/usr/local/src/testsuits/0007_tiny$ ps aux | grep a.out ...
J_O_H_N 发表于 2011-12-05 16:15



    因为进程的栈结构在不断的被修改,正好不断的vfork
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP