1、编写一个C程序作为Linux内核的shell命令行解释程序。 增加功能以使用户可以使用“&”操作符作为命令的结束符。一个以“&”结尾的命令应该与shell并发执行。 增加功能以使用户可以使用“<”和“>”作为文件名前缀来重定向stdin和stdout描述符。同样,允许用户使用管道操作符“|”来同时执行两个进程,并把第一个进程的stdout重定向为第二个进程的stdin。
时间: 2023-12-25 16:06:26 浏览: 83
好的,下面是一个简单的示例程序,可以实现您提到的功能:
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <fcntl.h>
#define MAX_ARGS 100
#define MAX_COMMANDS 100
#define MAX_LINE_LENGTH 1024
int main(int argc, char *argv[]) {
int fd_in = 0, fd_out = 1, i, j, status;
int num_commands = 0, num_args = 0, background = 0;
char *commands[MAX_COMMANDS][MAX_ARGS];
char line[MAX_LINE_LENGTH], *token, *redirect_file;
pid_t pid, pgid;
// 循环读取用户输入的命令
while (1) {
printf("myshell> ");
fflush(stdout);
fgets(line, MAX_LINE_LENGTH, stdin);
line[strcspn(line, "\n")] = '\0';
// 解析命令行参数
token = strtok(line, " ");
while (token != NULL) {
if (strcmp(token, "&") == 0) {
background = 1;
break;
} else if (strcmp(token, "<") == 0) {
redirect_file = strtok(NULL, " ");
fd_in = open(redirect_file, O_RDONLY);
if (fd_in < 0) {
perror("open");
break;
}
} else if (strcmp(token, ">") == 0) {
redirect_file = strtok(NULL, " ");
fd_out = open(redirect_file, O_WRONLY | O_TRUNC | O_CREAT, 0644);
if (fd_out < 0) {
perror("open");
break;
}
} else if (strcmp(token, "|") == 0) {
commands[num_commands][num_args] = NULL;
num_args = 0;
num_commands++;
} else {
commands[num_commands][num_args++] = token;
}
token = strtok(NULL, " ");
}
commands[num_commands][num_args] = NULL;
// 创建进程并执行命令
pid = fork();
if (pid == 0) {
// 子进程
if (fd_in != 0) {
dup2(fd_in, 0);
close(fd_in);
}
if (fd_out != 1) {
dup2(fd_out, 1);
close(fd_out);
}
if (num_commands > 0) {
int fd[2];
pid_t pids[num_commands];
for (i = 0; i < num_commands; i++) {
pipe(fd);
pid = fork();
if (pid == 0) {
dup2(fd[1], 1);
close(fd[0]);
execvp(commands[i][0], commands[i]);
perror("execvp");
exit(1);
} else if (pid > 0) {
pids[i] = pid;
if (i == 0) {
pgid = pid;
setpgid(pid, pgid);
} else {
setpgid(pid, pgid);
}
dup2(fd[0], 0);
close(fd[1]);
} else {
perror("fork");
exit(1);
}
}
for (i = 0; i < num_commands; i++) {
waitpid(pids[i], &status, 0);
}
} else {
execvp(commands[0][0], commands[0]);
perror("execvp");
exit(1);
}
} else if (pid > 0) {
// 父进程
if (!background) {
waitpid(pid, &status, 0);
} else {
printf("Background job %d\n", pid);
}
} else {
perror("fork");
}
// 重置变量
num_args = 0;
num_commands = 0;
background = 0;
fd_in = 0;
fd_out = 1;
}
return 0;
}
```
这个程序可以按照您的要求解析命令行参数,并实现了重定向和管道功能。当一个命令以“&”结尾时,程序会在后台并发执行该命令。
当用户输入一个命令时,程序会首先解析该命令中的各个参数,将它们存入一个二维数组中。如果命令中包含重定向符号“<”或“>”,程序会打开相应的文件并将标准输入或标准输出重定向到该文件。如果命令中包含管道符号“|”,程序会创建多个进程,并将它们通过管道连接起来。
最后,程序会创建一个新进程并通过 execvp() 系统调用执行用户输入的命令。如果该命令以“&”结尾,则程序会在后台并发执行该命令,否则程序会等待该命令执行完成后再返回。
希望这个程序可以帮助到您,如果您有任何问题或疑问,请随时问我。
阅读全文