Linux进程总结(下)

进程创建

fork()

原理:为子进程重新创建一个task_struct,以及对应的虚拟地址空间和页表,并且将父进程的 数据(包括缓冲区的数据)和代码拷贝一份至子进程pcb中
返回值:对父进程而言:fork()成功返回子进程的进程id;失败返回-1.
对子进程而言:fork()成功返回0;失败返回-1。
fork返回值验证代码:

#include<stdio.h>                                                                                                 
#include<unistd.h>                                                                                                
#include<stdlib.h>                                                                                                
int main()                                                                                                        
{                                                                                                                 
     pid_t pid;                                                                                                      
     int count = 0;                                                                                                  
     printf("before: pid = %d\n", getpid());                                                                                                                                                                           
     pid = fork();                                                                                                                                                                                                                                                                                                  
     if(pid < 0) {                                                                                                             
       perror("fork");                                                                                                                                                    
     }                                                                                                             
     else if(pid == 0){                                                                                            
       printf("child:pid =  %d,  return = %d\n",  getpid(), pid);                                                                           
       exit(0);                                                                                                    
     }                         
     printf("after: pid = %d, return = %d\n", getpid(), pid);                                                      
     return 0;
}

在这里插入图片描述
失败原因:系统资源不够,无法再次创建进程
用户的进程数超过了限制
模拟不可再创建进程代码:

#include<stdio.h>                                                                                                 
#include<unistd.h>                                                                                                
#include<stdlib.h>                                                                                                
int main()                                                                                                        
{                                                                                                                 
   pid_t pid;                                                                                                      
   int count = 0;                                                                                                                                                                      
   while(1){                                                                                                       
   	  pid = fork();                                                                                                                                                                                                     
      usleep(2000);                                                                                                 
      if(pid < 0)                                                                                                   
      {                                                                                                             
  	     printf("this computer can fork %d times\n",count);                                                          
         return 1;                                                                                                   
      }                                                                                                             
     else if(pid == 0){
     	 printf("child have %d\n", count);                                                                                                                                                                 
         exit(0);                                                                                                    
      } 
      count++;                                                                                                              
   }                                                                                                                                                                 
   return 0;
}

在这里插入图片描述
vfork()
原理: 只为子进程创建一个task_struct,父子进程共享虚拟地址空间,父子进程中的任意一 个进程修改了数据,那么父子进程中的数据也会被修改
保证子进程先于父进程运行,并且只有子进程调用了exit之后,父进程才可以运行
代码验证:

#include<stdio.h>                                                                                                 
#include<unistd.h>                                                                                                
#include<stdlib.h> 
int main()                                                                                                        
{                                                                                                                 
    int value = 100;                                                                                                
    pid_t pid = vfork();                                                                                            
    if(pid == 0)                                                                                                    
    {                                                                                                               
        printf("child, pid = %d, ppid = %d, value = %d\n",getpid(), getppid(), value);                                
        value = 2020;                                                                                                 
        sleep(1);                                                                                                     
        printf("child, pid = %d, ppid = %d, value = %d\n",getpid(), getppid(), value);                                
        exit(0);                                                                                                      
    }                                                                                                               
    printf("child, pid = %d, ppid = %d, value = %d\n",getpid(), getppid(), value);                                  
    sleep(2);                                                                                                       
    printf("child, pid = %d, ppid = %d, value = %d\n",getpid(), getppid(), value);                                  
    return 0;                                                                                                       
}

进程终止:

三种退出情景
1.代码运行完毕,结果正确
2.代码运行完毕,结果不正确
3.代码运行异常终止

退出方法:(echo $? : 查看上一条命令的退出码)
main函数(主函数)中退出
return
exit(num)
调用exit(num)退出
调用_exit(num)退出
exit()、return、_exit()的区别:
1.return只有在主函数中才能结束进程,在非主函数中,只能退出该函数
2.return 在主函数中调用相当于exit()
3.exit() 是温和式退出,在调用了exit之后,进程会刷新缓冲区,关闭文件等…
4._exit() 是粗暴式退出,一旦调用_exit()后,进程会直接释放所有资源,结束进程
5.exit()和_exit() 在进程任意位置都能直接结束进程,其参数代表进程退出码!
:char* strerror(int num); 作用是将错误编号num 转换为字符串的错误信息

进程等待

必要性:避免形成僵尸进程,造成内存泄漏,资源浪费

等待方法
1.阻塞式等待:
pid_t wait(int* status);
成功返回被等待的进程的进程id
失败返回-1
status是一个输出型参数,代表获取子进程的退出状态(退出码)
2.非阻塞式等待:
pid_t waitpid(pid, status, options)
pid 设置为-1,表示等待任意进程
>0 表示要等待的进程的进程id
option :一个选项参数 可man了解
status(子进程退出状态(退出码))
如图:
在这里插入图片描述
相当于一个位图,4个字节,32个比特位
但是只用到了 低16位比特位
其中高8位代表退出码,低8位表示核心转储(第七位)和终止信号
进程若正常退出,那么只有退出码,没有终止信号(只用到高8位)
若异常退出,那么没有退出码,只有终止信号(只用到低8位)

进程程序替换

重点:程序替换,并没有创建新的进程,只是将原有的代码和数据替换为新的可执行程序的代码 和数据

程序替换函数
execl(文件路径,变长的命令行参数…) 命令行参数必须以NULL结尾
execlp(文件名,变长的命令行参数…)
execle(文件路径,变长的命令行参数…,自己配置的环境变量数组)
execv(文件路径,命令行参数数组)
execvp(文件名,命令行参数数组)
execve(文件路径,命令行参数数组,自己配置的环境变量数组)
注:替换成功之后,程序便从替换处开始执行新的程序,不再返回
替换成功,没有返回值,替换失败,返回-1
只有execve是系统调用函数,其他均是被封装的库函数
进程替换 ls 指令 代码:

#include<unistd.h>                                                                                              
#include<stdlib.h> 
int main()                                                                                                      
{                                                                                                               
    //execl("/usr/bin/ls", "ls", "-al", NULL);                                                                    
    printf("-----------\n");                                                                                      
    //execlp("ls", "ls", "-al", NULL);                                                                            
    char* env[] = {                                                                                               
      "AAAA=aaaa",                                                                                                
      NULL,     //must use NULL become last                                                                       
    };                                                                                                            
    //execle("./a.out", "./a.out", NULL, env);                                                                    
    //printf("---------------\n");                                                                                
    char* argv[] = {                                                                                              
      "ls",                                                                                                       
      "-al",                                                                                                      
      NULL                                                                                                        
    };                                                                                                            
    char *argv1[] = {"./a.out", NULL};                                                                            
    //execv("/usr/bin/ls", argv);                                                                                 
    //execvp("ls", argv);                                                                                         
    execve("./a.out", argv1, env);                                                                                
} 

关于一些细的知识点,还是有些不熟,我会下次补全!!
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值