进程替换、写一个简单的shell程序

进程替换

进程替换概念

进程替换意思就是,让一个进程替换另一个进程。Linux系统提供一系列接口来实现进程替换。需要注意的是,进程替换仅仅是当前进程在磁盘中的程序文件被另一个进程的程序替换,而内存中的pcb并没有替换,也就是说进程替换不创建新进程,而是让老进程执行新的代码。

替换函数

Linux提供了多个替换函数但是本质都是一样的,仅仅是使用方式不同。

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[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);

函数解释:这些函数的第一个参数均是待替换的程序的名称(需要带路径),后续参数均是 ,执行待替换进程携带的一些参数。例如 : ls -a -l 中的 “-a” “-l” 。 以NULL作为参数的结尾。
这些函数的命名都是有一定的规律:
l(list):参数以列表的形式给定。
v(vector):参数保存在一个指针数组,传参时传数组名。
p(path): 传参时不用带路径,系统会到默认的路径中去找文件
e(env):表示自己创建的环境变量

替换函数的简单使用

下面列出几个最常用的替换函数的简单使用

int main()    
{
    
        
    execl("/usr/bin/ls", "ls", "-a", "-l", NULL);     
    return 0;                                                                                                                
}  
 
int main()    
{
    
        
    execlp("ls", "ls", "-a", "-l", NULL);    
    return 0;                                                                                                                
}  
int main()    
{
    
        
    char *args[] = {
    
    "ls", "-a", "-l", NULL};    
    execv("/usr/bin/ls", args);    
    return 0;                                                                                                                
}  
int main()    
{
    
        
    char *args[] = {
    
    "ls", "-a", "-l", NULL};    
    execv("ls", args);   
    return 0;                                                                                                                
}  

Linux下一切皆文件,命令也是如此,每个命令都是一个程序保存在系统指定的目录下,当我们输入这个命令时实际上就是运行这个程序。
以上几个例子均是让ls程序替换掉我们写的主程序。运行主程序实际上就是执行ls -a -l 的命令。
但是实际我们并不会用其它进程替换我们的主程序,而是会通过fork()创建一个子进程,让它替换掉我们的子进程。
下面看一个实例。

写一个shell程序

#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <vector>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define MAXSIZE 1024
using namespace std;

int main()
{
    
    

    while(1)
    {
    
    
        pid_t id = fork();
        if(id < 0)
        {
    
    
            cout << "fork error!" << endl;
            exit(0);
        }
        else if(id == 0)
        {
    
    
            //child 
            //显示命令行界面 [minishell]# 
            cout << "[minishell]# ";

            //输入命令保存在cmd中
            char cmd[MAXSIZE] = {
    
    '\0'};
            fgets(cmd, MAXSIZE -1, stdin);
            cmd[strlen(cmd) - 1] = '\0';   //将读入的\n取消

            //解析string,将指令和参数保存到 args[] 中
            char *args[MAXSIZE / 100] = {
    
    NULL}; 
            char *ps = strtok(cmd, " ");
            int i = 0;
            while(ps)
            {
    
    
                args[i++] = ps;
                ps = strtok(NULL, " ");
            }
            //进程替换
            execvp(args[0], args);
            exit(0);
        }

        //父进程等待子进程的执行
        int status = 0;
        pid_t ret = waitpid(id, &status, 0);

        //检测等待过程是否成功
        if(ret == -1)
        {
    
    
            //函数调用失败
            cout << "wait error!" << endl;
        }
        else if(ret == id)
        {
    
    
            if(WIFEXITED(status))
            {
    
    
                //等待成功
                cout << WEXITSTATUS(status) << endl;
            }
            else 
            {
    
    
                cout << "killed by sign!" << endl;
            }
        }
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_50168448/article/details/115368140
今日推荐