shell命令管道未读完阻塞了子进程,与等待其结束的父进程死"锁"。
2017-10-31 16:27
495 查看
在exec执行一个子进程,我们希望使用管道取得子进程在重定向后的标准输出上的结果,同时等待子进程的结束。那么是等待子进程结束后才取管道数据,还是边取数据边等待子进程结束呢?
这里有一个调试的例子。u0_a89是例子中app的用户id。
android app 进程 5990,exec了一个sh子进程 6251,去执行命令子进程。
可以查看到app进程由zygote创建,app进程创建了6251,6251创建了6252,并且app进程及其子进程都阻塞去睡眠了。原本6252子进程执行着一个不要阻塞并且十分短小的任务,一瞬就应该完成并结束的。但却无端阻塞走去睡眠了。而sh子进程6251又在等待进程2652结束,app进程也在等待sh子进程结束,这就僵直了。
原因是app没有分配足够空间去取出管道中的数据,使得 read( pipe, buf, space /** 0 */) 返回 0,再加上epoll为ET触发,然后就没有去读管道了。管道堵满了数据,子进程不能完成数据的传输也被阻塞了。
一般来说,如果子进程执行的任务只有少量结果输出,不会塞满管道,即使你来不及去读出管道的数据,子进程也已经将结果都填进管道了,也就关闭管道写端,顺利结束。这种情况下,不论你是先读管道,抑或先等待子进程结束也者没有问题。但是当子进程任务输出大量结果数据时,情况就不一样了,你必须及时去读管道,让子进程可以去写管道。如果读的操作不注意,就会出现上面的错误,即使同时也在reactor上等待进程的结束事件,却永远都等不到那一刻了,因为互相死锁了。
这里有一个调试的例子。u0_a89是例子中app的用户id。
android app 进程 5990,exec了一个sh子进程 6251,去执行命令子进程。
可以查看到app进程由zygote创建,app进程创建了6251,6251创建了6252,并且app进程及其子进程都阻塞去睡眠了。原本6252子进程执行着一个不要阻塞并且十分短小的任务,一瞬就应该完成并结束的。但却无端阻塞走去睡眠了。而sh子进程6251又在等待进程2652结束,app进程也在等待sh子进程结束,这就僵直了。
原因是app没有分配足够空间去取出管道中的数据,使得 read( pipe, buf, space /** 0 */) 返回 0,再加上epoll为ET触发,然后就没有去读管道了。管道堵满了数据,子进程不能完成数据的传输也被阻塞了。
一般来说,如果子进程执行的任务只有少量结果输出,不会塞满管道,即使你来不及去读出管道的数据,子进程也已经将结果都填进管道了,也就关闭管道写端,顺利结束。这种情况下,不论你是先读管道,抑或先等待子进程结束也者没有问题。但是当子进程任务输出大量结果数据时,情况就不一样了,你必须及时去读管道,让子进程可以去写管道。如果读的操作不注意,就会出现上面的错误,即使同时也在reactor上等待进程的结束事件,却永远都等不到那一刻了,因为互相死锁了。
相关文章推荐
- shell同时启多个进程,并等待所有子进程结束,再做接下来的操作,最好能获取每个子进程的退出状态
- shell同时启多个进程,并等待所有子进程结束
- 编写程序,子进程通过管道向父进程发出字符串"ok".
- C语言父子进程shell命令重定向到管道传递(双管道)
- 1.写多进程,一个父进程,两个子进程,一个运行ls –l, 另一个暂停5s,父进程先阻塞等待第一个子进程的结束,然后用非阻塞等另一个进程退出,收集到第二个子进程结束的信息,父进程就返回。
- ShellExecute Winexec参考 Delphi运行命令等待结束
- Windows批处理 调用程序后 不等待子进程 父进程继续执行命令
- Linux下利用fork()创建子进程并使父进程等待子进程结束
- Windows批处理 调用程序后 不等待子进程 父进程继续执行命令
- curl 命令,curl监控网页shell脚本,curl多进程实现并控制进程数
- linux命令(进程结束):killall命令
- 函数: waitpid - 等待子进程中断或结束
- 二十. 通过管道组合Shell命令获取系统运行数据:
- Shell命令中重定向与管道的概念
- 验证子进程退出时会给父进程发送信号的机制 、 编写父进程等待子进程的异步版本
- 【一天一个shell命令】好管家-进程-ps
- vb6创建子进程并等待子进程的退出。
- 用管道实现"ls | wc -l"命令
- 用"ntsd"命令杀掉古怪的进程
- Ubuntu 15.04 中结束进程的命令