【C++高并发服务器WebServer】-2:exec函数簇、进程控制

本文目录

一、exec函数簇介绍

exec 函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件。

exec函数族的函数执行成功后不会返回,因为调用进程的实体,包括代码段,数据段和堆栈等都已经被新的内容(也就是新的进程信息会替换原进程的"用户区"的信息)取代,只留下进程ID等一些表面上的信息仍保持原样(比如PID、PPID、进程组号等这些在内核区的PCB中的信息),颇有些神似"三十六计"中的"金蝉脱壳"。看上去还是旧的躯壳,却已经注入了新的灵魂。只有调用失败了,它们才会返回-1,从原程序的调用点接着往下执行。

二、exec函数簇

cpp 复制代码
int execl(const char *path,const char *arg,.../* (char *) NULL */);
int execlp(const char *file,const char *arg,.../* (char *) NULL */);
int execle(const char *path,const char *arg,.../* (char *) NULL ,char * const envp[] */;

int execv(const char *path,char *const argv[]);
int execvp(const char *file ,char *const argv[]);
int execvp(const char *file,char *const argv[], char *const envp[]);

//前面几个都是标准c库的函数,下面这个是linux的函数,一般来说就最上面两个用的最多。
int execve(const char *filename,char *const argv[],char *const envp[]); 

l:list参数地址列表,以空指针结尾。
v:vector存有各参数地址的指针数组的地址。
p:path按PATH环境变量指定的目录搜索可执行文件。
e:environment存有环境变量字符串地址的指针数组地址。

输入man 3 exec查看标准C库的文档解释:

首先在某个文件夹下创建hello.c文件,代码如下:

cpp 复制代码
#include <stdio.h>

int main() {    

    printf("hello, world\n");

    return 0;
}

然后在同级文件夹下创建execl.c文件,然后通过gcc exec.c -o exec进行编译。

cpp 复制代码
/*
    #include<unistd.h>
    int execl(const char *path, const char *arg, ...);
    参数:
        -path:
            需要指定的执行的文件路径或者相对路径的名称
            比如a.out 或者/home/linux/a.out
            执行a.out的时候可以传递一些参数,所以后面都是可变参数
        -arg:
            是执行可执行文件需要的参数列表
            第一个参数一般没有什么作用,为了方便,一般写的是程序的名称、
            从第二个参数开始往后,就是程序执行所需要的参数。
            参数最后需要以NULL结束(哨兵)。
    返回值:
        只有出错的时候才会有返回值,返回-1,并且设置errno。
        如果调用成功,没有返回值。
        为什么没有返回值?因为用户区的内容已经被替换了。
*/

#include <unistd.h>
#include <stdio.h>
#include<sys/types.h>


int main() {

    // 创建一个子进程,在子进程中执行exec函数族中的函数
    pid_t pid = fork();

    if(pid > 0) {
        // 父进程
        printf("我是父进程, pid : %d\n",getpid());
        sleep(1);
    }else if(pid == 0) {
        // 子进程
        execl("hello","hello",NULL);
		//也可以试着跑一下系统的shell命令,也就是ps aux查看进程的命令,ps是可执行文件,aux是参数。
		//execl("/bin/ps", "ps", "aux", NULL);	
    }
    for(int i = 0; i < 3; i++) {
        printf("i = %d, pid = %d\n", i, getpid());
    }

    return 0;
}

运行./exec,会发现输出了hello,world! 并且只有父进程在输出for循环,子进程因为跳出实现另一个进程,不会再往下执行了。

下面的execlp函数则是到环境变量(输入env 即可查看环境变量,可以看到ps的环境变量是/usr/local/bin,所以下面的代码是可以成功找到ps并且执行的。)中去找可执行文件,所以不需要路径。

cpp 复制代码
/*  
    #include <unistd.h>
    int execlp(const char *file, const char *arg, ... );
        - 会到环境变量中查找指定的可执行文件,如果找到了就执行,找不到就执行不成功。
        - 参数:
            - file:需要执行的可执行文件的文件名
                a.out
                ps

            - arg:是执行可执行文件所需要的参数列表
                第一个参数一般没有什么作用,为了方便,一般写的是执行的程序的名称
                从第二个参数开始往后,就是程序执行所需要的的参数列表。
                参数最后需要以NULL结束(哨兵)

        - 返回值:
            只有当调用失败,才会有返回值,返回-1,并且设置errno
            如果调用成功,没有返回值。


        int execv(const char *path, char *const argv[]);
        argv是需要的参数的一个字符串数组
        char * argv[] = {"ps", "aux", NULL};
        execv("/bin/ps", argv);

*/
#include <unistd.h>
#include <stdio.h>

int main() {

    // 创建一个子进程,在子进程中执行exec函数族中的函数
    pid_t pid = fork();

    if(pid > 0) {
        // 父进程
        printf("i am parent process, pid : %d\n",getpid());
        sleep(1);
    }else if(pid == 0) {
        // 子进程
        execlp("ps", "ps", "aux", NULL);
        printf("i am child process, pid : %d\n", getpid());
    }

    for(int i = 0; i < 3; i++) {
        printf("i = %d, pid = %d\n", i, getpid());
    }

    return 0;
}
相关推荐
AuroBreeze19 小时前
xv6-2023 - primes Lab
linux·运维·服务器
hsjkdhs20 小时前
C++之拷贝构造(浅拷贝与深拷贝)、this指针、内联函数
c++
默|笙20 小时前
【c++】红黑树的部分实现
开发语言·c++
DIY机器人工房20 小时前
NAT 模式、命令行版、桥接模式方式给ubuntu虚拟机配网步骤:
linux·网络协议·ubuntu·嵌入式·桥接模式·diy机器人工房
轩情吖20 小时前
Qt常用控件之QSpinBox
开发语言·c++·qt·控件·桌面级开发·qspinbox·微调框
wdfk_prog21 小时前
[Linux]学习笔记系列 -- lib/sort.c 通用的排序库(Generic Sorting Library) 为内核提供标准的、高效的排序功能
linux·运维·c语言·笔记·stm32·学习·bug
shark_dev21 小时前
C/C++ 指针详解与各种指针定义
c语言·c++
tpoog21 小时前
[C++项目组件]cpp-httplib与 websocketpp的简单介绍和使用
开发语言·c++
黑马金牌编程21 小时前
简易分析慢 SQL 的流程和方法
linux·数据库·mysql·性能优化·性能分析·慢日志
什么半岛铁盒21 小时前
C++项目:仿muduo库高并发服务器---------LoopThreadPool模块和TcpServer模块的实现
linux·服务器·c++·mysql·ubuntu