gpt4 book ai didi

c - shell后台进程

转载 作者:太空宇宙 更新时间:2023-11-04 08:19:25 26 4
gpt4 key购买 nike

我想实现自己的 shell。我坚持执行后台进程。实际上,我写了一些代码,但我不确定它是否有效。

我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define MAX_LINE 80 /* 80 chars per line, per command, should be enough. */
#define HISTORY_SIZE 5 /*keep track of 5 most recent commands*/

int cmd_count; /*global to keep track of most recent commands entered*/
char history[HISTORY_SIZE][MAX_LINE]; /* global so it can be accessed in interrupt handler. */


void viewHistory()
{
int i;

if (cmd_count < 1)
printf("No command history to show. \n");
else {
printf("\n\n");
for (i = (cmd_count >= HISTORY_SIZE) ? cmd_count - HISTORY_SIZE:0;
i < cmd_count; i++)
printf("%d: %s\n",i+1,history[i%HISTORY_SIZE]);
}
//printf("SystemsIIShell->");
}



int setup(char inputBuffer[], char *args[],int *background)
{
int length, /* # of characters in the command line */
i, /* loop index for accessing inputBuffer array */
start, /* index where beginning of next command parameter is */
ct; /* index of where to place the next parameter into args[] */

int temp;

ct = 0;

/* read what the user enters on the command line */
length = read(STDIN_FILENO, inputBuffer, MAX_LINE);

start = -1;
if (length == 0)
exit(0); /* ^d was entered, end of user command stream */
if (length < 0){
perror("error reading the command");
exit(-1); /* terminate with error code of -1 */
}else{
inputBuffer[length]='\0';
if(inputBuffer[0]=='r'){
if(inputBuffer[1]=='r'){
if(cmd_count==0){
printf("No recent command can be found in the history. \n");
return 0;
}
strcpy(inputBuffer,history[(cmd_count)% HISTORY_SIZE]);
}else{
temp = atoi(&inputBuffer[1]);
if(temp < 1 || temp > cmd_count || temp <= cmd_count -HISTORY_SIZE){
printf("Command number cannot be found. \n");
return 0;

}
strcpy(inputBuffer,history[(temp-1)%HISTORY_SIZE]);

}
length = strlen(inputBuffer);

}
cmd_count++;
strcpy(history[(cmd_count-1)%HISTORY_SIZE], inputBuffer);
for (i = 0; i < length; i++) {
if (inputBuffer[i] == '&') {
inputBuffer[i] = '\0';
*background = 1;
--length;
break;
}

}
}

/* examine every character in the inputBuffer */
for (i = 0; i < length; i++) {
switch (inputBuffer[i]){
case ' ':
case '\t' : /* argument separators */
if(start != -1){
args[ct] = &inputBuffer[start]; /* set up pointer */
ct++;
}
inputBuffer[i] = '\0'; /* add a null char; make a C string */
start = -1;
break;

case '\n': /* should be the final char examined */
if (start != -1){
args[ct] = &inputBuffer[start];
ct++;
}
inputBuffer[i] = '\0';
args[ct] = NULL; /* no more arguments to this command */
break;

case '&':
*background = 1;
inputBuffer[i] = '\0';
break;

default : /* some other character */
if (start == -1)
start = i;
}
}
args[ct] = NULL; /* just in case the input line was > 80 */
}

int main(void)
{
char inputBuffer[MAX_LINE]; /* buffer to hold the command entered */
int background; /* equals 1 if a command is followed by '&' */
char *args[MAX_LINE/2+1];/* command line (of 80) has max of 40 arguments */

while (1){ /* Program terminates normally inside setup */
background = 0;
printf("SystemsIIShell->");
fflush(0);
setup(inputBuffer, args, &background); /* get next command */

pid_t child; /* process id for child */
int status; /* status for execvp */

child = fork(); /* create a child process*/

if(child < 0){ /* if the child process didn't return 0, the fork is failed */
printf("Fork failed! \n");

}else if(child==0){ /* child process */
if(inputBuffer[0]=='history' || inputBuffer[0] =='h'){
viewHistory();
return 0;
}
status = execvp(args[0],args);
if(status !=0){
printf("%s: command not found. \n", args[0]);
}

}else{ /* parent process */
if(background == 0)
waitpid(child,&background,0);

}

/* the steps are:
(1) fork a child process using fork()
(2) the child process will invoke execvp()
(3) if background == 0, the parent will wait,
otherwise returns to the setup() function. */

}return 0;

我没有添加完整的代码,但其他的都是真的。我调用 execv 并且它有效。当我在控制台上写的时候:

输出端:

$ gedit  ------->it works correctly because it is a foreground


$ gedit & -----> it opens a gedit file which name is "&"
$ firefox ---> it works correctly
$ firefox & ---> it opens a firefox window which url is www.&.com

如何解决?有什么建议吗?

编辑部分:https://github.com/iqbalhasnan/CSE2431-System-II/blob/master/lab2/lab2.c --> 我用这段代码作为引用

最佳答案

你不是在执行后台进程,你是在尝试使用计算机上已经实现的 shell 的语法启动后台进程(但老实说,很难说出缩进是怎么回事。那是真的很糟糕。你能让它变得可读吗?)。 '&' 字符由您的 shell 识别,而不是由 execvp 识别。看看this similar looking question这是针对您的问题的谷歌搜索中的第一个匹配项。

关于c - shell后台进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34049865/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com