进程控制

进程控制


文章目录

  • 进程控制
  • 进程控制
    • 1.创建
    • 2.进程退出
    • 3.进程等待
    • 4.进程替换


进程控制

进程控制:创建、退出、等待、替换

1.创建

创建:   pid_t fork();–通过复制父进程创建一个子进程–父子进程代码共享,数据独有
  返回值:错误返回-1,对于父进程返回值大于0-子进程的pid,对于子进程返回0
写实拷贝技术:创建子进程后,子进程与父进程各自有自己的虚拟地址空间,但是数据映射的实际上是同一块物理内存,等到内存发生改变的时候为子进程重新开辟一块独立的空间,保存子进程的数据(保持进程独立性)

提高fork创建子进程的效率

pid_t vfork(void)--通过复制父进程创建一个子进程-父子进程共用虚拟地址空间

创建子进程后,父进程会阻塞直到子进程 exit退出或者(程序替换)之后才会运行
共用同一个虚拟地址空间,同时运行会造成栈混乱
vfork创建的子进程不能在main函数中return退出

2.进程退出

进程退出:退出一个进程

  • main函数中调用return;
  • 使用库函数void exit(int status);–在任意位置调用都可以退出进程–退出之前刷新文件缓冲区
  • 使用系统调用接口void_exit(int status);–在任意位置调用都可以退出进程

代码如下:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 void fun(){
     
  5     exit(0);//_exit(0);
  6 }
  7 int main()
  8 {
     
  9     printf("nihao");
 10     sleep(2);
 11     fun();
 12     printf("-------\n");
 13     return 0;
 14     //exit(0);
 15 }

运行结果:
在这里插入图片描述
但如果用"_exit"就不会刷新缓冲区

进程的退出返回值:   正常退出:通过三种退出方式退出的进程(结果是否符合预期)
    异常退出:程序因为某些错误异常崩溃退出
    进程的返回值,实际上只使用了一个字节进行保存

3.进程等待

概念:父进程等待子进程的退出,获取退出子进程的返回值,释放退出子进程的资源–>为了避免产生僵尸进程

操作:

pid_t wait(int *status);--阻塞函数

status:一个整型空间的地址,用于获取退出子进程的返回值
返回值:成功返回退出子进程的pid,失败返回-1;
等待任意一个子进程的退出,如果当前没有子进程退出则一直阻塞等待
只要有退出的子进程,这个接口就会立即进行处理后返回

阻塞:为了完成一个功能,发起一个调用,若当前不具备完成条件,则一直等待
非阻塞:为了完成一个功能,发起一个调用,若当前不具备完成条件,则立即返回
代码如下:

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<unistd.h>
  4 #include<sys/wait.h>
  5 int main()
  6 {
     
  7     pid_t pid = fork();
  8     if(pid < 0){
     
  9         perror("fork error");
 10         exit(-1);
 11     }else if(pid == 0){
     
 12         //child
 13         sleep(5);
 14         exit(0);
 15     }else{
     
 16         //parents
 17         int childpid = wait(NULL);
 18         printf("%d----%d\n",pid,childpid);
 19         while(1)
 20             sleep(1);
 21     }
 22     return 0;
 23 }

pid_t waitpid(pid_t pid, int *status, int options);

可以等待任意一个子进程退出,也可以只等待指定的子进程退出
可以阻塞等待子进程退出,也可以非阻塞等待子进程退出

  • pid:-1表示等待任意子进程,大于0表示等待指定的子进程
  • status:用于获取退出子进程的返回值
  • options:0-默认阻塞等待;WNOHANG-设置非阻塞等待
  • 返回值:错误返回-1;没有子进程退出返回0;有子进程退出返回子进程pid

退出子进程返回值/wait的参数获取到的值:status

进程控制_第1张图片
一个程序在运行中,如果产生了某种错误(比如内存访问错误)系统就会给进程发送一个指定的信号表示进程出现了某个错误事件,收到这个信号后,进程(崩溃)退出
异常信号退出值为0,表示进程正常退出,非0表示异常退出
代码转换:1.判断进程是否正常退出;2.获取退出的实际返回值
          status & 0x7f == 0;   (status >> 8) 0xff

4.进程替换

程序替换:替换一个进程正在调度运行的程序,程序替换,只是替换了运行的程序,而pcb中也只是重新初始化了一些信息(虚拟地址空间,页表……)
在一个进程中执行程序替换接口,就能实现改变当前调用进程运行的程序

exec函数族:一个系统调用接口+五个库函数

       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 execvpe(const char *file, char *const argv[],char *const envp[]);

第一个参数是新的程序文件路径名,第二个参数是程序运行参数,第三个参数是环境变量
exec函数有p时,程序文件若是命令程序可以不用带路径默认去path环境变量指定的路径下找程序

带p的函数,常用于执行替换命令程序时使用
exec函数有e时,表示由我们自己设定环境变量,否则默认使用原有环境变量
代码如下:

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<sys/wait.h>
  4 #include<unistd.h>
  5 int main()
  6 {
     
  7     pid_t pid = fork();
  8     if(pid < 0){
     
  9         perror("fork error");
 10         exit(-1);
 11     }else if(pid == 0){
     
 12         execlp("ls","ls","-l",NULL);
 13         perror("程序替换失败");
 14         exit(0);
 15     }
 16     wait(NULL);
 17     printf("子进程已经退出\n");
 18     return 0;
 19 }


你可能感兴趣的:(Linux)