当前位置: 首页 > article >正文

Linux中的进程替换

目录

进程替换

替换函数

execl 

execlp

execv

execvp

execle

简单的命令行解释器

对cd命令进行特殊处理

echo$?


进程替换

创建子进程的目的?

a.让子进程执行父进程代码的一部分->执行父进程对应的磁盘代码的一部分

b.让子进程执行一个全新的程序->让子进程,加载磁盘上指定的程序,执行新的代码和数据(进程程序替换)

替换函数

#include <unistd.h>`
 
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[])

 给所有的exec*系列函数传参时,最后一个必须为NULL

execl 

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

int main()
{
    printf("process is running...\n");
    execl("/usr/bin/ls","ls","-a","-l",NULL);
    printf("process is running...\n");
}

运行myexe等价于执行ls命令。

为什么printf没有被打印?

printf位于exec之后,当execl执行完成之后,代码已经被覆盖,并开始执行新的程序和代码了,所以printf无法执行。

 及如果execl发生了返回,意味着execl函数调用失败。

程序替换时代码可能发生写时拷贝。

虚拟地址空间+页表可以保证进程独立性。

一旦有执行流想替换代码或数据就会发生写时拷贝。

execlp

execlp("ls","ls","-a","-l",NULL);

第一个ls是指明要执行的程序

第二个ls是告诉系统要如何执行

execv

char* const argv[]={
            "ls",
            "-a",
            "-l",
            NULL
        };
        execv("/usr/bin/ls",argv);

execvp

char* const argv[]={
            "ls",
            "-a",
            "-l",
            NULL
        };
        execvp("ls",argv);

makefile默认只能形成一个可执行程序,从上往下扫描先根据第一个目标文件,形成目标对象。

#!/bin/bash

echo "hello shell"
echo "hello shell"
execl("./myshell","myshell.sh","-a","-l",NULL);

execle

exec*系列的函数可以将程序加载到内存中,在Linux中加载的方式为通过exec*加载(加载器)

只有execve是系统调用。

字符串切割:strtok,strtok读到NULL时结束。

简单的命令行解释器

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>

#define NUM 1024
#define OPT_NUM 64
char lineCommand[NUM];
char* myargv[OPT_NUM];

int main()
{
    while (1)
    {
        printf("用户名@主机名# ");
        fflush(stdout);
        // 获取用户输入
        char *s = fgets(lineCommand, sizeof(lineCommand) - 1, stdin);
        assert(s != NULL);
        lineCommand[strlen(lineCommand) - 1] = 0;
        myargv[0]=strtok(lineCommand," ");
        //"la -a -l"
        int i = 1;
        while (myargv[i++] = strtok(NULL, " "));
        pid_t id=fork();
        assert(id!=-1);
        if(id==0)
        {
            execvp(myargv[0],myargv);
            exit(1);
        }
        waitpid(id,NULL,0);

    }
    
    return 0;
}


对cd命令进行特殊处理

if(myargv[0]!=NULL&&strcmp(myargv[0],"cd")==0)
        {
            if(myargv[1]!=NULL) chdir(myargv[1]);
            continue;
        }

向cd这种不需要子进程执行,而是让shell自己执行的命令称为内建/内置命令。

内建/内置命令

及shell内部的一个函数

echo$?

if(myargv[0]!=NULL&&myargv[1]!=NULL&&strcmp(myargv[0],"echo"))
        {
            if(strcmp(myargv[1],"$?"))
            {
                printf("%d,%d\n",lastCode,lastSig);
            }
            else
            {
                printf("%s\n",myargv[1]);
            }
            continue;
        }

查看最近一个进程的退出码。


http://www.kler.cn/a/321656.html

相关文章:

  • 领夹麦克风哪个品牌好,手机领夹麦克风哪个牌子好,选购推荐
  • C++(Day35)
  • 谷歌Gemini发布iOS版App,live语音聊天免费用!
  • 深度学习的多主机多GPU协同训练
  • 博物馆实景复刻:开启沉浸式文化体验的新篇章
  • SpringBoot开发——整合AJ-Captcha实现安全高效的滑动验证码
  • linux:chown用法详解
  • 微调大模型(Finetuning Large Language Models)—Where finetuning fits in(二)
  • Oracle 相关的工具使用 SQL Developer , sqlplus
  • Kotlin:变量声明,null安全,条件语句,函数,类与对象
  • SpringBoot-全局处理异常,时间格式,跨域,拦截器,监听器
  • Brave编译指南2024 MacOS篇-获取源码(三)
  • 如何解决: Java商城系统开发过程中 开发难度大和时间紧的问题
  • python-rpc-windows服务器C#项目远程调用Linux服务器上的python脚本
  • 数据库常见概念
  • React学习笔记(2.0)
  • 【rust】 基于rust编写wasm,实现markdown转换为html文本
  • Lab1 Xv6 and Unix utilities
  • 推荐、nlp、算法题等相关复习(0922-0929)
  • 计算机毕业设计宠物领养网站我的发布领养领养用户信息/springboot/javaWEB/J2EE/MYSQL数据库/vue前后分离小程序
  • HalconDotNet实现OCR详解
  • 比较 Python Web 框架:Django、FastAPI 和 Flask
  • 如何使用 ChatGPT 生成万字长文?
  • verilog中非阻塞多个if 优先级判断。
  • 介绍与部署 Zabbix 监控系统
  • C#知识|基础知识点巩固拾遗