自学内容网 自学内容网

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自己执行的命令称为内建/内置命令。

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;
        }

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


原文地址:https://blog.csdn.net/2301_77479435/article/details/142532446

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!