进程控制
进程创建:
fork()—复制。返回值,写时复制
vfork()
vfork()创建子进程—子进程与父进程公用同一块虚拟地址空间,为了防止调用栈混乱,因此阻塞父进程知道子进程调用exit()退出或者进行程序替换。
vfork的子进程不能下main函数中return退出,因为释放资源后,父进程陷入混乱崩溃
fork / vfork / clone —fork和vfork在内核中都是调用clone实现进程的创建
进程退出
进程退出的场景:
正常退出,结果符合预期
正常退出,结果不符合预期
异常退出
终止方式:main函数中的return;exit(int statu);_exit(int statu)
exit库函数,退出时刷新缓冲区
_exit系统调用接口,退出时,不会刷新缓冲区,直接释放资源
进程等待:等待子进程退出—为了避免产生僵尸进程
pid_t wait(int status)—阻塞等待任意一个子进程退出
阻塞: 发起一个系统调用完成功能,当前如果不具备完成条件;则等待知道完成功能后返回
非阻塞: 当前如果不具备完成条件;则立刻报错返回
if((statu&0x7f)==0)
{
printf("child exit code:%d\n",(statu>>8)&0xff);
}
程序替换:
替换一个进程所正在运行的程序—重新加载其它程序到内存,映射进程虚拟地址空间与内存的映射位置到新的程序地址上;(代码段修改映射位置,数据段重新 初始化)进程重新从main函数开始调度运行
如何进程程序替换:
execl — execlp — execle
execv — execvp — execve
l和v的区别:传参的区别
l是程序运行参数使用函数的实参平铺的形式赋予—execl(ls,ls,-l -a,NULL)
v是程序运行参数使用字符串指针数组赋予—argv[0]=ls argv[1]=-l / execl(ls,argv
带p和不带p的区别
带p:程序名称可以不带路径,直接去PATH环境变量所指定的路径下找程序—execlp(ls,·····)
不带p:程序名称必须带路径—execl(/bin/ls,······)
带e和不带e的区别:
带e:给进程自定义环境变量—env[0]=“myenv=100” execle(ls,·····,NULL,env)
不带e:继承原有默认的环境变量—execl(ls,·····);
自主实现一个shell—minishell:
shell:命令行解释器—解释执行用户的输入(完成相对应的功能)
1、获取标准输中的字符串
2、对字符串进行解析[ ls -l -a][ls][-l][-a]
3、创建子进程
4、子进程中进行程序替换
5、父进程进行进程等待—避免僵尸进程