进程控制——进程替换、模拟shell

一、进程替换

  1、进程替换
    替换一个进程正在调度运行的程序,即重新加载另一个程序到内存中,将现有的一个子进程的pcb的内存指针所指向的内存空间指向这个新的程序(更新页表的映射信息),则这个现有的子进程就跑去调度这个新的程序了;在这里插入图片描述
  2、程序替换的意义
    fork创建的子进程,代码共享数据独有,父子进程干的是一样的事情;但是通常情况下,我们创建一个子进程的目的并不是为了让子进程与自己干一个事情,而是让子进程运行调度一个新的程序,让他去干其他事情,这就是程序替换的意义;
  3、库函数接口

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

    path:新程序的路径及名称;
    file:新程序的名称;
    arg:命令行参数,最后以NULL结尾
    argv[ ]:将所有命令行参数放到一个字符串指针数组中进行传参;
    envp[ ]:环境变量;
  4、各接口函数的区别

	(1)l和v的区别:l是将命令行参数一个一个输入,v是将命令行参数保存到数组中;
	(2)有p没有p的区别:有p的第一个参数是写程序名称,没有p写的是路径名;
	(3)有e没有e的区别:有e是要传入环境变量;

二、模拟实现shell

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

#define IN 1
#define OUT 0

//程序替换
void do_exec(char* argv[])
{
	pid_t pid;

	if ((pid = fork()) == -1)
	{
		//无法创建子进程,shell出现故障
		printf("shell程序出现故障,正在维修...\n");
	}

	if (pid == 0)
	{
		//子进程进行程序替换
		int ret = execvp(argv[0], argv);

		//如果走到这里,说明程序替换失败,该命令没被找到,退出
		printf("%s command not found\n", argv[0]);
		exit(1);
	}
	else
	{
		//父进程阻塞等待子进程执行完毕,进行回收
		int status;
		waitpid(pid, &status, 0);
	}
}

//解析命令
void do_parse(char* buf)
{
	int argc = 0;    //命令行参数个数
	char* argv[10] = {};    //命令行参数字符指针数组
	int status = OUT;   //当前位置是否有字符的状态标记
	int i = 0;

	while (buf[i] != '\0')
	{
		//当当前位置状态为OUT,并且有字符时,将命令行参数指针指向当前位置(存入一个命令行参数),并将状态置为IN
		if (status == OUT && !isspace(buf[i]))
		{
			argv[argc++] = buf + i;
			status = IN;
		}
		//当当前位置为空时,将当前位置置为\0(保证一个命令行参数以\0结尾),状态置为OUT
		else if (isspace(buf[i]))
		{
			buf[i] = '\0';
			status = OUT;
		}
		i++;
	}
	//最后将最后一个命令行参数置为NULL
	argv[argc] = NULL;

	//进行程序替换
	do_exec(argv);
}

//读取一行字符,返回读取的字符个数
int get_input(char* buf)
{
	//清空buf缓存区
	memset(buf, 0x00, sizeof(buf));
	//输入一串字符,如果没有成功输入,则清空buf缓存区
	if (scanf("%[^\n]%*c", buf) != 1)
	{
		char c;
		do {
			c = getchar();
		} while (c != '\n');
	}
	
	return strlen(buf);
}

int main()
{
	//创建一个存输入字符的缓冲区
	char buf[512];

	//循环shell提示
	while (1)
	{
		//打印shell提示
		printf("[myshell] #");
		//如果读取0个字符(即直接按回车,则继续下一轮读取命令)
		if (get_input(buf) == 0)
			continue;
		//命令解析
		do_parse(buf);
	}
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值