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

发布时间:2021-11-08 17:08:36 作者:柒染
来源:亿速云 阅读:159

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

大致分为6个阶段

1

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

2

Listener进程fork子进程1

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

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

3

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

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

4

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

5

Listenerserver 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异常则listenerhang”

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的源代码里有注释。但是,这种想法是否是科学的,或者是否是最先进的,保留疑问。
个人猜测,在1020年前,操作系统内核可能还不如现在的稳定健壮,僵尸进程的情况必须考虑在内,所以做出double fork的策略。
但是,double fork是由其副作用的。
首先,一个进程是内核里非常复杂(消耗资源)的组成。
一个进程要生成,至少需要4个元素:
1task_struct结构体对象。
2、进程私有地址空间。
3、内核态堆栈。
4、可执行代码。
在调用fork一个进程的时候,这些资源是需要生成好了,才能生成进程的,exit的时候(准确的说是父进程wait返回或者是僵死进程的数据结构被回收之后),这些资源都是要释放的,这些过程都涉及到大量数据结构的遍历以及加锁(smp下的spinlock)。
Oracle采取了悲观的暴力策略,不管三七二十一,一来就forkexit,而事实上,这个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

1Oracle采用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的网络处理方式,在2013727日看来,弊大于利。
3、我个人觉得这种double fork的方式更多的是从DBA的管理上来设计的。因为Oracle提供listenerstart/stop/restart接口。如果没有采用double fork方式,一旦listener stop了,所有的server process必然成为孤儿进程(此时,server process可能正在执行复杂的transaction,风险太大),而server process显然不应该在正式干活的时候受到listener的运行状态的影响,所以直接在一开始就把这个有风险的操作主动做了,掌握控制权。

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

推荐阅读:
  1. linux中如何使用fork函数来创建一个子进程并且说明父进程和子进程的随机返回问题
  2. 编写一个程序,使用fork函数来创建一个子进程,并分别输出父子进程的进程ID

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

fork listener

上一篇:怎么解决Oracle报错ORA-01194、ORA-01110问题

下一篇:如何解决nagios 升级遇到的坑CHECK_NRPE: Error - Could not complete SSL handshake.

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》