进程控制1

进程创建
fork函数–>创建子进程函数
返回值
失败
小于0,表示创建失败
成功
大于0,返回给父进程
等于0,返回给子进程
原理:子进程拷贝父进程PCB
int vfork()函数 -->创建子进程的函数
1.vfork函数创建出来的子进程拷贝父进程的PCB,并且子进程PCB当中的内存指针指向了父进程的进程虚拟地址空间言外之意,两父子进程共用同一个虚拟地址空间
2.存在的问题
调用栈混乱的问题
3.vfork是如何解决这样的问题
让子进程先运行,运行完毕再让父进程运行。
进程终止
1.含义:进程的退出
2.场景:
2.1程序跑完了所以代码从main函数的return返回
代码跑完了,结果正确
代码跑完了,结果不正确
2.2程序没有跑完所有代码,直接崩溃掉了
6号信号—>double free
11号信号—>解引用,空指针,访问越界(gdb调试当中)
3.退出方法
3.1main函数的return返回
3.2库函数的exit函数,终止掉一个进程
void exit(int status);
status:进程在退出的时候,可以指定退出码是多少
echo $? //能够获取最后一个终止进程的退出码
3.3系统调用_exit函数,终止掉一个进程
4.exit和_exit的区别
在这里插入图片描述
读缓冲区和写缓冲区,exit这样的函数会刷新缓冲区
_exit函数,并不会刷新缓冲区
在这里插入图片描述

原理:缓冲区是C库当中维护的,并不是内核维护的,调用exit会先刷新缓冲区在结束进程
调用_exit直接是调用系统调用,拿不到缓冲区,会直接到操作系统内核结束进程
5.什么情况下会刷新缓冲区
5.1从main函数的return返回会刷新缓冲区
5.2 "\n"也会刷新缓冲区
5.3 fflush函数,强制刷新缓冲区
5.4调用exit函数也会刷新缓冲区
执行自定义清理函数
int atexit(void (function)(void));(回调函数)
参数是函数指针,接收返回值是void,参数是void的函数
作用:
调用atexit函数,参数是一个函数的地址,会先将这个函数的地址保存下来,等待进程退出的时候,再来调用这个函数;
进程等待
1.为什么要进程等待?
为了防止产生僵尸进程
2.进程等待的方法
pid_t wait(int
status);
status:输出型参数
status带出的int类型的值,int占用4个字节,但只用到后面两个字节(16个比特位)
在这里插入图片描述
正常退出的时候,只用到退出码,后面的8个bit位全部为0;
判断一个程序是否是正常退出,只需要判断是否接收到信号
status & 0x7f
0 00 00 00
1 11 11 11
在这里插入图片描述
大于0:异常退出,有终止信号
等于0:正常退出
获取coredump标志位
标志位 = (status>>7)& 0x1
等于0:没有coredump标志位
等于1:有coredump标志位
获取退出码
退出码 = (status>>8)& 0xFF
使用方法:
创建一个子进程,子进程正常逻辑,父进程调用wait函数来进行等待,当子进程正常退出的时候,父进程由于在等待,所以父进程会回收子进程资源,子进程就不变成僵尸进程。

结论:
1.wait函数等待到了子进程,所以子进程没变成僵尸进程
2.父进程当中一开始调用wait函数,父进程就会被阻塞在wait函数当中。
看到现象:当父进程执行到wait函数时,父进程“似乎”卡死到了wait函数当中;
pstack命令:查看函数的调用堆栈,可以看出来目前进程在执行什么代码
pstack[pid]
3.子进程不退出,wait函数调用不返回
父进程当前所属现象就是阻塞:
阻塞:
当调用函数需要等待一定条件成熟的时候,条件成熟则返回,条件不成熟则继续等待
对于调用函数进入到阻塞状态的进程而言,什么代码都执行不了,除非调用当前阻塞的这个函数返回了之后才能去执行其他代码;
非阻塞:
当调用函数需要等待一定条件成熟的时候返回,条件不成熟则报错返回
问题:
子进程和父进程是一个独立的进程,子进程退出时,父进程怎么知道子进程退出?子进程是如何通知父进程的?
子进程退出的时候,会给父进程发送一个信号,信号叫做SIGCHLD,进程对SIGCHLD信号默认是忽略处理;
梳理下僵尸进程产生的原因:子进程退出,父进程收到子进程的退出信号SIGCHLD,但是父进程对该信号忽略处理,所以导致子进程资源无法释放
没有在父进程调用wait函数等待之前,子进程也会变成僵尸进程;
进程等待:wait函数
将父进程收到的SIGCHLD信号进行处理,子进程才可以正常退出
进程等待续
1.waitpid函数
函数模型:pid_t waitpid(pid_t pid,int* status,int options)
参数含义:
pid:告诉waitpid函数,需要等待的子进程的进程号
pid == -1:表示等待任意子进程
pid > 0 :表示等待指定子进程,子进程的进程号就为传入的pid的值
status:和wait函数当中的status参数含义一致
options:设置waitpid函数是阻塞还是非阻塞
0:表示阻塞
WNOHANG:表示非阻塞,如果调用非阻塞,当子进程没有退出的时候,waitpid函数会报错返回
waitpid(pid > 0,status,0)= =>相当于wait函数
wait函数就是调用waitpid函数实现的;
返回值
成功返回子进程pid;
失败返回0;
2.进程等待的测试
2.1获取status当中的字段的值
退出码:(status>>8)&0xFF
coredump标志位:(status>>7)&0x1
信号:status&0x7F
2.2非阻塞
进程程序替换
进程替换是将已经跑起来的进程,替换成为执行其他程序的进程
1.将正在执行代码的进程当中的进程虚拟地址空间里面的数据段和代码段替换成为新的程序的数据段代码段,当前在执行的进程就会执行替换之后的程序的代码;
2.堆和栈需要更新—>更新为新进程的堆栈
3.进程程序替换接口
3.1 exec函数簇:不是一个函数,而是有一堆函数
3.2 exexcl函数
函数原型: int execl(const char* path,const char* arg,…);
参数:
path:带路径的可执行程序,要替换的程序的路径以及替换程序的名字
arg:给可执行程序传递的参数
注意:传递 的第一个参数必须是可执行程序的名称
后面依次传递参数,使用"逗号"隔开
如果已经写完了传递的参数,需要在传入一NULL, 表示已经传入完毕
返回值:
只有替换失败了才会有返回值,返回小于0(linux下是-1)
如果成功,则没有返回值,ps下已经去执行新的程序了,和之前旧的程序就没有关系了(旧程序进程终止新进程执行)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值