Linux【进程控制】

进程创建

在Linux中使用fork函数,通过复制调用进程来创建一个新的进程,新的进程为子进程

原理:进程调用fork函数,当控制转移到内核中的fork代码后,内核分配新的内存块和内核数据结构给子进程,将父进程的部分数据结构拷贝到子进程,添加子进程到系统进程列表中,fork返回,开始调度器调度

父子进程:代码共享,数据独有
fork函数返回值:父进程返回子进程的pid;子进程返回0

代码实现:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 
  4 int main() {
  5   int g_val=10;
  6   pid_t pid=fork();
  7   if(pid<0){
  8     return -1;                                                                      
  9   }else if(pid==0){                                  
 10     g_val=20;                        
 11     printf("i am child:%d,%d\n",getpid(),g_val);
 12   }else{                                              
 13     printf("i am parent:%d,%d\n",getpid(),g_val);
 14   }                                                                                                              
 15   return 0;                             
 16 }   

在这里插入图片描述
使用fork函数成功创建了一个子进程,子进程pid为4186,父进程pid为4185。在子进程中将g_val修改为20,父进程打印出来的仍是10,不难看出父子进程之间代码共享,数据独有的特性

vfork:vfork也可以用来创建子进程,父子进程共用同一个虚拟地址空间。但现在已经被淘汰了

进程等待

进程等待就是等待子进程的退出(状态改变),获取子进程的退出返回值(退出原因),避免僵尸进程

进程等待的方法:

wait方法
pid_t wait(int *status);
status:为NULL时表示不关心子进程的退出状态
一直等待任意一个子进程的退出,子进程退出后返回值放入参数status中,若一直没有子进程退出,wait函数将一直阻塞

waitpid方法
pid_t waitpid(pid_t pid,int *status,int options);
pid: -1等待任意一个子进程,pid>0等待指定的子进程
options:0为默认阻塞;WNOHANG将waitpid设置为非阻塞
阻塞等待任意一个子进程或指定的子进程退出

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 #include<errno.h>
  5 #include<string.h>
  6 #include<sys/wait>
  7 
  8 int main() {
  9   int pid=fork();
 10   if(pid<0) {
 11     //直接打印错误原因
 12     perror("fork error");
 13     //errno是一个全局变量,存储系统调用出现错误原因编号
 14     printf("fork error:%s\n",strerror(errno));
 15   }else if(pid ==0){
 16     sleep(3);
 17     exit(0);
 18   }
 19   //wait(NULL);                                                                                                  
 20   //waitpid(pid,NULL,0);
 21   while(1){
 22     printf("i am parent!\n");
 23     sleep(1);
 24   }
 25   return 0;
 26 }

在这里插入图片描述
没有进行进程等待,可以看出子进程先于父进程退出,操作系统为了保存退出原因,不能将子进程资源全部释放,子进程成为了僵尸进程

将注释掉的19/20行代码取消注释,使用wait或者waitpid方法来等待子进程的退出,可以看到子进程成功退出,并且没有成为僵尸进程
在这里插入图片描述

进程终止

进程退出的场景:
代码运行完毕,结果符合预期正常退出
代码运行完毕,结果不符合预期正常退出
代码异常终止

进程常见的退出方式:
正常终止:从main函数返回、调用exit库函数、调用_exit系统接口
异常终止:Ctrl + c

return退出

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 
  4 int main() {
  5   printf("hello!");                                                                                             
  6   return 0;
  7 }

在这里插入图片描述
exit函数

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 
  4 int main() {
  5   printf("hello!");                                                                                             
  6   exit(1);
  7 }

在这里插入图片描述
_exit系统调用接口

  1 #include<stdio.h>
  2 #include<stdlib.h>          
  3 #include<unistd.h>
  4                                                                                                                  
  5 int main() {                      
  6   printf("hello!");                                                                                            
  7   _exit(1);                                        
  8 }  

在这里插入图片描述
对比上面三种退出方式,我们可以看到这三种退出,前两种的结果是打印内容然后退出,在退出前会刷新缓冲区,_exit系统调用接口直接退出,退出前不会刷新缓冲区,并将缓冲区中的数据丢弃

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值