listener为何要进行fork两次子进程

listener为何要进行fork两次子进程,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

创新互联是一家专注于成都网站制作、网站建设和联通机房服务器托管的网络公司,有着丰富的建站经验和案例。

大致分为6个阶段

1

客户端向数据库发起连接请求,listener负责响应接受;

2

Listener进程fork子进程1;

如果子进程1运行时间过长,则会导致listener长时间等待(期间不接受其他数据库连接);如果子进程1异常则listener会hang;--这句话质疑着很多,我也只是从相关资料摘抄的,没有试验根据

Ps–ef | grep tnslsnr显示的ppid!=1的进程便是

3

子进程1fork子进程2,然后前者退出;

此时listener等待接受子进程2的数据

4

子进程2执行系统调用exec oracle,变为oracle server process,其向listener发送自身元数据(比如pid)

5

Listener向server procees发送客户端数据,然后写入listener.log;

直到此刻listener任务完成,可以接着处理下一个连接

6

Server process与客户端交互,完成后续工作

问题:

为何listener要创建fork两次子进程,直接采用第一个子进程调用exec oracle不可以么?

 

 

以下是回复,个人受教很多

 

本帖最后由 Yong Huang 于 2013-6-28 08:48 编辑

It's always a good habit to give reference, unless you find all this out completely from your own test.

I've done such test a long time ago. What you described is basically correct. But this

“如果子进程1运行时间过长,则会导致listener长时间等待(期间不接受其他数据库连接);如果子进程1异常则listener会hang”

is new to me. I'd like to know the source.

The reason why listener needs to fork twice is related to the requirement of a UNIX daemon. The best answer is here:

http://stackoverflow.com/questio ... n-creating-a-daemon

Basically, if it forked only once, the server (shadow) process would still have a parent i.e. the tnslsnr process instead of init (pid 1). Forking twice, after the first child exits, the second child will definitely become an orphan and then init becomes its parent.

You may ask why bother to make sure the server process is a daemon. I think the answer is just that Oracle wants to make sure the server process is independent of the listener, so if the listener dies, existing server processes continue to function because they're immune from signals that will be sent to the listener.

 

freas

发表于 2013-6-29 00:57:21 |只看该作者

Yong Huang发表于 2013-6-28 22:46
It's always a good habit to give reference, unless you find all this out completely from your own te ...


有哪些原因会导致僵死进程?
一般认为父进程fork之后,会调用wait()函数等待子进程结束,父进程获取到子进程结束(子进程自己调用exit())的信息后,操作系统内核才彻底释放一个进程的所有信息。
这里分两种异常情况。1、父进程没有调用wait,从而产生僵死进程。2、父进程由于某些原因,先于子进程退出,子进程成为孤儿进程被init收养,当子进程调用exit退出后,成为僵死进程,被init处理掉。
Oracle采用的double fork策略和第二点比较类似,不过,Oracle的想法比较悲观,觉得父进程(listener)一定会异常,所以它直接把第一次fork出的子进程手工杀死(fork之后就exit),强制把fork2变成孤儿进程。
至于Oracle为什么会这么想,也就无从得知了或许在Oracle的源代码里有注释。但是,这种想法是否是科学的,或者是否是最先进的,保留疑问。
个人猜测,在10到20年前,操作系统内核可能还不如现在的稳定健壮,僵尸进程的情况必须考虑在内,所以做出double fork的策略。
但是,double fork是由其副作用的。
首先,一个进程是内核里非常复杂(消耗资源)的组成。
一个进程要生成,至少需要4个元素:
1、task_struct结构体对象。
2、进程私有地址空间。
3、内核态堆栈。
4、可执行代码。
在调用fork一个进程的时候,这些资源是需要生成好了,才能生成进程的,exit的时候(准确的说是父进程wait返回或者是僵死进程的数据结构被回收之后),这些资源都是要释放的,这些过程都涉及到大量数据结构的遍历以及加锁(smp下的spinlock)。
而Oracle采取了悲观的暴力策略,不管三七二十一,一来就fork再exit,而事实上,这个fork1的进程是啥实事儿都没做的。假设是oltp系统,假设它的并发量大一点,比如每秒钟来个上千次连接的,操作系统仅为Oracle就要fork 2k次,exit至少1k次,这个资源消耗就大了。

 

Yong

> Oracle为什么会这么想,也就无从得知了

Didn't you already answer this question? "Oracle的想法比较悲观,觉得父进程(listener)一定会异常". In case the listener crashes, the server process must be protected from crashing. Although I think it's possible to program the child to not receive any signal delivered to the parent (tnslsnr), it's safer to just fork one more time and let the first child exit.

I haven't checked 12c. But I think somebody says beginning with 12c, Oracle on UNIX/Linux adopts the thread model as on Windows. Hope somebody can check.

freas

1、Oracle采用doule fork主要你是为了预防子进程退出时,listener已经crash了,子进程成为僵死进程没有解决策略。至于"in case the listener crashes, the server process must be protected from crashing",父进程crash,子进程仍然可以正常运行,只是子进程调用exit之后,会成为僵死进程。
2、“> Oracle为什么会这么想,也就无从得知了

Didn't you already answer this question? "Oracle
的想法比较悲观,觉得父进程(listener)一定会异常". ”我只是从技术层面猜测一下,而且,在上面的猜测里,double fork的方法作为一个server的网络处理方式,在2013年7月27日看来,弊大于利。
3、我个人觉得这种double fork的方式更多的是从DBA的管理上来设计的。因为Oracle提供listener的start/stop/restart接口。如果没有采用double fork方式,一旦listener stop了,所有的server process必然成为孤儿进程(此时,server process可能正在执行复杂的transaction,风险太大),而server process显然不应该在“正式干活”的时候受到listener的运行状态的影响,所以直接在一开始就把这个有风险的操作主动做了,掌握控制权。

关于listener为何要进行fork两次子进程问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注创新互联行业资讯频道了解更多相关知识。


网站名称:listener为何要进行fork两次子进程
当前路径:http://azwzsj.com/article/giiooi.html