Ped*_*ira 1 c linux operating-system
我的任务是实现这个镜像 Linux shell 的 myshell 程序。这是我大学操作系统入门课程的范围。他们向我们提供了基本的 shell 代码并要求我们篡改它。
练习之一是实现终止自定义 shell 的退出命令。我使用 strcmp 做到了这一点。然而我觉得这是一个非常hacky的解决方案——感觉就像作弊。
这是源代码:
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
int main(int argc, char* argv[]){
char buf[1024];
char* args[256];
pid_t pid;
for( ; ; ){
char* command;
fprintf(stdout, "$ ");
if((command = fgets(buf, sizeof(buf), stdin)) == NULL){
break;
}
command[strlen(buf) -1] = '\0';
//saving commands to a memory file so I can
//print them out later on with tail (through
//myhistory)
FILE* f = fopen("mem.txt", "a");
fwrite(command, sizeof(char), strlen(command), f);
fputc('\n', f);
fclose(f);
int i = 0;
do{
if(i == 0) args[i] = strtok(command, " ");
else args[i] = strtok(NULL, " ");
i++;
}while(args[i-1] != NULL);
//hacky exit command I'm trying to improve on
if(!strcmp(args[0], "exit")) exit(EXIT_SUCCESS);
if((pid = fork()) == -1){
fprintf(stderr, "%s: cant fork command: %s",
argv[0], strerror(errno));
continue;
} else if (pid == 0){
execvp(args[0], args);
fprintf(stderr, "%s: couldn't exec %s: %s\n",
argv[0], buf, strerror(errno));
exit(EXIT_FAILURE);
}
if((pid = waitpid(pid, NULL, 0)) < 0)
fprintf(stderr, "%s: waitpid error: %s\n",
argv[0], strerror(errno));
}
exit(EXIT_SUCCESS);
}
Run Code Online (Sandbox Code Playgroud)
我这样写了退出命令:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
int main(){
kill(getpid(), 0);
}
Run Code Online (Sandbox Code Playgroud)
但这并没有帮助,因为我只是杀死了孩子。我怎么能通过孩子杀死父母呢?是的,我知道我可以将父 PID 传递给 exit 命令并以这种方式终止它,但有些事情告诉我有一个更干净的解决方案,不需要硬编码控制流逻辑。
在“真正的”shell 中,类似的命令exit是“shell 内置”。它们不是启动另一个程序的外部命令,而是由 shell 在内部执行。
您可以通过各种方式、strcmp、字典等来实现这些,但它们本质上只是您当前正在做的事情的美化版本。所以,是的,继续做你正在做的事情。