1.linux的僵尸进程和孤儿进程的区别,如何清理僵尸进程?(kill僵尸进程的父进程)
僵尸进程
一个子进程在其父进程没有调用wait()或waitpid()的情况下退出,这个子进程就是僵尸进程。僵尸进程是当子进程比父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸进程。如果其父进程还存在而一直不调用wait,则该僵尸进程将无法回收,等到其父进程退出后该进程将被init回收。
孤儿进程
一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对他们完成状态收集工作。
一个可选的解决方法是,杀死父进程(需要谨慎……),于是僵尸进程成为”孤儿进程”,它由给1号进程init收养,init 进程会周期性地去调用 wait 系统调用来清除它的僵尸孩子。因此,你会发现父进程死掉之后,僵尸进程也跟着消失,其实是 init 进程在为其收尸!
2.如何查看僵尸进程信息?如何统计僵尸进程数量?
(ps - ef | grep defunct;ps -ef | grep defunct | wc - l)
僵尸进程的产生
一个进程终止的方法很多,进程终止后有些信息对于父进程和内核还是很有用的,例如进程的ID号、进程的退出状态、进程运行的CPU时间等。因此进程在终止时,回收所有内核分配给它的内存、关闭它打开的所有文件等等,但是还会保留以上极少的信息,以供父进程使用。父进程可以使用 wait/waitpid 等系统调用来为子进程收拾,做一些收尾工作。
因此,一个僵尸进程产生的过程是:父进程调用fork创建子进程后,子进程运行直至其终止,它立即从内存中移除,但进程描述符仍然保留在内存中(进程描述符占有极少的内存空间)。子进程的状态变成EXIT_ZOMBIE,并且向父进程发送SIGCHLD 信号,父进程此时应该调用 wait() 系统调用来获取子进程的退出状态以及其它的信息。在 wait 调用之后,僵尸进程就完全从内存中移除。因此一个僵尸存在于其终止到父进程调用 wait 等函数这个时间的间隙,一般很快就消失,但如果编程不合理,父进程从不调用 wait 等系统调用来收集僵尸进程,那么这些进程会一直存在内存中。
//查看僵尸进程信息
ps - ef | grep defunct
//统计僵尸进程数量
ps -ef | grep defunct | wc - l
3.并发和并行的区别?
并发(Concurrent):指两个或多个事件在同一时间间隔内发生,即交替做不同事的能力,多线程是并发的一种形式。例如垃圾回收时,用户线程与垃圾收集线程同时执行(但不一定是并行的,可能会交替执行),用户程序在继续运行,而垃圾收集程序运行于另一个CPU上。
并行(Parallel):指两个或者多个事件在同一时刻发生,即同时做不同事的能力。例如垃圾回收时,多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。
4.进程和线程的区别?
进程是资源分配的最小单位,线程是CPU调度的最小单位
进程包括线程
资源开销:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。
包含关系:如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。
内存分配:同一进程的线程共享本进程的地址空间和资源,而进程之间的地址空间和资源是相互独立的。
影响关系:一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。
执行过程:每个独立的进程有程序运行的入口、顺序执行序列和程序出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制,两者均可并发执行。
5.进程通信的方式有哪些?
管道、消息队列、共享内存、信号量、套接字Socket
6.BIO 和 NIO ?是那个层面的实现?
BIO 阻塞 IO;NIO 非阻塞 IO。IO是操作系统层面实现的,在进行IO操作时不是直接操作物理硬件,而是通过缓冲区的复制进行的,一般来说是用户缓冲区和内核缓冲区之间复制。BIO 像 read 操作需要等数据准备好才会接着往下执行;NIO 则是通过轮询,若没有准备好则去处理别的事,偶尔查看,如果备好了就往下执行。