gdb调试多进程
set follow-fork-mode parent/child:设置调试父进程或子进程
set detach-on-fork on/off:设置调试模式,on表示调试当前进程时,其他进程继续运行;off表示调试当前进程的时候,其他进程被gdb挂起。
info inferiors:打印存在的进程
inferior 2:切换到进程2,以调试进程2
c:continue 使进程继续执行
detach inferiors 2:使进程2脱离gdb的调试
n:单步调试
exec函数族:
什么是函数族?功能相同或相似的一组函数,类似c++函数重载,函数名一样,参数不一样
可执行文件a.out的用户区对应原来进程里面的用户区(包括代码区),接下来进程执行的是可执行文件a.out里的代码,并且从a.out的main函数开始执行;
execl():略 也可以执行shell命令
创建一个子进程,在子进程中执行exec函数族中的函数,子进程其余代码不会执行,但是父进程的代码不受影响,还是会执行;
execlp():会到环境变量中查找可执行程序(env(shell)中的path)
进程控制:
fork()读时共享,写时复制,降低内存的消耗,因为读的时候没有必要再复制一份;
进程退出:
exit:原理:子进程结束,释放用户区数据,内核数据由父进程回收,所以父进程需要获取子进程的退出状态;是标准c库的函数;刷新io缓冲:把数据刷新到控制台;
_exit:linux系统函数
孤儿进程:
出现孤儿进程后,内核把孤儿进程的父进程设置为init,而init进程会循环地wait()它的已经退出的子进程。这样,当孤儿进程结束生命周期时,init进程就会代表党和政府出面处理它的一切善后工作。
僵尸进程:
每个进程结束后,会释放自己地址空间中的用户区数据,但内核区的pcb没有办法自己释放,需要父进程去释放。进程终止时,父进程尚未回收(父进程卡住了),子进程残留资源(pcb)存放于内核中,变成僵尸进程。
僵尸进程不能被kill -9 杀死。
如果父进程不调用wait()或waitpid()的话,那保留的那段信息就不会释放,进程好就会一直被占用。如果产生很多僵尸进程,那么系统没有为创建新进程可以用的进程号。
如何解决僵尸进程?
使父进程死亡,让pid为1的进程来托管僵尸进程
在父进程中使用wait或waitpid
wait函数
等待任意一个子进程结束,如果任意一个子进程结束了,次函数会回收子进程;
调用wait函数的进程会被挂起(阻塞),直到它的一个子进程退出(可以用杀掉子进程kill -9 13478)(13478是子进程pid)或收到一个不能被忽略的信号时才被唤醒(相当于继续往下执行);
正常情况下返回子进程的pid
如果没有子进程了,函数立刻返回,返回-1;如果子进程都已经结束了,也会立即返回,返回-1;
如果我们只想清理掉僵尸进程而对子进程如何死掉毫不在意,那么可以将int* state 设为NULL,比如wait(NULL)
创建5个子进程:
for(in