看看进程、线程的父子关系

来源:互联网 发布:云计算 iaas 编辑:程序博客网 时间:2024/04/27 13:16

线程的父子关系

    一般利用pthread库让让主线程去创建子线程,从而形成一个线程的父子关系。

    主线程调用pthread_join来等待子线程的结束,然后释放子进程占有的栈、id、私有数据等资源。这样设计阻塞的好处是父线程会等到子线程结束后才结束,这样不至于父线程关闭导致子线程没有结束就被关闭。可见父子线程默认情况下是有紧密联系的,父线程需要为子线程处理身后事。

    现在,我期望让父子线程没有关系,让子线程在结束的时候自己去释放自己的资源,那么需要调用pthread_detach来解开默认的父子关系。这样,父线程不再会顾忌子线程的结束与否。“不受约束”的子线程很可能因父线程的结束而异常关闭。

#include<iostream>#include<pthread.h>using namespace std;void* fun(void*){pthread_detach(pthread_self());//父子关系的接触与否依赖于这句,可以观察有和没有的运行结果的区别。cout<<"fun begins!"<<endl;int i;for(i=0;i<1000000000;i++);cout<<"fun is over! i="<<i<<endl;return NULL;}int main(){cout<<"main begins."<<endl;pthread_t tid;int err = pthread_create(&tid, NULL, fun, NULL);void * tret;err = pthread_join(tid, &tret);cout<<"main is over."<<endl;return 0;}

    从运行结果看出,在不调用pthread_detach的情况下,父线程会在pthread_join阻塞,等候子线程结束后再唤醒并结束。若调用了pthread_detach,父线程会直接关闭,导致子线程被迫关闭。


进程的父子关系

   一般利用系统调用fork在主进程创建子进程(见fork),从而形成一个父子进程。

    同样,一般要求父进程wait子进程结束的信号,然后去处理子进程的“身后事”,否则子进程将会变为僵尸进程(见《僵尸进程和孤儿进程》),显然属于父子关系处理不当的情况。如果父进程比子进程先结束,父子的关系会自然脱离,子进程变为孤儿进程,其“身后事”交给init办理。

    现在,我期望父子进程结束这种关系,成为两个独立的进程。对于线程来说,父子线程即使再怎么独立,也总是属于同一个进程的,因为共享了太多的资源。对于进程来说,父子进程的关系一旦解除之后,就可以认为进程没有关系了,子进程的身后事交给init来解决。

   APUE里提出一个fork两次的方法,通过创建了爷孙三代来使得进程关系彻底脱离,不过借助于第三个进程太麻烦了。利用系统调用setsid(void)就可以直接做到,setsid的作用是将当前进程加入到一个新的会话中。

#include<iostream>#include<unistd.h>using namespace std;int main(){if(fork() != 0){cout<<"father begins."<<endl;int i=0;for(;i<1000000000;i++);for(;i<1000000000;i++);for(;i<1000000000;i++);for(;i<1000000000;i++);for(;i<1000000000;i++);for(;i<1000000000;i++);cout<<"father is over. i="<<i<<endl;}else{cout<<"son begins."<<endl;pid_t pid = setsid();//有没有这句:父子关系是否脱离的区别cout<<"son is over."<<endl;}return 0;}

程序运行起来,在另一个终端ps u观察进程的状态,可以看到父子关系是否脱离情况下子进程的状态的不同。从结果看出,不调用setsid的情况下,子进程提前结束会成为Zombie进程;调用setsid的情况下,子线程提前结束会完整释放其资源。

0 0
原创粉丝点击