进程控制~

进程创建

pid_t fork(void)

通过fork()创建一个子进程,返回值有两个:

情况\返回值\进程父进程子进程
创建成功子进程的pid0
创建失败-1

【Note】进程创建应用了写时拷贝技术

pid_t vfork(void)

通过vfork()创建子进程,会阻塞父进程

阻塞:为了完成一个功能,发起调用,若当前不具备完成条件,则一直等待

非阻塞:为了完成一个功能,发起调用,若当前不具备完成条件,则报错返回

【Note】父子进程共用同一虚拟地址空间

进程退出

1.main()return——会刷新缓冲区
2.调用库函数exit()——会刷新缓冲区
3.系统系统调用接口_exit()——不会刷新缓冲区,直接释放资源

进程退出情况分为:正常退出、异常退出

系统调用错误原因获取接口:perror()stderror(errno)

进程等待

父进程等待子进程退出,获取子进程退出状态及运行结果的操作,正确使用进程等待,可以及时释放资源,避免僵尸进程的出现。

pid_t wait(int* status)

wait()是一个阻塞函数,会阻塞父进程,当子进程没有返回时,父进程会一直等待子进程的返回值。

status:用于获取子进程的退出返回值(后面有详细解释)
返回值:成功返回则为子进程的pid,失败返回-1

pid_t waitpid(pid_t pid,int* status,int option)

waitpid()可以等待任意一个子进程退出,也可以等待一个指定的子进程退出;它可以设置为默认阻塞接口,也可以设为非阻塞接口

pid:设为-1表示等待一个子进程,>0表示等待指定子进程
status:用于获取返回值
options0表示默认阻塞等待,WNOHANG设置为非阻塞
返回值大于0即子进程的pid,等于0表示没有子进程退出,错误返回-1

status组成初探

status(一个int型数据)组成如下所示:
statusstatus我们暂时关心的是其低16位数据:

低16位中的高8位表示子进程的退出返回值;获取方式:status>>8&0xff

低16位中的低8位的最高位表示该子进程结束时是否产生coredump文件;获取方式:status>>7&1

低16位中的低8位的剩余7位表示异常信号值;获取方式:status&0x7f

wait中status的获取例子

  #include <stdio.h>    
  #include <stdlib.h>    
  #include <sys/wait.h>    
  #include <unistd.h>    
  #include <string.h>    
      
  int main(){    
      int ret = fork();    
      if(ret<0){    
          printf("creat child_process failed!\n");    
          return -1;    
      }    
      else if(ret == 0){    
          printf("i am child\n");    
         // char* str = NULL;    
         // memcpy(str,"test",4);                                                                         
          sleep(5);    
          exit(99);    
      }    
      else{    
          int ret,status;    
          while((ret = waitpid(-1,&status,0))==0){    
              sleep(1);    
          }    
          printf("coredump_flag is %d\n",status>>7&1);    
          printf("exit_value is %d\n",status>>8&0xff);    
          printf("signal_abnormal is %d\n",status&0x7f);    
          if(status&0x7f!=0){    
              printf("异常信号值非0!返回值没有意义!\n");    
          }    
      }    
      return 0;    

在这里插入图片描述

进程程序替换

fork()创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec()函数以执行另一个程序。

当进程调用一种exec()函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变

excel()函数族:

#include <unistd.h>
extern char** environ;
int execl(const char*path,const char arg,……);
int execlp(const char *file,const char* arg,……)int execle(const char*path,const char arg,……,char* const envp[]);
int execv(const char* path,char* const argv[]);
int execvp(const char* file,char* const argv[])
int execve(const char* file,char* const argv[],char* const envp[]);

命名理解

l(list):表示参数采用列表
v(vector):表示参数采用数组
p(path):有p自动搜索环境变量PATH
e(env):表示自己维护环境变量

函数名参数格式是否带路径是否使用当前环境变量
execl列表
execlp列表
execle列表否,须自己组装环境变量
execv数组
execvp数组
execve数组否,须自己组装环境变量

一个replace例子

#include <stdio.h>    
#include <unistd.h>    
#include <stdlib.h>    
      
int main(int argc,char* argv[]){    
    printf("程序即将开始替换!\n");    
    execl("/usr/bin/ls","ls","-a","-l",NULL);    
    printf("替换之后的代码!\n");                                                                       
    return 0;
    }

运行效果:
在这里插入图片描述可以发现,当程序运行到第6行时,程序发生替换,main被替为ls,因此打印出main的一句提示后,后面输出的ls运行结果,ls运行结束,程序即运行终止。

换句话说,当发生程序替换后,替换之后的语句将不再执行!

结语

我的本质就是复读机!复读虽然不快乐但很高效!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值