Linux中的进程控制
目录
进程控制
fork函数初识
fork详解
写时拷贝
退出码
进程常见退出方法
exit/_exit
进程等待
wait方法
waitpid
代码实现
非阻塞式等待
进程控制
fork函数初识
fork详解
1.如何理解fork有两个返回值?
fork()函数执行后,存在父子两个执行流。所以会有两个返回值。
2.如何理解fork返回之后,给父进程返回子进程pid,给子进程返回0?
一个孩子只有一个父亲,所以子进程不需要父进程的id值。
一个父亲可以有多个孩子,故需要有pid标识具体是哪一个孩子。
3.如何理解同一个id值,会保存两个不同的值,让if else if同时执行?
同一个id,地址是一样的但是内容却有可能不一样。
pid_t id=fork();
返回的本质就是写入,返回时会发生写时拷贝,谁先返回,谁就会先写入。(进程具有独立性)
写时拷贝
通常,父子代码共享,父子再不写入时,数据也是共享的,当任意一方试图写入,便以写时拷贝的方式各自一份副 本。具体见下图:
退出码
return 0;
0为进程退出时候对应的退出码,标定进程退出的结果是否正确。
./mytest
运行一个进程
echo $?
$?:永远记录最近一个进程在命令行中执行完毕时,对应的退出码。即main函数的返回值。
echo:自身的退出码为0.
Linux共提供了134个。
ls
ls使用c语言写的,Linux下一切皆文件。
进程常见退出方法
正常终止(可以通过 echo $? 查看进程退出码):
1. 从main返回
2. 调用exit
3. _exit
异常退出:
ctrl + c,信号终止
exit/_exit
exit: 终止进程,主动刷新缓冲区
_exit: 终止进程,不会刷新缓冲区
缓冲区--->是一个用户级缓存区。
进程等待
父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息(进程为什么要等待)
wait方法
#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int*status);
返回值:
成功返回被等待进程pid,失败返回-1。
参数:
输出型参数,获取子进程退出状态,不关心则可以设置成为NULL
waitpid
#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int*status);
返回值:
成功返回被等待进程pid,失败返回-1。
参数:
输出型参数,获取子进程退出状态,不关心则可以设置成为NULL
pid_ t waitpid(pid_t pid, int *status, int options);
options为0,代表阻塞式等待。
通过status应体现出这三种状况:
代码运行完毕,结果正确
代码运行完毕,结果不正确
代码异常终止
status不是被整体使用的,status有自己的位图结构。
代码实现
非阻塞式等待
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
int main()
{
pid_t id=fork();
assert(id!=-1);
if(id==0)
{
int cnt=10;
while(cnt)
{
printf("child running,pid: %d, ppid: %d, cnt:%d\n",getpid(),getppid(),cnt);
sleep(3);
}
exit(6);
}
int status =0;
while (1)
{
//非阻塞式等待,父进程检测后立即返回
pid_t ret=waitpid(id+1,&status,WNOHANG);
if(ret==0)
{
//waitpid调用成功,子进程还未退出
printf("wait done,but child is running.....\n");
}
else if(ret>0)
{
//waitpid调用成功,子进程退出
printf("wait success,exit code: %d, sig: %d\n",(status>>8)&0xff,status&0x7f);
}
else
{
printf("waitpid call failed\n");
break;
}
}
return 0;
}
waitpid:检测子进程退出信息,将子进程退出信息(存在子进程的PCB中)通过status拿到。
status:
WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出) WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)
options:
WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进 程的ID。