Linux进程控制——Linux进程程序替换

简介: Linux进程控制——Linux进程程序替换

前言:Linux进程控制包含了进程终止,进程等待,进程程序替换。走到现在我们也只剩下进程程序替换没介绍了,那么让我们来看看进程程序替换到底是什么!


本篇主要内容:

替换原理

替换函数

实现简易shell


我们所创建的所有的子进程,执行的代码,都是父进程代码的一部分,如果我们想让子进程执行新的程序,执行全新的代码和访问全新的数据,不在和父进程有瓜葛这就要用到我们的进程替换了!!!


1. 替换原理

我们先介绍一个exec函数,方便我们读下面的代码

execl:

我们直接来看代码分析:

  1 #include <stdio.h>
  2 #include <sys/types.h>                                                                                                                                                                 
  3 #include <unistd.h>
  4 #include <wait.h>
  5 int main()
  6 {
  7     pid_t id = fork();
  8     if(id == 0)
  9     {
 10         printf("pid: %d, exec command begin\n", getpid());
 11         sleep(2);
 12         execl("/usr/bin/ls", "ls", "-a", "-l", NULL);
 13         printf("pid: %d, exec command end\n", getpid());
 14     }
 15     else{
 16         pid_t rid = waitpid(-1, NULL, 0);
 17         if(rid > 0)
 18         {
 19             printf("wait success, pid: %d\n", rid);
 20         }
 21     }
 22     return 0;
 23 }

我们用fork创建子进程后执行的是和父进程相同的程序,子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。

  • 操作系统在调用exec函数时,只要将整个进程的代码和数据用新程序的代码和数据进行替换。
  • 子进程往往会共享父进程的代码和数据,因为有写时拷贝的技术,有新数据写入时,会重新开辟空间所以不会相互影响,保证父子进程的独立性。


但是我们仔细查看代码和执行结果后发现,竟然有一段代码没有执行!

13  printf("pid: %d, exec command end\n", getpid());

其实是调用exec程序替换,只要exec替换新程序成功了,子进程就回去执行新的程序,因此后面的代码将不会被执行


2. 替换函数

在进程程序替换中,替换函数必不可少,让我们来看看这类函数!

RETURN VALUE:
The exec() functions error has occurred return only if an The return value is -1 and errno to indicate the error

而exec开头的函数一共介绍6种,它们只会在出错时返回 -1!

我们以一下两点来理解:

  • 必须先找到这个可执行程序怎么执行
  • 必须告诉exec,怎么执行*

2.1 execl类型函数

execl我们在上面简单了解了,我们就介绍一下剩下两个

execlp:

int main()
{
    {
        printf("pid: %d, exec command begin\n", getpid());
        sleep(2);
        execlp("ls", "ls", "-a", "-l", NULL);  
        //第一个ls代表怎么找到这个程序 
        //第二个ls其实是命令的一部分,对应怎么执行                                                                                                                                    
        printf("pid: %d, exec command end\n", getpid());
                     
    }                                              
    return 0;                          
}  

在使用execlp函数时,我们并没有加上路径,但是我们依然能够获得想要的结果,正是因为p代表了PATH他会自动去环境变量PATH中根据file来寻找可执行程序!!!


execlpe:

// mytest源代码
int main()
{
    char *const myenv[] = {
         "myenv1=2004",
         "myenv2=2005",
         "myenv3=2005",
         "myenv4=2005",
          NULL
    };                                                                                                                                                                               
    printf("exec command begin\n");
    execle("./myprocess", "myprocess", NULL, myenv);


// myprocess源代码
int main(int agrc, char *agrv[], char *env[])
{
    for(int i = 0; env[i]; i++)
    {
        printf("[%d]: %s\n", i, env[i]);
    }
    return 0;
} 

这是exec*函数程序替换,我们在下文会讲


2.2 execv类型函数

execv其实就是在execl的基础上多了一个指针数组,情况大差不差我们就不具体介绍了!具体关系如下图:

execv 和 execvp:

int main()
{
  char *const argv[] = {
    "ls",
    "-a",
    "-l",
    NULL
  };
    printf("pid: %d, exec command begin\n", getpid());
    sleep(2);
    execv("/usr/bin/ls", argv);       
    //execvp("ls", argv);                                                                                                                         
    printf("pid: %d, exec command end\n", getpid());  
      
    return 0;                          
}  

其实exec这类函数命令有一定的规律:

  • l(list) : 表示参数采用列表
  • v(vector) : 参数用数组
  • p(path) : 有p自动搜索环境变量PATH
  • e(env) : 表示自己维护环境变量


3. 实现简易shell

我们用程序替换是可以用C语言把C++调用起来的

// test.c
int main()
{
    printf("pid: %d, exec command begin\n", getpid());
    execl("./myprocess", "myprocess", NULL);                                                                                                                               
    return 0;
}

// test.cc
int main()
{
    std::cout << "hello c++" << std::endl;
    std::cout << "hello c++" << std::endl;
    std::cout << "hello c++" << std::endl;
    std::cout << "hello c++" << std::endl;                                                                                                                                             
    return 0;
}

Makefile:

.PHONY:all
 all:mytest myprocess
 
 myprocess:test.cc
     g++ -o $@ $^ -std=c++11
  
 mytest:test.c
     gcc -o $@ $^ -std=c99
     
.PHONY:clean
clean:
     rm -f mytest myprocess 

因为我们要同时编译两个程序,所以我们要对Makefile进行一下调整

我们通过程序替换将C++用C语言调用起来了


那我们除了调用C++还能调用别的嘛?

  • 显而易见当然是可以的!!!
// test.sh
// 会简单编写就好
#!/usr/bin/bash
echo "hello Linux"
echo "hello world"
touch code

// test.c
int main()
{
    printf("pid: %d, exec command begin\n", getpid());
    execl("/usr/bin/bash", "bash", "test.sh", NULL);                                                                                                                               
    return 0;
}

当然除了我们讲的这两个,其实所有语言都能通过进程程序替换来调用,因为我们用任意语言写的程序都会变成进程,只要是进程就都可以用exec*来替换——系统大于一切


4. 总结

进程程序替换能够让我们只用C语言就可以调用其他任何语言去执行,极大程度上带来了便利,也可以帮助我们完成很多任务,好了,关于Linux进程控制我们先了解到这,下次我们将进入新的章节!

谢谢大家支持本篇到这里就结束了

目录
相关文章
|
11天前
|
算法 Linux 调度
深入理解Linux操作系统的进程管理
本文旨在探讨Linux操作系统中的进程管理机制,包括进程的创建、执行、调度和终止等环节。通过对Linux内核中相关模块的分析,揭示其高效的进程管理策略,为开发者提供优化程序性能和资源利用率的参考。
34 1
|
6天前
|
SQL 运维 监控
南大通用GBase 8a MPP Cluster Linux端SQL进程监控工具
南大通用GBase 8a MPP Cluster Linux端SQL进程监控工具
|
14天前
|
运维 监控 Linux
Linux操作系统的守护进程与服务管理深度剖析####
本文作为一篇技术性文章,旨在深入探讨Linux操作系统中守护进程与服务管理的机制、工具及实践策略。不同于传统的摘要概述,本文将以“守护进程的生命周期”为核心线索,串联起Linux服务管理的各个方面,从守护进程的定义与特性出发,逐步深入到Systemd的工作原理、服务单元文件编写、服务状态管理以及故障排查技巧,为读者呈现一幅Linux服务管理的全景图。 ####
|
20天前
|
缓存 算法 Linux
Linux内核的心脏:深入理解进程调度器
本文探讨了Linux操作系统中至关重要的组成部分——进程调度器。通过分析其工作原理、调度算法以及在不同场景下的表现,揭示它是如何高效管理CPU资源,确保系统响应性和公平性的。本文旨在为读者提供一个清晰的视图,了解在多任务环境下,Linux是如何智能地分配处理器时间给各个进程的。
|
1月前
|
存储 运维 监控
深入Linux基础:文件系统与进程管理详解
深入Linux基础:文件系统与进程管理详解
70 8
|
27天前
|
网络协议 Linux 虚拟化
如何在 Linux 系统中查看进程的详细信息?
如何在 Linux 系统中查看进程的详细信息?
54 1
|
27天前
|
Linux
如何在 Linux 系统中查看进程占用的内存?
如何在 Linux 系统中查看进程占用的内存?
|
7月前
|
Linux Shell 调度
【Linux】7. 进程概念
【Linux】7. 进程概念
69 3
|
7月前
|
存储 缓存 Linux
【Linux】进程概念(冯诺依曼体系结构、操作系统、进程)-- 详解
【Linux】进程概念(冯诺依曼体系结构、操作系统、进程)-- 详解
|
4月前
|
Linux Shell 调度
【在Linux世界中追寻伟大的One Piece】Linux进程概念
【在Linux世界中追寻伟大的One Piece】Linux进程概念
42 1