进程控制(创建,终止,等待,程序替换)

进程创建

 在linux中进程的创建使用pid_t fork(void),通过复制父进程创建一个新的子进程。

返回值:子进程中返回0,父进程返回新创建子进程pid,出错返回-1。

 如图所示,上面将牵扯到写实拷贝技术:子进程复制了父进程中大部分信息,子进程也有自己的变量,自己的变量经过页表映射后将访问和父进程相同物理地址,当这块内存空间的数据即将要修改,则给子进程重新开辟内存空间,并拷贝数据过去。每个变量都应该有自己的储存空间,这就是进程之间的独立性。

其目的在于提升子进程创建效率,避免不必要的内存消耗。

pid_t vfork(void)--创建一个子进程,父子进程共用一块虚拟地址空间,创建一个子进程并阻塞父进程,直到自己退出,或程序替换之后,父进程再开始运行。对于pid_t fork(void)创建子进程,父子进程谁先运行看系统调度,但是对于pid_t vfork(void),一定是子进程先运行,只有子进程退出或者程序替换之后父进程才会继续运行

进程终止


进程退出场景:代码运行完毕,结果正确,代码运行完毕,结果不正确,代码异常终止。
进程常见退出方法:

正常终止(可以通过 echo $? 查看进程退出码):
1. 从main中使用return返回(仅在main函数中使用时退出函数运行)
2. 调用库函数exit
3. 系统调用接口_exit(不刷新缓冲区)

exit和_exit的区别在于退出程序前,是否会将缓冲区中的数据进行刷新写入文件中。
异常退出
ctrl + c,信号终

程序退出返回值的意义:return以及exit给与的数据其实就是进程的返回码,作用:表示当前进程处理的结果。

void perror(const char *msg) 打印上一步系统调用失败的原因

extern int errno;在进程pcb中有个全局变量int errno,每个系统调用接口在执行的时候,都会重置errno(错误编号)。                                                                                                                          const char *strerror(int errno);根据错误编号,返回对应编号的字符串错误原因

进程等待

父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息,避免僵尸进程
pid_t wait(int*status);wait是一个阻塞接口,功能是等待当前调用者的任意一个子进程退出(如果已经有退出的直接处理返回),获取返回值,释放资源。status参数是一个int空间的地址,用于返回指定空间中存放子进程的退出返回值。                                                                                               阻塞接口:为了完成一个功能发起一个调用,但是这个调用完成条件不具备,则接口一直等待不返回。

非阻塞接口:为了完成一个功能发起一个调用,但是这个调用完成条件不具备,则立即报错返回

返回值:成功返回被等待进程pid,失败返回-1。
参数:输出型参数,获取子进程退出状态,不关心则可以设置成为NULL
pid_ t waitpid(pid_t pid, int *status, int options);waitpid接口可以等待任意一个子进程退出,也可以等待指定的子进程退出。0-默认、WNOHANG-非阻塞
返回值:
当正常返回的时候waitpid返回收集到的子进程的进程ID;
如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;
参数:
pid:
Pid=-1,等待任一个子进程。与wait等效。
Pid>0.等待其进程ID与pid相等的子进程。
status:
WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)
options:0-默认阻塞等待;WNOHANG-设置为非阻塞,当前没有子进程退出立即报错返回
WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。

若正常结束,则返回该子进程的ID

如何判断进程是否正常退出?

status整形四字节中,低16位的高8位存放退出码;低七位存异常退出信号值。取出status种的低七位,status&0x7f

如何从status中取出退出码?取出status种的低16位中的高八位,(status>>8)&0xff

程序替换

pcb是描述程序的运行过程

为什么创建子进程?是为了完成一段任务,

1.做与父进程相同的事情,分担压力。

2.完成另一个任务(执行一段代码if(fork()==0{})

如果把另一个任务的代码和当前代码合在一起,程序庞大。所以让子进程这个pcb管理调度这个程序的运行。

程序替换:替换掉一个pcb所描述的要管理调度的程序,替换成另一个程序。简单理解:将一个新程序加载到内存中,修改当前pcb进程的页表映射信息,初始化到地址空间,让其调度管理新程序。

程序替换之后,相当于PCB来说,调度了一个新程序(不关心以前的程序--被释放),新程序运行完毕,就会退出进程。

操作接口:

int execve(const char *path, char *const argv[], char *const envp[]);

功能:将Path这个路径名所指定的程序加载到内存中,然后让当前进程调度管理这个程序的运行,而程序运行有可能会有运行参数和环境变量。

argv用于设定这个程序的运行参数;                                                                                           envp用于设定这个程序的环境变量,                                                                                             返回值:成功无返回值(成功运行新的程序了),失败返回-1;

int execve(char *path, char *argv[], char *env[]);

 int execvp(const char *file, char *const argv[]);不用指定路径,默认会在path环境变量指定路径下找。环境变量默认使用当前已有环境变量。execvp(“ls”, argv);等价于execve(“bin/ls”, argv,env)

execv后面如果有e就表示需要手动设置环境变量,没有e则表示使用默认环境变量

execv后面如果有p就表示不需要路径,默认到PATH指定路径下找,没有p则需要指定路径。execvp(“ls”, argv)   execve(“bin/ls”, argv,env)    execv(“bin/ls”, argv)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值