1、进程创建
2、进程终止
3、进程等待
1、进程创建
进程的创建是通过fork函数实现的,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。(进程的本质是:内核数据结构+进程代码和数据)
#include<unistd.h>
pid_t id = fork();
返回值:子进程返回0,父进程返回子进程id,出错返回-1
进程调用fork,当控制转移到内核中的fork代码后,内核做:
1、分配新的内存块和内核数据结构给子进程
2、将父进程部分数据结构内容拷贝至子进程
3、添加子进程到系统进程列表中
4、fork返回,开始调度器调度
因为fork创建出来的子进程也是一个进程,进程具有独立性,子进程也要有自己的代码和数据,而一般而言,并没有加载的过程,所以子进程没有自己的代码和数据,所以,子进程只能使用父进程的代码和数据,这里就用到了写时拷贝技术。
写时拷贝:父子代码共享,父子不再写入时,数据也是共享的,当任意一方试图写入时,便以写时拷贝的方式各自拷贝一份副本。
OS选择的写时拷贝技术可以对父子进程进行分离,提高整机内存的使用率。
2、进程终止
进程退出的场景:
·代码运行完毕,结果正确
·代码运行完毕,结果不正确
·代码异常终止
进程常见退出方法:
1、从main函数中返回
2、调用exit
3、调用_exit
_exit函数
#include <unistd.h>void _exit(int status);参数: status 定义了进程的终止状态,父进程通过 wait 来获取该值
#include <unistd.h>void exit(int status);
echo $? \\取最近一次进程退出的退出码
3、进程等待
进程等待的必要性:
进程等待的方法:
wait方法
#include<sys/types.h>#include<sys/wait.h>pid_t wait(int*status);返回值:成功返回被等待进程 pid ,失败返回 -1 。参数:输出型参数,获取子进程退出状态 , 不关心则可以设置成为 NULL
waitpid方法
pid_ t waitpid(pid_t pid, int *status, int options);返回值:当正常返回的时候 waitpid 返回收集到的子进程的进程 ID ;如果设置了选项 WNOHANG, 而调用中 waitpid 发现没有已退出的子进程可收集 , 则返回 0 ;如果调用中出错 , 则返回 -1, 这时 errno 会被设置成相应的值以指示错误所在;参数:pid :Pid=-1, 等待任一个子进程。与 wait 等效。Pid>0. 等待其进程 ID 与 pid 相等的子进程。status:WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)WEXITSTATUS(status): 若 WIFEXITED 非零,提取子进程退出码。(查看进程的退出码)options:WNOHANG: 若 pid 指定的子进程没有结束,则 waitpid() 函数返回 0 ,不予以等待。若正常结束,则返回该子进程的 ID 。
注:
int main()
{
pid_t pid;
pid = fork();
if(pid < 0){
printf("%s fork error\n",__FUNCTION__);
return 1;
} else if( pid == 0 ){ //child
printf("child is run, pid is : %d\n",getpid());
sleep(5);
exit(257);
} else{
int status = 0;
pid_t ret = waitpid(-1, &status, 0);//阻塞式等待,等待5S
printf("this is test for wait\n");
if( WIFEXITED(status) && ret == pid ){
printf("wait child 5s success, child return code is :%d.\n",WEXITSTATUS(status));
}else{
printf("wait child failed, return.\n");
return 1;
}
}
return 0;
}
运行结果:
[root@localhost linux]# ./a.out
child is run, pid is : 45110
this is test for wait
wait child 5s success, child return code is :1.
进程的非阻塞等待方式
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{
pid_t pid;
pid = fork();
if(pid < 0){
printf("%s fork error\n",__FUNCTION__);
return 1;
}else if( pid == 0 ){ //child
printf("child is run, pid is : %d\n",getpid());
sleep(5);
exit(1);
} else{
int status = 0;
pid_t ret = 0;
do
{
ret = waitpid(-1, &status, WNOHANG);//非阻塞式等待
if( ret == 0 ){
printf("child is running\n");
}
sleep(1);
}while(ret == 0);
if( WIFEXITED(status) && ret == pid ){
printf("wait child 5s success, child return code is :%d.\n",WEXITSTATUS(status));
}else{
printf("wait child failed, return.\n");
return 1;
}
}
return 0;
}