Linux操作系统:fork+exec进程创建
进程创建
执行了3次ps -f,ps -f的父进程的ID(PPID)都是一样的,也就是bash
实际上Linux上这个bash就是不断的复制自身,然后把复制出来的用exec替换成想要执行的程序
运行ps,发现ps是bash的一个子进程,原因就是bash把自己复制了一份,然后替换成了ps
替换,这里就体现了写时拷贝的意义,如果全部都要替换,那么最开始的复制是没有意义的;
注意,用了写时拷贝就支付值了几个页表的银蛇,内容还没有复制,然后执行了替换exec
在Linux中 新的进程的产生过程(进程创建):
fork(复制进程)
exec系列:将当前进程替换为另一个进程
进程替换exec系列
execl,execlp,execle,execv,execvp//库函数
execve//系统调用
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{printf("main pid=%d\n",getpid());execl("/usr/bin/ps","ps","-f",(char *)0);exit(0);
}
execl:只是将原来的程序换成了ps程序,但是PCB并没有变化,但是PCB里面的有些值被修改了,比如PCB中程序的名字换成了新程序的名字;
新的进程从主函数的第一行开始执行,也就是ps程序的主函数的第一行代码开始执行,这个和fork方法不一样,fork返回以后,从fork所在位置开始执行;
所以直接在execl下面打印一个失败,如果成功就根本不会执行到这里;
printf("execl error\n");
剩余exec系列:
execlp("ps","ps","-f",(char *)0);//int main(int argc,char *argv[],char *envp[])
execle("/usr/bin/ps","ps","-f",(char *)0,envp);//int main(int argc,char *argv[],char *envp[])
char *myargv[]={"ps","-f",0};
execv("/usr/bin/ps",myargv);//int main(int argc,char *argv[],char *envp[])
char *myargv[]={"ps","-f",0};
execvp("ps",myargv);int execve(const char * path, char* const argv[],char* const envp[]); //系统调用
//int main(int argc,char *argv[],char *envp[])char *myargv[]={"ps","-f",0};
execve("/usr/bin/ps",myargv,envp);
进程创建演示:
(1)创建ps命令-execl的使用
exec系列单独是能使用的,但是没有多大意义。通常我们会结合fork一起使用;
fork+exec()是Linux上创建新进程的方式;
#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<assert.h>#include<wait.h>int main()
{printf("main pid=%d,ppid=%d\n",getpid(),getppid());pid_t pid=fork();assert(pid!=-1);if(pid==0){printf("child pid=%d,ppid=%d\n",getpid(),getppid());// execl("/bin/ps","-f",(char *)0);//省略了ps也对,但是最好写成上面的;execl("/usr/bin/ps","ps","-f",NULL);printf("execl error");exit(0);}wait(NULL);exit(0);}