minishell编写时遇到的奇怪问题

minishell编写时遇到的奇怪问题

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
	
#define SZ_CMD 128
#define SZ_ARGV 8

#define DEBUGE

int cmd_parse(char *cmd_str, char *file, char **argv)
{
	if(cmd_str == NULL)
		return-1;

	char* p_cmd_argv = NULL;
	int index = 0;

	file = strtok(cmd_str, " ");

#ifdef DEBUGE
	printf("file: %s. \n",file);
	
#endif

	while((p_cmd_argv = strtok(NULL," "))!=NULL)
	{
		argv[index] = p_cmd_argv;

#ifdef DEBUGE
	printf("argv: %s. \n",argv[index]);
#endif

		index++;
	
	}

	return 0;
}

int create_process(char *file, char **argv)
{

	if(NULL == file || NULL == argv)
	{
		printf("create_process() args is NULL.\n");
		printf("file: %s. \n",file);
		return -1;
	}

	pid_t cpid = 0;

	cpid=fork();// 创建子线程

	if(cpid == -1)
	{
		perror("[Error]: process create faile ");
		exit(EXIT_FAILURE);
	}
	else if(cpid == 0)// 子进程执行任务
	{
		int ret = 0;

		ret = execvp(file, argv);
		if(ret != 0)
		{
			printf("cpfuncp is excute faile.\n");
			return -1;
		}

		exit(EXIT_SUCCESS);// 由子进程调用 exit() 函数退出

	}
	else if(cpid > 0)// 父进程执行任务
	{
		pid_t rpid = 0;
		int status = 0;

		rpid = wait(&status);

	}

	return 0;
}

int excute(char *cmd)
{
	char *cmd_file = NULL;
	char *cmd_arg_list[SZ_ARGV] = {NULL};
	
	cmd_parse(cmd, cmd_file, cmd_arg_list);

	create_process(cmd_file, cmd_arg_list);
	
	return 0;
}

int main(int argc, const char *argv[])
{
	char command[SZ_CMD] ={0};

	printf("miniShell > ");

	fgets(command, SZ_CMD, stdin);
	command[strlen(command)-1]='\0';

	excute(command);
	return 0;
}

代码有两个问题:

  1. excute()函数调用 cmd_parse()函数,传入cmd_file, cmd_arg_list两个指针,将命令名和参数分割。 cmd_parse()函数调用接收,cmd_file和 cmd_arg_list获取到参数了,但是cmd_file离开 cmd_parse()函数后,cmd_file的值马上变成了NULL。

  2. 在minishell 中输入的ls -l 和命令行中输入的ls -l,预期不一样

https://img1.sycdn.imooc.com//climg/6460f1f0099b978005060286.jpg

正在回答

登陆购买课程后可参与讨论,去登陆

1回答

问题1:你的指针传递的是局部变量,excute()函数中本身cmd_file的值就是NULL,所以传参到另一个函数file也是NULL,file和cmd_file是两个内存,file做任何操作,不影响cmd_file.所以要传递二次指针。

    cmd_parse(cmd, &cmd_file, cmd_arg_list);


问题2:你的代码参数传递的有问题。execvp(file, argv); 里面的内容应该填充类型下面的用法。
char *argv[] = {"ls","-l",NULL};
execvp("ls",argv); 
运行结果:
https://img1.sycdn.imooc.com//climg/6461c34f08ffd3d511180333.jpg
修改后的代码如下:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <unistd.h>

     

#define SZ_CMD 128

#define SZ_ARGV 8

 

#define DEBUGE

 

int cmd_parse(char *cmd_str, char **file, char **argv)

{

    if(cmd_str == NULL)

        return-1;

 

    char* p_cmd_argv = NULL;

    int index = 0;

 

    *file = strtok(cmd_str, " ");

 

#ifdef DEBUGE

    printf("file: %s. \n",*file);

     

#endif

 

argv[index ++] = *file;

    while((p_cmd_argv = strtok(NULL," "))!=NULL)

    {

        argv[index] = p_cmd_argv;

#ifdef DEBUGE

    printf("argv: %s. \n",argv[index]);

#endif

 

        index++;

     

    }

 

    return 0;

}

 

int create_process(char *file, char **argv)

{

 

    if(NULL == file || NULL == argv)

    {

        printf("create_process() args is NULL.\n");

        printf("file: %s. \n",file);

        return -1;

    }

 

    pid_t cpid = 0;

 

    cpid=fork();// 创建子线程

 

    if(cpid == -1)

    {

        perror("[Error]: process create faile ");

        exit(EXIT_FAILURE);

    }

    else if(cpid == 0)// 子进程执行任务

    {

        int ret = 0;

 

        ret = execvp(file, argv);

        if(ret != 0)

        {

            printf("cpfuncp is excute faile.\n");

            return -1;

        }

 

        exit(EXIT_SUCCESS);// 由子进程调用 exit() 函数退出

 

    }

    else if(cpid > 0)// 父进程执行任务

    {

        pid_t rpid = 0;

        int status = 0;

 

        rpid = wait(&status);

 

    }

 

    return 0;

}

 

int excute(char *cmd)

{

    char *cmd_file = NULL;

    char *cmd_arg_list[SZ_ARGV] = {NULL};

int i = 0;

     

    cmd_parse(cmd, &cmd_file, cmd_arg_list);

# if DEBUG

printf("=================================\n");

printf("cmd_file = %s\n",cmd_file);


for(i = 0;cmd_arg_list[i] != NULL;i++)

{

printf("%s \n",cmd_arg_list[i]);

}

printf("=================================\n");

#endif

 

    create_process(cmd_file, cmd_arg_list);

     

    return 0;

}

 

int main(int argc, const char *argv[])

{

    char command[SZ_CMD] ={0};

 

    printf("miniShell > ");

 

    fgets(command, SZ_CMD, stdin);

    command[strlen(command)-1]='\0';

 

    excute(command);

    return 0;

}


  • 慕小白0101 提问者 #1

    大白老师,我还有一个问题

    int func(char *p){}
    int main()
    {    char *p="123";
        func(p);
    }

    func(p),传进func()函数里的时字符串”123“的地址 还是字符串”123“?

    2023-05-15 15:17:20
  • 慕小白0101 提问者 #2

    从minishell的结果里看,func(p),传进func()函数里的是字符串”123“,func(p)是值传递而不是传地址

    2023-05-15 15:19:34
  • 无__名 回复 提问者 慕小白0101 #3

    传递的就是字符串的地址,字符串"123" 是存储在.rodata 区域里,在函数里面是通过地址来获取字符串的内容

    2023-05-17 17:46:22
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师