本文属于牛客网上的一个项目笔记:Linux高性能服务器开发课
创建子进程
函数原型
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
功能:创建一个子进程,失败返回-1;
参数:无
说明:pid_t其实是一个int,在fork函数这一行,父子进程都开始执行,如果在父进程中,执行完fork后,会得到>0的pid,在子进程中执行完后,会得到0。
用例:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main(){
pid_t pid = fork();
// getpid() 获取当前进程pid getppid() 获得当前进程的父进程的pid
if(pid > 0){
//pid>0 在父进程 当cpu切换到父进程时,运行这一段代码
printf("main %d,%d\n",getpid(),getppid());
}else if( pid== 0){
//pid=0 在子进程 当cpu切换到子进程时,运行这一段代码
printf("child %d,%d\n",getpid(),getppid());
}
//这段代码在父子进程中都运行
for(int i=0;i<3;i++){
printf("i = %d,getpid=%d\n",i,getpid());
// sleep(1);
}
return 0;
}
子进程是读时共享,写时复制。在fork后,子进程复制父进程的代码段/数据段/BSS段/堆/栈等所有用户空间信息;在内核中操作系统重新为其申请了一个PCB,并使用父进程的PCB进行初始化;
exec函数族
exec函数族中的函数会调用起另一个进程,被调进程会替换掉调用进程。因此,为了防止父进程被替换掉,往往都在子进程中使用exec函数族。
execl()
函数原型
#include <unistd.h>
int execl(const char *path,const char *arg,...);
功能:调用起另一个进程
参数:- path:需要指定的执行的文件的(绝对)路径
- arg:是执行文件所需要的参数列表 可以是很多个参数,参考main函数参数以null结束
返回值:只有调用出错时返回-1设置errno
用例:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
pid_t pid = fork();
if(pid == 0){
printf("1我是子进程,pid是%d,我的父进程是%d\n",getpid(),getppid());
execl("/home/fang/newcodercpp/lesson03/hello","hello",NULL);
printf("2我是子进程,pid是%d,我的父进程是%d\n",getpid(),getppid());
}else if(pid > 0){
printf("我是main进程,pid是%d\n",getpid());
sleep(1);
}
for(int i=0;i<3;i++){
printf("i=%d,pid是%d\n",i,getpid());
}
return 0;
}
execlp()
函数原型:
int execlp(const char *file,const char *arg,...);
会到环境变量中查找file,找到就执行
- file 可执行文件的文件名
- arg
用例:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
pid_t pid = fork();
if(pid == 0){
printf("1我是子进程,pid是%d,我的父进程是%d\n",getpid(),getppid());
execlp("ls","ls","-all",NULL);
printf("2我是子进程,pid是%d,我的父进程是%d\n",getpid(),getppid());
}else if(pid > 0){
printf("我是main进程,pid是%d\n",getpid());
sleep(1);
}
for(int i=0;i<3;i++){
printf("i=%d,pid是%d\n",i,getpid());
}
}
execve()
函数原型:
int execve(const char *filename,char *const argv[], char *const envp[]);
自定义一个环境变量的数组,会临时的网系统环境变量中添加进去自己定义的
- filename 字符串所代表的文件路径
- argv[] 利用指针数组来传递给执行文件,并且需要以空指针(NULL)结束
-envp[] 为传递给执行文件的新环境变量数组
如 char *envp[] = {"PATH=/home/fang/01","PATH=/home/fang/02"...,NULL}
用例
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
pid_t pid = fork();
if(pid == 0){
printf("子进程\n");
char *envp[]={"PATH=/home/fang/newcodercpp/lesson04/","PATH=/home/fang/newcodercpp/lesson03/",NULL};
char *argv[]={"app",NULL};
char *filename = "/home/fang/newcodercpp/lesson03/app";
execve(filename,argv,envp);
}else if(pid > 0){
printf("主进程\n");
}
}
execvp()
原型:
int execv(const char *file,char *const argv[]);
-argv[] 参数列表数组
如 char *argv[] = {"ls","参数1","参数2","参数3"...}
execv("ls",argv[]);
用例:NULL